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,6 +2,9 @@ package com.genersoft.iot.vmp.conf;
2 2
3 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; 3 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
4 import com.genersoft.iot.vmp.utils.DateUtil; 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 import org.springframework.beans.factory.annotation.Value; 8 import org.springframework.beans.factory.annotation.Value;
6 import org.springframework.context.annotation.Configuration; 9 import org.springframework.context.annotation.Configuration;
7 import org.springframework.util.ObjectUtils; 10 import org.springframework.util.ObjectUtils;
@@ -15,6 +18,8 @@ import java.util.regex.Pattern; @@ -15,6 +18,8 @@ import java.util.regex.Pattern;
15 @Configuration("mediaConfig") 18 @Configuration("mediaConfig")
16 public class MediaConfig{ 19 public class MediaConfig{
17 20
  21 + private final static Logger logger = LoggerFactory.getLogger(MediaConfig.class);
  22 +
18 // 修改必须配置,不再支持自动获取 23 // 修改必须配置,不再支持自动获取
19 @Value("${media.id}") 24 @Value("${media.id}")
20 private String id; 25 private String id;
@@ -174,7 +179,7 @@ public class MediaConfig{ @@ -174,7 +179,7 @@ public class MediaConfig{
174 try { 179 try {
175 hostAddress = InetAddress.getByName(sdpIp).getHostAddress(); 180 hostAddress = InetAddress.getByName(sdpIp).getHostAddress();
176 } catch (UnknownHostException e) { 181 } catch (UnknownHostException e) {
177 - throw new RuntimeException(e); 182 + logger.error("[获取SDP IP]: 域名解析失败");
178 } 183 }
179 return hostAddress; 184 return hostAddress;
180 } 185 }
src/main/java/com/genersoft/iot/vmp/conf/SystemInfoTimerTask.java
1 package com.genersoft.iot.vmp.conf; 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 import com.genersoft.iot.vmp.storager.IRedisCatchStorage; 4 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
4 import com.genersoft.iot.vmp.utils.SystemInfoUtils; 5 import com.genersoft.iot.vmp.utils.SystemInfoUtils;
  6 +import org.slf4j.Logger;
  7 +import org.slf4j.LoggerFactory;
5 import org.springframework.beans.factory.annotation.Autowired; 8 import org.springframework.beans.factory.annotation.Autowired;
6 import org.springframework.scheduling.annotation.Scheduled; 9 import org.springframework.scheduling.annotation.Scheduled;
7 import org.springframework.stereotype.Component; 10 import org.springframework.stereotype.Component;
@@ -14,6 +17,8 @@ import java.util.Map; @@ -14,6 +17,8 @@ import java.util.Map;
14 @Component 17 @Component
15 public class SystemInfoTimerTask { 18 public class SystemInfoTimerTask {
16 19
  20 + private Logger logger = LoggerFactory.getLogger(SystemInfoTimerTask.class);
  21 +
17 @Autowired 22 @Autowired
18 private IRedisCatchStorage redisCatchStorage; 23 private IRedisCatchStorage redisCatchStorage;
19 24
@@ -27,7 +32,7 @@ public class SystemInfoTimerTask { @@ -27,7 +32,7 @@ public class SystemInfoTimerTask {
27 Map<String, String> networkInterfaces = SystemInfoUtils.getNetworkInterfaces(); 32 Map<String, String> networkInterfaces = SystemInfoUtils.getNetworkInterfaces();
28 redisCatchStorage.addNetInfo(networkInterfaces); 33 redisCatchStorage.addNetInfo(networkInterfaces);
29 } catch (InterruptedException e) { 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,35 +2,23 @@ package com.genersoft.iot.vmp.conf;
2 2
3 import com.genersoft.iot.vmp.common.VersionPo; 3 import com.genersoft.iot.vmp.common.VersionPo;
4 import com.genersoft.iot.vmp.utils.GitUtil; 4 import com.genersoft.iot.vmp.utils.GitUtil;
5 -import com.genersoft.iot.vmp.utils.JarFileUtils;  
6 import org.springframework.beans.factory.annotation.Autowired; 5 import org.springframework.beans.factory.annotation.Autowired;
7 import org.springframework.stereotype.Component; 6 import org.springframework.stereotype.Component;
8 7
9 -import java.util.Map;  
10 -  
11 @Component 8 @Component
12 public class VersionInfo { 9 public class VersionInfo {
13 10
14 @Autowired 11 @Autowired
15 - VersionConfig config;  
16 - @Autowired  
17 GitUtil gitUtil; 12 GitUtil gitUtil;
18 - @Autowired  
19 - JarFileUtils jarFileUtils;  
20 13
21 public VersionPo getVersion() { 14 public VersionPo getVersion() {
22 VersionPo versionPo = new VersionPo(); 15 VersionPo versionPo = new VersionPo();
23 - Map<String,String> map=jarFileUtils.readJarFile();  
24 versionPo.setGIT_Revision(gitUtil.getGitCommitId()); 16 versionPo.setGIT_Revision(gitUtil.getGitCommitId());
25 - versionPo.setCreate_By(map.get("Created-By"));  
26 versionPo.setGIT_BRANCH(gitUtil.getBranch()); 17 versionPo.setGIT_BRANCH(gitUtil.getBranch());
27 versionPo.setGIT_URL(gitUtil.getGitUrl()); 18 versionPo.setGIT_URL(gitUtil.getGitUrl());
28 versionPo.setBUILD_DATE(gitUtil.getBuildDate()); 19 versionPo.setBUILD_DATE(gitUtil.getBuildDate());
29 - versionPo.setArtifactId(config.getArtifactId());  
30 versionPo.setGIT_Revision_SHORT(gitUtil.getCommitIdShort()); 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 return versionPo; 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,7 +41,7 @@ public class SipLayer{
41 41
42 @Bean("sipStack") 42 @Bean("sipStack")
43 @DependsOn({"sipFactory"}) 43 @DependsOn({"sipFactory"})
44 - SipStack createSipStack() throws PeerUnavailableException { 44 + SipStackImpl createSipStack() throws PeerUnavailableException {
45 sipStack = ( SipStackImpl )sipFactory.createSipStack(DefaultProperties.getProperties(sipConfig.getMonitorIp(), false)); 45 sipStack = ( SipStackImpl )sipFactory.createSipStack(DefaultProperties.getProperties(sipConfig.getMonitorIp(), false));
46 return sipStack; 46 return sipStack;
47 } 47 }
@@ -56,7 +56,6 @@ public class SipLayer{ @@ -56,7 +56,6 @@ public class SipLayer{
56 tcpSipProvider = (SipProviderImpl)sipStack.createSipProvider(tcpListeningPoint); 56 tcpSipProvider = (SipProviderImpl)sipStack.createSipProvider(tcpListeningPoint);
57 tcpSipProvider.setDialogErrorsAutomaticallyHandled(); 57 tcpSipProvider.setDialogErrorsAutomaticallyHandled();
58 tcpSipProvider.addSipListener(sipProcessorObserver); 58 tcpSipProvider.addSipListener(sipProcessorObserver);
59 -// tcpSipProvider.setAutomaticDialogSupportEnabled(false);  
60 logger.info("[Sip Server] TCP 启动成功 {}:{}", sipConfig.getMonitorIp(), sipConfig.getPort()); 59 logger.info("[Sip Server] TCP 启动成功 {}:{}", sipConfig.getMonitorIp(), sipConfig.getPort());
61 } catch (TransportNotSupportedException e) { 60 } catch (TransportNotSupportedException e) {
62 e.printStackTrace(); 61 e.printStackTrace();
@@ -80,7 +79,6 @@ public class SipLayer{ @@ -80,7 +79,6 @@ public class SipLayer{
80 udpListeningPoint = sipStack.createListeningPoint(sipConfig.getMonitorIp(), sipConfig.getPort(), "UDP"); 79 udpListeningPoint = sipStack.createListeningPoint(sipConfig.getMonitorIp(), sipConfig.getPort(), "UDP");
81 udpSipProvider = (SipProviderImpl)sipStack.createSipProvider(udpListeningPoint); 80 udpSipProvider = (SipProviderImpl)sipStack.createSipProvider(udpListeningPoint);
82 udpSipProvider.addSipListener(sipProcessorObserver); 81 udpSipProvider.addSipListener(sipProcessorObserver);
83 -// udpSipProvider.setAutomaticDialogSupportEnabled(false);  
84 } catch (TransportNotSupportedException e) { 82 } catch (TransportNotSupportedException e) {
85 e.printStackTrace(); 83 e.printStackTrace();
86 } catch (InvalidArgumentException e) { 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,6 +4,9 @@ import javax.sip.Dialog;
4 import java.util.EventObject; 4 import java.util.EventObject;
5 5
6 public class DeviceNotFoundEvent extends EventObject { 6 public class DeviceNotFoundEvent extends EventObject {
  7 +
  8 + private String callId;
  9 +
7 /** 10 /**
8 * Constructs a prototypical Event. 11 * Constructs a prototypical Event.
9 * 12 *
@@ -14,8 +17,11 @@ public class DeviceNotFoundEvent extends EventObject { @@ -14,8 +17,11 @@ public class DeviceNotFoundEvent extends EventObject {
14 super(dialog); 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 package com.genersoft.iot.vmp.gb28181.bean; 1 package com.genersoft.iot.vmp.gb28181.bean;
2 2
3 import gov.nist.javax.sip.message.SIPRequest; 3 import gov.nist.javax.sip.message.SIPRequest;
  4 +import gov.nist.javax.sip.message.SIPResponse;
4 5
5 public class SipTransactionInfo { 6 public class SipTransactionInfo {
6 7
@@ -9,11 +10,11 @@ public class SipTransactionInfo { @@ -9,11 +10,11 @@ public class SipTransactionInfo {
9 private String toTag; 10 private String toTag;
10 private String viaBranch; 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 public SipTransactionInfo() { 20 public SipTransactionInfo() {
src/main/java/com/genersoft/iot/vmp/gb28181/bean/SsrcTransaction.java
@@ -8,10 +8,11 @@ public class SsrcTransaction { @@ -8,10 +8,11 @@ public class SsrcTransaction {
8 private String channelId; 8 private String channelId;
9 private String callId; 9 private String callId;
10 private String stream; 10 private String stream;
11 - private byte[] transaction;  
12 - private byte[] dialog;  
13 private String mediaServerId; 11 private String mediaServerId;
14 private String ssrc; 12 private String ssrc;
  13 +
  14 + private SipTransactionInfo sipTransactionInfo;
  15 +
15 private VideoStreamSessionManager.SessionType type; 16 private VideoStreamSessionManager.SessionType type;
16 17
17 public String getDeviceId() { 18 public String getDeviceId() {
@@ -46,22 +47,6 @@ public class SsrcTransaction { @@ -46,22 +47,6 @@ public class SsrcTransaction {
46 this.stream = stream; 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 public String getMediaServerId() { 50 public String getMediaServerId() {
66 return mediaServerId; 51 return mediaServerId;
67 } 52 }
@@ -85,4 +70,12 @@ public class SsrcTransaction { @@ -85,4 +70,12 @@ public class SsrcTransaction {
85 public void setType(VideoStreamSessionManager.SessionType type) { 70 public void setType(VideoStreamSessionManager.SessionType type) {
86 this.type = type; 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 package com.genersoft.iot.vmp.gb28181.bean; 1 package com.genersoft.iot.vmp.gb28181.bean;
2 2
3 -import com.genersoft.iot.vmp.utils.SerializeUtils;  
4 import gov.nist.javax.sip.message.SIPRequest; 3 import gov.nist.javax.sip.message.SIPRequest;
5 import gov.nist.javax.sip.message.SIPResponse; 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 import javax.sip.ServerTransaction; 6 import javax.sip.ServerTransaction;
11 import javax.sip.header.*; 7 import javax.sip.header.*;
12 -import javax.sip.message.Request;  
13 8
14 public class SubscribeInfo { 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,6 +10,7 @@ import org.springframework.stereotype.Component;
10 import javax.sip.*; 10 import javax.sip.*;
11 import javax.sip.header.CallIdHeader; 11 import javax.sip.header.CallIdHeader;
12 import javax.sip.message.Response; 12 import javax.sip.message.Response;
  13 +import java.text.ParseException;
13 import java.time.Instant; 14 import java.time.Instant;
14 import java.util.Map; 15 import java.util.Map;
15 import java.util.concurrent.ConcurrentHashMap; 16 import java.util.concurrent.ConcurrentHashMap;
@@ -56,8 +57,7 @@ public class SipSubscribe { @@ -56,8 +57,7 @@ public class SipSubscribe {
56 logger.debug("errorSubscribes.size:{}",errorSubscribes.size()); 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,18 +81,13 @@ public class SipSubscribe {
81 public EventResultType type; 81 public EventResultType type;
82 public String msg; 82 public String msg;
83 public String callId; 83 public String callId;
84 - public Dialog dialog;  
85 public EventObject event; 84 public EventObject event;
86 85
87 - public EventResult() {  
88 - }  
89 -  
90 public EventResult(EventObject event) { 86 public EventResult(EventObject event) {
91 this.event = event; 87 this.event = event;
92 if (event instanceof ResponseEvent) { 88 if (event instanceof ResponseEvent) {
93 ResponseEvent responseEvent = (ResponseEvent)event; 89 ResponseEvent responseEvent = (ResponseEvent)event;
94 Response response = responseEvent.getResponse(); 90 Response response = responseEvent.getResponse();
95 - this.dialog = responseEvent.getDialog();  
96 this.type = EventResultType.response; 91 this.type = EventResultType.response;
97 if (response != null) { 92 if (response != null) {
98 this.msg = response.getReasonPhrase(); 93 this.msg = response.getReasonPhrase();
@@ -127,12 +122,10 @@ public class SipSubscribe { @@ -127,12 +122,10 @@ public class SipSubscribe {
127 this.statusCode = -1024; 122 this.statusCode = -1024;
128 this.callId = dialogTerminatedEvent.getDialog().getCallId().getCallId(); 123 this.callId = dialogTerminatedEvent.getDialog().getCallId().getCallId();
129 }else if (event instanceof DeviceNotFoundEvent) { 124 }else if (event instanceof DeviceNotFoundEvent) {
130 - DeviceNotFoundEvent deviceNotFoundEvent = (DeviceNotFoundEvent)event;  
131 this.type = EventResultType.deviceNotFoundEvent; 125 this.type = EventResultType.deviceNotFoundEvent;
132 this.msg = "设备未找到"; 126 this.msg = "设备未找到";
133 this.statusCode = -1024; 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,7 +51,6 @@ public class AlarmEventListener implements ApplicationListener&lt;AlarmEvent&gt; {
51 } 51 }
52 // 移除已关闭的连接 52 // 移除已关闭的连接
53 it.remove(); 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,6 +36,7 @@ public class RequestTimeoutEventImpl implements ApplicationListener&lt;RequestTimeo
36 } 36 }
37 deviceService.offline(device.getDeviceId()); 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,6 +18,9 @@ import org.springframework.stereotype.Component;
18 import org.springframework.util.ObjectUtils; 18 import org.springframework.util.ObjectUtils;
19 import org.springframework.util.StringUtils; 19 import org.springframework.util.StringUtils;
20 20
  21 +import javax.sip.InvalidArgumentException;
  22 +import javax.sip.SipException;
  23 +import java.text.ParseException;
21 import java.util.*; 24 import java.util.*;
22 25
23 /** 26 /**
@@ -96,7 +99,12 @@ public class CatalogEventLister implements ApplicationListener&lt;CatalogEvent&gt; { @@ -96,7 +99,12 @@ public class CatalogEventLister implements ApplicationListener&lt;CatalogEvent&gt; {
96 } 99 }
97 if (deviceChannelList.size() > 0) { 100 if (deviceChannelList.size() > 0) {
98 logger.info("[Catalog事件: {}]平台:{},影响通道{}个", event.getType(), event.getPlatformId(), deviceChannelList.size()); 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 }else if (parentPlatformMap.keySet().size() > 0) { 109 }else if (parentPlatformMap.keySet().size() > 0) {
102 for (String gbId : parentPlatformMap.keySet()) { 110 for (String gbId : parentPlatformMap.keySet()) {
@@ -112,7 +120,12 @@ public class CatalogEventLister implements ApplicationListener&lt;CatalogEvent&gt; { @@ -112,7 +120,12 @@ public class CatalogEventLister implements ApplicationListener&lt;CatalogEvent&gt; {
112 DeviceChannel deviceChannel = new DeviceChannel(); 120 DeviceChannel deviceChannel = new DeviceChannel();
113 deviceChannel.setChannelId(gbId); 121 deviceChannel.setChannelId(gbId);
114 deviceChannelList.add(deviceChannel); 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,7 +150,12 @@ public class CatalogEventLister implements ApplicationListener&lt;CatalogEvent&gt; {
137 } 150 }
138 if (deviceChannelList.size() > 0) { 151 if (deviceChannelList.size() > 0) {
139 logger.info("[Catalog事件: {}]平台:{},影响通道{}个", event.getType(), event.getPlatformId(), deviceChannelList.size()); 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 }else if (parentPlatformMap.keySet().size() > 0) { 160 }else if (parentPlatformMap.keySet().size() > 0) {
143 for (String gbId : parentPlatformMap.keySet()) { 161 for (String gbId : parentPlatformMap.keySet()) {
@@ -157,7 +175,12 @@ public class CatalogEventLister implements ApplicationListener&lt;CatalogEvent&gt; { @@ -157,7 +175,12 @@ public class CatalogEventLister implements ApplicationListener&lt;CatalogEvent&gt; {
157 DeviceChannel deviceChannelByStream = gbStreamService.getDeviceChannelListByStreamWithStatus(gbStream, gbStream.getCatalogId(), platform); 175 DeviceChannel deviceChannelByStream = gbStreamService.getDeviceChannelListByStreamWithStatus(gbStream, gbStream.getCatalogId(), platform);
158 deviceChannelList.add(deviceChannelByStream); 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,19 +3,15 @@ package com.genersoft.iot.vmp.gb28181.session;
3 import java.util.ArrayList; 3 import java.util.ArrayList;
4 import java.util.List; 4 import java.util.List;
5 5
6 -import javax.sip.ClientTransaction;  
7 -import javax.sip.Dialog;  
8 -  
9 import com.genersoft.iot.vmp.common.VideoManagerConstants; 6 import com.genersoft.iot.vmp.common.VideoManagerConstants;
10 import com.genersoft.iot.vmp.conf.UserSetting; 7 import com.genersoft.iot.vmp.conf.UserSetting;
  8 +import com.genersoft.iot.vmp.gb28181.bean.SipTransactionInfo;
11 import com.genersoft.iot.vmp.gb28181.bean.SsrcTransaction; 9 import com.genersoft.iot.vmp.gb28181.bean.SsrcTransaction;
12 -import com.genersoft.iot.vmp.utils.SerializeUtils;  
13 import com.genersoft.iot.vmp.utils.redis.RedisUtil; 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 import org.springframework.beans.factory.annotation.Autowired; 12 import org.springframework.beans.factory.annotation.Autowired;
16 import org.springframework.stereotype.Component; 13 import org.springframework.stereotype.Component;
17 import org.springframework.util.ObjectUtils; 14 import org.springframework.util.ObjectUtils;
18 -import org.springframework.util.StringUtils;  
19 15
20 /** 16 /**
21 * @description:视频流session管理器,管理视频预览、预览回放的通信句柄 17 * @description:视频流session管理器,管理视频预览、预览回放的通信句柄
@@ -42,15 +38,14 @@ public class VideoStreamSessionManager { @@ -42,15 +38,14 @@ public class VideoStreamSessionManager {
42 * @param callId 一次请求的CallID 38 * @param callId 一次请求的CallID
43 * @param stream 流名称 39 * @param stream 流名称
44 * @param mediaServerId 所使用的流媒体ID 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 SsrcTransaction ssrcTransaction = new SsrcTransaction(); 44 SsrcTransaction ssrcTransaction = new SsrcTransaction();
49 ssrcTransaction.setDeviceId(deviceId); 45 ssrcTransaction.setDeviceId(deviceId);
50 ssrcTransaction.setChannelId(channelId); 46 ssrcTransaction.setChannelId(channelId);
51 ssrcTransaction.setStream(stream); 47 ssrcTransaction.setStream(stream);
52 - byte[] transactionByteArray = SerializeUtils.serialize(transaction);  
53 - ssrcTransaction.setTransaction(transactionByteArray); 48 + ssrcTransaction.setSipTransactionInfo(new SipTransactionInfo(response));
54 ssrcTransaction.setCallId(callId); 49 ssrcTransaction.setCallId(callId);
55 ssrcTransaction.setSsrc(ssrc); 50 ssrcTransaction.setSsrc(ssrc);
56 ssrcTransaction.setMediaServerId(mediaServerId); 51 ssrcTransaction.setMediaServerId(mediaServerId);
@@ -62,53 +57,6 @@ public class VideoStreamSessionManager { @@ -62,53 +57,6 @@ public class VideoStreamSessionManager {
62 + "_" + deviceId + "_" + channelId + "_" + callId + "_" + stream, ssrcTransaction); 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 public SsrcTransaction getSsrcTransaction(String deviceId, String channelId, String callId, String stream){ 60 public SsrcTransaction getSsrcTransaction(String deviceId, String channelId, String callId, String stream){
113 61
114 if (ObjectUtils.isEmpty(deviceId)) { 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,9 +10,7 @@ import org.slf4j.LoggerFactory;
10 import org.springframework.scheduling.annotation.Async; 10 import org.springframework.scheduling.annotation.Async;
11 import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; 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 import javax.sip.header.ToHeader; 14 import javax.sip.header.ToHeader;
17 import java.text.ParseException; 15 import java.text.ParseException;
18 import java.util.Timer; 16 import java.util.Timer;
@@ -44,23 +42,29 @@ public class CatalogSubscribeTask implements ISubscribeTask { @@ -44,23 +42,29 @@ public class CatalogSubscribeTask implements ISubscribeTask {
44 if (dynamicTask.get(taskKey) != null) { 42 if (dynamicTask.get(taskKey) != null) {
45 dynamicTask.stop(taskKey); 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 this.request = null; 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 if (sipRequest != null) { 68 if (sipRequest != null) {
65 this.request = sipRequest; 69 this.request = sipRequest;
66 } 70 }
@@ -80,18 +84,22 @@ public class CatalogSubscribeTask implements ISubscribeTask { @@ -80,18 +84,22 @@ public class CatalogSubscribeTask implements ISubscribeTask {
80 dynamicTask.stop(taskKey); 84 dynamicTask.stop(taskKey);
81 } 85 }
82 device.setSubscribeCycleForCatalog(0); 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,9 +11,7 @@ import org.slf4j.Logger;
11 import org.slf4j.LoggerFactory; 11 import org.slf4j.LoggerFactory;
12 import org.springframework.scheduling.annotation.Async; 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 import javax.sip.header.ToHeader; 15 import javax.sip.header.ToHeader;
18 import java.text.ParseException; 16 import java.text.ParseException;
19 import java.util.Timer; 17 import java.util.Timer;
@@ -43,23 +41,28 @@ public class MobilePositionSubscribeTask implements ISubscribeTask { @@ -43,23 +41,28 @@ public class MobilePositionSubscribeTask implements ISubscribeTask {
43 if (dynamicTask.get(taskKey) != null) { 41 if (dynamicTask.get(taskKey) != null) {
44 dynamicTask.stop(taskKey); 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 this.request = null; 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 if (sipRequest != null) { 66 if (sipRequest != null) {
64 this.request = sipRequest; 67 this.request = sipRequest;
65 } 68 }
@@ -79,18 +82,22 @@ public class MobilePositionSubscribeTask implements ISubscribeTask { @@ -79,18 +82,22 @@ public class MobilePositionSubscribeTask implements ISubscribeTask {
79 dynamicTask.stop(taskKey); 82 dynamicTask.stop(taskKey);
80 } 83 }
81 device.setSubscribeCycleForMobilePosition(0); 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 package com.genersoft.iot.vmp.gb28181.transmit.cmd; 1 package com.genersoft.iot.vmp.gb28181.transmit.cmd;
2 2
3 import com.genersoft.iot.vmp.common.StreamInfo; 3 import com.genersoft.iot.vmp.common.StreamInfo;
  4 +import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException;
4 import com.genersoft.iot.vmp.gb28181.bean.*; 5 import com.genersoft.iot.vmp.gb28181.bean.*;
5 import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; 6 import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
6 import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe; 7 import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe;
@@ -14,6 +15,11 @@ import javax.sip.Dialog; @@ -14,6 +15,11 @@ import javax.sip.Dialog;
14 import javax.sip.InvalidArgumentException; 15 import javax.sip.InvalidArgumentException;
15 import javax.sip.SipException; 16 import javax.sip.SipException;
16 import java.text.ParseException; 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 * @description:设备能力接口,用于定义设备的控制、查询能力 25 * @description:设备能力接口,用于定义设备的控制、查询能力
@@ -30,7 +36,7 @@ public interface ISIPCommander { @@ -30,7 +36,7 @@ public interface ISIPCommander {
30 * @param leftRight 镜头左移右移 0:停止 1:左移 2:右移 36 * @param leftRight 镜头左移右移 0:停止 1:左移 2:右移
31 * @param upDown 镜头上移下移 0:停止 1:上移 2:下移 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,7 +47,7 @@ public interface ISIPCommander {
41 * @param upDown 镜头上移下移 0:停止 1:上移 2:下移 47 * @param upDown 镜头上移下移 0:停止 1:上移 2:下移
42 * @param moveSpeed 镜头移动速度 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,7 +56,7 @@ public interface ISIPCommander {
50 * @param channelId 预览通道 56 * @param channelId 预览通道
51 * @param inOut 镜头放大缩小 0:停止 1:缩小 2:放大 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,7 +65,7 @@ public interface ISIPCommander {
59 * @param channelId 预览通道 65 * @param channelId 预览通道
60 * @param inOut 镜头放大缩小 0:停止 1:缩小 2:放大 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,7 +78,7 @@ public interface ISIPCommander {
72 * @param moveSpeed 镜头移动速度 78 * @param moveSpeed 镜头移动速度
73 * @param zoomSpeed 镜头缩放速度 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 * 前端控制,包括PTZ指令、FI指令、预置位指令、巡航指令、扫描指令和辅助开关指令 84 * 前端控制,包括PTZ指令、FI指令、预置位指令、巡航指令、扫描指令和辅助开关指令
@@ -84,7 +90,7 @@ public interface ISIPCommander { @@ -84,7 +90,7 @@ public interface ISIPCommander {
84 * @param parameter2 数据2 90 * @param parameter2 数据2
85 * @param combineCode2 组合码2 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,14 +98,14 @@ public interface ISIPCommander {
92 * @param channelId 预览通道 98 * @param channelId 预览通道
93 * @param cmdString 前端控制指令串 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 * @param device 视频设备 105 * @param device 视频设备
100 * @param channelId 预览通道 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,7 +115,7 @@ public interface ISIPCommander {
109 * @param startTime 开始时间,格式要求:yyyy-MM-dd HH:mm:ss 115 * @param startTime 开始时间,格式要求:yyyy-MM-dd HH:mm:ss
110 * @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss 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,34 +128,35 @@ public interface ISIPCommander {
122 */ 128 */
123 void downloadStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, 129 void downloadStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId,
124 String startTime, String endTime, int downloadSpeed, InviteStreamCallback inviteStreamCallback, InviteStreamCallback hookEvent, 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 void streamByeCmd(String deviceId, String channelId, String stream, String callId, SipSubscribe.Event okEvent); 136 void streamByeCmd(String deviceId, String channelId, String stream, String callId, SipSubscribe.Event okEvent);
131 void streamByeCmd(String deviceId, String channelId, String stream, String callId); 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,8 +164,10 @@ public interface ISIPCommander {
157 * @param streamInfo 164 * @param streamInfo
158 * @param content 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,7 +175,16 @@ public interface ISIPCommander {
166 * @param device 视频设备 175 * @param device 视频设备
167 */ 176 */
168 boolean audioBroadcastCmd(Device device, String channelId, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent); 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,21 +192,21 @@ public interface ISIPCommander {
174 * @param channelId 预览通道 192 * @param channelId 预览通道
175 * @param recordCmdStr 录像命令:Record / StopRecord 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 * @param device 视频设备 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 * @param device 视频设备 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,7 +215,7 @@ public interface ISIPCommander {
197 * @param alarmMethod 报警方式(可选) 215 * @param alarmMethod 报警方式(可选)
198 * @param alarmType 报警类型(可选) 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 * 强制关键帧命令,设备收到此命令应立刻发送一个IDR帧 221 * 强制关键帧命令,设备收到此命令应立刻发送一个IDR帧
@@ -205,7 +223,7 @@ public interface ISIPCommander { @@ -205,7 +223,7 @@ public interface ISIPCommander {
205 * @param device 视频设备 223 * @param device 视频设备
206 * @param channelId 预览通道 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,14 +233,14 @@ public interface ISIPCommander {
215 * @param resetTime 自动归位时间间隔,开启看守位时使用,单位:秒(s) 233 * @param resetTime 自动归位时间间隔,开启看守位时使用,单位:秒(s)
216 * @param presetIndex 调用预置位编号,开启看守位时使用,取值范围0~255 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 * @param device 视频设备 241 * @param device 视频设备
224 */ 242 */
225 - boolean deviceConfigCmd(Device device); 243 + void deviceConfigCmd(Device device);
226 244
227 /** 245 /**
228 * 设备配置命令:basicParam 246 * 设备配置命令:basicParam
@@ -234,14 +252,14 @@ public interface ISIPCommander { @@ -234,14 +252,14 @@ public interface ISIPCommander {
234 * @param heartBeatInterval 心跳间隔时间(可选) 252 * @param heartBeatInterval 心跳间隔时间(可选)
235 * @param heartBeatCount 心跳超时次数(可选) 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 * @param device 视频设备 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,14 +267,14 @@ public interface ISIPCommander {
249 * @param device 视频设备 267 * @param device 视频设备
250 * @return 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 * @param device 视频设备 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,7 +284,7 @@ public interface ISIPCommander {
266 * @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss 284 * @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss
267 * @param sn 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,8 +298,8 @@ public interface ISIPCommander {
280 * @param endTime 报警发生终止时间(可选) 298 * @param endTime 报警发生终止时间(可选)
281 * @return true = 命令发送成功 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,21 +308,21 @@ public interface ISIPCommander {
290 * @param channelId 通道编码(可选) 308 * @param channelId 通道编码(可选)
291 * @param configType 配置类型: 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 * @param device 视频设备 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 * @param device 视频设备 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,7 +330,7 @@ public interface ISIPCommander {
312 * @param device 视频设备 330 * @param device 视频设备
313 * @return true = 命令发送成功 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,14 +343,14 @@ public interface ISIPCommander {
325 * @param endTime 报警发生终止时间(可选) 343 * @param endTime 报警发生终止时间(可选)
326 * @return true = 命令发送成功 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 * @param device 视频设备 350 * @param device 视频设备
333 * @return true = 命令发送成功 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,7 +359,7 @@ public interface ISIPCommander {
341 * @param channelId 通道id 359 * @param channelId 通道id
342 * @param cmdString 前端控制指令串 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,5 +368,11 @@ public interface ISIPCommander {
350 * @param deviceAlarm 报警信息信息 368 * @param deviceAlarm 报警信息信息
351 * @return 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,7 +4,10 @@ import com.genersoft.iot.vmp.gb28181.bean.*;
4 import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; 4 import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
5 import com.genersoft.iot.vmp.service.bean.GPSMsgInfo; 5 import com.genersoft.iot.vmp.service.bean.GPSMsgInfo;
6 6
  7 +import javax.sip.InvalidArgumentException;
  8 +import javax.sip.SipException;
7 import javax.sip.header.WWWAuthenticateHeader; 9 import javax.sip.header.WWWAuthenticateHeader;
  10 +import java.text.ParseException;
8 import java.util.List; 11 import java.util.List;
9 12
10 public interface ISIPCommanderForPlatform { 13 public interface ISIPCommanderForPlatform {
@@ -14,15 +17,15 @@ public interface ISIPCommanderForPlatform { @@ -14,15 +17,15 @@ public interface ISIPCommanderForPlatform {
14 * @param parentPlatform 17 * @param parentPlatform
15 * @return 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 * @param parentPlatform 25 * @param parentPlatform
23 * @return 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,7 +33,7 @@ public interface ISIPCommanderForPlatform {
30 * @param parentPlatform 33 * @param parentPlatform
31 * @return callId(作为接受回复的判定) 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,8 +45,8 @@ public interface ISIPCommanderForPlatform {
42 * @param size 45 * @param size
43 * @return 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 * 向上级回复DeviceInfo查询信息 52 * 向上级回复DeviceInfo查询信息
@@ -52,7 +55,7 @@ public interface ISIPCommanderForPlatform { @@ -52,7 +55,7 @@ public interface ISIPCommanderForPlatform {
52 * @param fromTag 55 * @param fromTag
53 * @return 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 * 向上级回复DeviceStatus查询信息 61 * 向上级回复DeviceStatus查询信息
@@ -61,7 +64,7 @@ public interface ISIPCommanderForPlatform { @@ -61,7 +64,7 @@ public interface ISIPCommanderForPlatform {
61 * @param fromTag 64 * @param fromTag
62 * @return 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,7 +73,7 @@ public interface ISIPCommanderForPlatform {
70 * @param subscribeInfo 订阅相关的信息 73 * @param subscribeInfo 订阅相关的信息
71 * @return 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,21 +81,21 @@ public interface ISIPCommanderForPlatform {
78 * @param deviceAlarm 报警信息信息 81 * @param deviceAlarm 报警信息信息
79 * @return 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 * 回复catalog事件-增加/更新 87 * 回复catalog事件-增加/更新
85 * @param parentPlatform 88 * @param parentPlatform
86 * @param deviceChannels 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 * 回复catalog事件-删除 94 * 回复catalog事件-删除
92 * @param parentPlatform 95 * @param parentPlatform
93 * @param deviceChannels 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 * 回复recordInfo 101 * 回复recordInfo
@@ -101,7 +104,7 @@ public interface ISIPCommanderForPlatform { @@ -101,7 +104,7 @@ public interface ISIPCommanderForPlatform {
101 * @param fromTag fromTag 104 * @param fromTag fromTag
102 * @param recordInfo 录像信息 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 * 录像播放推送完成时发送MediaStatus消息 110 * 录像播放推送完成时发送MediaStatus消息
@@ -109,13 +112,13 @@ public interface ISIPCommanderForPlatform { @@ -109,13 +112,13 @@ public interface ISIPCommanderForPlatform {
109 * @param sendRtpItem 112 * @param sendRtpItem
110 * @return 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 * 向发起点播的上级回复bye 118 * 向发起点播的上级回复bye
116 * @param platform 平台信息 119 * @param platform 平台信息
117 * @param callId callId 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,6 +10,9 @@ import javax.sip.header.*;
10 import javax.sip.message.Request; 10 import javax.sip.message.Request;
11 11
12 import com.genersoft.iot.vmp.common.StreamInfo; 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 import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; 16 import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
14 import com.genersoft.iot.vmp.gb28181.utils.SipUtils; 17 import com.genersoft.iot.vmp.gb28181.utils.SipUtils;
15 import com.genersoft.iot.vmp.storager.IRedisCatchStorage; 18 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
@@ -17,6 +20,7 @@ import com.genersoft.iot.vmp.utils.GitUtil; @@ -17,6 +20,7 @@ import com.genersoft.iot.vmp.utils.GitUtil;
17 import gov.nist.javax.sip.SipProviderImpl; 20 import gov.nist.javax.sip.SipProviderImpl;
18 import gov.nist.javax.sip.SipStackImpl; 21 import gov.nist.javax.sip.SipStackImpl;
19 import gov.nist.javax.sip.message.SIPRequest; 22 import gov.nist.javax.sip.message.SIPRequest;
  23 +import gov.nist.javax.sip.message.SIPResponse;
20 import gov.nist.javax.sip.stack.SIPDialog; 24 import gov.nist.javax.sip.stack.SIPDialog;
21 import org.springframework.beans.factory.annotation.Autowired; 25 import org.springframework.beans.factory.annotation.Autowired;
22 import org.springframework.beans.factory.annotation.Qualifier; 26 import org.springframework.beans.factory.annotation.Qualifier;
@@ -168,34 +172,37 @@ public class SIPRequestHeaderProvider { @@ -168,34 +172,37 @@ public class SIPRequestHeaderProvider {
168 return request; 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 Request request = null; 176 Request request = null;
173 //请求行 177 //请求行
174 SipURI requestLine = sipFactory.createAddressFactory().createSipURI(channelId, device.getHostAddress()); 178 SipURI requestLine = sipFactory.createAddressFactory().createSipURI(channelId, device.getHostAddress());
175 // via 179 // via
176 ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>(); 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 viaHeaders.add(viaHeader); 182 viaHeaders.add(viaHeader);
179 //from 183 //from
180 SipURI fromSipURI = sipFactory.createAddressFactory().createSipURI(sipConfig.getId(),sipConfig.getDomain()); 184 SipURI fromSipURI = sipFactory.createAddressFactory().createSipURI(sipConfig.getId(),sipConfig.getDomain());
181 Address fromAddress = sipFactory.createAddressFactory().createAddress(fromSipURI); 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 //to 187 //to
184 SipURI toSipURI = sipFactory.createAddressFactory().createSipURI(channelId,device.getHostAddress()); 188 SipURI toSipURI = sipFactory.createAddressFactory().createSipURI(channelId,device.getHostAddress());
185 Address toAddress = sipFactory.createAddressFactory().createAddress(toSipURI); 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 //Forwards 192 //Forwards
189 MaxForwardsHeader maxForwards = sipFactory.createHeaderFactory().createMaxForwardsHeader(70); 193 MaxForwardsHeader maxForwards = sipFactory.createHeaderFactory().createMaxForwardsHeader(70);
190 194
191 //ceq 195 //ceq
192 CSeqHeader cSeqHeader = sipFactory.createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(), Request.BYE); 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 request = sipFactory.createMessageFactory().createRequest(requestLine, Request.BYE, callIdHeader, cSeqHeader,fromHeader, toHeader, viaHeaders, maxForwards); 198 request = sipFactory.createMessageFactory().createRequest(requestLine, Request.BYE, callIdHeader, cSeqHeader,fromHeader, toHeader, viaHeaders, maxForwards);
195 199
196 request.addHeader(SipUtils.createUserAgentHeader(sipFactory, gitUtil)); 200 request.addHeader(SipUtils.createUserAgentHeader(sipFactory, gitUtil));
197 201
198 Address concatAddress = sipFactory.createAddressFactory().createAddress(sipFactory.createAddressFactory().createSipURI(sipConfig.getId(), sipConfig.getIp()+":"+sipConfig.getPort())); 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 return request; 207 return request;
201 } 208 }
@@ -251,47 +258,72 @@ public class SIPRequestHeaderProvider { @@ -251,47 +258,72 @@ public class SIPRequestHeaderProvider {
251 return request; 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 throws SipException, ParseException, InvalidArgumentException { 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 return null; 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,6 +5,7 @@ import com.genersoft.iot.vmp.common.StreamInfo;
5 import com.genersoft.iot.vmp.conf.DynamicTask; 5 import com.genersoft.iot.vmp.conf.DynamicTask;
6 import com.genersoft.iot.vmp.conf.SipConfig; 6 import com.genersoft.iot.vmp.conf.SipConfig;
7 import com.genersoft.iot.vmp.conf.UserSetting; 7 import com.genersoft.iot.vmp.conf.UserSetting;
  8 +import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException;
8 import com.genersoft.iot.vmp.gb28181.bean.*; 9 import com.genersoft.iot.vmp.gb28181.bean.*;
9 import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; 10 import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
10 import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; 11 import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
@@ -22,17 +23,20 @@ import com.genersoft.iot.vmp.service.bean.SSRCInfo; @@ -22,17 +23,20 @@ import com.genersoft.iot.vmp.service.bean.SSRCInfo;
22 import com.genersoft.iot.vmp.storager.IRedisCatchStorage; 23 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
23 import com.genersoft.iot.vmp.storager.IVideoManagerStorage; 24 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
24 import com.genersoft.iot.vmp.utils.GitUtil; 25 import com.genersoft.iot.vmp.utils.GitUtil;
  26 +import gov.nist.javax.sip.SIPConstants;
25 import gov.nist.javax.sip.SipProviderImpl; 27 import gov.nist.javax.sip.SipProviderImpl;
26 import gov.nist.javax.sip.SipStackImpl; 28 import gov.nist.javax.sip.SipStackImpl;
27 -import gov.nist.javax.sip.message.MessageFactoryImpl;  
28 import gov.nist.javax.sip.message.SIPRequest; 29 import gov.nist.javax.sip.message.SIPRequest;
  30 +import gov.nist.javax.sip.message.SIPResponse;
29 import gov.nist.javax.sip.stack.SIPClientTransaction; 31 import gov.nist.javax.sip.stack.SIPClientTransaction;
  32 +import gov.nist.javax.sip.stack.SIPClientTransactionImpl;
30 import gov.nist.javax.sip.stack.SIPDialog; 33 import gov.nist.javax.sip.stack.SIPDialog;
31 import org.slf4j.Logger; 34 import org.slf4j.Logger;
32 import org.slf4j.LoggerFactory; 35 import org.slf4j.LoggerFactory;
33 import org.springframework.beans.factory.annotation.Autowired; 36 import org.springframework.beans.factory.annotation.Autowired;
34 import org.springframework.beans.factory.annotation.Qualifier; 37 import org.springframework.beans.factory.annotation.Qualifier;
35 import org.springframework.context.annotation.DependsOn; 38 import org.springframework.context.annotation.DependsOn;
  39 +import org.springframework.context.annotation.Lazy;
36 import org.springframework.stereotype.Component; 40 import org.springframework.stereotype.Component;
37 import org.springframework.util.ObjectUtils; 41 import org.springframework.util.ObjectUtils;
38 42
@@ -41,765 +45,598 @@ import javax.sip.address.Address; @@ -41,765 +45,598 @@ import javax.sip.address.Address;
41 import javax.sip.address.SipURI; 45 import javax.sip.address.SipURI;
42 import javax.sip.header.*; 46 import javax.sip.header.*;
43 import javax.sip.message.Request; 47 import javax.sip.message.Request;
  48 +import javax.sip.message.Response;
44 import java.lang.reflect.Field; 49 import java.lang.reflect.Field;
45 import java.text.ParseException; 50 import java.text.ParseException;
46 import java.util.ArrayList; 51 import java.util.ArrayList;
47 import java.util.HashSet; 52 import java.util.HashSet;
48 import java.util.List; 53 import java.util.List;
49 54
50 -/**  
51 - * @description:设备能力接口,用于定义设备的控制、查询能力 55 +/**
  56 + * @description:设备能力接口,用于定义设备的控制、查询能力
52 * @author: swwheihei 57 * @author: swwheihei
53 - * @date: 2020年5月3日 下午9:22:48 58 + * @date: 2020年5月3日 下午9:22:48
54 */ 59 */
55 @Component 60 @Component
56 @DependsOn("sipLayer") 61 @DependsOn("sipLayer")
57 public class SIPCommander implements ISIPCommander { 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 public static String frontEndCmdString(int cmdCode, int parameter1, int parameter2, int combineCode2) { 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 // content.append("f=v/2/5/25/1/4000a/1/8/1" + "\r\n"); // 未发现支持此特性的设备 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 * @param device 视频设备 640 * @param device 视频设备
804 */ 641 */
805 @Override 642 @Override
@@ -815,1039 +652,846 @@ public class SIPCommander implements ISIPCommander { @@ -815,1039 +652,846 @@ public class SIPCommander implements ISIPCommander {
815 broadcastXml.append("<TargetID>" + channelId + "</TargetID>\r\n"); 652 broadcastXml.append("<TargetID>" + channelId + "</TargetID>\r\n");
816 broadcastXml.append("</Notify>\r\n"); 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,12 +13,9 @@ import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
13 import com.genersoft.iot.vmp.service.IMediaServerService; 13 import com.genersoft.iot.vmp.service.IMediaServerService;
14 import com.genersoft.iot.vmp.service.bean.GPSMsgInfo; 14 import com.genersoft.iot.vmp.service.bean.GPSMsgInfo;
15 import com.genersoft.iot.vmp.storager.IRedisCatchStorage; 15 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
16 -import com.genersoft.iot.vmp.utils.SerializeUtils;  
17 import gov.nist.javax.sip.SipProviderImpl; 16 import gov.nist.javax.sip.SipProviderImpl;
18 -import gov.nist.javax.sip.SipStackImpl;  
19 import gov.nist.javax.sip.message.MessageFactoryImpl; 17 import gov.nist.javax.sip.message.MessageFactoryImpl;
20 import gov.nist.javax.sip.message.SIPRequest; 18 import gov.nist.javax.sip.message.SIPRequest;
21 -import gov.nist.javax.sip.stack.SIPDialog;  
22 import org.slf4j.Logger; 19 import org.slf4j.Logger;
23 import org.slf4j.LoggerFactory; 20 import org.slf4j.LoggerFactory;
24 import org.springframework.beans.factory.annotation.Autowired; 21 import org.springframework.beans.factory.annotation.Autowired;
@@ -32,13 +29,10 @@ import org.springframework.util.ObjectUtils; @@ -32,13 +29,10 @@ import org.springframework.util.ObjectUtils;
32 29
33 import com.genersoft.iot.vmp.utils.DateUtil; 30 import com.genersoft.iot.vmp.utils.DateUtil;
34 import javax.sip.*; 31 import javax.sip.*;
35 -import javax.sip.address.SipURI;  
36 import javax.sip.header.*; 32 import javax.sip.header.*;
37 import javax.sip.message.Request; 33 import javax.sip.message.Request;
38 -import java.lang.reflect.Field;  
39 import java.text.ParseException; 34 import java.text.ParseException;
40 import java.util.ArrayList; 35 import java.util.ArrayList;
41 -import java.util.HashSet;  
42 import java.util.List; 36 import java.util.List;
43 37
44 @Component 38 @Component
@@ -79,19 +73,18 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { @@ -79,19 +73,18 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
79 private SubscribeHolder subscribeHolder; 73 private SubscribeHolder subscribeHolder;
80 74
81 @Override 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 @Override 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 @Override 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 Request request; 88 Request request;
96 if (!registerAgain ) { 89 if (!registerAgain ) {
97 CallIdHeader callIdHeader = null; 90 CallIdHeader callIdHeader = null;
@@ -128,23 +121,10 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { @@ -128,23 +121,10 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
128 } 121 }
129 122
130 transmitRequest(parentPlatform, request, null, okEvent); 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 @Override 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 String characterSet = parentPlatform.getCharacterSet(); 128 String characterSet = parentPlatform.getCharacterSet();
149 StringBuffer keepaliveXml = new StringBuffer(200); 129 StringBuffer keepaliveXml = new StringBuffer(200);
150 keepaliveXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n"); 130 keepaliveXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n");
@@ -165,11 +145,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { @@ -165,11 +145,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
165 SipUtils.getNewViaTag(), 145 SipUtils.getNewViaTag(),
166 callIdHeader); 146 callIdHeader);
167 transmitRequest(parentPlatform, request, errorEvent, okEvent); 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 private void transmitRequest(ParentPlatform parentPlatform, Request request) throws SipException { 151 private void transmitRequest(ParentPlatform parentPlatform, Request request) throws SipException {
@@ -208,39 +184,32 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { @@ -208,39 +184,32 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
208 * @return 184 * @return
209 */ 185 */
210 @Override 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 if ( parentPlatform ==null) { 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 @Override 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 if ( parentPlatform ==null) { 209 if ( parentPlatform ==null) {
240 - return false; 210 + return ;
241 } 211 }
242 sendCatalogResponse(channels, parentPlatform, sn, fromTag, 0); 212 sendCatalogResponse(channels, parentPlatform, sn, fromTag, 0);
243 - return true;  
244 } 213 }
245 private String getCatalogXml(List<DeviceChannel> channels, String sn, ParentPlatform parentPlatform, int size) { 214 private String getCatalogXml(List<DeviceChannel> channels, String sn, ParentPlatform parentPlatform, int size) {
246 String characterSet = parentPlatform.getCharacterSet(); 215 String characterSet = parentPlatform.getCharacterSet();
@@ -302,30 +271,30 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { @@ -302,30 +271,30 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
302 return catalogXml.toString(); 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 if (index >= channels.size()) { 275 if (index >= channels.size()) {
307 return; 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 sendCatalogResponse(channels, parentPlatform, sn, fromTag, indexNext); 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,36 +305,29 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
336 * @return 305 * @return
337 */ 306 */
338 @Override 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 if (parentPlatform == null) { 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,129 +338,103 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
376 * @return 338 * @return
377 */ 339 */
378 @Override 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 if (parentPlatform == null) { 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 @Override 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 if (parentPlatform == null) { 367 if (parentPlatform == null) {
412 - return false; 368 + return;
413 } 369 }
414 if (logger.isDebugEnabled()) { 370 if (logger.isDebugEnabled()) {
415 logger.debug("[发送 移动位置订阅] {}/{}->{},{}", parentPlatform.getServerGBId(), gpsMsgInfo.getId(), gpsMsgInfo.getLng(), gpsMsgInfo.getLat()); 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 @Override 395 @Override
452 - public boolean sendAlarmMessage(ParentPlatform parentPlatform, DeviceAlarm deviceAlarm) { 396 + public void sendAlarmMessage(ParentPlatform parentPlatform, DeviceAlarm deviceAlarm) throws SipException, InvalidArgumentException, ParseException {
453 if (parentPlatform == null) { 397 if (parentPlatform == null) {
454 - return false; 398 + return;
455 } 399 }
456 logger.info("[发送报警通知] {}/{}->{},{}: {}", parentPlatform.getServerGBId(), deviceAlarm.getChannelId(), 400 logger.info("[发送报警通知] {}/{}->{},{}: {}", parentPlatform.getServerGBId(), deviceAlarm.getChannelId(),
457 deviceAlarm.getLongitude(), deviceAlarm.getLatitude(), JSONObject.toJSON(deviceAlarm)); 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 @Override 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 if (parentPlatform == null || deviceChannels == null || deviceChannels.size() == 0 || subscribeInfo == null) { 430 if (parentPlatform == null || deviceChannels == null || deviceChannels.size() == 0 || subscribeInfo == null) {
495 - return false; 431 + return;
496 } 432 }
497 if (index == null) { 433 if (index == null) {
498 index = 0; 434 index = 0;
499 } 435 }
500 if (index >= deviceChannels.size()) { 436 if (index >= deviceChannels.size()) {
501 - return true; 437 + return;
502 } 438 }
503 List<DeviceChannel> channels; 439 List<DeviceChannel> channels;
504 if (index + parentPlatform.getCatalogGroup() < deviceChannels.size()) { 440 if (index + parentPlatform.getCatalogGroup() < deviceChannels.size()) {
@@ -506,32 +442,25 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { @@ -506,32 +442,25 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
506 }else { 442 }else {
507 channels = deviceChannels.subList(index, deviceChannels.size()); 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 sendNotifyForCatalogAddOrUpdate(type, parentPlatform, deviceChannels, subscribeInfo, 452 sendNotifyForCatalogAddOrUpdate(type, parentPlatform, deviceChannels, subscribeInfo,
517 finalIndex + parentPlatform.getCatalogGroup()); 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 SubscribeInfo subscribeInfo, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent ) 462 SubscribeInfo subscribeInfo, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent )
534 - throws NoSuchFieldException, IllegalAccessException, SipException, ParseException, InvalidArgumentException { 463 + throws SipException, ParseException, InvalidArgumentException {
535 MessageFactoryImpl messageFactory = (MessageFactoryImpl) sipFactory.createMessageFactory(); 464 MessageFactoryImpl messageFactory = (MessageFactoryImpl) sipFactory.createMessageFactory();
536 String characterSet = parentPlatform.getCharacterSet(); 465 String characterSet = parentPlatform.getCharacterSet();
537 // 设置编码, 防止中文乱码 466 // 设置编码, 防止中文乱码
@@ -539,50 +468,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { @@ -539,50 +468,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
539 468
540 SIPRequest notifyRequest = headerProviderPlatformProvider.createNotifyRequest(parentPlatform, catalogXmlContent, subscribeInfo); 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 private String getCatalogXmlContentForCatalogAddOrUpdate(ParentPlatform parentPlatform, List<DeviceChannel> channels, int sumNum, String type, SubscribeInfo subscribeInfo) { 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,20 +527,21 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
641 } 527 }
642 528
643 @Override 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 if (parentPlatform == null 532 if (parentPlatform == null
647 || deviceChannels == null 533 || deviceChannels == null
648 || deviceChannels.size() == 0 534 || deviceChannels.size() == 0
649 || subscribeInfo == null) { 535 || subscribeInfo == null) {
650 - return false; 536 + logger.warn("[缺少必要参数]");
  537 + return;
651 } 538 }
652 539
653 if (index == null) { 540 if (index == null) {
654 index = 0; 541 index = 0;
655 } 542 }
656 if (index >= deviceChannels.size()) { 543 if (index >= deviceChannels.size()) {
657 - return true; 544 + return;
658 } 545 }
659 List<DeviceChannel> channels; 546 List<DeviceChannel> channels;
660 if (index + parentPlatform.getCatalogGroup() < deviceChannels.size()) { 547 if (index + parentPlatform.getCatalogGroup() < deviceChannels.size()) {
@@ -662,28 +549,19 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { @@ -662,28 +549,19 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
662 }else { 549 }else {
663 channels = deviceChannels.subList(index, deviceChannels.size()); 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 sendNotifyForCatalogOther(type, parentPlatform, deviceChannels, subscribeInfo, 558 sendNotifyForCatalogOther(type, parentPlatform, deviceChannels, subscribeInfo,
672 finalIndex + parentPlatform.getCatalogGroup()); 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 private String getCatalogXmlContentForCatalogOther(ParentPlatform parentPlatform, List<DeviceChannel> channels, String type) { 567 private String getCatalogXmlContentForCatalogOther(ParentPlatform parentPlatform, List<DeviceChannel> channels, String type) {
@@ -713,113 +591,81 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { @@ -713,113 +591,81 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
713 return catalogXml.toString(); 591 return catalogXml.toString();
714 } 592 }
715 @Override 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 if ( parentPlatform ==null) { 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 @Override 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 @Override 667 @Override
822 - public void streamByeCmd(ParentPlatform platform, String callId) { 668 + public void streamByeCmd(ParentPlatform platform, String callId) throws SipException, InvalidArgumentException, ParseException {
823 if (platform == null) { 669 if (platform == null) {
824 return; 670 return;
825 } 671 }
@@ -830,7 +676,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { @@ -830,7 +676,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
830 } 676 }
831 677
832 @Override 678 @Override
833 - public void streamByeCmd(ParentPlatform platform, SendRtpItem sendRtpItem) { 679 + public void streamByeCmd(ParentPlatform platform, SendRtpItem sendRtpItem) throws SipException, InvalidArgumentException, ParseException {
834 if (sendRtpItem == null ) { 680 if (sendRtpItem == null ) {
835 logger.info("[向上级发送BYE], sendRtpItem 为NULL"); 681 logger.info("[向上级发送BYE], sendRtpItem 为NULL");
836 return; 682 return;
@@ -846,25 +692,10 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { @@ -846,25 +692,10 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
846 mediaServerService.releaseSsrc(mediaServerItem.getId(), sendRtpItem.getSsrc()); 692 mediaServerService.releaseSsrc(mediaServerItem.getId(), sendRtpItem.getSsrc());
847 zlmrtpServerFactory.closeRTPServer(mediaServerItem, sendRtpItem.getStreamId()); 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,6 +7,7 @@ import gov.nist.javax.sip.SipStackImpl;
7 import gov.nist.javax.sip.message.SIPRequest; 7 import gov.nist.javax.sip.message.SIPRequest;
8 import gov.nist.javax.sip.message.SIPResponse; 8 import gov.nist.javax.sip.message.SIPResponse;
9 import gov.nist.javax.sip.stack.SIPServerTransaction; 9 import gov.nist.javax.sip.stack.SIPServerTransaction;
  10 +import gov.nist.javax.sip.stack.SIPServerTransactionImpl;
10 import org.apache.commons.lang3.ArrayUtils; 11 import org.apache.commons.lang3.ArrayUtils;
11 import org.dom4j.Document; 12 import org.dom4j.Document;
12 import org.dom4j.DocumentException; 13 import org.dom4j.DocumentException;
@@ -57,33 +58,34 @@ public abstract class SIPRequestProcessorParent { @@ -57,33 +58,34 @@ public abstract class SIPRequestProcessorParent {
57 */ 58 */
58 public ServerTransaction getServerTransaction(RequestEvent evt) { 59 public ServerTransaction getServerTransaction(RequestEvent evt) {
59 Request request = evt.getRequest(); 60 Request request = evt.getRequest();
60 - ServerTransaction serverTransaction = evt.getServerTransaction(); 61 + SIPServerTransactionImpl serverTransaction = (SIPServerTransactionImpl)evt.getServerTransaction();
61 // 判断TCP还是UDP 62 // 判断TCP还是UDP
62 ViaHeader reqViaHeader = (ViaHeader) request.getHeader(ViaHeader.NAME); 63 ViaHeader reqViaHeader = (ViaHeader) request.getHeader(ViaHeader.NAME);
63 String transport = reqViaHeader.getTransport(); 64 String transport = reqViaHeader.getTransport();
  65 + if (serverTransaction != null && serverTransaction.getOriginalRequest() == null) {
  66 + serverTransaction.setOriginalRequest((SIPRequest) evt.getRequest());
  67 + }
64 boolean isTcp = "TCP".equals(transport); 68 boolean isTcp = "TCP".equals(transport);
65 69
66 if (serverTransaction == null) { 70 if (serverTransaction == null) {
67 try { 71 try {
68 if (isTcp) { 72 if (isTcp) {
69 SipStackImpl stack = (SipStackImpl)tcpSipProvider.getSipStack(); 73 SipStackImpl stack = (SipStackImpl)tcpSipProvider.getSipStack();
70 - serverTransaction = (SIPServerTransaction) stack.findTransaction((SIPRequest)request, true); 74 + serverTransaction = (SIPServerTransactionImpl) stack.findTransaction((SIPRequest)request, true);
71 if (serverTransaction == null) { 75 if (serverTransaction == null) {
72 - serverTransaction = tcpSipProvider.getNewServerTransaction(request); 76 + serverTransaction = (SIPServerTransactionImpl)tcpSipProvider.getNewServerTransaction(request);
73 } 77 }
74 } else { 78 } else {
75 SipStackImpl stack = (SipStackImpl)udpSipProvider.getSipStack(); 79 SipStackImpl stack = (SipStackImpl)udpSipProvider.getSipStack();
76 - serverTransaction = (SIPServerTransaction) stack.findTransaction((SIPRequest)request, true); 80 + serverTransaction = (SIPServerTransactionImpl) stack.findTransaction((SIPRequest)request, true);
77 if (serverTransaction == null) { 81 if (serverTransaction == null) {
78 - serverTransaction = udpSipProvider.getNewServerTransaction(request); 82 + serverTransaction = (SIPServerTransactionImpl)udpSipProvider.getNewServerTransaction(request);
79 } 83 }
80 } 84 }
81 } catch (TransactionAlreadyExistsException e) { 85 } catch (TransactionAlreadyExistsException e) {
82 logger.error(e.getMessage()); 86 logger.error(e.getMessage());
83 } catch (TransactionUnavailableException e) { 87 } catch (TransactionUnavailableException e) {
84 logger.error(e.getMessage()); 88 logger.error(e.getMessage());
85 - }finally {  
86 -  
87 } 89 }
88 } 90 }
89 return serverTransaction; 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,12 +29,16 @@ import org.springframework.beans.factory.annotation.Autowired;
29 import org.springframework.stereotype.Component; 29 import org.springframework.stereotype.Component;
30 30
31 import javax.sip.*; 31 import javax.sip.*;
  32 +import javax.sip.InvalidArgumentException;
32 import javax.sip.RequestEvent; 33 import javax.sip.RequestEvent;
  34 +import javax.sip.SipException;
33 import javax.sip.address.SipURI; 35 import javax.sip.address.SipURI;
34 import javax.sip.header.CallIdHeader; 36 import javax.sip.header.CallIdHeader;
35 import javax.sip.header.FromHeader; 37 import javax.sip.header.FromHeader;
36 import javax.sip.header.HeaderAddress; 38 import javax.sip.header.HeaderAddress;
37 import java.text.ParseException; 39 import java.text.ParseException;
  40 +import javax.sip.header.ToHeader;
  41 +import java.text.ParseException;
38 import java.util.*; 42 import java.util.*;
39 43
40 /** 44 /**
@@ -105,8 +109,8 @@ public class AckRequestProcessor extends SIPRequestProcessorParent implements In @@ -105,8 +109,8 @@ public class AckRequestProcessor extends SIPRequestProcessorParent implements In
105 SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(platformGbId, channelId, null, callIdHeader.getCallId()); 109 SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(platformGbId, channelId, null, callIdHeader.getCallId());
106 String is_Udp = sendRtpItem.isTcp() ? "0" : "1"; 110 String is_Udp = sendRtpItem.isTcp() ? "0" : "1";
107 MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId()); 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 param.put("vhost","__defaultVhost__"); 114 param.put("vhost","__defaultVhost__");
111 param.put("app",sendRtpItem.getApp()); 115 param.put("app",sendRtpItem.getApp());
112 param.put("stream",sendRtpItem.getStreamId()); 116 param.put("stream",sendRtpItem.getStreamId());
@@ -187,7 +191,11 @@ public class AckRequestProcessor extends SIPRequestProcessorParent implements In @@ -187,7 +191,11 @@ public class AckRequestProcessor extends SIPRequestProcessorParent implements In
187 // TODO 可能是语音对讲 191 // TODO 可能是语音对讲
188 }else { 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 package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl; 1 package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl;
2 2
3 import com.genersoft.iot.vmp.common.StreamInfo; 3 import com.genersoft.iot.vmp.common.StreamInfo;
  4 +import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException;
4 import com.genersoft.iot.vmp.gb28181.bean.Device; 5 import com.genersoft.iot.vmp.gb28181.bean.Device;
5 import com.genersoft.iot.vmp.gb28181.bean.InviteStreamType; 6 import com.genersoft.iot.vmp.gb28181.bean.InviteStreamType;
6 import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem; 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 +13,12 @@ import com.genersoft.iot.vmp.gb28181.transmit.event.request.ISIPRequestProcessor
12 import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; 13 import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
13 import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; 14 import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
14 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; 15 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
  16 +import com.genersoft.iot.vmp.service.IDeviceService;
15 import com.genersoft.iot.vmp.service.IMediaServerService; 17 import com.genersoft.iot.vmp.service.IMediaServerService;
16 import com.genersoft.iot.vmp.service.IPlayService; 18 import com.genersoft.iot.vmp.service.IPlayService;
17 import com.genersoft.iot.vmp.service.bean.MessageForPushChannel; 19 import com.genersoft.iot.vmp.service.bean.MessageForPushChannel;
18 import com.genersoft.iot.vmp.storager.IRedisCatchStorage; 20 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
19 import com.genersoft.iot.vmp.storager.IVideoManagerStorage; 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 import org.slf4j.Logger; 22 import org.slf4j.Logger;
23 import org.slf4j.LoggerFactory; 23 import org.slf4j.LoggerFactory;
24 import org.springframework.beans.factory.InitializingBean; 24 import org.springframework.beans.factory.InitializingBean;
@@ -52,6 +52,9 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In @@ -52,6 +52,9 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In
52 private IRedisCatchStorage redisCatchStorage; 52 private IRedisCatchStorage redisCatchStorage;
53 53
54 @Autowired 54 @Autowired
  55 + private IDeviceService deviceService;
  56 +
  57 + @Autowired
55 private IVideoManagerStorage storager; 58 private IVideoManagerStorage storager;
56 59
57 @Autowired 60 @Autowired
@@ -81,9 +84,13 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In @@ -81,9 +84,13 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In
81 */ 84 */
82 @Override 85 @Override
83 public void process(RequestEvent evt) { 86 public void process(RequestEvent evt) {
  87 +
84 try { 88 try {
85 responseAck(getServerTransaction(evt), Response.OK); 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 String platformGbId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(FromHeader.NAME)).getAddress().getURI()).getUser(); 94 String platformGbId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(FromHeader.NAME)).getAddress().getURI()).getUser();
88 String channelId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(ToHeader.NAME)).getAddress().getURI()).getUser(); 95 String channelId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(ToHeader.NAME)).getAddress().getURI()).getUser();
89 SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(platformGbId, channelId, null, callIdHeader.getCallId()); 96 SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(platformGbId, channelId, null, callIdHeader.getCallId());
@@ -103,7 +110,17 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In @@ -103,7 +110,17 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In
103 if (totalReaderCount <= 0) { 110 if (totalReaderCount <= 0) {
104 logger.info("[收到bye] {} 无其它观看者,通知设备停止推流", streamId); 111 logger.info("[收到bye] {} 无其它观看者,通知设备停止推流", streamId);
105 if (sendRtpItem.getPlayType().equals(InviteStreamType.PLAY)) { 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 if (sendRtpItem.isOnlyAudio()) { 125 if (sendRtpItem.isOnlyAudio()) {
109 playService.stopAudioBroadcast(sendRtpItem.getDeviceId(), sendRtpItem.getChannelId()); 126 playService.stopAudioBroadcast(sendRtpItem.getDeviceId(), sendRtpItem.getChannelId());
@@ -127,8 +144,7 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In @@ -127,8 +144,7 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In
127 } 144 }
128 SsrcTransaction ssrcTransactionForPlay = streamSession.getSsrcTransaction(device.getDeviceId(), channelId, "play", null); 145 SsrcTransaction ssrcTransactionForPlay = streamSession.getSsrcTransaction(device.getDeviceId(), channelId, "play", null);
129 if (ssrcTransactionForPlay != null){ 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 // 释放ssrc 148 // 释放ssrc
133 MediaServerItem mediaServerItem = mediaServerService.getOne(ssrcTransactionForPlay.getMediaServerId()); 149 MediaServerItem mediaServerItem = mediaServerService.getOne(ssrcTransactionForPlay.getMediaServerId());
134 if (mediaServerItem != null) { 150 if (mediaServerItem != null) {
@@ -147,12 +163,6 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In @@ -147,12 +163,6 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In
147 streamSession.remove(device.getDeviceId(), channelId, ssrcTransactionForPlayBack.getStream()); 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,16 +366,20 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
366 content.append("m=video " + sendRtpItem.getLocalPort() + " RTP/AVP 96\r\n"); 366 content.append("m=video " + sendRtpItem.getLocalPort() + " RTP/AVP 96\r\n");
367 content.append("a=sendonly\r\n"); 367 content.append("a=sendonly\r\n");
368 content.append("a=rtpmap:96 PS/90000\r\n"); 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 content.append("f=\r\n"); 370 content.append("f=\r\n");
371 371
372 try { 372 try {
373 // 超时未收到Ack应该回复bye,当前等待时间为10秒 373 // 超时未收到Ack应该回复bye,当前等待时间为10秒
374 dynamicTask.startDelay(callIdHeader.getCallId(), () -> { 374 dynamicTask.startDelay(callIdHeader.getCallId(), () -> {
375 logger.info("Ack 等待超时"); 375 logger.info("Ack 等待超时");
376 - mediaServerService.releaseSsrc(mediaServerItemInUSe.getId(), ssrc); 376 + mediaServerService.releaseSsrc(mediaServerItemInUSe.getId(), sendRtpItem.getSsrc());
377 // 回复bye 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 }, 60 * 1000); 383 }, 60 * 1000);
380 responseSdpAck(serverTransaction, content.toString(), platform); 384 responseSdpAck(serverTransaction, content.toString(), platform);
381 385
@@ -455,6 +459,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements @@ -455,6 +459,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
455 SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId, null, device.isSsrcCheck(), false); 459 SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId, null, device.isSsrcCheck(), false);
456 logger.info(JSONObject.toJSONString(ssrcInfo)); 460 logger.info(JSONObject.toJSONString(ssrcInfo));
457 sendRtpItem.setStreamId(ssrcInfo.getStream()); 461 sendRtpItem.setStreamId(ssrcInfo.getStream());
  462 + sendRtpItem.setSsrc(ssrc.equals(ssrcDefault) ? ssrcInfo.getSsrc() : ssrc);
458 463
459 // 写入redis, 超时时回复 464 // 写入redis, 超时时回复
460 redisCatchStorage.updateSendRTPSever(sendRtpItem); 465 redisCatchStorage.updateSendRTPSever(sendRtpItem);
@@ -691,12 +696,8 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements @@ -691,12 +696,8 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
691 mediaListManager.removedChannelOnlineEventLister(gbStream.getApp(), gbStream.getStream()); 696 mediaListManager.removedChannelOnlineEventLister(gbStream.getApp(), gbStream.getStream());
692 try { 697 try {
693 responseAck(serverTransaction, Response.TEMPORARILY_UNAVAILABLE, response.getMsg()); 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,12 +764,8 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
763 mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId); 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,10 +124,9 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements
124 } 124 }
125 } catch (DocumentException e) { 125 } catch (DocumentException e) {
126 logger.error("处理NOTIFY消息时错误", e); 126 logger.error("处理NOTIFY消息时错误", e);
127 - } finally {  
128 - taskQueueHandlerRun = false;  
129 } 127 }
130 } 128 }
  129 + taskQueueHandlerRun = false;
131 }); 130 });
132 } 131 }
133 } catch (SipException | InvalidArgumentException | ParseException e) { 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,7 +93,9 @@ public class InfoRequestProcessor extends SIPRequestProcessorParent implements I
93 responseAck(serverTransaction, Response.NOT_FOUND, "device "+ deviceId +" not found"); 93 responseAck(serverTransaction, Response.NOT_FOUND, "device "+ deviceId +" not found");
94 logger.warn("[设备未找到 ]: {}", deviceId); 94 logger.warn("[设备未找到 ]: {}", deviceId);
95 if (sipSubscribe.getErrorSubscribe(callIdHeader.getCallId()) != null){ 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 sipSubscribe.getErrorSubscribe(callIdHeader.getCallId()).response(eventResult); 99 sipSubscribe.getErrorSubscribe(callIdHeader.getCallId()).response(eventResult);
98 }; 100 };
99 }else { 101 }else {
@@ -113,23 +115,15 @@ public class InfoRequestProcessor extends SIPRequestProcessorParent implements I @@ -113,23 +115,15 @@ public class InfoRequestProcessor extends SIPRequestProcessorParent implements I
113 // 失败的回复 115 // 失败的回复
114 try { 116 try {
115 responseAck(serverTransaction, eventResult.statusCode, eventResult.msg); 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 }, eventResult -> { 121 }, eventResult -> {
124 // 成功的回复 122 // 成功的回复
125 try { 123 try {
126 responseAck(serverTransaction, eventResult.statusCode); 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,8 +89,6 @@ public class MessageRequestProcessor extends SIPRequestProcessorParent implement
89 ParentPlatform parentPlatform = storage.queryParentPlatByServerGBId(deviceId); 89 ParentPlatform parentPlatform = storage.queryParentPlatByServerGBId(deviceId);
90 try { 90 try {
91 if (device != null && parentPlatform != null) { 91 if (device != null && parentPlatform != null) {
92 -  
93 - logger.warn("[重复]平台与设备编号重复:{}", deviceId);  
94 SIPRequest request = (SIPRequest) evt.getRequest(); 92 SIPRequest request = (SIPRequest) evt.getRequest();
95 String hostAddress = request.getRemoteAddress().getHostAddress(); 93 String hostAddress = request.getRemoteAddress().getHostAddress();
96 int remotePort = request.getRemotePort(); 94 int remotePort = request.getRemotePort();
@@ -105,7 +103,9 @@ public class MessageRequestProcessor extends SIPRequestProcessorParent implement @@ -105,7 +103,9 @@ public class MessageRequestProcessor extends SIPRequestProcessorParent implement
105 responseAck(serverTransaction, Response.NOT_FOUND, "device "+ deviceId +" not found"); 103 responseAck(serverTransaction, Response.NOT_FOUND, "device "+ deviceId +" not found");
106 logger.warn("[设备未找到 ]: {}", deviceId); 104 logger.warn("[设备未找到 ]: {}", deviceId);
107 if (sipSubscribe.getErrorSubscribe(callIdHeader.getCallId()) != null){ 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 sipSubscribe.getErrorSubscribe(callIdHeader.getCallId()).response(eventResult); 109 sipSubscribe.getErrorSubscribe(callIdHeader.getCallId()).response(eventResult);
110 }; 110 };
111 }else { 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,6 +16,8 @@ import org.slf4j.Logger;
16 import org.slf4j.LoggerFactory; 16 import org.slf4j.LoggerFactory;
17 import org.springframework.beans.factory.InitializingBean; 17 import org.springframework.beans.factory.InitializingBean;
18 import org.springframework.beans.factory.annotation.Autowired; 18 import org.springframework.beans.factory.annotation.Autowired;
  19 +import org.springframework.beans.factory.annotation.Qualifier;
  20 +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
19 import org.springframework.stereotype.Component; 21 import org.springframework.stereotype.Component;
20 import org.springframework.util.ObjectUtils; 22 import org.springframework.util.ObjectUtils;
21 import org.springframework.util.StringUtils; 23 import org.springframework.util.StringUtils;
@@ -48,6 +50,10 @@ public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent @@ -48,6 +50,10 @@ public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent
48 @Autowired 50 @Autowired
49 private SIPCommanderFroPlatform cmderFroPlatform; 51 private SIPCommanderFroPlatform cmderFroPlatform;
50 52
  53 + @Qualifier("taskExecutor")
  54 + @Autowired
  55 + private ThreadPoolTaskExecutor taskExecutor;
  56 +
51 @Override 57 @Override
52 public void afterPropertiesSet() throws Exception { 58 public void afterPropertiesSet() throws Exception {
53 controlMessageHandler.addHandler(cmdType, this); 59 controlMessageHandler.addHandler(cmdType, this);
@@ -71,34 +77,30 @@ public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent @@ -71,34 +77,30 @@ public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent
71 if (parentPlatform.getServerGBId().equals(targetGBId)) { 77 if (parentPlatform.getServerGBId().equals(targetGBId)) {
72 // 远程启动本平台:需要在重新启动程序后先对SipStack解绑 78 // 远程启动本平台:需要在重新启动程序后先对SipStack解绑
73 logger.info("执行远程启动本平台命令"); 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 } else { 104 } else {
103 // 远程启动指定设备 105 // 远程启动指定设备
104 } 106 }
@@ -111,37 +113,29 @@ public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent @@ -111,37 +113,29 @@ public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent
111 try { 113 try {
112 responseAck(serverTransaction, Response.NOT_FOUND); 114 responseAck(serverTransaction, Response.NOT_FOUND);
113 return; 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,12 +217,8 @@ public class AlarmNotifyMessageHandler extends SIPRequestProcessorParent impleme
217 // 回复200 OK 217 // 回复200 OK
218 try { 218 try {
219 responseAck(getServerTransaction(evt), Response.OK); 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 Element deviceIdElement = rootElement.element("DeviceID"); 223 Element deviceIdElement = rootElement.element("DeviceID");
228 String channelId = deviceIdElement.getText().toString(); 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,12 +78,8 @@ public class KeepaliveNotifyMessageHandler extends SIPRequestProcessorParent imp
78 deviceService.online(device); 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 package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify.cmd; 1 package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify.cmd;
2 2
3 import com.genersoft.iot.vmp.common.StreamInfo; 3 import com.genersoft.iot.vmp.common.StreamInfo;
  4 +import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException;
4 import com.genersoft.iot.vmp.gb28181.bean.Device; 5 import com.genersoft.iot.vmp.gb28181.bean.Device;
5 import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; 6 import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
6 import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem; 7 import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem;
@@ -67,12 +68,8 @@ public class MediaStatusNotifyMessageHandler extends SIPRequestProcessorParent i @@ -67,12 +68,8 @@ public class MediaStatusNotifyMessageHandler extends SIPRequestProcessorParent i
67 // 回复200 OK 68 // 回复200 OK
68 try { 69 try {
69 responseAck(getServerTransaction(evt), Response.OK); 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 CallIdHeader callIdHeader = (CallIdHeader)evt.getRequest().getHeader(CallIdHeader.NAME); 74 CallIdHeader callIdHeader = (CallIdHeader)evt.getRequest().getHeader(CallIdHeader.NAME);
78 String NotifyType =getText(rootElement, "NotifyType"); 75 String NotifyType =getText(rootElement, "NotifyType");
@@ -89,7 +86,12 @@ public class MediaStatusNotifyMessageHandler extends SIPRequestProcessorParent i @@ -89,7 +86,12 @@ public class MediaStatusNotifyMessageHandler extends SIPRequestProcessorParent i
89 // 先从会话内查找 86 // 先从会话内查找
90 SsrcTransaction ssrcTransaction = sessionManager.getSsrcTransaction(null, null, callIdHeader.getCallId(), null); 87 SsrcTransaction ssrcTransaction = sessionManager.getSsrcTransaction(null, null, callIdHeader.getCallId(), null);
91 if (ssrcTransaction != null) { // 兼容海康 媒体通知 消息from字段不是设备ID的问题 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 // 如果级联播放,需要给上级发送此通知 TODO 多个上级同时观看一个下级 可能存在停错的问题,需要将点播CallId进行上下级绑定 96 // 如果级联播放,需要给上级发送此通知 TODO 多个上级同时观看一个下级 可能存在停错的问题,需要将点播CallId进行上下级绑定
95 SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(null, ssrcTransaction.getChannelId(), null, null); 97 SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(null, ssrcTransaction.getChannelId(), null, null);
@@ -99,7 +101,11 @@ public class MediaStatusNotifyMessageHandler extends SIPRequestProcessorParent i @@ -99,7 +101,11 @@ public class MediaStatusNotifyMessageHandler extends SIPRequestProcessorParent i
99 logger.warn("[级联消息发送]:发送MediaStatus发现上级平台{}不存在", sendRtpItem.getPlatformId()); 101 logger.warn("[级联消息发送]:发送MediaStatus发现上级平台{}不存在", sendRtpItem.getPlatformId());
100 return; 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,12 +59,8 @@ public class AlarmQueryMessageHandler extends SIPRequestProcessorParent implemen
59 logger.info("不支持alarm查询"); 59 logger.info("不支持alarm查询");
60 try { 60 try {
61 responseAck(getServerTransaction(evt), Response.NOT_FOUND, "not support alarm query"); 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,12 +100,8 @@ public class CatalogQueryMessageHandler extends SIPRequestProcessorParent implem
100 // 回复无通道 100 // 回复无通道
101 cmderFroPlatform.catalogQuery(null, parentPlatform, sn, fromHeader.getTag(), 0); 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,14 +49,14 @@ public class DeviceInfoQueryMessageHandler extends SIPRequestProcessorParent imp
49 try { 49 try {
50 // 回复200 OK 50 // 回复200 OK
51 responseAck(getServerTransaction(evt), Response.OK); 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 String sn = rootElement.element("SN").getText(); 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,14 +62,14 @@ public class DeviceStatusQueryMessageHandler extends SIPRequestProcessorParent i
62 // 回复200 OK 62 // 回复200 OK
63 try { 63 try {
64 responseAck(getServerTransaction(evt), Response.OK); 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 String sn = rootElement.element("SN").getText(); 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,53 +103,45 @@ public class RecordInfoQueryMessageHandler extends SIPRequestProcessorParent imp
103 DeviceChannel deviceChannel = storager.queryChannelInParentPlatform(parentPlatform.getServerGBId(), channelId); 103 DeviceChannel deviceChannel = storager.queryChannelInParentPlatform(parentPlatform.getServerGBId(), channelId);
104 // 接收录像数据 104 // 接收录像数据
105 recordEndEventListener.addEndEventHandler(deviceChannel.getDeviceId(), channelId, (recordInfo)->{ 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 }else if (channelSources.get(1).getCount() > 0) { // 直播流 133 }else if (channelSources.get(1).getCount() > 0) { // 直播流
134 // TODO 134 // TODO
135 try { 135 try {
136 responseAck(serverTransaction, Response.NOT_IMPLEMENTED); // 回复未实现 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 }else { // 错误的请求 140 }else { // 错误的请求
145 try { 141 try {
146 responseAck(serverTransaction, Response.BAD_REQUEST); 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,7 +63,7 @@ public class BroadcastResponseMessageHandler extends SIPRequestProcessorParent i
63 audioBroadcastManager.update(audioBroadcastCatch); 63 audioBroadcastManager.update(audioBroadcastCatch);
64 responseAck(evt, Response.OK); 64 responseAck(evt, Response.OK);
65 } catch (ParseException | SipException | InvalidArgumentException e) { 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,24 +56,8 @@ public class CatalogResponseMessageHandler extends SIPRequestProcessorParent imp
56 private IVideoManagerStorage storager; 56 private IVideoManagerStorage storager;
57 57
58 @Autowired 58 @Autowired
59 - private DeferredResultHolder deferredResultHolder;  
60 -  
61 - @Autowired  
62 private CatalogDataCatch catalogDataCatch; 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 @Qualifier("taskExecutor") 61 @Qualifier("taskExecutor")
78 @Autowired 62 @Autowired
79 private ThreadPoolTaskExecutor taskExecutor; 63 private ThreadPoolTaskExecutor taskExecutor;
@@ -87,89 +71,74 @@ public class CatalogResponseMessageHandler extends SIPRequestProcessorParent imp @@ -87,89 +71,74 @@ public class CatalogResponseMessageHandler extends SIPRequestProcessorParent imp
87 public void handForDevice(RequestEvent evt, Device device, Element element) { 71 public void handForDevice(RequestEvent evt, Device device, Element element) {
88 taskQueue.offer(new HandlerCatchData(evt, device, element)); 72 taskQueue.offer(new HandlerCatchData(evt, device, element));
89 // 回复200 OK 73 // 回复200 OK
  74 + ServerTransaction serverTransaction = getServerTransaction(evt);
90 try { 75 try {
91 - ServerTransaction serverTransaction = getServerTransaction(evt);  
92 responseAck(serverTransaction, Response.OK); 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,7 +151,7 @@ public class CatalogResponseMessageHandler extends SIPRequestProcessorParent imp
182 public SyncStatus getChannelSyncProgress(String deviceId) { 151 public SyncStatus getChannelSyncProgress(String deviceId) {
183 if (catalogDataCatch.get(deviceId) == null) { 152 if (catalogDataCatch.get(deviceId) == null) {
184 return null; 153 return null;
185 - }else { 154 + } else {
186 return catalogDataCatch.getSyncStatus(deviceId); 155 return catalogDataCatch.getSyncStatus(deviceId);
187 } 156 }
188 } 157 }
@@ -190,7 +159,7 @@ public class CatalogResponseMessageHandler extends SIPRequestProcessorParent imp @@ -190,7 +159,7 @@ public class CatalogResponseMessageHandler extends SIPRequestProcessorParent imp
190 public boolean isSyncRunning(String deviceId) { 159 public boolean isSyncRunning(String deviceId) {
191 if (catalogDataCatch.get(deviceId) == null) { 160 if (catalogDataCatch.get(deviceId) == null) {
192 return false; 161 return false;
193 - }else { 162 + } else {
194 return catalogDataCatch.isSyncRunning(deviceId); 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,12 +63,8 @@ public class ConfigDownloadResponseMessageHandler extends SIPRequestProcessorPar
63 msg.setKey(key); 63 msg.setKey(key);
64 msg.setData(json); 64 msg.setData(json);
65 deferredResultHolder.invokeAllResult(msg); 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,12 +58,8 @@ public class DeviceControlResponseMessageHandler extends SIPRequestProcessorPare
58 msg.setKey(key); 58 msg.setKey(key);
59 msg.setData(json); 59 msg.setData(json);
60 deferredResultHolder.invokeAllResult(msg); 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,12 +60,8 @@ public class DeviceStatusResponseMessageHandler extends SIPRequestProcessorParen
60 // 回复200 OK 60 // 回复200 OK
61 try { 61 try {
62 responseAck(getServerTransaction(evt), Response.OK); 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 Element deviceIdElement = element.element("DeviceID"); 66 Element deviceIdElement = element.element("DeviceID");
71 Element onlineElement = element.element("Online"); 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,12 +50,12 @@ public class PresetQueryResponseMessageHandler extends SIPRequestProcessorParent
50 50
51 @Override 51 @Override
52 public void handForDevice(RequestEvent evt, Device device, Element element) { 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 if (rootElement == null) { 59 if (rootElement == null) {
60 logger.warn("[ 设备预置位查询应答 ] content cannot be null, {}", evt.getRequest()); 60 logger.warn("[ 设备预置位查询应答 ] content cannot be null, {}", evt.getRequest());
61 responseAck(serverTransaction, Response.BAD_REQUEST); 61 responseAck(serverTransaction, Response.BAD_REQUEST);
@@ -66,32 +66,29 @@ public class PresetQueryResponseMessageHandler extends SIPRequestProcessorParent @@ -66,32 +66,29 @@ public class PresetQueryResponseMessageHandler extends SIPRequestProcessorParent
66 //该字段可能为通道或则设备的id 66 //该字段可能为通道或则设备的id
67 String deviceId = getText(rootElement, "DeviceID"); 67 String deviceId = getText(rootElement, "DeviceID");
68 String key = DeferredResultHolder.CALLBACK_CMD_PRESETQUERY + deviceId; 68 String key = DeferredResultHolder.CALLBACK_CMD_PRESETQUERY + deviceId;
69 - if (snElement == null || presetListNumElement == null) { 69 + if (snElement == null || presetListNumElement == null) {
70 responseAck(serverTransaction, Response.BAD_REQUEST, "xml error"); 70 responseAck(serverTransaction, Response.BAD_REQUEST, "xml error");
71 return; 71 return;
72 } 72 }
73 int sumNum = Integer.parseInt(presetListNumElement.attributeValue("Num")); 73 int sumNum = Integer.parseInt(presetListNumElement.attributeValue("Num"));
74 List<PresetQuerySipReq> presetQuerySipReqList = new ArrayList<>(); 74 List<PresetQuerySipReq> presetQuerySipReqList = new ArrayList<>();
75 if (sumNum > 0) { 75 if (sumNum > 0) {
76 - for (Iterator<Element> presetIterator = presetListNumElement.elementIterator();presetIterator.hasNext();){ 76 + for (Iterator<Element> presetIterator = presetListNumElement.elementIterator(); presetIterator.hasNext(); ) {
77 Element itemListElement = presetIterator.next(); 77 Element itemListElement = presetIterator.next();
78 PresetQuerySipReq presetQuerySipReq = new PresetQuerySipReq(); 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 presetQuerySipReqList.add(presetQuerySipReq); 90 presetQuerySipReqList.add(presetQuerySipReq);
91 -  
92 -  
93 } 91 }
94 -  
95 } 92 }
96 RequestMessage requestMessage = new RequestMessage(); 93 RequestMessage requestMessage = new RequestMessage();
97 requestMessage.setKey(key); 94 requestMessage.setKey(key);
@@ -99,13 +96,9 @@ public class PresetQueryResponseMessageHandler extends SIPRequestProcessorParent @@ -99,13 +96,9 @@ public class PresetQueryResponseMessageHandler extends SIPRequestProcessorParent
99 deferredResultHolder.invokeAllResult(requestMessage); 96 deferredResultHolder.invokeAllResult(requestMessage);
100 responseAck(serverTransaction, Response.OK); 97 responseAck(serverTransaction, Response.OK);
101 } catch (DocumentException e) { 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,21 +147,16 @@ public class RecordInfoResponseMessageHandler extends SIPRequestProcessorParent
147 } 147 }
148 } 148 }
149 } catch (DocumentException e) { 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 taskQueueHandlerRun = false; 160 taskQueueHandlerRun = false;
166 } 161 }
167 } 162 }
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/response/impl/InviteResponseProcessor.java
1 package com.genersoft.iot.vmp.gb28181.transmit.event.response.impl; 1 package com.genersoft.iot.vmp.gb28181.transmit.event.response.impl;
2 2
3 import com.genersoft.iot.vmp.conf.SipConfig; 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 import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; 6 import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
5 import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver; 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 import com.genersoft.iot.vmp.gb28181.transmit.event.response.SIPResponseProcessorAbstract; 10 import com.genersoft.iot.vmp.gb28181.transmit.event.response.SIPResponseProcessorAbstract;
7 import com.genersoft.iot.vmp.gb28181.utils.SipUtils; 11 import com.genersoft.iot.vmp.gb28181.utils.SipUtils;
  12 +import com.genersoft.iot.vmp.service.IDeviceService;
8 import com.genersoft.iot.vmp.utils.GitUtil; 13 import com.genersoft.iot.vmp.utils.GitUtil;
9 import gov.nist.javax.sip.ResponseEventExt; 14 import gov.nist.javax.sip.ResponseEventExt;
  15 +import gov.nist.javax.sip.SipProviderImpl;
10 import gov.nist.javax.sip.message.SIPResponse; 16 import gov.nist.javax.sip.message.SIPResponse;
11 import gov.nist.javax.sip.stack.SIPClientTransaction; 17 import gov.nist.javax.sip.stack.SIPClientTransaction;
12 import gov.nist.javax.sip.stack.SIPDialog; 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 import org.slf4j.Logger; 21 import org.slf4j.Logger;
14 import org.slf4j.LoggerFactory; 22 import org.slf4j.LoggerFactory;
15 import org.springframework.beans.factory.annotation.Autowired; 23 import org.springframework.beans.factory.annotation.Autowired;
  24 +import org.springframework.beans.factory.annotation.Qualifier;
16 import org.springframework.stereotype.Component; 25 import org.springframework.stereotype.Component;
17 26
18 import javax.sdp.SdpFactory; 27 import javax.sdp.SdpFactory;
@@ -54,6 +63,20 @@ public class InviteResponseProcessor extends SIPResponseProcessorAbstract { @@ -54,6 +63,20 @@ public class InviteResponseProcessor extends SIPResponseProcessorAbstract {
54 @Autowired 63 @Autowired
55 private GitUtil gitUtil; 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 @Override 80 @Override
58 public void afterPropertiesSet() throws Exception { 81 public void afterPropertiesSet() throws Exception {
59 // 添加消息处理的订阅 82 // 添加消息处理的订阅
@@ -71,7 +94,8 @@ public class InviteResponseProcessor extends SIPResponseProcessorAbstract { @@ -71,7 +94,8 @@ public class InviteResponseProcessor extends SIPResponseProcessorAbstract {
71 @Override 94 @Override
72 public void process(ResponseEvent evt ){ 95 public void process(ResponseEvent evt ){
73 try { 96 try {
74 - Response response = evt.getResponse(); 97 +
  98 + SIPResponse response = (SIPResponse)evt.getResponse();
75 int statusCode = response.getStatusCode(); 99 int statusCode = response.getStatusCode();
76 // trying不会回复 100 // trying不会回复
77 if (statusCode == Response.TRYING) { 101 if (statusCode == Response.TRYING) {
@@ -80,10 +104,7 @@ public class InviteResponseProcessor extends SIPResponseProcessorAbstract { @@ -80,10 +104,7 @@ public class InviteResponseProcessor extends SIPResponseProcessorAbstract {
80 // 下发ack 104 // 下发ack
81 if (statusCode == Response.OK) { 105 if (statusCode == Response.OK) {
82 ResponseEventExt event = (ResponseEventExt)evt; 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 String contentString = new String(response.getRawContent()); 108 String contentString = new String(response.getRawContent());
88 // jainSip不支持y=字段, 移除以解析。 109 // jainSip不支持y=字段, 移除以解析。
89 int ssrcIndex = contentString.indexOf("y="); 110 int ssrcIndex = contentString.indexOf("y=");
@@ -96,29 +117,15 @@ public class InviteResponseProcessor extends SIPResponseProcessorAbstract { @@ -96,29 +117,15 @@ public class InviteResponseProcessor extends SIPResponseProcessorAbstract {
96 } else { 117 } else {
97 sdp = SdpFactory.getInstance().createSessionDescription(contentString); 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,10 +15,13 @@ import org.slf4j.LoggerFactory;
15 import org.springframework.beans.factory.annotation.Autowired; 15 import org.springframework.beans.factory.annotation.Autowired;
16 import org.springframework.stereotype.Component; 16 import org.springframework.stereotype.Component;
17 17
  18 +import javax.sip.InvalidArgumentException;
18 import javax.sip.ResponseEvent; 19 import javax.sip.ResponseEvent;
  20 +import javax.sip.SipException;
19 import javax.sip.header.CallIdHeader; 21 import javax.sip.header.CallIdHeader;
20 import javax.sip.header.WWWAuthenticateHeader; 22 import javax.sip.header.WWWAuthenticateHeader;
21 import javax.sip.message.Response; 23 import javax.sip.message.Response;
  24 +import java.text.ParseException;
22 25
23 /** 26 /**
24 * @description:Register响应处理器 27 * @description:Register响应处理器
@@ -87,7 +90,11 @@ public class RegisterResponseProcessor extends SIPResponseProcessorAbstract { @@ -87,7 +90,11 @@ public class RegisterResponseProcessor extends SIPResponseProcessorAbstract {
87 90
88 if (response.getStatusCode() == Response.UNAUTHORIZED) { 91 if (response.getStatusCode() == Response.UNAUTHORIZED) {
89 WWWAuthenticateHeader www = (WWWAuthenticateHeader)response.getHeader(WWWAuthenticateHeader.NAME); 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 }else if (response.getStatusCode() == Response.OK){ 98 }else if (response.getStatusCode() == Response.OK){
92 99
93 if (platformRegisterInfo.isRegister()) { 100 if (platformRegisterInfo.isRegister()) {
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/timeout/impl/TimeoutProcessorImpl.java
1 package com.genersoft.iot.vmp.gb28181.transmit.event.timeout.impl; 1 package com.genersoft.iot.vmp.gb28181.transmit.event.timeout.impl;
2 2
  3 +import com.genersoft.iot.vmp.conf.SystemInfoTimerTask;
3 import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; 4 import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
4 import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver; 5 import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver;
5 import com.genersoft.iot.vmp.gb28181.transmit.event.timeout.ITimeoutProcessor; 6 import com.genersoft.iot.vmp.gb28181.transmit.event.timeout.ITimeoutProcessor;
  7 +import org.slf4j.Logger;
  8 +import org.slf4j.LoggerFactory;
6 import org.springframework.beans.factory.InitializingBean; 9 import org.springframework.beans.factory.InitializingBean;
7 import org.springframework.beans.factory.annotation.Autowired; 10 import org.springframework.beans.factory.annotation.Autowired;
8 import org.springframework.stereotype.Component; 11 import org.springframework.stereotype.Component;
@@ -13,6 +16,8 @@ import javax.sip.header.CallIdHeader; @@ -13,6 +16,8 @@ import javax.sip.header.CallIdHeader;
13 @Component 16 @Component
14 public class TimeoutProcessorImpl implements InitializingBean, ITimeoutProcessor { 17 public class TimeoutProcessorImpl implements InitializingBean, ITimeoutProcessor {
15 18
  19 + private Logger logger = LoggerFactory.getLogger(TimeoutProcessorImpl.class);
  20 +
16 @Autowired 21 @Autowired
17 private SIPProcessorObserver processorObserver; 22 private SIPProcessorObserver processorObserver;
18 23
@@ -36,7 +41,7 @@ public class TimeoutProcessorImpl implements InitializingBean, ITimeoutProcessor @@ -36,7 +41,7 @@ public class TimeoutProcessorImpl implements InitializingBean, ITimeoutProcessor
36 sipSubscribe.removeErrorSubscribe(callId); 41 sipSubscribe.removeErrorSubscribe(callId);
37 sipSubscribe.removeOkSubscribe(callId); 42 sipSubscribe.removeOkSubscribe(callId);
38 } catch (Exception e) { 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,4 +70,47 @@ public class SipUtils {
70 return String.valueOf(System.currentTimeMillis()); 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 package com.genersoft.iot.vmp.media.zlm; 1 package com.genersoft.iot.vmp.media.zlm;
2 2
  3 +import java.text.ParseException;
3 import java.util.HashMap; 4 import java.util.HashMap;
4 import java.util.List; 5 import java.util.List;
5 import java.util.Map; 6 import java.util.Map;
@@ -7,6 +8,7 @@ import java.util.Map; @@ -7,6 +8,7 @@ import java.util.Map;
7 import com.alibaba.fastjson.JSON; 8 import com.alibaba.fastjson.JSON;
8 import com.genersoft.iot.vmp.common.StreamInfo; 9 import com.genersoft.iot.vmp.common.StreamInfo;
9 import com.genersoft.iot.vmp.conf.UserSetting; 10 import com.genersoft.iot.vmp.conf.UserSetting;
  11 +import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException;
10 import com.genersoft.iot.vmp.gb28181.bean.*; 12 import com.genersoft.iot.vmp.gb28181.bean.*;
11 import com.genersoft.iot.vmp.gb28181.event.EventPublisher; 13 import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
12 import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; 14 import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
@@ -31,6 +33,8 @@ import com.alibaba.fastjson.JSONObject; @@ -31,6 +33,8 @@ import com.alibaba.fastjson.JSONObject;
31 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; 33 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
32 34
33 import javax.servlet.http.HttpServletRequest; 35 import javax.servlet.http.HttpServletRequest;
  36 +import javax.sip.InvalidArgumentException;
  37 +import javax.sip.SipException;
34 38
35 /** 39 /**
36 * @description:针对 ZLMediaServer的hook事件监听 40 * @description:针对 ZLMediaServer的hook事件监听
@@ -59,6 +63,9 @@ public class ZLMHttpHookListener { @@ -59,6 +63,9 @@ public class ZLMHttpHookListener {
59 private IRedisCatchStorage redisCatchStorage; 63 private IRedisCatchStorage redisCatchStorage;
60 64
61 @Autowired 65 @Autowired
  66 + private IDeviceService deviceService;
  67 +
  68 + @Autowired
62 private IMediaServerService mediaServerService; 69 private IMediaServerService mediaServerService;
63 70
64 @Autowired 71 @Autowired
@@ -515,7 +522,11 @@ public class ZLMHttpHookListener { @@ -515,7 +522,11 @@ public class ZLMHttpHookListener {
515 String platformId = sendRtpItem.getPlatformId(); 522 String platformId = sendRtpItem.getPlatformId();
516 ParentPlatform platform = storager.queryParentPlatByServerGBId(platformId); 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,21 +563,41 @@ public class ZLMHttpHookListener {
552 if (sendRtpItems.size() > 0) { 563 if (sendRtpItems.size() > 0) {
553 for (SendRtpItem sendRtpItem : sendRtpItems) { 564 for (SendRtpItem sendRtpItem : sendRtpItems) {
554 ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(sendRtpItem.getPlatformId()); 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 redisCatchStorage.deleteSendRTPServer(parentPlatform.getServerGBId(), sendRtpItem.getChannelId(), 571 redisCatchStorage.deleteSendRTPServer(parentPlatform.getServerGBId(), sendRtpItem.getChannelId(),
557 sendRtpItem.getCallId(), sendRtpItem.getStreamId()); 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 redisCatchStorage.stopPlay(streamInfoForPlayCatch); 586 redisCatchStorage.stopPlay(streamInfoForPlayCatch);
564 storager.stopPlay(streamInfoForPlayCatch.getDeviceID(), streamInfoForPlayCatch.getChannelId()); 587 storager.stopPlay(streamInfoForPlayCatch.getDeviceID(), streamInfoForPlayCatch.getChannelId());
565 }else{ 588 }else{
566 StreamInfo streamInfoForPlayBackCatch = redisCatchStorage.queryPlayback(null, null, streamId, null); 589 StreamInfo streamInfoForPlayBackCatch = redisCatchStorage.queryPlayback(null, null, streamId, null);
567 if (streamInfoForPlayBackCatch != null) { 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 redisCatchStorage.stopPlayback(streamInfoForPlayBackCatch.getDeviceID(), 601 redisCatchStorage.stopPlayback(streamInfoForPlayBackCatch.getDeviceID(),
571 streamInfoForPlayBackCatch.getChannelId(), streamInfoForPlayBackCatch.getStream(), null); 602 streamInfoForPlayBackCatch.getChannelId(), streamInfoForPlayBackCatch.getStream(), null);
572 }else { 603 }else {
@@ -689,7 +720,11 @@ public class ZLMHttpHookListener { @@ -689,7 +720,11 @@ public class ZLMHttpHookListener {
689 if (sendRtpItems.size() > 0) { 720 if (sendRtpItems.size() > 0) {
690 for (SendRtpItem sendRtpItem : sendRtpItems) { 721 for (SendRtpItem sendRtpItem : sendRtpItems) {
691 ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(sendRtpItem.getPlatformId()); 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 redisCatchStorage.deleteSendRTPServer(parentPlatform.getServerGBId(), sendRtpItem.getChannelId(), 728 redisCatchStorage.deleteSendRTPServer(parentPlatform.getServerGBId(), sendRtpItem.getChannelId(),
694 sendRtpItem.getCallId(), sendRtpItem.getStreamId()); 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,7 +68,6 @@ public class ZLMMediaListManager {
68 private Map<String, ChannelOnlineEvent> channelOnPublishEvents = new ConcurrentHashMap<>(); 68 private Map<String, ChannelOnlineEvent> channelOnPublishEvents = new ConcurrentHashMap<>();
69 69
70 public StreamPushItem addPush(MediaItem mediaItem) { 70 public StreamPushItem addPush(MediaItem mediaItem) {
71 - // 查找此直播流是否存在redis预设gbId  
72 StreamPushItem transform = streamPushService.transform(mediaItem); 71 StreamPushItem transform = streamPushService.transform(mediaItem);
73 StreamPushItem pushInDb = streamPushService.getPush(mediaItem.getApp(), mediaItem.getStream()); 72 StreamPushItem pushInDb = streamPushService.getPush(mediaItem.getApp(), mediaItem.getStream());
74 transform.setPushIng(mediaItem.isRegist()); 73 transform.setPushIng(mediaItem.isRegist());
@@ -82,15 +81,14 @@ public class ZLMMediaListManager { @@ -82,15 +81,14 @@ public class ZLMMediaListManager {
82 streamPushMapper.update(transform); 81 streamPushMapper.update(transform);
83 gbStreamMapper.updateMediaServer(mediaItem.getApp(), mediaItem.getStream(), mediaItem.getMediaServerId()); 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 return transform; 93 return transform;
96 } 94 }
@@ -99,11 +97,12 @@ public class ZLMMediaListManager { @@ -99,11 +97,12 @@ public class ZLMMediaListManager {
99 MediaServerItem mediaServerItem = mediaServerService.getOne(mediaServerId); 97 MediaServerItem mediaServerItem = mediaServerService.getOne(mediaServerId);
100 // 查看推流状态 98 // 查看推流状态
101 if (zlmrtpServerFactory.isStreamReady(mediaServerItem, app, stream)) { 99 if (zlmrtpServerFactory.isStreamReady(mediaServerItem, app, stream)) {
102 - if (getChannelOnlineEventLister(app, stream) != null) { 100 + ChannelOnlineEvent channelOnlineEventLister = getChannelOnlineEventLister(app, stream);
  101 + if (channelOnlineEventLister != null) {
103 try { 102 try {
104 - getChannelOnlineEventLister(app, stream).run(app, stream, mediaServerId); 103 + channelOnlineEventLister.run(app, stream, mediaServerId);
105 } catch (ParseException e) { 104 } catch (ParseException e) {
106 - throw new RuntimeException(e); 105 + logger.error("sendStreamEvent: ", e);
107 } 106 }
108 removedChannelOnlineEventLister(app, stream); 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,6 +26,9 @@ import org.springframework.stereotype.Service;
26 import org.springframework.util.ObjectUtils; 26 import org.springframework.util.ObjectUtils;
27 import org.springframework.util.StringUtils; 27 import org.springframework.util.StringUtils;
28 28
  29 +import javax.sip.InvalidArgumentException;
  30 +import javax.sip.SipException;
  31 +import java.text.ParseException;
29 import java.time.Instant; 32 import java.time.Instant;
30 import java.util.ArrayList; 33 import java.util.ArrayList;
31 import java.util.Collections; 34 import java.util.Collections;
@@ -95,7 +98,11 @@ public class DeviceServiceImpl implements IDeviceService { @@ -95,7 +98,11 @@ public class DeviceServiceImpl implements IDeviceService {
95 logger.info("[设备上线,首次注册]: {},查询设备信息以及通道信息", device.getDeviceId()); 98 logger.info("[设备上线,首次注册]: {},查询设备信息以及通道信息", device.getDeviceId());
96 deviceMapper.add(device); 99 deviceMapper.add(device);
97 redisCatchStorage.updateDevice(device); 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 sync(device); 106 sync(device);
100 }else { 107 }else {
101 if(device.getOnline() == 0){ 108 if(device.getOnline() == 0){
@@ -104,7 +111,11 @@ public class DeviceServiceImpl implements IDeviceService { @@ -104,7 +111,11 @@ public class DeviceServiceImpl implements IDeviceService {
104 logger.info("[设备上线,离线状态下重新注册]: {},查询设备信息以及通道信息", device.getDeviceId()); 111 logger.info("[设备上线,离线状态下重新注册]: {},查询设备信息以及通道信息", device.getDeviceId());
105 deviceMapper.update(device); 112 deviceMapper.update(device);
106 redisCatchStorage.updateDevice(device); 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 sync(device); 119 sync(device);
109 // TODO 如果设备下的通道级联到了其他平台,那么需要发送事件或者notify给上级平台 120 // TODO 如果设备下的通道级联到了其他平台,那么需要发送事件或者notify给上级平台
110 }else { 121 }else {
@@ -129,6 +140,7 @@ public class DeviceServiceImpl implements IDeviceService { @@ -129,6 +140,7 @@ public class DeviceServiceImpl implements IDeviceService {
129 140
130 @Override 141 @Override
131 public void offline(String deviceId) { 142 public void offline(String deviceId) {
  143 + logger.info("[设备离线], device:{}", deviceId);
132 Device device = deviceMapper.getDeviceByDeviceId(deviceId); 144 Device device = deviceMapper.getDeviceByDeviceId(deviceId);
133 if (device == null) { 145 if (device == null) {
134 return; 146 return;
@@ -238,15 +250,28 @@ public class DeviceServiceImpl implements IDeviceService { @@ -238,15 +250,28 @@ public class DeviceServiceImpl implements IDeviceService {
238 } 250 }
239 int sn = (int)((Math.random()*9+1)*100000); 251 int sn = (int)((Math.random()*9+1)*100000);
240 catalogResponseMessageHandler.setChannelSyncReady(device, sn); 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 catalogResponseMessageHandler.setChannelSyncEnd(device.getDeviceId(), errorMsg); 261 catalogResponseMessageHandler.setChannelSyncEnd(device.getDeviceId(), errorMsg);
244 - }); 262 + }
245 } 263 }
246 264
247 @Override 265 @Override
248 public Device queryDevice(String deviceId) { 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 @Override 277 @Override
@@ -266,7 +291,11 @@ public class DeviceServiceImpl implements IDeviceService { @@ -266,7 +291,11 @@ public class DeviceServiceImpl implements IDeviceService {
266 if (device == null || device.getOnline() == 0) { 291 if (device == null || device.getOnline() == 0) {
267 return; 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,7 +20,10 @@ import org.slf4j.LoggerFactory;
20 import org.springframework.beans.factory.annotation.Autowired; 20 import org.springframework.beans.factory.annotation.Autowired;
21 import org.springframework.stereotype.Service; 21 import org.springframework.stereotype.Service;
22 22
  23 +import javax.sip.InvalidArgumentException;
  24 +import javax.sip.SipException;
23 import javax.sip.TimeoutEvent; 25 import javax.sip.TimeoutEvent;
  26 +import java.text.ParseException;
24 import java.util.HashMap; 27 import java.util.HashMap;
25 import java.util.List; 28 import java.util.List;
26 import java.util.Map; 29 import java.util.Map;
@@ -99,9 +102,13 @@ public class PlatformServiceImpl implements IPlatformService { @@ -99,9 +102,13 @@ public class PlatformServiceImpl implements IPlatformService {
99 if (parentPlatform.isEnable()) { 102 if (parentPlatform.isEnable()) {
100 // 保存时启用就发送注册 103 // 保存时启用就发送注册
101 // 注册成功时由程序直接调用了online方法 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 return result > 0; 113 return result > 0;
107 } 114 }
@@ -130,46 +137,62 @@ public class PlatformServiceImpl implements IPlatformService { @@ -130,46 +137,62 @@ public class PlatformServiceImpl implements IPlatformService {
130 // 添加注册任务 137 // 添加注册任务
131 dynamicTask.startDelay(registerTaskKey, 138 dynamicTask.startDelay(registerTaskKey,
132 // 注册失败(注册成功时由程序直接调用了online方法) 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 (parentPlatform.getExpires() - 10) *1000); 147 (parentPlatform.getExpires() - 10) *1000);
135 148
136 final String keepaliveTaskKey = KEEPALIVE_KEY_PREFIX + parentPlatform.getServerGBId(); 149 final String keepaliveTaskKey = KEEPALIVE_KEY_PREFIX + parentPlatform.getServerGBId();
137 if (!dynamicTask.contains(keepaliveTaskKey)) { 150 if (!dynamicTask.contains(keepaliveTaskKey)) {
138 // 添加心跳任务 151 // 添加心跳任务
139 dynamicTask.startCron(keepaliveTaskKey, 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 (parentPlatform.getKeepTimeout() - 10)*1000); 196 (parentPlatform.getKeepTimeout() - 10)*1000);
174 } 197 }
175 } 198 }
@@ -225,14 +248,18 @@ public class PlatformServiceImpl implements IPlatformService { @@ -225,14 +248,18 @@ public class PlatformServiceImpl implements IPlatformService {
225 @Override 248 @Override
226 public void login(ParentPlatform parentPlatform) { 249 public void login(ParentPlatform parentPlatform) {
227 final String registerTaskKey = REGISTER_KEY_PREFIX + parentPlatform.getServerGBId(); 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 @Override 265 @Override
@@ -259,7 +286,12 @@ public class PlatformServiceImpl implements IPlatformService { @@ -259,7 +286,12 @@ public class PlatformServiceImpl implements IPlatformService {
259 continue; 286 continue;
260 } 287 }
261 // 发送GPS消息 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,13 +2,18 @@ package com.genersoft.iot.vmp.service.impl;
2 2
3 import java.math.BigDecimal; 3 import java.math.BigDecimal;
4 import java.math.RoundingMode; 4 import java.math.RoundingMode;
  5 +import java.text.ParseException;
5 import java.util.*; 6 import java.util.*;
6 7
7 import javax.sip.InvalidArgumentException; 8 import javax.sip.InvalidArgumentException;
8 import javax.sip.ResponseEvent; 9 import javax.sip.ResponseEvent;
  10 +import javax.sip.SipException;
9 11
10 import com.genersoft.iot.vmp.gb28181.bean.*; 12 import com.genersoft.iot.vmp.gb28181.bean.*;
11 import com.genersoft.iot.vmp.conf.exception.ControllerException; 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 import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; 17 import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
13 import org.slf4j.Logger; 18 import org.slf4j.Logger;
14 import org.slf4j.LoggerFactory; 19 import org.slf4j.LoggerFactory;
@@ -118,6 +123,10 @@ public class PlayServiceImpl implements IPlayService { @@ -118,6 +123,10 @@ public class PlayServiceImpl implements IPlayService {
118 @Autowired 123 @Autowired
119 private VideoStreamSessionManager streamSession; 124 private VideoStreamSessionManager streamSession;
120 125
  126 +
  127 + @Autowired
  128 + private IDeviceService deviceService;
  129 +
121 @Autowired 130 @Autowired
122 private UserSetting userSetting; 131 private UserSetting userSetting;
123 132
@@ -289,14 +298,14 @@ public class PlayServiceImpl implements IPlayService { @@ -289,14 +298,14 @@ public class PlayServiceImpl implements IPlayService {
289 System.out.println("设置超时任务: " + timeOutTaskKey); 298 System.out.println("设置超时任务: " + timeOutTaskKey);
290 dynamicTask.startDelay( timeOutTaskKey,()->{ 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 timeoutCallback.run(0, "点播超时"); 309 timeoutCallback.run(0, "点播超时");
301 mediaServerService.releaseSsrc(mediaServerItem.getId(), finalSsrcInfo.getSsrc()); 310 mediaServerService.releaseSsrc(mediaServerItem.getId(), finalSsrcInfo.getSsrc());
302 mediaServerService.closeRTPServer(mediaServerItem, finalSsrcInfo.getStream()); 311 mediaServerService.closeRTPServer(mediaServerItem, finalSsrcInfo.getStream());
@@ -310,73 +319,87 @@ public class PlayServiceImpl implements IPlayService { @@ -310,73 +319,87 @@ public class PlayServiceImpl implements IPlayService {
310 logger.info("[点播端口分配异常],deviceId={},channelId={},ssrcInfo={}", device.getDeviceId(), channelId, ssrcInfo); 319 logger.info("[点播端口分配异常],deviceId={},channelId={},ssrcInfo={}", device.getDeviceId(), channelId, ssrcInfo);
311 return; 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 return; 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 dynamicTask.stop(timeOutTaskKey); 393 dynamicTask.stop(timeOutTaskKey);
373 mediaServerService.closeRTPServer(mediaServerItem, finalSsrcInfo.getStream()); 394 mediaServerService.closeRTPServer(mediaServerItem, finalSsrcInfo.getStream());
374 // 释放ssrc 395 // 释放ssrc
375 mediaServerService.releaseSsrc(mediaServerItem.getId(), finalSsrcInfo.getSsrc()); 396 mediaServerService.releaseSsrc(mediaServerItem.getId(), finalSsrcInfo.getSsrc());
376 397
377 streamSession.remove(device.getDeviceId(), channelId, finalSsrcInfo.getStream()); 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 @Override 405 @Override
@@ -467,17 +490,18 @@ public class PlayServiceImpl implements IPlayService { @@ -467,17 +490,18 @@ public class PlayServiceImpl implements IPlayService {
467 playBackResult.setCode(ErrorCode.ERROR100.getCode()); 490 playBackResult.setCode(ErrorCode.ERROR100.getCode());
468 playBackResult.setMsg("回放超时"); 491 playBackResult.setMsg("回放超时");
469 playBackResult.setData(requestMessage); 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 // 点播超时回复BYE 同时释放ssrc以及此次点播的资源 499 // 点播超时回复BYE 同时释放ssrc以及此次点播的资源
474 - cmder.streamByeCmd(device.getDeviceId(), channelId, ssrcInfo.getStream(), null);  
475 - }else {  
476 mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); 500 mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc());
477 mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream()); 501 mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream());
478 streamSession.remove(deviceId, channelId, ssrcInfo.getStream()); 502 streamSession.remove(deviceId, channelId, ssrcInfo.getStream());
479 } 503 }
480 - cmder.streamByeCmd(device.getDeviceId(), channelId, ssrcInfo.getStream(), null); 504 +
481 // 回复之前所有的点播请求 505 // 回复之前所有的点播请求
482 playBackCallback.call(playBackResult); 506 playBackCallback.call(playBackResult);
483 result.setResult(WVPResult.fail(ErrorCode.ERROR100.getCode(), "回放超时")); 507 result.setResult(WVPResult.fail(ErrorCode.ERROR100.getCode(), "回放超时"));
@@ -517,59 +541,67 @@ public class PlayServiceImpl implements IPlayService { @@ -517,59 +541,67 @@ public class PlayServiceImpl implements IPlayService {
517 playBackCallback.call(playBackResult); 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 return; 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 return result; 605 return result;
574 } 606 }
575 607
@@ -615,54 +647,57 @@ public class PlayServiceImpl implements IPlayService { @@ -615,54 +647,57 @@ public class PlayServiceImpl implements IPlayService {
615 downloadResult.setCode(ErrorCode.ERROR100.getCode()); 647 downloadResult.setCode(ErrorCode.ERROR100.getCode());
616 downloadResult.setMsg("录像下载请求超时"); 648 downloadResult.setMsg("录像下载请求超时");
617 hookCallBack.call(downloadResult); 649 hookCallBack.call(downloadResult);
618 - SIPDialog dialog = streamSession.getDialogByStream(deviceId, channelId, ssrcInfo.getStream()); 650 +
619 // 点播超时回复BYE 同时释放ssrc以及此次点播的资源 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 mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); 657 mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc());
625 mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream()); 658 mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream());
626 streamSession.remove(deviceId, channelId, ssrcInfo.getStream()); 659 streamSession.remove(deviceId, channelId, ssrcInfo.getStream());
627 } 660 }
628 - cmder.streamByeCmd(device.getDeviceId(), channelId, ssrcInfo.getStream(), null);  
629 // 回复之前所有的点播请求 661 // 回复之前所有的点播请求
630 hookCallBack.call(downloadResult); 662 hookCallBack.call(downloadResult);
631 }, userSetting.getPlayTimeout()); 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 hookCallBack.call(downloadResult); 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 return result; 701 return result;
667 } 702 }
668 703
@@ -741,7 +776,11 @@ public class PlayServiceImpl implements IPlayService { @@ -741,7 +776,11 @@ public class PlayServiceImpl implements IPlayService {
741 for (SendRtpItem sendRtpItem : sendRtpItems) { 776 for (SendRtpItem sendRtpItem : sendRtpItems) {
742 if (sendRtpItem.getMediaServerId().equals(mediaServerId)) { 777 if (sendRtpItem.getMediaServerId().equals(mediaServerId)) {
743 ParentPlatform platform = storager.queryParentPlatByServerGBId(sendRtpItem.getPlatformId()); 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,8 +789,17 @@ public class PlayServiceImpl implements IPlayService {
750 if (allSsrc.size() > 0) { 789 if (allSsrc.size() > 0) {
751 for (SsrcTransaction ssrcTransaction : allSsrc) { 790 for (SsrcTransaction ssrcTransaction : allSsrc) {
752 if(ssrcTransaction.getMediaServerId().equals(mediaServerId)) { 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,7 +93,6 @@ public class StreamPushUploadFileHandler extends AnalysisEventListener&lt;StreamPus
93 try { 93 try {
94 gBMap.put(streamPushExcelDto.getApp() + streamPushExcelDto.getStream(), streamPushExcelDto.getGbId()); 94 gBMap.put(streamPushExcelDto.getApp() + streamPushExcelDto.getStream(), streamPushExcelDto.getGbId());
95 }catch (IllegalArgumentException e) { 95 }catch (IllegalArgumentException e) {
96 - e.printStackTrace();  
97 errorGBList.add(streamPushExcelDto.getGbId() + "(不同的app+stream使用了相同的国标ID)"); 96 errorGBList.add(streamPushExcelDto.getGbId() + "(不同的app+stream使用了相同的国标ID)");
98 return; 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,7 +16,10 @@ import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
16 import org.springframework.stereotype.Component; 16 import org.springframework.stereotype.Component;
17 import org.springframework.util.ObjectUtils; 17 import org.springframework.util.ObjectUtils;
18 18
  19 +import javax.sip.InvalidArgumentException;
  20 +import javax.sip.SipException;
19 import javax.validation.constraints.NotNull; 21 import javax.validation.constraints.NotNull;
  22 +import java.text.ParseException;
20 import java.util.List; 23 import java.util.List;
21 import java.util.concurrent.ConcurrentLinkedQueue; 24 import java.util.concurrent.ConcurrentLinkedQueue;
22 25
@@ -78,16 +81,28 @@ public class RedisAlarmMsgListener implements MessageListener { @@ -78,16 +81,28 @@ public class RedisAlarmMsgListener implements MessageListener {
78 List<ParentPlatform> parentPlatforms = storage.queryEnableParentPlatformList(true); 81 List<ParentPlatform> parentPlatforms = storage.queryEnableParentPlatformList(true);
79 if (parentPlatforms.size() > 0) { 82 if (parentPlatforms.size() > 0) {
80 for (ParentPlatform parentPlatform : parentPlatforms) { 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 }else { 91 }else {
85 Device device = storage.queryVideoDevice(gbId); 92 Device device = storage.queryVideoDevice(gbId);
86 ParentPlatform platform = storage.queryParentPlatByServerGBId(gbId); 93 ParentPlatform platform = storage.queryParentPlatByServerGBId(gbId);
87 if (device != null && platform == null) { 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 }else if (device == null && platform != null){ 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 }else { 106 }else {
92 logger.warn("无法确定" + gbId + "是平台还是设备"); 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,7 +156,7 @@ public class RedisGbPlayMsgListener implements MessageListener {
156 try { 156 try {
157 playMsgCallback.handler(responseSendItemMsg); 157 playMsgCallback.handler(responseSendItemMsg);
158 } catch (ParseException e) { 158 } catch (ParseException e) {
159 - throw new RuntimeException(e); 159 + logger.error("[REDIS消息处理异常] ", e);
160 } 160 }
161 } 161 }
162 break; 162 break;
src/main/java/com/genersoft/iot/vmp/utils/GpsUtil.java
@@ -17,49 +17,6 @@ public class GpsUtil { @@ -17,49 +17,6 @@ public class GpsUtil {
17 public static BaiduPoint Wgs84ToBd09(String xx, String yy) { 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 double lng = Double.parseDouble(xx); 20 double lng = Double.parseDouble(xx);
64 double lat = Double.parseDouble(yy); 21 double lat = Double.parseDouble(yy);
65 Double[] gcj02 = Coordtransform.WGS84ToGCJ02(lng, lat); 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 package com.genersoft.iot.vmp.vmanager.gb28181.MobilePosition; 1 package com.genersoft.iot.vmp.vmanager.gb28181.MobilePosition;
2 2
  3 +import java.text.ParseException;
3 import java.util.List; 4 import java.util.List;
4 import java.util.UUID; 5 import java.util.UUID;
5 6
@@ -31,6 +32,9 @@ import org.springframework.web.bind.annotation.RequestParam; @@ -31,6 +32,9 @@ import org.springframework.web.bind.annotation.RequestParam;
31 import org.springframework.web.bind.annotation.RestController; 32 import org.springframework.web.bind.annotation.RestController;
32 import org.springframework.web.context.request.async.DeferredResult; 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,13 +109,18 @@ public class MobilePositionController {
105 Device device = storager.queryVideoDevice(deviceId); 109 Device device = storager.queryVideoDevice(deviceId);
106 String uuid = UUID.randomUUID().toString(); 110 String uuid = UUID.randomUUID().toString();
107 String key = DeferredResultHolder.CALLBACK_CMD_MOBILEPOSITION + deviceId; 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 DeferredResult<MobilePosition> result = new DeferredResult<MobilePosition>(5*1000L); 124 DeferredResult<MobilePosition> result = new DeferredResult<MobilePosition>(5*1000L);
116 result.onTimeout(()->{ 125 result.onTimeout(()->{
117 logger.warn(String.format("获取移动位置信息超时")); 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 +6,7 @@ import com.genersoft.iot.vmp.gb28181.bean.DeviceAlarm;
6 import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; 6 import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
7 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander; 7 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
8 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform; 8 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
  9 +import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookListener;
9 import com.genersoft.iot.vmp.service.IDeviceAlarmService; 10 import com.genersoft.iot.vmp.service.IDeviceAlarmService;
10 import com.genersoft.iot.vmp.storager.IVideoManagerStorage; 11 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
11 import com.genersoft.iot.vmp.utils.DateUtil; 12 import com.genersoft.iot.vmp.utils.DateUtil;
@@ -16,6 +17,8 @@ import io.swagger.v3.oas.annotations.Operation; @@ -16,6 +17,8 @@ import io.swagger.v3.oas.annotations.Operation;
16 import io.swagger.v3.oas.annotations.Parameter; 17 import io.swagger.v3.oas.annotations.Parameter;
17 import io.swagger.v3.oas.annotations.responses.ApiResponse; 18 import io.swagger.v3.oas.annotations.responses.ApiResponse;
18 import io.swagger.v3.oas.annotations.tags.Tag; 19 import io.swagger.v3.oas.annotations.tags.Tag;
  20 +import org.slf4j.Logger;
  21 +import org.slf4j.LoggerFactory;
19 import org.springframework.beans.factory.annotation.Autowired; 22 import org.springframework.beans.factory.annotation.Autowired;
20 import org.springframework.http.HttpStatus; 23 import org.springframework.http.HttpStatus;
21 import org.springframework.http.ResponseEntity; 24 import org.springframework.http.ResponseEntity;
@@ -23,6 +26,9 @@ import org.springframework.util.ObjectUtils; @@ -23,6 +26,9 @@ import org.springframework.util.ObjectUtils;
23 import org.springframework.util.StringUtils; 26 import org.springframework.util.StringUtils;
24 import org.springframework.web.bind.annotation.*; 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 import java.time.LocalDateTime; 32 import java.time.LocalDateTime;
27 import java.util.Arrays; 33 import java.util.Arrays;
28 import java.util.List; 34 import java.util.List;
@@ -33,6 +39,8 @@ import java.util.List; @@ -33,6 +39,8 @@ import java.util.List;
33 @RequestMapping("/api/alarm") 39 @RequestMapping("/api/alarm")
34 public class AlarmController { 40 public class AlarmController {
35 41
  42 + private final static Logger logger = LoggerFactory.getLogger(AlarmController.class);
  43 +
36 @Autowired 44 @Autowired
37 private IDeviceAlarmService deviceAlarmService; 45 private IDeviceAlarmService deviceAlarmService;
38 46
@@ -108,9 +116,19 @@ public class AlarmController { @@ -108,9 +116,19 @@ public class AlarmController {
108 deviceAlarm.setLatitude(39.33333); 116 deviceAlarm.setLatitude(39.33333);
109 117
110 if (device != null && platform == null) { 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 }else if (device == null && platform != null){ 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 }else { 132 }else {
115 throw new ControllerException(ErrorCode.ERROR100.getCode(),"无法确定" + deviceId + "是平台还是设备"); 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,12 +8,14 @@
8 package com.genersoft.iot.vmp.vmanager.gb28181.device; 8 package com.genersoft.iot.vmp.vmanager.gb28181.device;
9 9
10 import com.alibaba.fastjson.JSONObject; 10 import com.alibaba.fastjson.JSONObject;
  11 +import com.genersoft.iot.vmp.conf.exception.ControllerException;
11 import com.genersoft.iot.vmp.gb28181.bean.Device; 12 import com.genersoft.iot.vmp.gb28181.bean.Device;
12 import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; 13 import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
13 import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; 14 import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
14 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; 15 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
15 import com.genersoft.iot.vmp.storager.IVideoManagerStorage; 16 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
16 17
  18 +import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
17 import io.swagger.v3.oas.annotations.Operation; 19 import io.swagger.v3.oas.annotations.Operation;
18 import io.swagger.v3.oas.annotations.Parameter; 20 import io.swagger.v3.oas.annotations.Parameter;
19 import io.swagger.v3.oas.annotations.tags.Tag; 21 import io.swagger.v3.oas.annotations.tags.Tag;
@@ -26,6 +28,9 @@ import org.springframework.util.StringUtils; @@ -26,6 +28,9 @@ import org.springframework.util.StringUtils;
26 import org.springframework.web.bind.annotation.*; 28 import org.springframework.web.bind.annotation.*;
27 import org.springframework.web.context.request.async.DeferredResult; 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 import java.util.UUID; 34 import java.util.UUID;
30 35
31 @Tag(name = "国标设备配置") 36 @Tag(name = "国标设备配置")
@@ -75,14 +80,19 @@ public class DeviceConfig { @@ -75,14 +80,19 @@ public class DeviceConfig {
75 Device device = storager.queryVideoDevice(deviceId); 80 Device device = storager.queryVideoDevice(deviceId);
76 String uuid = UUID.randomUUID().toString(); 81 String uuid = UUID.randomUUID().toString();
77 String key = DeferredResultHolder.CALLBACK_CMD_DEVICECONFIG + deviceId + channelId; 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 result.onTimeout(() -> { 96 result.onTimeout(() -> {
87 logger.warn(String.format("设备配置操作超时, 设备未返回应答指令")); 97 logger.warn(String.format("设备配置操作超时, 设备未返回应答指令"));
88 // 释放rtpserver 98 // 释放rtpserver
@@ -121,14 +131,19 @@ public class DeviceConfig { @@ -121,14 +131,19 @@ public class DeviceConfig {
121 String key = DeferredResultHolder.CALLBACK_CMD_CONFIGDOWNLOAD + (ObjectUtils.isEmpty(channelId) ? deviceId : channelId); 131 String key = DeferredResultHolder.CALLBACK_CMD_CONFIGDOWNLOAD + (ObjectUtils.isEmpty(channelId) ? deviceId : channelId);
122 String uuid = UUID.randomUUID().toString(); 132 String uuid = UUID.randomUUID().toString();
123 Device device = storager.queryVideoDevice(deviceId); 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 result.onTimeout(()->{ 147 result.onTimeout(()->{
133 logger.warn(String.format("获取设备配置超时")); 148 logger.warn(String.format("获取设备配置超时"));
134 // 释放rtpserver 149 // 释放rtpserver
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceControl.java
@@ -29,6 +29,9 @@ import org.springframework.util.StringUtils; @@ -29,6 +29,9 @@ import org.springframework.util.StringUtils;
29 import org.springframework.web.bind.annotation.*; 29 import org.springframework.web.bind.annotation.*;
30 import org.springframework.web.context.request.async.DeferredResult; 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 import java.util.UUID; 35 import java.util.UUID;
33 36
34 @Tag(name = "国标设备控制") 37 @Tag(name = "国标设备控制")
@@ -61,10 +64,12 @@ public class DeviceControl { @@ -61,10 +64,12 @@ public class DeviceControl {
61 logger.debug("设备远程启动API调用"); 64 logger.debug("设备远程启动API调用");
62 } 65 }
63 Device device = storager.queryVideoDevice(deviceId); 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,13 +106,18 @@ public class DeviceControl {
101 return result; 106 return result;
102 } 107 }
103 resultHolder.put(key, uuid, result); 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 return result; 122 return result;
113 } 123 }
@@ -123,21 +133,26 @@ public class DeviceControl { @@ -123,21 +133,26 @@ public class DeviceControl {
123 @Parameter(name = "channelId", description = "通道国标编号", required = true) 133 @Parameter(name = "channelId", description = "通道国标编号", required = true)
124 @Parameter(name = "guardCmdStr", description = "命令, 可选值:SetGuard(布防),ResetGuard(撤防)", required = true) 134 @Parameter(name = "guardCmdStr", description = "命令, 可选值:SetGuard(布防),ResetGuard(撤防)", required = true)
125 @GetMapping("/guard/{deviceId}/{guardCmdStr}") 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 if (logger.isDebugEnabled()) { 137 if (logger.isDebugEnabled()) {
128 logger.debug("布防/撤防API调用"); 138 logger.debug("布防/撤防API调用");
129 } 139 }
130 Device device = storager.queryVideoDevice(deviceId); 140 Device device = storager.queryVideoDevice(deviceId);
131 String key = DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + deviceId + channelId; 141 String key = DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + deviceId + channelId;
132 String uuid =UUID.randomUUID().toString(); 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 resultHolder.put(key, uuid, result); 156 resultHolder.put(key, uuid, result);
142 result.onTimeout(() -> { 157 result.onTimeout(() -> {
143 logger.warn(String.format("布防/撤防操作超时, 设备未返回应答指令")); 158 logger.warn(String.format("布防/撤防操作超时, 设备未返回应答指令"));
@@ -174,14 +189,19 @@ public class DeviceControl { @@ -174,14 +189,19 @@ public class DeviceControl {
174 Device device = storager.queryVideoDevice(deviceId); 189 Device device = storager.queryVideoDevice(deviceId);
175 String uuid = UUID.randomUUID().toString(); 190 String uuid = UUID.randomUUID().toString();
176 String key = DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + deviceId + channelId; 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 result.onTimeout(() -> { 205 result.onTimeout(() -> {
186 logger.warn(String.format("报警复位操作超时, 设备未返回应答指令")); 206 logger.warn(String.format("报警复位操作超时, 设备未返回应答指令"));
187 // 释放rtpserver 207 // 释放rtpserver
@@ -205,23 +225,23 @@ public class DeviceControl { @@ -205,23 +225,23 @@ public class DeviceControl {
205 @Parameter(name = "deviceId", description = "设备国标编号", required = true) 225 @Parameter(name = "deviceId", description = "设备国标编号", required = true)
206 @Parameter(name = "channelId", description = "通道国标编号") 226 @Parameter(name = "channelId", description = "通道国标编号")
207 @GetMapping("/i_frame/{deviceId}") 227 @GetMapping("/i_frame/{deviceId}")
208 - public ResponseEntity<String> iFrame(@PathVariable String deviceId, 228 + public JSONObject iFrame(@PathVariable String deviceId,
209 @RequestParam(required = false) String channelId) { 229 @RequestParam(required = false) String channelId) {
210 if (logger.isDebugEnabled()) { 230 if (logger.isDebugEnabled()) {
211 logger.debug("强制关键帧API调用"); 231 logger.debug("强制关键帧API调用");
212 } 232 }
213 Device device = storager.queryVideoDevice(deviceId); 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,7 +260,7 @@ public class DeviceControl {
240 @Parameter(name = "presetIndex", description = "调用预置位编号") 260 @Parameter(name = "presetIndex", description = "调用预置位编号")
241 @Parameter(name = "resetTime", description = "自动归位时间间隔") 261 @Parameter(name = "resetTime", description = "自动归位时间间隔")
242 @GetMapping("/home_position/{deviceId}/{enabled}") 262 @GetMapping("/home_position/{deviceId}/{enabled}")
243 - public DeferredResult<ResponseEntity<String>> homePositionApi(@PathVariable String deviceId, 263 + public DeferredResult<String> homePositionApi(@PathVariable String deviceId,
244 @PathVariable String enabled, 264 @PathVariable String enabled,
245 @RequestParam(required = false) String resetTime, 265 @RequestParam(required = false) String resetTime,
246 @RequestParam(required = false) String presetIndex, 266 @RequestParam(required = false) String presetIndex,
@@ -251,14 +271,19 @@ public class DeviceControl { @@ -251,14 +271,19 @@ public class DeviceControl {
251 String key = DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + (ObjectUtils.isEmpty(channelId) ? deviceId : channelId); 271 String key = DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + (ObjectUtils.isEmpty(channelId) ? deviceId : channelId);
252 String uuid = UUID.randomUUID().toString(); 272 String uuid = UUID.randomUUID().toString();
253 Device device = storager.queryVideoDevice(deviceId); 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 result.onTimeout(() -> { 287 result.onTimeout(() -> {
263 logger.warn(String.format("看守位控制操作超时, 设备未返回应答指令")); 288 logger.warn(String.format("看守位控制操作超时, 设备未返回应答指令"));
264 // 释放rtpserver 289 // 释放rtpserver
@@ -297,14 +322,14 @@ public class DeviceControl { @@ -297,14 +322,14 @@ public class DeviceControl {
297 @Parameter(name = "lengthx", description = "拉框长度像素值", required = true) 322 @Parameter(name = "lengthx", description = "拉框长度像素值", required = true)
298 @Parameter(name = "lengthy", description = "lengthy", required = true) 323 @Parameter(name = "lengthy", description = "lengthy", required = true)
299 @GetMapping("drag_zoom/zoom_in") 324 @GetMapping("drag_zoom/zoom_in")
300 - public ResponseEntity<String> dragZoomIn(@RequestParam String deviceId, 325 + public void dragZoomIn(@RequestParam String deviceId,
301 @RequestParam(required = false) String channelId, 326 @RequestParam(required = false) String channelId,
302 @RequestParam int length, 327 @RequestParam int length,
303 @RequestParam int width, 328 @RequestParam int width,
304 @RequestParam int midpointx, 329 @RequestParam int midpointx,
305 @RequestParam int midpointy, 330 @RequestParam int midpointy,
306 @RequestParam int lengthx, 331 @RequestParam int lengthx,
307 - @RequestParam int lengthy){ 332 + @RequestParam int lengthy) throws RuntimeException {
308 if (logger.isDebugEnabled()) { 333 if (logger.isDebugEnabled()) {
309 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)); 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,8 +343,12 @@ public class DeviceControl {
318 cmdXml.append("<LengthX>" + lengthx+ "</LengthX>\r\n"); 343 cmdXml.append("<LengthX>" + lengthx+ "</LengthX>\r\n");
319 cmdXml.append("<LengthY>" + lengthy+ "</LengthY>\r\n"); 344 cmdXml.append("<LengthY>" + lengthy+ "</LengthY>\r\n");
320 cmdXml.append("</DragZoomIn>\r\n"); 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,7 +373,7 @@ public class DeviceControl {
344 @Parameter(name = "lengthx", description = "拉框长度像素值", required = true) 373 @Parameter(name = "lengthx", description = "拉框长度像素值", required = true)
345 @Parameter(name = "lengthy", description = "拉框宽度像素值", required = true) 374 @Parameter(name = "lengthy", description = "拉框宽度像素值", required = true)
346 @GetMapping("/drag_zoom/zoom_out") 375 @GetMapping("/drag_zoom/zoom_out")
347 - public ResponseEntity<String> dragZoomOut(@RequestParam String deviceId, 376 + public void dragZoomOut(@RequestParam String deviceId,
348 @RequestParam(required = false) String channelId, 377 @RequestParam(required = false) String channelId,
349 @RequestParam int length, 378 @RequestParam int length,
350 @RequestParam int width, 379 @RequestParam int width,
@@ -366,7 +395,11 @@ public class DeviceControl { @@ -366,7 +395,11 @@ public class DeviceControl {
366 cmdXml.append("<LengthX>" + lengthx+ "</LengthX>\r\n"); 395 cmdXml.append("<LengthX>" + lengthx+ "</LengthX>\r\n");
367 cmdXml.append("<LengthY>" + lengthy+ "</LengthY>\r\n"); 396 cmdXml.append("<LengthY>" + lengthy+ "</LengthY>\r\n");
368 cmdXml.append("</DragZoomOut>\r\n"); 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,8 +39,11 @@ import org.springframework.web.context.request.async.DeferredResult;
39 39
40 import javax.servlet.http.HttpServletResponse; 40 import javax.servlet.http.HttpServletResponse;
41 import javax.sip.DialogState; 41 import javax.sip.DialogState;
  42 +import javax.sip.InvalidArgumentException;
  43 +import javax.sip.SipException;
42 import java.io.*; 44 import java.io.*;
43 import java.nio.file.Files; 45 import java.nio.file.Files;
  46 +import java.text.ParseException;
44 import java.util.*; 47 import java.util.*;
45 48
46 @Tag(name = "国标设备查询", description = "国标设备查询") 49 @Tag(name = "国标设备查询", description = "国标设备查询")
@@ -315,13 +318,18 @@ public class DeviceQuery { @@ -315,13 +318,18 @@ public class DeviceQuery {
315 result.setResult(new ResponseEntity(String.format("设备%s不存在", deviceId),HttpStatus.OK)); 318 result.setResult(new ResponseEntity(String.format("设备%s不存在", deviceId),HttpStatus.OK));
316 return result; 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 result.onTimeout(()->{ 333 result.onTimeout(()->{
326 logger.warn(String.format("获取设备状态超时")); 334 logger.warn(String.format("获取设备状态超时"));
327 // 释放rtpserver 335 // 释放rtpserver
@@ -368,14 +376,19 @@ public class DeviceQuery { @@ -368,14 +376,19 @@ public class DeviceQuery {
368 Device device = storager.queryVideoDevice(deviceId); 376 Device device = storager.queryVideoDevice(deviceId);
369 String key = DeferredResultHolder.CALLBACK_CMD_ALARM + deviceId; 377 String key = DeferredResultHolder.CALLBACK_CMD_ALARM + deviceId;
370 String uuid = UUID.randomUUID().toString(); 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 result.onTimeout(()->{ 392 result.onTimeout(()->{
380 logger.warn(String.format("设备报警查询超时")); 393 logger.warn(String.format("设备报警查询超时"));
381 // 释放rtpserver 394 // 释放rtpserver
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/media/MediaController.java
@@ -96,7 +96,7 @@ public class MediaController { @@ -96,7 +96,7 @@ public class MediaController {
96 try { 96 try {
97 Thread.sleep(1000); 97 Thread.sleep(1000);
98 } catch (InterruptedException e) { 98 } catch (InterruptedException e) {
99 - e.printStackTrace(); 99 + logger.error("[线程休眠失败], {}", e.getMessage());
100 } 100 }
101 if (useSourceIpAsStreamIp != null && useSourceIpAsStreamIp) { 101 if (useSourceIpAsStreamIp != null && useSourceIpAsStreamIp) {
102 String host = request.getHeader("Host"); 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,6 +29,9 @@ import org.springframework.util.ObjectUtils;
29 import org.springframework.web.bind.annotation.*; 29 import org.springframework.web.bind.annotation.*;
30 import com.genersoft.iot.vmp.conf.SipConfig; 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 import java.util.List; 35 import java.util.List;
33 36
34 /** 37 /**
@@ -212,20 +215,37 @@ public class PlatformController { @@ -212,20 +215,37 @@ public class PlatformController {
212 // 保存时启用就发送注册 215 // 保存时启用就发送注册
213 if (parentPlatform.isEnable()) { 216 if (parentPlatform.isEnable()) {
214 if (parentPlatformOld != null && parentPlatformOld.isStatus()) { 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 try { 223 try {
217 Thread.sleep(500); 224 Thread.sleep(500);
218 } catch (InterruptedException e) { 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 } else { 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 } else if (parentPlatformOld != null && parentPlatformOld.isEnable() && !parentPlatform.isEnable()) { // 关闭启用时注销 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 subscribeHolder.removeAllSubscribe(parentPlatform.getServerGBId()); 250 subscribeHolder.removeAllSubscribe(parentPlatform.getServerGBId());
231 } 251 }
@@ -258,17 +278,21 @@ public class PlatformController { @@ -258,17 +278,21 @@ public class PlatformController {
258 throw new ControllerException(ErrorCode.ERROR100.getCode(), "平台不存在"); 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 boolean deleteResult = storager.deleteParentPlatform(parentPlatform); 297 boolean deleteResult = storager.deleteParentPlatform(parentPlatform);
274 storager.delCatalogByPlatformId(parentPlatform.getServerGBId()); 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,6 +3,7 @@ package com.genersoft.iot.vmp.vmanager.gb28181.play;
3 import com.alibaba.fastjson.JSONArray; 3 import com.alibaba.fastjson.JSONArray;
4 import com.genersoft.iot.vmp.common.StreamInfo; 4 import com.genersoft.iot.vmp.common.StreamInfo;
5 import com.genersoft.iot.vmp.conf.exception.ControllerException; 5 import com.genersoft.iot.vmp.conf.exception.ControllerException;
  6 +import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException;
6 import com.genersoft.iot.vmp.gb28181.bean.SsrcTransaction; 7 import com.genersoft.iot.vmp.gb28181.bean.SsrcTransaction;
7 import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; 8 import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
8 import com.genersoft.iot.vmp.gb28181.bean.Device; 9 import com.genersoft.iot.vmp.gb28181.bean.Device;
@@ -37,6 +38,9 @@ import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; @@ -37,6 +38,9 @@ import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
37 import com.genersoft.iot.vmp.storager.IVideoManagerStorage; 38 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
38 import org.springframework.web.context.request.async.DeferredResult; 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 import java.util.List; 44 import java.util.List;
41 import java.util.UUID; 45 import java.util.UUID;
42 46
@@ -107,12 +111,23 @@ public class PlayController { @@ -107,12 +111,23 @@ public class PlayController {
107 throw new ControllerException(ErrorCode.ERROR400); 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 StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channelId); 119 StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channelId);
111 if (streamInfo == null) { 120 if (streamInfo == null) {
112 throw new ControllerException(ErrorCode.ERROR100.getCode(), "点播未找到"); 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 redisCatchStorage.stopPlay(streamInfo); 131 redisCatchStorage.stopPlay(streamInfo);
117 132
118 storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId()); 133 storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId());
@@ -201,42 +216,44 @@ public class PlayController { @@ -201,42 +216,44 @@ public class PlayController {
201 @Parameter(name = "timeout", description = "推流超时时间(秒)", required = true) 216 @Parameter(name = "timeout", description = "推流超时时间(秒)", required = true)
202 @GetMapping("/broadcast/{deviceId}/{channelId}") 217 @GetMapping("/broadcast/{deviceId}/{channelId}")
203 @PostMapping("/broadcast/{deviceId}/{channelId}") 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 if (logger.isDebugEnabled()) { 220 if (logger.isDebugEnabled()) {
206 logger.debug("语音广播API调用"); 221 logger.debug("语音广播API调用");
207 } 222 }
208 Device device = storager.queryVideoDevice(deviceId); 223 Device device = storager.queryVideoDevice(deviceId);
  224 + DeferredResult<String> result = new DeferredResult<>(3 * 1000L);
209 if (device == null) { 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 if (channelId == null) { 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 if (resultHolder.exist(key, null)) { 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 if (timeout == null){ 238 if (timeout == null){
236 timeout = 30; 239 timeout = 30;
237 } 240 }
238 - DeferredResult<WVPResult<AudioBroadcastResult>> result = new DeferredResult<>(timeout.longValue()*1000 + 2000);  
239 String uuid = UUID.randomUUID().toString(); 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 result.onTimeout(()->{ 257 result.onTimeout(()->{
241 WVPResult<AudioBroadcastResult> wvpResult = new WVPResult<>(); 258 WVPResult<AudioBroadcastResult> wvpResult = new WVPResult<>();
242 wvpResult.setCode(-1); 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,6 +2,7 @@ package com.genersoft.iot.vmp.vmanager.gb28181.playback;
2 2
3 import com.genersoft.iot.vmp.common.StreamInfo; 3 import com.genersoft.iot.vmp.common.StreamInfo;
4 import com.genersoft.iot.vmp.conf.exception.ControllerException; 4 import com.genersoft.iot.vmp.conf.exception.ControllerException;
  5 +import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException;
5 import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; 6 import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
6 import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; 7 import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
7 import com.genersoft.iot.vmp.storager.IRedisCatchStorage; 8 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
@@ -21,12 +22,15 @@ import org.springframework.web.bind.annotation.PathVariable; @@ -21,12 +22,15 @@ import org.springframework.web.bind.annotation.PathVariable;
21 import org.springframework.web.bind.annotation.RequestMapping; 22 import org.springframework.web.bind.annotation.RequestMapping;
22 import org.springframework.web.bind.annotation.RestController; 23 import org.springframework.web.bind.annotation.RestController;
23 24
24 -import com.alibaba.fastjson.JSONObject;  
25 import com.genersoft.iot.vmp.gb28181.bean.Device; 25 import com.genersoft.iot.vmp.gb28181.bean.Device;
26 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; 26 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
27 import com.genersoft.iot.vmp.storager.IVideoManagerStorage; 27 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
28 import org.springframework.web.context.request.async.DeferredResult; 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 * @author lin 35 * @author lin
32 */ 36 */
@@ -92,7 +96,15 @@ public class PlaybackController { @@ -92,7 +96,15 @@ public class PlaybackController {
92 if (ObjectUtils.isEmpty(deviceId) || ObjectUtils.isEmpty(channelId) || ObjectUtils.isEmpty(stream)) { 96 if (ObjectUtils.isEmpty(deviceId) || ObjectUtils.isEmpty(channelId) || ObjectUtils.isEmpty(stream)) {
93 throw new ControllerException(ErrorCode.ERROR400); 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,7 +119,11 @@ public class PlaybackController {
107 throw new ControllerException(ErrorCode.ERROR400.getCode(), "streamId不存在"); 119 throw new ControllerException(ErrorCode.ERROR400.getCode(), "streamId不存在");
108 } 120 }
109 Device device = storager.queryVideoDevice(streamInfo.getDeviceID()); 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,7 +138,11 @@ public class PlaybackController {
122 throw new ControllerException(ErrorCode.ERROR400.getCode(), "streamId不存在"); 138 throw new ControllerException(ErrorCode.ERROR400.getCode(), "streamId不存在");
123 } 139 }
124 Device device = storager.queryVideoDevice(streamInfo.getDeviceID()); 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,7 +158,11 @@ public class PlaybackController {
138 throw new ControllerException(ErrorCode.ERROR400.getCode(), "streamId不存在"); 158 throw new ControllerException(ErrorCode.ERROR400.getCode(), "streamId不存在");
139 } 159 }
140 Device device = storager.queryVideoDevice(streamInfo.getDeviceID()); 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 @Operation(summary = "回放倍速播放") 168 @Operation(summary = "回放倍速播放")
@@ -157,6 +181,10 @@ public class PlaybackController { @@ -157,6 +181,10 @@ public class PlaybackController {
157 throw new ControllerException(ErrorCode.ERROR100.getCode(), "不支持的speed(0.25 0.5 1、2、4)"); 181 throw new ControllerException(ErrorCode.ERROR100.getCode(), "不支持的speed(0.25 0.5 1、2、4)");
158 } 182 }
159 Device device = storager.queryVideoDevice(streamInfo.getDeviceID()); 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 package com.genersoft.iot.vmp.vmanager.gb28181.ptz; 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 import io.swagger.v3.oas.annotations.Operation; 6 import io.swagger.v3.oas.annotations.Operation;
5 import io.swagger.v3.oas.annotations.Parameter; 7 import io.swagger.v3.oas.annotations.Parameter;
6 import io.swagger.v3.oas.annotations.tags.Tag; 8 import io.swagger.v3.oas.annotations.tags.Tag;
@@ -18,6 +20,9 @@ import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; @@ -18,6 +20,9 @@ import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
18 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; 20 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
19 import com.genersoft.iot.vmp.storager.IVideoManagerStorage; 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 import java.util.UUID; 26 import java.util.UUID;
22 27
23 @Tag(name = "云台控制") 28 @Tag(name = "云台控制")
@@ -98,7 +103,12 @@ public class PtzController { @@ -98,7 +103,12 @@ public class PtzController {
98 default: 103 default:
99 break; 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,7 +127,12 @@ public class PtzController {
117 } 127 }
118 Device device = storager.queryVideoDevice(deviceId); 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,13 +161,18 @@ public class PtzController {
146 return result; 161 return result;
147 } 162 }
148 resultHolder.put(key, uuid, result); 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 return result; 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,7 +3,9 @@ package com.genersoft.iot.vmp.vmanager.gb28181.record;
3 import com.alibaba.fastjson.JSONObject; 3 import com.alibaba.fastjson.JSONObject;
4 import com.genersoft.iot.vmp.common.StreamInfo; 4 import com.genersoft.iot.vmp.common.StreamInfo;
5 import com.genersoft.iot.vmp.conf.exception.ControllerException; 5 import com.genersoft.iot.vmp.conf.exception.ControllerException;
  6 +import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException;
6 import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; 7 import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
  8 +import com.genersoft.iot.vmp.service.IDeviceService;
7 import com.genersoft.iot.vmp.service.IMediaServerService; 9 import com.genersoft.iot.vmp.service.IMediaServerService;
8 import com.genersoft.iot.vmp.service.IPlayService; 10 import com.genersoft.iot.vmp.service.IPlayService;
9 import com.genersoft.iot.vmp.utils.DateUtil; 11 import com.genersoft.iot.vmp.utils.DateUtil;
@@ -31,6 +33,9 @@ import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; @@ -31,6 +33,9 @@ import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
31 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; 33 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
32 import com.genersoft.iot.vmp.storager.IVideoManagerStorage; 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 import java.time.LocalDate; 39 import java.time.LocalDate;
35 import java.util.UUID; 40 import java.util.UUID;
36 41
@@ -54,6 +59,12 @@ public class GBRecordController { @@ -54,6 +59,12 @@ public class GBRecordController {
54 @Autowired 59 @Autowired
55 private IPlayService playService; 60 private IPlayService playService;
56 61
  62 + @Autowired
  63 + private IDeviceService deviceService;
  64 +
  65 +
  66 +
  67 +
57 @Operation(summary = "录像查询") 68 @Operation(summary = "录像查询")
58 @Parameter(name = "deviceId", description = "设备国标编号", required = true) 69 @Parameter(name = "deviceId", description = "设备国标编号", required = true)
59 @Parameter(name = "channelId", description = "通道国标编号", required = true) 70 @Parameter(name = "channelId", description = "通道国标编号", required = true)
@@ -81,13 +92,18 @@ public class GBRecordController { @@ -81,13 +92,18 @@ public class GBRecordController {
81 RequestMessage msg = new RequestMessage(); 92 RequestMessage msg = new RequestMessage();
82 msg.setId(uuid); 93 msg.setId(uuid);
83 msg.setKey(key); 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 // 录像查询以channelId作为deviceId查询 108 // 录像查询以channelId作为deviceId查询
93 resultHolder.put(key, uuid, result); 109 resultHolder.put(key, uuid, result);
@@ -131,14 +147,24 @@ public class GBRecordController { @@ -131,14 +147,24 @@ public class GBRecordController {
131 @GetMapping("/download/stop/{deviceId}/{channelId}/{stream}") 147 @GetMapping("/download/stop/{deviceId}/{channelId}/{stream}")
132 public void playStop(@PathVariable String deviceId, @PathVariable String channelId, @PathVariable String stream) { 148 public void playStop(@PathVariable String deviceId, @PathVariable String channelId, @PathVariable String stream) {
133 149
134 - cmder.streamByeCmd(deviceId, channelId, stream, null);  
135 -  
136 if (logger.isDebugEnabled()) { 150 if (logger.isDebugEnabled()) {
137 logger.debug(String.format("设备历史媒体下载停止 API调用,deviceId/channelId:%s_%s", deviceId, channelId)); 151 logger.debug(String.format("设备历史媒体下载停止 API调用,deviceId/channelId:%s_%s", deviceId, channelId));
138 } 152 }
139 153
140 if (deviceId == null || channelId == null) { 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 package com.genersoft.iot.vmp.web.gb28181; 1 package com.genersoft.iot.vmp.web.gb28181;
2 2
3 import com.alibaba.fastjson.JSONObject; 3 import com.alibaba.fastjson.JSONObject;
  4 +import com.genersoft.iot.vmp.conf.exception.ControllerException;
4 import com.genersoft.iot.vmp.gb28181.bean.Device; 5 import com.genersoft.iot.vmp.gb28181.bean.Device;
5 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; 6 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
6 import com.genersoft.iot.vmp.storager.IVideoManagerStorage; 7 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
  8 +import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
7 import org.slf4j.Logger; 9 import org.slf4j.Logger;
8 import org.slf4j.LoggerFactory; 10 import org.slf4j.LoggerFactory;
9 import org.springframework.beans.factory.annotation.Autowired; 11 import org.springframework.beans.factory.annotation.Autowired;
10 import org.springframework.web.bind.annotation.*; 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 * API兼容:设备控制 19 * API兼容:设备控制
14 */ 20 */
@@ -35,7 +41,7 @@ public class ApiControlController { @@ -35,7 +41,7 @@ public class ApiControlController {
35 * @return 41 * @return
36 */ 42 */
37 @RequestMapping(value = "/ptz") 43 @RequestMapping(value = "/ptz")
38 - private JSONObject list(String serial,String command, 44 + private void list(String serial,String command,
39 @RequestParam(required = false)Integer channel, 45 @RequestParam(required = false)Integer channel,
40 @RequestParam(required = false)String code, 46 @RequestParam(required = false)String code,
41 @RequestParam(required = false)Integer speed){ 47 @RequestParam(required = false)Integer speed){
@@ -48,9 +54,7 @@ public class ApiControlController { @@ -48,9 +54,7 @@ public class ApiControlController {
48 if (speed == null) {speed = 0;} 54 if (speed == null) {speed = 0;}
49 Device device = storager.queryVideoDevice(serial); 55 Device device = storager.queryVideoDevice(serial);
50 if (device == null) { 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 int cmdCode = 0; 59 int cmdCode = 0;
56 switch (command){ 60 switch (command){
@@ -91,7 +95,11 @@ public class ApiControlController { @@ -91,7 +95,11 @@ public class ApiControlController {
91 break; 95 break;
92 } 96 }
93 // 默认值 50 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,10 +3,12 @@ package com.genersoft.iot.vmp.web.gb28181;
3 import com.alibaba.fastjson.JSONObject; 3 import com.alibaba.fastjson.JSONObject;
4 import com.genersoft.iot.vmp.common.StreamInfo; 4 import com.genersoft.iot.vmp.common.StreamInfo;
5 import com.genersoft.iot.vmp.conf.UserSetting; 5 import com.genersoft.iot.vmp.conf.UserSetting;
  6 +import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException;
6 import com.genersoft.iot.vmp.gb28181.bean.Device; 7 import com.genersoft.iot.vmp.gb28181.bean.Device;
7 import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; 8 import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
8 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; 9 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
9 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; 10 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
  11 +import com.genersoft.iot.vmp.service.IDeviceService;
10 import com.genersoft.iot.vmp.service.IPlayService; 12 import com.genersoft.iot.vmp.service.IPlayService;
11 import com.genersoft.iot.vmp.storager.IRedisCatchStorage; 13 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
12 import com.genersoft.iot.vmp.storager.IVideoManagerStorage; 14 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
@@ -17,6 +19,10 @@ import org.springframework.beans.factory.annotation.Autowired; @@ -17,6 +19,10 @@ import org.springframework.beans.factory.annotation.Autowired;
17 import org.springframework.web.bind.annotation.*; 19 import org.springframework.web.bind.annotation.*;
18 import org.springframework.web.context.request.async.DeferredResult; 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 * API兼容:实时直播 27 * API兼容:实时直播
22 */ 28 */
@@ -41,6 +47,9 @@ public class ApiStreamController { @@ -41,6 +47,9 @@ public class ApiStreamController {
41 private IRedisCatchStorage redisCatchStorage; 47 private IRedisCatchStorage redisCatchStorage;
42 48
43 @Autowired 49 @Autowired
  50 + private IDeviceService deviceService;
  51 +
  52 + @Autowired
44 private IPlayService playService; 53 private IPlayService playService;
45 54
46 /** 55 /**
@@ -74,10 +83,12 @@ public class ApiStreamController { @@ -74,10 +83,12 @@ public class ApiStreamController {
74 JSONObject result = new JSONObject(); 83 JSONObject result = new JSONObject();
75 result.put("error","device[ " + serial + " ]未找到"); 84 result.put("error","device[ " + serial + " ]未找到");
76 resultDeferredResult.setResult(result); 85 resultDeferredResult.setResult(result);
  86 + return resultDeferredResult;
77 }else if (device.getOnline() == 0) { 87 }else if (device.getOnline() == 0) {
78 JSONObject result = new JSONObject(); 88 JSONObject result = new JSONObject();
79 result.put("error","device[ " + code + " ]offline"); 89 result.put("error","device[ " + code + " ]offline");
80 resultDeferredResult.setResult(result); 90 resultDeferredResult.setResult(result);
  91 + return resultDeferredResult;
81 } 92 }
82 resultDeferredResult.onTimeout(()->{ 93 resultDeferredResult.onTimeout(()->{
83 logger.info("播放等待超时"); 94 logger.info("播放等待超时");
@@ -93,10 +104,12 @@ public class ApiStreamController { @@ -93,10 +104,12 @@ public class ApiStreamController {
93 JSONObject result = new JSONObject(); 104 JSONObject result = new JSONObject();
94 result.put("error","channel[ " + code + " ]未找到"); 105 result.put("error","channel[ " + code + " ]未找到");
95 resultDeferredResult.setResult(result); 106 resultDeferredResult.setResult(result);
  107 + return resultDeferredResult;
96 }else if (deviceChannel.getStatus() == 0) { 108 }else if (deviceChannel.getStatus() == 0) {
97 JSONObject result = new JSONObject(); 109 JSONObject result = new JSONObject();
98 result.put("error","channel[ " + code + " ]offline"); 110 result.put("error","channel[ " + code + " ]offline");
99 resultDeferredResult.setResult(result); 111 resultDeferredResult.setResult(result);
  112 + return resultDeferredResult;
100 } 113 }
101 MediaServerItem newMediaServerItem = playService.getNewMediaServerItem(device); 114 MediaServerItem newMediaServerItem = playService.getNewMediaServerItem(device);
102 PlayResult play = playService.play(newMediaServerItem, serial, code, (mediaServerItem, response)->{ 115 PlayResult play = playService.play(newMediaServerItem, serial, code, (mediaServerItem, response)->{
@@ -134,18 +147,6 @@ public class ApiStreamController { @@ -134,18 +147,6 @@ public class ApiStreamController {
134 result.put("RelaySize", ""); 147 result.put("RelaySize", "");
135 result.put("ChannelPTZType", "0"); 148 result.put("ChannelPTZType", "0");
136 resultDeferredResult.setResult(result); 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 }, (eventResult) -> { 150 }, (eventResult) -> {
150 JSONObject result = new JSONObject(); 151 JSONObject result = new JSONObject();
151 result.put("error", "channel[ " + code + " ] " + eventResult.msg); 152 result.put("error", "channel[ " + code + " ] " + eventResult.msg);
@@ -177,7 +178,19 @@ public class ApiStreamController { @@ -177,7 +178,19 @@ public class ApiStreamController {
177 result.put("error","未找到流信息"); 178 result.put("error","未找到流信息");
178 return result; 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 redisCatchStorage.stopPlay(streamInfo); 194 redisCatchStorage.stopPlay(streamInfo);
182 storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId()); 195 storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId());
183 return null; 196 return null;