Commit d7355a671bc749ad3e5e4f56f09264285f369f32

Authored by 648540858
Committed by GitHub
2 parents a574ff09 2ea1bc8a

Merge pull request #625 from 648540858/wvp-dialog

强化对与不通设备的兼容能力
Showing 74 changed files with 3175 additions and 3430 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;
@@ -9,6 +10,11 @@ import com.genersoft.iot.vmp.service.bean.SSRCInfo; @@ -9,6 +10,11 @@ import com.genersoft.iot.vmp.service.bean.SSRCInfo;
9 import gov.nist.javax.sip.message.SIPRequest; 10 import gov.nist.javax.sip.message.SIPRequest;
10 11
11 import javax.sip.Dialog; 12 import javax.sip.Dialog;
  13 +import javax.sip.InvalidArgumentException;
  14 +import javax.sip.PeerUnavailableException;
  15 +import javax.sip.SipException;
  16 +import javax.sip.message.Request;
  17 +import java.text.ParseException;
12 18
13 /** 19 /**
14 * @description:设备能力接口,用于定义设备的控制、查询能力 20 * @description:设备能力接口,用于定义设备的控制、查询能力
@@ -25,7 +31,7 @@ public interface ISIPCommander { @@ -25,7 +31,7 @@ public interface ISIPCommander {
25 * @param leftRight 镜头左移右移 0:停止 1:左移 2:右移 31 * @param leftRight 镜头左移右移 0:停止 1:左移 2:右移
26 * @param upDown 镜头上移下移 0:停止 1:上移 2:下移 32 * @param upDown 镜头上移下移 0:停止 1:上移 2:下移
27 */ 33 */
28 - boolean ptzdirectCmd(Device device,String channelId,int leftRight, int upDown); 34 + void ptzdirectCmd(Device device,String channelId,int leftRight, int upDown) throws InvalidArgumentException, ParseException, SipException;
29 35
30 /** 36 /**
31 * 云台方向放控制 37 * 云台方向放控制
@@ -36,7 +42,7 @@ public interface ISIPCommander { @@ -36,7 +42,7 @@ public interface ISIPCommander {
36 * @param upDown 镜头上移下移 0:停止 1:上移 2:下移 42 * @param upDown 镜头上移下移 0:停止 1:上移 2:下移
37 * @param moveSpeed 镜头移动速度 43 * @param moveSpeed 镜头移动速度
38 */ 44 */
39 - boolean ptzdirectCmd(Device device,String channelId,int leftRight, int upDown, int moveSpeed); 45 + void ptzdirectCmd(Device device,String channelId,int leftRight, int upDown, int moveSpeed) throws InvalidArgumentException, ParseException, SipException;
40 46
41 /** 47 /**
42 * 云台缩放控制,使用配置文件中的默认镜头缩放速度 48 * 云台缩放控制,使用配置文件中的默认镜头缩放速度
@@ -45,7 +51,7 @@ public interface ISIPCommander { @@ -45,7 +51,7 @@ public interface ISIPCommander {
45 * @param channelId 预览通道 51 * @param channelId 预览通道
46 * @param inOut 镜头放大缩小 0:停止 1:缩小 2:放大 52 * @param inOut 镜头放大缩小 0:停止 1:缩小 2:放大
47 */ 53 */
48 - boolean ptzZoomCmd(Device device,String channelId,int inOut); 54 + void ptzZoomCmd(Device device,String channelId,int inOut) throws InvalidArgumentException, ParseException, SipException;
49 55
50 /** 56 /**
51 * 云台缩放控制 57 * 云台缩放控制
@@ -54,7 +60,7 @@ public interface ISIPCommander { @@ -54,7 +60,7 @@ public interface ISIPCommander {
54 * @param channelId 预览通道 60 * @param channelId 预览通道
55 * @param inOut 镜头放大缩小 0:停止 1:缩小 2:放大 61 * @param inOut 镜头放大缩小 0:停止 1:缩小 2:放大
56 */ 62 */
57 - boolean ptzZoomCmd(Device device,String channelId,int inOut, int moveSpeed); 63 + void ptzZoomCmd(Device device,String channelId,int inOut, int moveSpeed) throws InvalidArgumentException, ParseException, SipException;
58 64
59 /** 65 /**
60 * 云台控制,支持方向与缩放控制 66 * 云台控制,支持方向与缩放控制
@@ -67,7 +73,7 @@ public interface ISIPCommander { @@ -67,7 +73,7 @@ public interface ISIPCommander {
67 * @param moveSpeed 镜头移动速度 73 * @param moveSpeed 镜头移动速度
68 * @param zoomSpeed 镜头缩放速度 74 * @param zoomSpeed 镜头缩放速度
69 */ 75 */
70 - boolean ptzCmd(Device device,String channelId,int leftRight, int upDown, int inOut, int moveSpeed, int zoomSpeed); 76 + void ptzCmd(Device device,String channelId,int leftRight, int upDown, int inOut, int moveSpeed, int zoomSpeed) throws InvalidArgumentException, SipException, ParseException;
71 77
72 /** 78 /**
73 * 前端控制,包括PTZ指令、FI指令、预置位指令、巡航指令、扫描指令和辅助开关指令 79 * 前端控制,包括PTZ指令、FI指令、预置位指令、巡航指令、扫描指令和辅助开关指令
@@ -79,7 +85,7 @@ public interface ISIPCommander { @@ -79,7 +85,7 @@ public interface ISIPCommander {
79 * @param parameter2 数据2 85 * @param parameter2 数据2
80 * @param combineCode2 组合码2 86 * @param combineCode2 组合码2
81 */ 87 */
82 - boolean frontEndCmd(Device device, String channelId, int cmdCode, int parameter1, int parameter2, int combineCode2); 88 + void frontEndCmd(Device device, String channelId, int cmdCode, int parameter1, int parameter2, int combineCode2) throws SipException, InvalidArgumentException, ParseException;
83 89
84 /** 90 /**
85 * 前端控制指令(用于转发上级指令) 91 * 前端控制指令(用于转发上级指令)
@@ -87,14 +93,14 @@ public interface ISIPCommander { @@ -87,14 +93,14 @@ public interface ISIPCommander {
87 * @param channelId 预览通道 93 * @param channelId 预览通道
88 * @param cmdString 前端控制指令串 94 * @param cmdString 前端控制指令串
89 */ 95 */
90 - boolean fronEndCmd(Device device, String channelId, String cmdString, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent); 96 + void fronEndCmd(Device device, String channelId, String cmdString, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException;
91 97
92 /** 98 /**
93 * 请求预览视频流 99 * 请求预览视频流
94 * @param device 视频设备 100 * @param device 视频设备
95 * @param channelId 预览通道 101 * @param channelId 预览通道
96 */ 102 */
97 - void playStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, ZlmHttpHookSubscribe.Event event, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent); 103 + void playStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, ZlmHttpHookSubscribe.Event event, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
98 104
99 /** 105 /**
100 * 请求回放视频流 106 * 请求回放视频流
@@ -104,7 +110,7 @@ public interface ISIPCommander { @@ -104,7 +110,7 @@ public interface ISIPCommander {
104 * @param startTime 开始时间,格式要求:yyyy-MM-dd HH:mm:ss 110 * @param startTime 开始时间,格式要求:yyyy-MM-dd HH:mm:ss
105 * @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss 111 * @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss
106 */ 112 */
107 - void playbackStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInf, Device device, String channelId, String startTime, String endTime,InviteStreamCallback inviteStreamCallback, InviteStreamCallback event, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent); 113 + 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;
108 114
109 /** 115 /**
110 * 请求历史媒体下载 116 * 请求历史媒体下载
@@ -117,33 +123,33 @@ public interface ISIPCommander { @@ -117,33 +123,33 @@ public interface ISIPCommander {
117 */ 123 */
118 void downloadStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, 124 void downloadStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId,
119 String startTime, String endTime, int downloadSpeed, InviteStreamCallback inviteStreamCallback, InviteStreamCallback hookEvent, 125 String startTime, String endTime, int downloadSpeed, InviteStreamCallback inviteStreamCallback, InviteStreamCallback hookEvent,
120 - SipSubscribe.Event errorEvent); 126 + SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
121 127
122 /** 128 /**
123 * 视频流停止 129 * 视频流停止
124 */ 130 */
125 - void streamByeCmd(String deviceId, String channelId, String stream, String callId, SipSubscribe.Event okEvent);  
126 - void streamByeCmd(String deviceId, String channelId, String stream, String callId); 131 + void streamByeCmd(Device device, String channelId, String stream, String callId, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException, SsrcTransactionNotFoundException;
  132 + void streamByeCmd(Device device, String channelId, String stream, String callId) throws InvalidArgumentException, ParseException, SipException, SsrcTransactionNotFoundException;
127 133
128 /** 134 /**
129 * 回放暂停 135 * 回放暂停
130 */ 136 */
131 - void playPauseCmd(Device device, StreamInfo streamInfo); 137 + void playPauseCmd(Device device, StreamInfo streamInfo) throws InvalidArgumentException, ParseException, SipException;
132 138
133 /** 139 /**
134 * 回放恢复 140 * 回放恢复
135 */ 141 */
136 - void playResumeCmd(Device device, StreamInfo streamInfo); 142 + void playResumeCmd(Device device, StreamInfo streamInfo) throws InvalidArgumentException, ParseException, SipException;
137 143
138 /** 144 /**
139 * 回放拖动播放 145 * 回放拖动播放
140 */ 146 */
141 - void playSeekCmd(Device device, StreamInfo streamInfo, long seekTime); 147 + void playSeekCmd(Device device, StreamInfo streamInfo, long seekTime) throws InvalidArgumentException, ParseException, SipException;
142 148
143 /** 149 /**
144 * 回放倍速播放 150 * 回放倍速播放
145 */ 151 */
146 - void playSpeedCmd(Device device, StreamInfo streamInfo, Double speed); 152 + void playSpeedCmd(Device device, StreamInfo streamInfo, Double speed) throws InvalidArgumentException, ParseException, SipException;
147 153
148 /** 154 /**
149 * 回放控制 155 * 回放控制
@@ -151,23 +157,24 @@ public interface ISIPCommander { @@ -151,23 +157,24 @@ public interface ISIPCommander {
151 * @param streamInfo 157 * @param streamInfo
152 * @param content 158 * @param content
153 */ 159 */
154 - void playbackControlCmd(Device device, StreamInfo streamInfo, String content,SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent); 160 + void playbackControlCmd(Device device, StreamInfo streamInfo, String content,SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) throws SipException, InvalidArgumentException, ParseException;
155 161
156 - /** 162 +
  163 + /**
157 * 语音广播 164 * 语音广播
158 * 165 *
159 * @param device 视频设备 166 * @param device 视频设备
160 * @param channelId 预览通道 167 * @param channelId 预览通道
161 */ 168 */
162 - boolean audioBroadcastCmd(Device device,String channelId); 169 + void audioBroadcastCmd(Device device,String channelId);
163 170
164 /** 171 /**
165 * 语音广播 172 * 语音广播
166 * 173 *
167 * @param device 视频设备 174 * @param device 视频设备
168 */ 175 */
169 - void audioBroadcastCmd(Device device, SipSubscribe.Event okEvent);  
170 - boolean audioBroadcastCmd(Device device); 176 + void audioBroadcastCmd(Device device, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException;
  177 + void audioBroadcastCmd(Device device) throws InvalidArgumentException, SipException, ParseException;
171 178
172 /** 179 /**
173 * 音视频录像控制 180 * 音视频录像控制
@@ -176,21 +183,21 @@ public interface ISIPCommander { @@ -176,21 +183,21 @@ public interface ISIPCommander {
176 * @param channelId 预览通道 183 * @param channelId 预览通道
177 * @param recordCmdStr 录像命令:Record / StopRecord 184 * @param recordCmdStr 录像命令:Record / StopRecord
178 */ 185 */
179 - boolean recordCmd(Device device, String channelId, String recordCmdStr, SipSubscribe.Event errorEvent); 186 + void recordCmd(Device device, String channelId, String recordCmdStr, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
180 187
181 /** 188 /**
182 * 远程启动控制命令 189 * 远程启动控制命令
183 * 190 *
184 * @param device 视频设备 191 * @param device 视频设备
185 */ 192 */
186 - boolean teleBootCmd(Device device); 193 + void teleBootCmd(Device device) throws InvalidArgumentException, SipException, ParseException;
187 194
188 /** 195 /**
189 * 报警布防/撤防命令 196 * 报警布防/撤防命令
190 * 197 *
191 * @param device 视频设备 198 * @param device 视频设备
192 */ 199 */
193 - boolean guardCmd(Device device, String guardCmdStr, SipSubscribe.Event errorEvent); 200 + void guardCmd(Device device, String guardCmdStr, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
194 201
195 /** 202 /**
196 * 报警复位命令 203 * 报警复位命令
@@ -199,7 +206,7 @@ public interface ISIPCommander { @@ -199,7 +206,7 @@ public interface ISIPCommander {
199 * @param alarmMethod 报警方式(可选) 206 * @param alarmMethod 报警方式(可选)
200 * @param alarmType 报警类型(可选) 207 * @param alarmType 报警类型(可选)
201 */ 208 */
202 - boolean alarmCmd(Device device, String alarmMethod, String alarmType, SipSubscribe.Event errorEvent); 209 + void alarmCmd(Device device, String alarmMethod, String alarmType, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
203 210
204 /** 211 /**
205 * 强制关键帧命令,设备收到此命令应立刻发送一个IDR帧 212 * 强制关键帧命令,设备收到此命令应立刻发送一个IDR帧
@@ -207,7 +214,7 @@ public interface ISIPCommander { @@ -207,7 +214,7 @@ public interface ISIPCommander {
207 * @param device 视频设备 214 * @param device 视频设备
208 * @param channelId 预览通道 215 * @param channelId 预览通道
209 */ 216 */
210 - boolean iFrameCmd(Device device, String channelId); 217 + void iFrameCmd(Device device, String channelId) throws InvalidArgumentException, SipException, ParseException;
211 218
212 /** 219 /**
213 * 看守位控制命令 220 * 看守位控制命令
@@ -217,14 +224,14 @@ public interface ISIPCommander { @@ -217,14 +224,14 @@ public interface ISIPCommander {
217 * @param resetTime 自动归位时间间隔,开启看守位时使用,单位:秒(s) 224 * @param resetTime 自动归位时间间隔,开启看守位时使用,单位:秒(s)
218 * @param presetIndex 调用预置位编号,开启看守位时使用,取值范围0~255 225 * @param presetIndex 调用预置位编号,开启看守位时使用,取值范围0~255
219 */ 226 */
220 - boolean homePositionCmd(Device device, String channelId, String enabled, String resetTime, String presetIndex, SipSubscribe.Event errorEvent); 227 + void homePositionCmd(Device device, String channelId, String enabled, String resetTime, String presetIndex, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
221 228
222 /** 229 /**
223 * 设备配置命令 230 * 设备配置命令
224 * 231 *
225 * @param device 视频设备 232 * @param device 视频设备
226 */ 233 */
227 - boolean deviceConfigCmd(Device device); 234 + void deviceConfigCmd(Device device);
228 235
229 /** 236 /**
230 * 设备配置命令:basicParam 237 * 设备配置命令:basicParam
@@ -236,14 +243,14 @@ public interface ISIPCommander { @@ -236,14 +243,14 @@ public interface ISIPCommander {
236 * @param heartBeatInterval 心跳间隔时间(可选) 243 * @param heartBeatInterval 心跳间隔时间(可选)
237 * @param heartBeatCount 心跳超时次数(可选) 244 * @param heartBeatCount 心跳超时次数(可选)
238 */ 245 */
239 - boolean deviceBasicConfigCmd(Device device, String channelId, String name, String expiration, String heartBeatInterval, String heartBeatCount, SipSubscribe.Event errorEvent); 246 + void deviceBasicConfigCmd(Device device, String channelId, String name, String expiration, String heartBeatInterval, String heartBeatCount, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
240 247
241 /** 248 /**
242 * 查询设备状态 249 * 查询设备状态
243 * 250 *
244 * @param device 视频设备 251 * @param device 视频设备
245 */ 252 */
246 - boolean deviceStatusQuery(Device device, SipSubscribe.Event errorEvent); 253 + void deviceStatusQuery(Device device, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
247 254
248 /** 255 /**
249 * 查询设备信息 256 * 查询设备信息
@@ -251,14 +258,14 @@ public interface ISIPCommander { @@ -251,14 +258,14 @@ public interface ISIPCommander {
251 * @param device 视频设备 258 * @param device 视频设备
252 * @return 259 * @return
253 */ 260 */
254 - boolean deviceInfoQuery(Device device); 261 + void deviceInfoQuery(Device device) throws InvalidArgumentException, SipException, ParseException;
255 262
256 /** 263 /**
257 * 查询目录列表 264 * 查询目录列表
258 * 265 *
259 * @param device 视频设备 266 * @param device 视频设备
260 */ 267 */
261 - boolean catalogQuery(Device device, int sn, SipSubscribe.Event errorEvent); 268 + void catalogQuery(Device device, int sn, SipSubscribe.Event errorEvent) throws SipException, InvalidArgumentException, ParseException;
262 269
263 /** 270 /**
264 * 查询录像信息 271 * 查询录像信息
@@ -268,7 +275,7 @@ public interface ISIPCommander { @@ -268,7 +275,7 @@ public interface ISIPCommander {
268 * @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss 275 * @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss
269 * @param sn 276 * @param sn
270 */ 277 */
271 - boolean recordInfoQuery(Device device, String channelId, String startTime, String endTime, int sn, Integer Secrecy, String type, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent); 278 + 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;
272 279
273 /** 280 /**
274 * 查询报警信息 281 * 查询报警信息
@@ -282,8 +289,8 @@ public interface ISIPCommander { @@ -282,8 +289,8 @@ public interface ISIPCommander {
282 * @param endTime 报警发生终止时间(可选) 289 * @param endTime 报警发生终止时间(可选)
283 * @return true = 命令发送成功 290 * @return true = 命令发送成功
284 */ 291 */
285 - boolean alarmInfoQuery(Device device, String startPriority, String endPriority, String alarmMethod,  
286 - String alarmType, String startTime, String endTime, SipSubscribe.Event errorEvent); 292 + void alarmInfoQuery(Device device, String startPriority, String endPriority, String alarmMethod,
  293 + String alarmType, String startTime, String endTime, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
287 294
288 /** 295 /**
289 * 查询设备配置 296 * 查询设备配置
@@ -292,21 +299,21 @@ public interface ISIPCommander { @@ -292,21 +299,21 @@ public interface ISIPCommander {
292 * @param channelId 通道编码(可选) 299 * @param channelId 通道编码(可选)
293 * @param configType 配置类型: 300 * @param configType 配置类型:
294 */ 301 */
295 - boolean deviceConfigQuery(Device device, String channelId, String configType, SipSubscribe.Event errorEvent); 302 + void deviceConfigQuery(Device device, String channelId, String configType, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
296 303
297 /** 304 /**
298 * 查询设备预置位置 305 * 查询设备预置位置
299 * 306 *
300 * @param device 视频设备 307 * @param device 视频设备
301 */ 308 */
302 - boolean presetQuery(Device device, String channelId, SipSubscribe.Event errorEvent); 309 + void presetQuery(Device device, String channelId, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
303 310
304 /** 311 /**
305 * 查询移动设备位置数据 312 * 查询移动设备位置数据
306 * 313 *
307 * @param device 视频设备 314 * @param device 视频设备
308 */ 315 */
309 - boolean mobilePostitionQuery(Device device, SipSubscribe.Event errorEvent); 316 + void mobilePostitionQuery(Device device, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
310 317
311 /** 318 /**
312 * 订阅、取消订阅移动位置 319 * 订阅、取消订阅移动位置
@@ -314,7 +321,7 @@ public interface ISIPCommander { @@ -314,7 +321,7 @@ public interface ISIPCommander {
314 * @param device 视频设备 321 * @param device 视频设备
315 * @return true = 命令发送成功 322 * @return true = 命令发送成功
316 */ 323 */
317 - SIPRequest mobilePositionSubscribe(Device device, SIPRequest request, SipSubscribe.Event okEvent , SipSubscribe.Event errorEvent); 324 + SIPRequest mobilePositionSubscribe(Device device, SIPRequest request, SipSubscribe.Event okEvent , SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
318 325
319 /** 326 /**
320 * 订阅、取消订阅报警信息 327 * 订阅、取消订阅报警信息
@@ -327,14 +334,14 @@ public interface ISIPCommander { @@ -327,14 +334,14 @@ public interface ISIPCommander {
327 * @param endTime 报警发生终止时间(可选) 334 * @param endTime 报警发生终止时间(可选)
328 * @return true = 命令发送成功 335 * @return true = 命令发送成功
329 */ 336 */
330 - boolean alarmSubscribe(Device device, int expires, String startPriority, String endPriority, String alarmMethod, String alarmType, String startTime, String endTime); 337 + void alarmSubscribe(Device device, int expires, String startPriority, String endPriority, String alarmMethod, String alarmType, String startTime, String endTime) throws InvalidArgumentException, SipException, ParseException;
331 338
332 /** 339 /**
333 * 订阅、取消订阅目录信息 340 * 订阅、取消订阅目录信息
334 * @param device 视频设备 341 * @param device 视频设备
335 * @return true = 命令发送成功 342 * @return true = 命令发送成功
336 */ 343 */
337 - SIPRequest catalogSubscribe(Device device, SIPRequest request, SipSubscribe.Event okEvent ,SipSubscribe.Event errorEvent); 344 + SIPRequest catalogSubscribe(Device device, SIPRequest request, SipSubscribe.Event okEvent ,SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
338 345
339 /** 346 /**
340 * 拉框控制命令 347 * 拉框控制命令
@@ -343,7 +350,7 @@ public interface ISIPCommander { @@ -343,7 +350,7 @@ public interface ISIPCommander {
343 * @param channelId 通道id 350 * @param channelId 通道id
344 * @param cmdString 前端控制指令串 351 * @param cmdString 前端控制指令串
345 */ 352 */
346 - boolean dragZoomCmd(Device device, String channelId, String cmdString); 353 + void dragZoomCmd(Device device, String channelId, String cmdString) throws InvalidArgumentException, SipException, ParseException;
347 354
348 355
349 /** 356 /**
@@ -352,5 +359,11 @@ public interface ISIPCommander { @@ -352,5 +359,11 @@ public interface ISIPCommander {
352 * @param deviceAlarm 报警信息信息 359 * @param deviceAlarm 报警信息信息
353 * @return 360 * @return
354 */ 361 */
355 - boolean sendAlarmMessage(Device device, DeviceAlarm deviceAlarm); 362 + void sendAlarmMessage(Device device, DeviceAlarm deviceAlarm) throws InvalidArgumentException, SipException, ParseException;
  363 +
  364 + void transmitRequest(String transport, Request request) throws SipException, ParseException ;
  365 +
  366 + void transmitRequest(String transport, Request request, SipSubscribe.Event errorEvent) throws SipException, ParseException;
  367 +
  368 + void transmitRequest(String transport, Request request, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent) throws SipException, ParseException;
356 } 369 }
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,1791 +45,1444 @@ import javax.sip.address.Address; @@ -41,1791 +45,1444 @@ 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.HashSet; 51 import java.util.HashSet;
47 52
48 -/**  
49 - * @description:设备能力接口,用于定义设备的控制、查询能力 53 +/**
  54 + * @description:设备能力接口,用于定义设备的控制、查询能力
50 * @author: swwheihei 55 * @author: swwheihei
51 - * @date: 2020年5月3日 下午9:22:48 56 + * @date: 2020年5月3日 下午9:22:48
52 */ 57 */
53 @Component 58 @Component
54 @DependsOn("sipLayer") 59 @DependsOn("sipLayer")
55 public class SIPCommander implements ISIPCommander { 60 public class SIPCommander implements ISIPCommander {
56 61
57 - private final Logger logger = LoggerFactory.getLogger(SIPCommander.class);  
58 -  
59 - @Autowired  
60 - private SipConfig sipConfig;  
61 -  
62 - @Autowired  
63 - private SipFactory sipFactory;  
64 -  
65 - @Autowired  
66 - private GitUtil gitUtil;  
67 -  
68 - @Autowired  
69 - @Qualifier(value="tcpSipProvider")  
70 - private SipProviderImpl tcpSipProvider;  
71 -  
72 - @Autowired  
73 - @Qualifier(value="udpSipProvider")  
74 - private SipProviderImpl udpSipProvider;  
75 -  
76 - @Autowired  
77 - private SIPRequestHeaderProvider headerProvider;  
78 -  
79 - @Autowired  
80 - private VideoStreamSessionManager streamSession;  
81 -  
82 - @Autowired  
83 - private IVideoManagerStorage storager;  
84 -  
85 - @Autowired  
86 - private IRedisCatchStorage redisCatchStorage;  
87 -  
88 - @Autowired  
89 - private UserSetting userSetting;  
90 -  
91 - @Autowired  
92 - private ZlmHttpHookSubscribe subscribe;  
93 -  
94 - @Autowired  
95 - private SipSubscribe sipSubscribe;  
96 -  
97 - @Autowired  
98 - private IMediaServerService mediaServerService;  
99 -  
100 - @Autowired  
101 - private DynamicTask dynamicTask;  
102 -  
103 -  
104 - /**  
105 - * 云台方向放控制,使用配置文件中的默认镜头移动速度  
106 - *  
107 - * @param device 控制设备  
108 - * @param channelId 预览通道  
109 - * @param leftRight 镜头左移右移 0:停止 1:左移 2:右移  
110 - * @param upDown 镜头上移下移 0:停止 1:上移 2:下移  
111 - */  
112 - @Override  
113 - public boolean ptzdirectCmd(Device device, String channelId, int leftRight, int upDown) {  
114 - return ptzCmd(device, channelId, leftRight, upDown, 0, sipConfig.getPtzSpeed(), 0);  
115 - }  
116 -  
117 - /**  
118 - * 云台方向放控制  
119 - *  
120 - * @param device 控制设备  
121 - * @param channelId 预览通道  
122 - * @param leftRight 镜头左移右移 0:停止 1:左移 2:右移  
123 - * @param upDown 镜头上移下移 0:停止 1:上移 2:下移  
124 - * @param moveSpeed 镜头移动速度  
125 - */  
126 - @Override  
127 - public boolean ptzdirectCmd(Device device, String channelId, int leftRight, int upDown, int moveSpeed) {  
128 - return ptzCmd(device, channelId, leftRight, upDown, 0, moveSpeed, 0);  
129 - }  
130 -  
131 - /**  
132 - * 云台缩放控制,使用配置文件中的默认镜头缩放速度  
133 - *  
134 - * @param device 控制设备  
135 - * @param channelId 预览通道  
136 - * @param inOut 镜头放大缩小 0:停止 1:缩小 2:放大  
137 - */  
138 - @Override  
139 - public boolean ptzZoomCmd(Device device, String channelId, int inOut) {  
140 - return ptzCmd(device, channelId, 0, 0, inOut, 0, sipConfig.getPtzSpeed());  
141 - }  
142 -  
143 - /**  
144 - * 云台缩放控制  
145 - *  
146 - * @param device 控制设备  
147 - * @param channelId 预览通道  
148 - * @param inOut 镜头放大缩小 0:停止 1:缩小 2:放大  
149 - * @param zoomSpeed 镜头缩放速度  
150 - */  
151 - @Override  
152 - public boolean ptzZoomCmd(Device device, String channelId, int inOut, int zoomSpeed) {  
153 - return ptzCmd(device, channelId, 0, 0, inOut, 0, zoomSpeed);  
154 - }  
155 -  
156 - /**  
157 - * 云台指令码计算  
158 - *  
159 - * @param leftRight 镜头左移右移 0:停止 1:左移 2:右移  
160 - * @param upDown 镜头上移下移 0:停止 1:上移 2:下移  
161 - * @param inOut 镜头放大缩小 0:停止 1:缩小 2:放大  
162 - * @param moveSpeed 镜头移动速度 默认 0XFF (0-255)  
163 - * @param zoomSpeed 镜头缩放速度 默认 0X1 (0-255)  
164 - */  
165 - public static String cmdString(int leftRight, int upDown, int inOut, int moveSpeed, int zoomSpeed) {  
166 - int cmdCode = 0;  
167 - if (leftRight == 2) {  
168 - cmdCode|=0x01; // 右移  
169 - } else if(leftRight == 1) {  
170 - cmdCode|=0x02; // 左移  
171 - }  
172 - if (upDown == 2) {  
173 - cmdCode|=0x04; // 下移  
174 - } else if(upDown == 1) {  
175 - cmdCode|=0x08; // 上移  
176 - }  
177 - if (inOut == 2) {  
178 - cmdCode |= 0x10; // 放大  
179 - } else if(inOut == 1) {  
180 - cmdCode |= 0x20; // 缩小  
181 - }  
182 - StringBuilder builder = new StringBuilder("A50F01");  
183 - String strTmp;  
184 - strTmp = String.format("%02X", cmdCode);  
185 - builder.append(strTmp, 0, 2);  
186 - strTmp = String.format("%02X", moveSpeed);  
187 - builder.append(strTmp, 0, 2);  
188 - builder.append(strTmp, 0, 2);  
189 - strTmp = String.format("%X", zoomSpeed);  
190 - builder.append(strTmp, 0, 1).append("0");  
191 - //计算校验码  
192 - int checkCode = (0XA5 + 0X0F + 0X01 + cmdCode + moveSpeed + moveSpeed + (zoomSpeed /*<< 4*/ & 0XF0)) % 0X100;  
193 - strTmp = String.format("%02X", checkCode);  
194 - builder.append(strTmp, 0, 2);  
195 - return builder.toString();  
196 -}  
197 -  
198 - /**  
199 - * 云台指令码计算  
200 - *  
201 - * @param cmdCode 指令码  
202 - * @param parameter1 数据1  
203 - * @param parameter2 数据2  
204 - * @param combineCode2 组合码2  
205 - */ 62 + private final Logger logger = LoggerFactory.getLogger(SIPCommander.class);
  63 +
  64 + @Autowired
  65 + private SipConfig sipConfig;
  66 +
  67 + @Autowired
  68 + private SipFactory sipFactory;
  69 +
  70 + @Autowired
  71 + private GitUtil gitUtil;
  72 +
  73 + @Autowired
  74 + @Qualifier(value = "tcpSipProvider")
  75 + private SipProviderImpl tcpSipProvider;
  76 +
  77 + @Autowired
  78 + @Qualifier(value = "udpSipProvider")
  79 + private SipProviderImpl udpSipProvider;
  80 +
  81 + @Autowired
  82 + private SIPRequestHeaderProvider headerProvider;
  83 +
  84 + @Autowired
  85 + private VideoStreamSessionManager streamSession;
  86 +
  87 + @Autowired
  88 + private UserSetting userSetting;
  89 +
  90 + @Autowired
  91 + private ZlmHttpHookSubscribe subscribe;
  92 +
  93 + @Autowired
  94 + private SipSubscribe sipSubscribe;
  95 +
  96 + @Autowired
  97 + private IMediaServerService mediaServerService;
  98 +
  99 +
  100 + /**
  101 + * 云台方向放控制,使用配置文件中的默认镜头移动速度
  102 + *
  103 + * @param device 控制设备
  104 + * @param channelId 预览通道
  105 + * @param leftRight 镜头左移右移 0:停止 1:左移 2:右移
  106 + * @param upDown 镜头上移下移 0:停止 1:上移 2:下移
  107 + */
  108 + @Override
  109 + public void ptzdirectCmd(Device device, String channelId, int leftRight, int upDown) throws InvalidArgumentException, ParseException, SipException {
  110 + ptzCmd(device, channelId, leftRight, upDown, 0, sipConfig.getPtzSpeed(), 0);
  111 + }
  112 +
  113 + /**
  114 + * 云台方向放控制
  115 + *
  116 + * @param device 控制设备
  117 + * @param channelId 预览通道
  118 + * @param leftRight 镜头左移右移 0:停止 1:左移 2:右移
  119 + * @param upDown 镜头上移下移 0:停止 1:上移 2:下移
  120 + * @param moveSpeed 镜头移动速度
  121 + */
  122 + @Override
  123 + public void ptzdirectCmd(Device device, String channelId, int leftRight, int upDown, int moveSpeed) throws InvalidArgumentException, ParseException, SipException {
  124 + ptzCmd(device, channelId, leftRight, upDown, 0, moveSpeed, 0);
  125 + }
  126 +
  127 + /**
  128 + * 云台缩放控制,使用配置文件中的默认镜头缩放速度
  129 + *
  130 + * @param device 控制设备
  131 + * @param channelId 预览通道
  132 + * @param inOut 镜头放大缩小 0:停止 1:缩小 2:放大
  133 + */
  134 + @Override
  135 + public void ptzZoomCmd(Device device, String channelId, int inOut) throws InvalidArgumentException, ParseException, SipException {
  136 + ptzCmd(device, channelId, 0, 0, inOut, 0, sipConfig.getPtzSpeed());
  137 + }
  138 +
  139 + /**
  140 + * 云台缩放控制
  141 + *
  142 + * @param device 控制设备
  143 + * @param channelId 预览通道
  144 + * @param inOut 镜头放大缩小 0:停止 1:缩小 2:放大
  145 + * @param zoomSpeed 镜头缩放速度
  146 + */
  147 + @Override
  148 + public void ptzZoomCmd(Device device, String channelId, int inOut, int zoomSpeed) throws InvalidArgumentException, ParseException, SipException {
  149 + ptzCmd(device, channelId, 0, 0, inOut, 0, zoomSpeed);
  150 + }
  151 +
  152 + /**
  153 + * 云台指令码计算
  154 + *
  155 + * @param cmdCode 指令码
  156 + * @param parameter1 数据1
  157 + * @param parameter2 数据2
  158 + * @param combineCode2 组合码2
  159 + */
206 public static String frontEndCmdString(int cmdCode, int parameter1, int parameter2, int combineCode2) { 160 public static String frontEndCmdString(int cmdCode, int parameter1, int parameter2, int combineCode2) {
207 - StringBuilder builder = new StringBuilder("A50F01");  
208 - String strTmp;  
209 - strTmp = String.format("%02X", cmdCode);  
210 - builder.append(strTmp, 0, 2);  
211 - strTmp = String.format("%02X", parameter1);  
212 - builder.append(strTmp, 0, 2);  
213 - strTmp = String.format("%02X", parameter2);  
214 - builder.append(strTmp, 0, 2);  
215 - strTmp = String.format("%X", combineCode2);  
216 - builder.append(strTmp, 0, 1).append("0");  
217 - //计算校验码  
218 - int checkCode = (0XA5 + 0X0F + 0X01 + cmdCode + parameter1 + parameter2 + (combineCode2 & 0XF0)) % 0X100;  
219 - strTmp = String.format("%02X", checkCode);  
220 - builder.append(strTmp, 0, 2);  
221 - return builder.toString();  
222 - }  
223 -  
224 - /**  
225 - * 云台控制,支持方向与缩放控制  
226 - *  
227 - * @param device 控制设备  
228 - * @param channelId 预览通道  
229 - * @param leftRight 镜头左移右移 0:停止 1:左移 2:右移  
230 - * @param upDown 镜头上移下移 0:停止 1:上移 2:下移  
231 - * @param inOut 镜头放大缩小 0:停止 1:缩小 2:放大  
232 - * @param moveSpeed 镜头移动速度  
233 - * @param zoomSpeed 镜头缩放速度  
234 - */  
235 - @Override  
236 - public boolean ptzCmd(Device device, String channelId, int leftRight, int upDown, int inOut, int moveSpeed,  
237 - int zoomSpeed) {  
238 - try {  
239 - String cmdStr= cmdString(leftRight, upDown, inOut, moveSpeed, zoomSpeed);  
240 - StringBuffer ptzXml = new StringBuffer(200);  
241 - String charset = device.getCharset();  
242 - ptzXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");  
243 - ptzXml.append("<Control>\r\n");  
244 - ptzXml.append("<CmdType>DeviceControl</CmdType>\r\n");  
245 - ptzXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");  
246 - ptzXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n");  
247 - ptzXml.append("<PTZCmd>" + cmdStr + "</PTZCmd>\r\n");  
248 - ptzXml.append("<Info>\r\n");  
249 - ptzXml.append("<ControlPriority>5</ControlPriority>\r\n");  
250 - ptzXml.append("</Info>\r\n");  
251 - ptzXml.append("</Control>\r\n");  
252 -  
253 - CallIdHeader callIdHeader = device.getTransport().equalsIgnoreCase("TCP") ? tcpSipProvider.getNewCallId()  
254 - : udpSipProvider.getNewCallId();  
255 -  
256 - Request request = headerProvider.createMessageRequest(device, ptzXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null, callIdHeader);  
257 -  
258 - transmitRequest(device, request);  
259 - return true;  
260 - } catch (SipException | ParseException | InvalidArgumentException e) {  
261 - e.printStackTrace();  
262 - }  
263 - return false;  
264 - }  
265 -  
266 - /**  
267 - * 前端控制,包括PTZ指令、FI指令、预置位指令、巡航指令、扫描指令和辅助开关指令  
268 - *  
269 - * @param device 控制设备  
270 - * @param channelId 预览通道  
271 - * @param cmdCode 指令码  
272 - * @param parameter1 数据1  
273 - * @param parameter2 数据2  
274 - * @param combineCode2 组合码2  
275 - */  
276 - @Override  
277 - public boolean frontEndCmd(Device device, String channelId, int cmdCode, int parameter1, int parameter2, int combineCode2) {  
278 - try {  
279 - String cmdStr= frontEndCmdString(cmdCode, parameter1, parameter2, combineCode2);  
280 - logger.debug("控制字符串:" + cmdStr);  
281 - StringBuffer ptzXml = new StringBuffer(200);  
282 - String charset = device.getCharset();  
283 - ptzXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");  
284 - ptzXml.append("<Control>\r\n");  
285 - ptzXml.append("<CmdType>DeviceControl</CmdType>\r\n");  
286 - ptzXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");  
287 - ptzXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n");  
288 - ptzXml.append("<PTZCmd>" + cmdStr + "</PTZCmd>\r\n");  
289 - ptzXml.append("<Info>\r\n");  
290 - ptzXml.append("<ControlPriority>5</ControlPriority>\r\n");  
291 - ptzXml.append("</Info>\r\n");  
292 - ptzXml.append("</Control>\r\n");  
293 -  
294 -  
295 - CallIdHeader callIdHeader = device.getTransport().equalsIgnoreCase("TCP") ? tcpSipProvider.getNewCallId()  
296 - : udpSipProvider.getNewCallId();  
297 -  
298 - Request request = headerProvider.createMessageRequest(device, ptzXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null, callIdHeader);  
299 - transmitRequest(device, request);  
300 - return true;  
301 - } catch (SipException | ParseException | InvalidArgumentException e) {  
302 - e.printStackTrace();  
303 - }  
304 - return false;  
305 - }  
306 -  
307 - /**  
308 - * 前端控制指令(用于转发上级指令)  
309 - * @param device 控制设备  
310 - * @param channelId 预览通道  
311 - * @param cmdString 前端控制指令串  
312 - */  
313 - @Override  
314 - public boolean fronEndCmd(Device device, String channelId, String cmdString, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) {  
315 - try {  
316 - StringBuffer ptzXml = new StringBuffer(200);  
317 - String charset = device.getCharset();  
318 - ptzXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");  
319 - ptzXml.append("<Control>\r\n");  
320 - ptzXml.append("<CmdType>DeviceControl</CmdType>\r\n");  
321 - ptzXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");  
322 - ptzXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n");  
323 - ptzXml.append("<PTZCmd>" + cmdString + "</PTZCmd>\r\n");  
324 - ptzXml.append("<Info>\r\n");  
325 - ptzXml.append("<ControlPriority>5</ControlPriority>\r\n");  
326 - ptzXml.append("</Info>\r\n");  
327 - ptzXml.append("</Control>\r\n");  
328 -  
329 -  
330 - CallIdHeader callIdHeader = device.getTransport().equalsIgnoreCase("TCP") ? tcpSipProvider.getNewCallId()  
331 - : udpSipProvider.getNewCallId();  
332 -  
333 - Request request = headerProvider.createMessageRequest(device, ptzXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null, callIdHeader);  
334 - transmitRequest(device, request, errorEvent, okEvent);  
335 - return true;  
336 - } catch (SipException | ParseException | InvalidArgumentException e) {  
337 - e.printStackTrace();  
338 - }  
339 - return false;  
340 - }  
341 -  
342 - /**  
343 - * 请求预览视频流  
344 - * @param device 视频设备  
345 - * @param channelId 预览通道  
346 - * @param event hook订阅  
347 - * @param errorEvent sip错误订阅  
348 - */  
349 - @Override  
350 - public void playStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId,  
351 - ZlmHttpHookSubscribe.Event event, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) {  
352 - String stream = ssrcInfo.getStream();  
353 - try {  
354 - if (device == null) {  
355 - return;  
356 - }  
357 -// String streamMode = device.getStreamMode().toUpperCase();  
358 -  
359 - logger.info("{} 分配的ZLM为: {} [{}:{}]", stream, mediaServerItem.getId(), mediaServerItem.getIp(), ssrcInfo.getPort());  
360 - HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", stream, true, "rtsp", mediaServerItem.getId());  
361 - subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, JSONObject json)->{  
362 - if (event != null) {  
363 - event.response(mediaServerItemInUse, json);  
364 - subscribe.removeSubscribe(hookSubscribe);  
365 - }  
366 - });  
367 - //  
368 - StringBuffer content = new StringBuffer(200);  
369 - content.append("v=0\r\n");  
370 - content.append("o="+ channelId+" 0 0 IN IP4 "+ mediaServerItem.getSdpIp() +"\r\n");  
371 - content.append("s=Play\r\n");  
372 - content.append("c=IN IP4 "+ mediaServerItem.getSdpIp() +"\r\n");  
373 - content.append("t=0 0\r\n");  
374 -  
375 - if (userSetting.isSeniorSdp()) {  
376 - if("TCP-PASSIVE".equalsIgnoreCase(device.getStreamMode())) {  
377 - content.append("m=video "+ ssrcInfo.getPort() +" TCP/RTP/AVP 96 126 125 99 34 98 97\r\n");  
378 - }else if ("TCP-ACTIVE".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("UDP".equalsIgnoreCase(device.getStreamMode())) {  
381 - content.append("m=video "+ ssrcInfo.getPort() +" RTP/AVP 96 126 125 99 34 98 97\r\n");  
382 - }  
383 - content.append("a=recvonly\r\n");  
384 - content.append("a=rtpmap:96 PS/90000\r\n");  
385 - content.append("a=fmtp:126 profile-level-id=42e01e\r\n");  
386 - content.append("a=rtpmap:126 H264/90000\r\n");  
387 - content.append("a=rtpmap:125 H264S/90000\r\n");  
388 - content.append("a=fmtp:125 profile-level-id=42e01e\r\n");  
389 - content.append("a=rtpmap:99 H265/90000\r\n");  
390 - content.append("a=rtpmap:98 H264/90000\r\n");  
391 - content.append("a=rtpmap:97 MPEG4/90000\r\n");  
392 - if("TCP-PASSIVE".equalsIgnoreCase(device.getStreamMode())){ // tcp被动模式  
393 - content.append("a=setup:passive\r\n");  
394 - content.append("a=connection:new\r\n");  
395 - }else if ("TCP-ACTIVE".equalsIgnoreCase(device.getStreamMode())) { // tcp主动模式  
396 - content.append("a=setup:active\r\n");  
397 - content.append("a=connection:new\r\n");  
398 - }  
399 - }else {  
400 - if("TCP-PASSIVE".equalsIgnoreCase(device.getStreamMode())) {  
401 - content.append("m=video "+ ssrcInfo.getPort() +" TCP/RTP/AVP 96 97 98 99\r\n");  
402 - }else if ("TCP-ACTIVE".equalsIgnoreCase(device.getStreamMode())) {  
403 - content.append("m=video "+ ssrcInfo.getPort() +" TCP/RTP/AVP 96 97 98 99\r\n");  
404 - }else if("UDP".equalsIgnoreCase(device.getStreamMode())) {  
405 - content.append("m=video "+ ssrcInfo.getPort() +" RTP/AVP 96 97 98 99\r\n");  
406 - }  
407 - content.append("a=recvonly\r\n");  
408 - content.append("a=rtpmap:96 PS/90000\r\n");  
409 - content.append("a=rtpmap:98 H264/90000\r\n");  
410 - content.append("a=rtpmap:97 MPEG4/90000\r\n");  
411 - content.append("a=rtpmap:99 H265/90000\r\n");  
412 - if ("TCP-PASSIVE".equalsIgnoreCase(device.getStreamMode())) { // tcp被动模式  
413 - content.append("a=setup:passive\r\n");  
414 - content.append("a=connection:new\r\n");  
415 - } else if ("TCP-ACTIVE".equalsIgnoreCase(device.getStreamMode())) { // tcp主动模式  
416 - content.append("a=setup:active\r\n");  
417 - content.append("a=connection:new\r\n");  
418 - }  
419 - }  
420 -  
421 - content.append("y="+ssrcInfo.getSsrc()+"\r\n");//ssrc  
422 - // f字段:f= v/编码格式/分辨率/帧率/码率类型/码率大小a/编码格式/码率大小/采样率 161 + StringBuilder builder = new StringBuilder("A50F01");
  162 + String strTmp;
  163 + strTmp = String.format("%02X", cmdCode);
  164 + builder.append(strTmp, 0, 2);
  165 + strTmp = String.format("%02X", parameter1);
  166 + builder.append(strTmp, 0, 2);
  167 + strTmp = String.format("%02X", parameter2);
  168 + builder.append(strTmp, 0, 2);
  169 + strTmp = String.format("%X", combineCode2);
  170 + builder.append(strTmp, 0, 1).append("0");
  171 + //计算校验码
  172 + int checkCode = (0XA5 + 0X0F + 0X01 + cmdCode + parameter1 + parameter2 + (combineCode2 & 0XF0)) % 0X100;
  173 + strTmp = String.format("%02X", checkCode);
  174 + builder.append(strTmp, 0, 2);
  175 + return builder.toString();
  176 + }
  177 +
  178 + /**
  179 + * 云台控制,支持方向与缩放控制
  180 + *
  181 + * @param device 控制设备
  182 + * @param channelId 预览通道
  183 + * @param leftRight 镜头左移右移 0:停止 1:左移 2:右移
  184 + * @param upDown 镜头上移下移 0:停止 1:上移 2:下移
  185 + * @param inOut 镜头放大缩小 0:停止 1:缩小 2:放大
  186 + * @param moveSpeed 镜头移动速度
  187 + * @param zoomSpeed 镜头缩放速度
  188 + */
  189 + @Override
  190 + public void ptzCmd(Device device, String channelId, int leftRight, int upDown, int inOut, int moveSpeed,
  191 + int zoomSpeed) throws InvalidArgumentException, SipException, ParseException {
  192 + String cmdStr = SipUtils.cmdString(leftRight, upDown, inOut, moveSpeed, zoomSpeed);
  193 + StringBuffer ptzXml = new StringBuffer(200);
  194 + String charset = device.getCharset();
  195 + ptzXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
  196 + ptzXml.append("<Control>\r\n");
  197 + ptzXml.append("<CmdType>DeviceControl</CmdType>\r\n");
  198 + ptzXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n");
  199 + ptzXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n");
  200 + ptzXml.append("<PTZCmd>" + cmdStr + "</PTZCmd>\r\n");
  201 + ptzXml.append("<Info>\r\n");
  202 + ptzXml.append("<ControlPriority>5</ControlPriority>\r\n");
  203 + ptzXml.append("</Info>\r\n");
  204 + ptzXml.append("</Control>\r\n");
  205 +
  206 + CallIdHeader callIdHeader = device.getTransport().equalsIgnoreCase("TCP") ? tcpSipProvider.getNewCallId()
  207 + : udpSipProvider.getNewCallId();
  208 +
  209 + Request request = headerProvider.createMessageRequest(device, ptzXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null, callIdHeader);
  210 +
  211 + transmitRequest(device.getTransport(), request);
  212 + }
  213 +
  214 + /**
  215 + * 前端控制,包括PTZ指令、FI指令、预置位指令、巡航指令、扫描指令和辅助开关指令
  216 + *
  217 + * @param device 控制设备
  218 + * @param channelId 预览通道
  219 + * @param cmdCode 指令码
  220 + * @param parameter1 数据1
  221 + * @param parameter2 数据2
  222 + * @param combineCode2 组合码2
  223 + */
  224 + @Override
  225 + public void frontEndCmd(Device device, String channelId, int cmdCode, int parameter1, int parameter2, int combineCode2) throws SipException, InvalidArgumentException, ParseException {
  226 +
  227 + String cmdStr = frontEndCmdString(cmdCode, parameter1, parameter2, combineCode2);
  228 + StringBuffer ptzXml = new StringBuffer(200);
  229 + String charset = device.getCharset();
  230 + ptzXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
  231 + ptzXml.append("<Control>\r\n");
  232 + ptzXml.append("<CmdType>DeviceControl</CmdType>\r\n");
  233 + ptzXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n");
  234 + ptzXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n");
  235 + ptzXml.append("<PTZCmd>" + cmdStr + "</PTZCmd>\r\n");
  236 + ptzXml.append("<Info>\r\n");
  237 + ptzXml.append("<ControlPriority>5</ControlPriority>\r\n");
  238 + ptzXml.append("</Info>\r\n");
  239 + ptzXml.append("</Control>\r\n");
  240 +
  241 +
  242 + CallIdHeader callIdHeader = device.getTransport().equalsIgnoreCase("TCP") ? tcpSipProvider.getNewCallId()
  243 + : udpSipProvider.getNewCallId();
  244 +
  245 + SIPRequest request = (SIPRequest) headerProvider.createMessageRequest(device, ptzXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null, callIdHeader);
  246 + transmitRequest(device.getTransport(), request);
  247 +
  248 + }
  249 +
  250 + /**
  251 + * 前端控制指令(用于转发上级指令)
  252 + *
  253 + * @param device 控制设备
  254 + * @param channelId 预览通道
  255 + * @param cmdString 前端控制指令串
  256 + */
  257 + @Override
  258 + public void fronEndCmd(Device device, String channelId, String cmdString, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException {
  259 +
  260 + StringBuffer ptzXml = new StringBuffer(200);
  261 + String charset = device.getCharset();
  262 + ptzXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
  263 + ptzXml.append("<Control>\r\n");
  264 + ptzXml.append("<CmdType>DeviceControl</CmdType>\r\n");
  265 + ptzXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n");
  266 + ptzXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n");
  267 + ptzXml.append("<PTZCmd>" + cmdString + "</PTZCmd>\r\n");
  268 + ptzXml.append("<Info>\r\n");
  269 + ptzXml.append("<ControlPriority>5</ControlPriority>\r\n");
  270 + ptzXml.append("</Info>\r\n");
  271 + ptzXml.append("</Control>\r\n");
  272 +
  273 +
  274 + CallIdHeader callIdHeader = device.getTransport().equalsIgnoreCase("TCP") ? tcpSipProvider.getNewCallId()
  275 + : udpSipProvider.getNewCallId();
  276 +
  277 + Request request = headerProvider.createMessageRequest(device, ptzXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null, callIdHeader);
  278 + transmitRequest(device.getTransport(), request, errorEvent, okEvent);
  279 +
  280 + }
  281 +
  282 + /**
  283 + * 请求预览视频流
  284 + *
  285 + * @param device 视频设备
  286 + * @param channelId 预览通道
  287 + * @param event hook订阅
  288 + * @param errorEvent sip错误订阅
  289 + */
  290 + @Override
  291 + public void playStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId,
  292 + ZlmHttpHookSubscribe.Event event, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException {
  293 + String stream = ssrcInfo.getStream();
  294 +
  295 + if (device == null) {
  296 + return;
  297 + }
  298 +
  299 + logger.info("{} 分配的ZLM为: {} [{}:{}]", stream, mediaServerItem.getId(), mediaServerItem.getIp(), ssrcInfo.getPort());
  300 + HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", stream, true, "rtsp", mediaServerItem.getId());
  301 + subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, JSONObject json) -> {
  302 + if (event != null) {
  303 + event.response(mediaServerItemInUse, json);
  304 + subscribe.removeSubscribe(hookSubscribe);
  305 + }
  306 + });
  307 + //
  308 + StringBuffer content = new StringBuffer(200);
  309 + content.append("v=0\r\n");
  310 + content.append("o=" + channelId + " 0 0 IN IP4 " + mediaServerItem.getSdpIp() + "\r\n");
  311 + content.append("s=Play\r\n");
  312 + content.append("c=IN IP4 " + mediaServerItem.getSdpIp() + "\r\n");
  313 + content.append("t=0 0\r\n");
  314 +
  315 + if (userSetting.isSeniorSdp()) {
  316 + if ("TCP-PASSIVE".equalsIgnoreCase(device.getStreamMode())) {
  317 + content.append("m=video " + ssrcInfo.getPort() + " TCP/RTP/AVP 96 126 125 99 34 98 97\r\n");
  318 + } else if ("TCP-ACTIVE".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 ("UDP".equalsIgnoreCase(device.getStreamMode())) {
  321 + content.append("m=video " + ssrcInfo.getPort() + " RTP/AVP 96 126 125 99 34 98 97\r\n");
  322 + }
  323 + content.append("a=recvonly\r\n");
  324 + content.append("a=rtpmap:96 PS/90000\r\n");
  325 + content.append("a=fmtp:126 profile-level-id=42e01e\r\n");
  326 + content.append("a=rtpmap:126 H264/90000\r\n");
  327 + content.append("a=rtpmap:125 H264S/90000\r\n");
  328 + content.append("a=fmtp:125 profile-level-id=42e01e\r\n");
  329 + content.append("a=rtpmap:99 H265/90000\r\n");
  330 + content.append("a=rtpmap:98 H264/90000\r\n");
  331 + content.append("a=rtpmap:97 MPEG4/90000\r\n");
  332 + if ("TCP-PASSIVE".equalsIgnoreCase(device.getStreamMode())) { // tcp被动模式
  333 + content.append("a=setup:passive\r\n");
  334 + content.append("a=connection:new\r\n");
  335 + } else if ("TCP-ACTIVE".equalsIgnoreCase(device.getStreamMode())) { // tcp主动模式
  336 + content.append("a=setup:active\r\n");
  337 + content.append("a=connection:new\r\n");
  338 + }
  339 + } else {
  340 + if ("TCP-PASSIVE".equalsIgnoreCase(device.getStreamMode())) {
  341 + content.append("m=video " + ssrcInfo.getPort() + " TCP/RTP/AVP 96 97 98 99\r\n");
  342 + } else if ("TCP-ACTIVE".equalsIgnoreCase(device.getStreamMode())) {
  343 + content.append("m=video " + ssrcInfo.getPort() + " TCP/RTP/AVP 96 97 98 99\r\n");
  344 + } else if ("UDP".equalsIgnoreCase(device.getStreamMode())) {
  345 + content.append("m=video " + ssrcInfo.getPort() + " RTP/AVP 96 97 98 99\r\n");
  346 + }
  347 + content.append("a=recvonly\r\n");
  348 + content.append("a=rtpmap:96 PS/90000\r\n");
  349 + content.append("a=rtpmap:98 H264/90000\r\n");
  350 + content.append("a=rtpmap:97 MPEG4/90000\r\n");
  351 + content.append("a=rtpmap:99 H265/90000\r\n");
  352 + if ("TCP-PASSIVE".equalsIgnoreCase(device.getStreamMode())) { // tcp被动模式
  353 + content.append("a=setup:passive\r\n");
  354 + content.append("a=connection:new\r\n");
  355 + } else if ("TCP-ACTIVE".equalsIgnoreCase(device.getStreamMode())) { // tcp主动模式
  356 + content.append("a=setup:active\r\n");
  357 + content.append("a=connection:new\r\n");
  358 + }
  359 + }
  360 +
  361 + content.append("y=" + ssrcInfo.getSsrc() + "\r\n");//ssrc
  362 + // f字段:f= v/编码格式/分辨率/帧率/码率类型/码率大小a/编码格式/码率大小/采样率
423 // content.append("f=v/2/5/25/1/4000a/1/8/1" + "\r\n"); // 未发现支持此特性的设备 363 // content.append("f=v/2/5/25/1/4000a/1/8/1" + "\r\n"); // 未发现支持此特性的设备
424 364
425 - CallIdHeader callIdHeader = device.getTransport().equalsIgnoreCase("TCP") ? tcpSipProvider.getNewCallId()  
426 - : udpSipProvider.getNewCallId();  
427 -  
428 - Request request = headerProvider.createInviteRequest(device, channelId, content.toString(), null, SipUtils.getNewFromTag(), null, ssrcInfo.getSsrc(), callIdHeader);  
429 -  
430 - transmitRequest(device, request, (e -> {  
431 - streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream());  
432 - mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc());  
433 - errorEvent.response(e);  
434 - }), e ->{  
435 - // 这里为例避免一个通道的点播只有一个callID这个参数使用一个固定值  
436 - streamSession.put(device.getDeviceId(), channelId ,"play", stream, ssrcInfo.getSsrc(), mediaServerItem.getId(), ((ResponseEvent)e.event).getClientTransaction(), VideoStreamSessionManager.SessionType.play);  
437 - Dialog sipDialog = null;  
438 - if (e.dialog == null) {  
439 - SIPClientTransaction clientTransaction = (SIPClientTransaction)((ResponseEvent)e.event).getClientTransaction();  
440 - sipDialog = new SIPDialog(clientTransaction, clientTransaction.getLastResponse());  
441 - }else {  
442 - sipDialog = e.dialog;  
443 - }  
444 - streamSession.put(device.getDeviceId(), channelId ,"play", sipDialog);  
445 - okEvent.response(e);  
446 - });  
447 -  
448 -  
449 - } catch ( SipException | ParseException | InvalidArgumentException e) {  
450 - e.printStackTrace();  
451 - }  
452 - }  
453 -  
454 - /**  
455 - * 请求回放视频流  
456 - *  
457 - * @param device 视频设备  
458 - * @param channelId 预览通道  
459 - * @param startTime 开始时间,格式要求:yyyy-MM-dd HH:mm:ss  
460 - * @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss  
461 - */  
462 - @Override  
463 - public void playbackStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId,  
464 - String startTime, String endTime, InviteStreamCallback inviteStreamCallback, InviteStreamCallback hookEvent,  
465 - SipSubscribe.Event okEvent,SipSubscribe.Event errorEvent) {  
466 - try {  
467 -  
468 - logger.info("{} 分配的ZLM为: {} [{}:{}]", ssrcInfo.getStream(), mediaServerItem.getId(), mediaServerItem.getIp(), ssrcInfo.getPort());  
469 -  
470 - StringBuffer content = new StringBuffer(200);  
471 - content.append("v=0\r\n");  
472 - content.append("o="+channelId+" 0 0 IN IP4 " + mediaServerItem.getSdpIp() + "\r\n");  
473 - content.append("s=Playback\r\n");  
474 - content.append("u="+channelId+":0\r\n");  
475 - content.append("c=IN IP4 "+mediaServerItem.getSdpIp()+"\r\n");  
476 - content.append("t="+DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(startTime)+" "  
477 - +DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(endTime) +"\r\n");  
478 -  
479 - String streamMode = device.getStreamMode();  
480 -  
481 - if (userSetting.isSeniorSdp()) {  
482 - if("TCP-PASSIVE".equalsIgnoreCase(streamMode)) {  
483 - content.append("m=video "+ ssrcInfo.getPort() +" TCP/RTP/AVP 96 126 125 99 34 98 97\r\n");  
484 - }else if ("TCP-ACTIVE".equalsIgnoreCase(streamMode)) {  
485 - content.append("m=video "+ ssrcInfo.getPort() +" TCP/RTP/AVP 96 126 125 99 34 98 97\r\n");  
486 - }else if("UDP".equalsIgnoreCase(streamMode)) {  
487 - content.append("m=video "+ ssrcInfo.getPort() +" RTP/AVP 96 126 125 99 34 98 97\r\n");  
488 - }  
489 - content.append("a=recvonly\r\n");  
490 - content.append("a=rtpmap:96 PS/90000\r\n");  
491 - content.append("a=fmtp:126 profile-level-id=42e01e\r\n");  
492 - content.append("a=rtpmap:126 H264/90000\r\n");  
493 - content.append("a=rtpmap:125 H264S/90000\r\n");  
494 - content.append("a=fmtp:125 profile-level-id=42e01e\r\n");  
495 - content.append("a=rtpmap:99 H265/90000\r\n");  
496 - content.append("a=rtpmap:98 H264/90000\r\n");  
497 - content.append("a=rtpmap:97 MPEG4/90000\r\n");  
498 - if("TCP-PASSIVE".equalsIgnoreCase(streamMode)){ // tcp被动模式  
499 - content.append("a=setup:passive\r\n");  
500 - content.append("a=connection:new\r\n");  
501 - }else if ("TCP-ACTIVE".equalsIgnoreCase(streamMode)) { // tcp主动模式  
502 - content.append("a=setup:active\r\n");  
503 - content.append("a=connection:new\r\n");  
504 - }  
505 - }else {  
506 - if("TCP-PASSIVE".equalsIgnoreCase(streamMode)) {  
507 - content.append("m=video "+ ssrcInfo.getPort() +" TCP/RTP/AVP 96 97 98 99\r\n");  
508 - }else if ("TCP-ACTIVE".equalsIgnoreCase(streamMode)) {  
509 - content.append("m=video "+ ssrcInfo.getPort() +" TCP/RTP/AVP 96 97 98 99\r\n");  
510 - }else if("UDP".equalsIgnoreCase(streamMode)) {  
511 - content.append("m=video "+ ssrcInfo.getPort() +" RTP/AVP 96 97 98 99\r\n");  
512 - }  
513 - content.append("a=recvonly\r\n");  
514 - content.append("a=rtpmap:96 PS/90000\r\n");  
515 - content.append("a=rtpmap:97 MPEG4/90000\r\n");  
516 - content.append("a=rtpmap:98 H264/90000\r\n");  
517 - content.append("a=rtpmap:99 H265/90000\r\n");  
518 - if("TCP-PASSIVE".equalsIgnoreCase(streamMode)){ // tcp被动模式  
519 - content.append("a=setup:passive\r\n");  
520 - content.append("a=connection:new\r\n");  
521 - }else if ("TCP-ACTIVE".equalsIgnoreCase(streamMode)) { // tcp主动模式  
522 - content.append("a=setup:active\r\n");  
523 - content.append("a=connection:new\r\n");  
524 - }  
525 - }  
526 -  
527 - content.append("y=" + ssrcInfo.getSsrc() + "\r\n");//ssrc  
528 -  
529 - CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()  
530 - : udpSipProvider.getNewCallId();  
531 - HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", ssrcInfo.getStream(), true, "rtsp", mediaServerItem.getId());  
532 - // 添加订阅  
533 - subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, JSONObject json)->{  
534 - if (hookEvent != null) {  
535 - InviteStreamInfo inviteStreamInfo = new InviteStreamInfo(mediaServerItemInUse, json, callIdHeader.getCallId(), "rtp", ssrcInfo.getStream());  
536 - hookEvent.call(inviteStreamInfo);  
537 - }  
538 - subscribe.removeSubscribe(hookSubscribe);  
539 - });  
540 - Request request = headerProvider.createPlaybackInviteRequest(device, channelId, content.toString(), null, SipUtils.getNewFromTag(), null, callIdHeader, ssrcInfo.getSsrc());  
541 -  
542 - transmitRequest(device, request, errorEvent, event -> {  
543 - ResponseEvent responseEvent = (ResponseEvent) event.event;  
544 - streamSession.put(device.getDeviceId(), channelId, callIdHeader.getCallId(), ssrcInfo.getStream(), ssrcInfo.getSsrc(), mediaServerItem.getId(), responseEvent.getClientTransaction(), VideoStreamSessionManager.SessionType.playback);  
545 - streamSession.put(device.getDeviceId(), channelId, callIdHeader.getCallId(), event.dialog);  
546 - okEvent.response(event);  
547 - });  
548 - if (inviteStreamCallback != null) {  
549 - inviteStreamCallback.call(new InviteStreamInfo(mediaServerItem, null, callIdHeader.getCallId(), "rtp", ssrcInfo.getStream()));  
550 - }  
551 - } catch ( SipException | ParseException | InvalidArgumentException e) {  
552 - e.printStackTrace();  
553 - }  
554 - }  
555 -  
556 - /**  
557 - * 请求历史媒体下载  
558 - *  
559 - * @param device 视频设备  
560 - * @param channelId 预览通道  
561 - * @param startTime 开始时间,格式要求:yyyy-MM-dd HH:mm:ss  
562 - * @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss  
563 - * @param downloadSpeed 下载倍速参数  
564 - */  
565 - @Override  
566 - public void downloadStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId,  
567 - String startTime, String endTime, int downloadSpeed, InviteStreamCallback inviteStreamCallback, InviteStreamCallback hookEvent,  
568 - SipSubscribe.Event errorEvent) {  
569 - try {  
570 - logger.info("{} 分配的ZLM为: {} [{}:{}]", ssrcInfo.getStream(), mediaServerItem.getId(), mediaServerItem.getIp(), ssrcInfo.getPort());  
571 -  
572 - StringBuffer content = new StringBuffer(200);  
573 - content.append("v=0\r\n");  
574 - content.append("o="+channelId+" 0 0 IN IP4 " + mediaServerItem.getSdpIp() + "\r\n");  
575 - content.append("s=Download\r\n");  
576 - content.append("u="+channelId+":0\r\n");  
577 - content.append("c=IN IP4 "+mediaServerItem.getSdpIp()+"\r\n");  
578 - content.append("t="+DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(startTime)+" "  
579 - +DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(endTime) +"\r\n");  
580 -  
581 - String streamMode = device.getStreamMode().toUpperCase();  
582 -  
583 - if (userSetting.isSeniorSdp()) {  
584 - if("TCP-PASSIVE".equals(streamMode)) {  
585 - content.append("m=video "+ ssrcInfo.getPort() +" TCP/RTP/AVP 96 126 125 99 34 98 97\r\n");  
586 - }else if ("TCP-ACTIVE".equals(streamMode)) {  
587 - content.append("m=video "+ ssrcInfo.getPort() +" TCP/RTP/AVP 96 126 125 99 34 98 97\r\n");  
588 - }else if("UDP".equals(streamMode)) {  
589 - content.append("m=video "+ ssrcInfo.getPort() +" RTP/AVP 96 126 125 99 34 98 97\r\n");  
590 - }  
591 - content.append("a=recvonly\r\n");  
592 - content.append("a=rtpmap:96 PS/90000\r\n");  
593 - content.append("a=fmtp:126 profile-level-id=42e01e\r\n");  
594 - content.append("a=rtpmap:126 H264/90000\r\n");  
595 - content.append("a=rtpmap:125 H264S/90000\r\n");  
596 - content.append("a=fmtp:125 profile-level-id=42e01e\r\n");  
597 - content.append("a=rtpmap:99 MP4V-ES/90000\r\n");  
598 - content.append("a=fmtp:99 profile-level-id=3\r\n");  
599 - content.append("a=rtpmap:98 H264/90000\r\n");  
600 - content.append("a=rtpmap:97 MPEG4/90000\r\n");  
601 - if("TCP-PASSIVE".equals(streamMode)){ // tcp被动模式  
602 - content.append("a=setup:passive\r\n");  
603 - content.append("a=connection:new\r\n");  
604 - }else if ("TCP-ACTIVE".equals(streamMode)) { // tcp主动模式  
605 - content.append("a=setup:active\r\n");  
606 - content.append("a=connection:new\r\n");  
607 - }  
608 - }else {  
609 - if("TCP-PASSIVE".equals(streamMode)) {  
610 - content.append("m=video "+ ssrcInfo.getPort() +" TCP/RTP/AVP 96 97 98 99\r\n");  
611 - }else if ("TCP-ACTIVE".equals(streamMode)) {  
612 - content.append("m=video "+ ssrcInfo.getPort() +" TCP/RTP/AVP 96 97 98 99\r\n");  
613 - }else if("UDP".equals(streamMode)) {  
614 - content.append("m=video "+ ssrcInfo.getPort() +" RTP/AVP 96 97 98 99\r\n");  
615 - }  
616 - content.append("a=recvonly\r\n");  
617 - content.append("a=rtpmap:96 PS/90000\r\n");  
618 - content.append("a=rtpmap:97 MPEG4/90000\r\n");  
619 - content.append("a=rtpmap:98 H264/90000\r\n");  
620 - content.append("a=rtpmap:99 H265/90000\r\n");  
621 - if("TCP-PASSIVE".equals(streamMode)){ // tcp被动模式  
622 - content.append("a=setup:passive\r\n");  
623 - content.append("a=connection:new\r\n");  
624 - }else if ("TCP-ACTIVE".equals(streamMode)) { // tcp主动模式  
625 - content.append("a=setup:active\r\n");  
626 - content.append("a=connection:new\r\n");  
627 - }  
628 - }  
629 - content.append("a=downloadspeed:" + downloadSpeed + "\r\n");  
630 -  
631 - content.append("y=" + ssrcInfo.getSsrc() + "\r\n");//ssrc  
632 -  
633 - CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()  
634 - : udpSipProvider.getNewCallId();  
635 -  
636 - HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", ssrcInfo.getStream(), true, null, mediaServerItem.getId());  
637 - // 添加订阅  
638 - subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, JSONObject json)->{  
639 - hookEvent.call(new InviteStreamInfo(mediaServerItem, json, callIdHeader.getCallId(), "rtp", ssrcInfo.getStream()));  
640 - subscribe.removeSubscribe(hookSubscribe);  
641 - hookSubscribe.getContent().put("regist", false);  
642 - hookSubscribe.getContent().put("schema", "rtsp");  
643 - // 添加流注销的订阅,注销了后向设备发送bye  
644 - subscribe.addSubscribe(hookSubscribe,  
645 - (MediaServerItem mediaServerItemForEnd, JSONObject jsonForEnd)->{  
646 - ClientTransaction transaction = streamSession.getTransaction(device.getDeviceId(), channelId, ssrcInfo.getStream(), callIdHeader.getCallId());  
647 - if (transaction != null) {  
648 - logger.info("[录像]下载结束, 发送BYE");  
649 - streamByeCmd(device.getDeviceId(), channelId, ssrcInfo.getStream(), callIdHeader.getCallId());  
650 - }  
651 - });  
652 - });  
653 -  
654 - Request request = headerProvider.createPlaybackInviteRequest(device, channelId, content.toString(), null, SipUtils.getNewFromTag(), null, callIdHeader, ssrcInfo.getSsrc());  
655 - if (inviteStreamCallback != null) {  
656 - inviteStreamCallback.call(new InviteStreamInfo(mediaServerItem, null, callIdHeader.getCallId(), "rtp", ssrcInfo.getStream()));  
657 - }  
658 - transmitRequest(device, request, errorEvent, okEvent->{  
659 - ResponseEvent responseEvent = (ResponseEvent) okEvent.event;  
660 - streamSession.put(device.getDeviceId(), channelId, callIdHeader.getCallId(), ssrcInfo.getStream(), ssrcInfo.getSsrc(), mediaServerItem.getId(), responseEvent.getClientTransaction(), VideoStreamSessionManager.SessionType.download);  
661 - streamSession.put(device.getDeviceId(), channelId, callIdHeader.getCallId(), okEvent.dialog);  
662 - });  
663 -  
664 -  
665 - } catch ( SipException | ParseException | InvalidArgumentException e) {  
666 - e.printStackTrace();  
667 - }  
668 - }  
669 -  
670 - /**  
671 - * 视频流停止, 不使用回调  
672 - */  
673 - @Override  
674 - public void streamByeCmd(String deviceId, String channelId, String stream, String callId) {  
675 - streamByeCmd(deviceId, channelId, stream, callId, null);  
676 - }  
677 -  
678 - /**  
679 - * 视频流停止  
680 - */  
681 - @Override  
682 - public void streamByeCmd(String deviceId, String channelId, String stream, String callId, SipSubscribe.Event okEvent) {  
683 - try {  
684 - SsrcTransaction ssrcTransaction = streamSession.getSsrcTransaction(deviceId, channelId, callId, stream);  
685 - ClientTransaction transaction = streamSession.getTransaction(deviceId, channelId, stream, callId);  
686 -  
687 - if (transaction == null ) {  
688 - logger.warn("[ {} -> {}]停止视频流的时候发现事务已丢失", deviceId, channelId);  
689 - SipSubscribe.EventResult<Object> eventResult = new SipSubscribe.EventResult<>();  
690 - if (okEvent != null) {  
691 - okEvent.response(eventResult);  
692 - }  
693 - return;  
694 - }  
695 - SIPDialog dialog;  
696 - if (callId != null) {  
697 - dialog = streamSession.getDialogByCallId(ssrcTransaction.getDeviceId(), ssrcTransaction.getChannelId(), callId);  
698 - }else {  
699 - if (stream == null && ssrcTransaction == null && ssrcTransaction.getStream() == null) {  
700 - return;  
701 - }  
702 - dialog = streamSession.getDialogByStream(ssrcTransaction.getDeviceId(), ssrcTransaction.getChannelId(), ssrcTransaction.getStream());  
703 - }  
704 - mediaServerService.releaseSsrc(ssrcTransaction.getMediaServerId(), ssrcTransaction.getSsrc());  
705 - mediaServerService.closeRTPServer(ssrcTransaction.getMediaServerId(), ssrcTransaction.getStream());  
706 - streamSession.remove(ssrcTransaction.getDeviceId(), ssrcTransaction.getChannelId(), ssrcTransaction.getStream());  
707 -  
708 - if (dialog == null) {  
709 - logger.warn("[ {} -> {}]停止视频流的时候发现对话已丢失", ssrcTransaction.getDeviceId(), ssrcTransaction.getChannelId());  
710 - return;  
711 - }  
712 - SipStack sipStack = udpSipProvider.getSipStack();  
713 - SIPDialog sipDialog = ((SipStackImpl) sipStack).putDialog(dialog);  
714 - if (dialog != sipDialog) {  
715 - dialog = sipDialog;  
716 - }else {  
717 - dialog.setSipProvider(udpSipProvider);  
718 - try {  
719 - Field sipStackField = SIPDialog.class.getDeclaredField("sipStack");  
720 - sipStackField.setAccessible(true);  
721 - sipStackField.set(dialog, sipStack);  
722 - Field eventListenersField = SIPDialog.class.getDeclaredField("eventListeners");  
723 - eventListenersField.setAccessible(true);  
724 - eventListenersField.set(dialog, new HashSet<>());  
725 - } catch (NoSuchFieldException | IllegalAccessException e) {  
726 - e.printStackTrace();  
727 - }  
728 - }  
729 -  
730 - Request byeRequest = dialog.createRequest(Request.BYE);  
731 - SipURI byeURI = (SipURI) byeRequest.getRequestURI();  
732 - SIPRequest request = (SIPRequest)transaction.getRequest();  
733 - byeURI.setHost(request.getRemoteAddress().getHostAddress());  
734 - byeURI.setPort(request.getRemotePort());  
735 - byeURI.setUser(channelId);  
736 - ViaHeader viaHeader = (ViaHeader) byeRequest.getHeader(ViaHeader.NAME);  
737 - String protocol = viaHeader.getTransport().toUpperCase();  
738 - viaHeader.setRPort();  
739 - // 增加Contact header  
740 - Address concatAddress = sipFactory.createAddressFactory().createAddress(sipFactory.createAddressFactory().createSipURI(sipConfig.getId(), sipConfig.getIp()+":"+sipConfig.getPort()));  
741 - byeRequest.addHeader(sipFactory.createHeaderFactory().createContactHeader(concatAddress));  
742 - UserAgentHeader userAgentHeader = SipUtils.createUserAgentHeader(sipFactory, gitUtil);  
743 - byeRequest.addHeader(userAgentHeader);  
744 - ClientTransaction clientTransaction = null;  
745 - if("TCP".equals(protocol)) {  
746 - clientTransaction = tcpSipProvider.getNewClientTransaction(byeRequest);  
747 - } else if("UDP".equals(protocol)) {  
748 - clientTransaction = udpSipProvider.getNewClientTransaction(byeRequest);  
749 - }  
750 -  
751 - CallIdHeader callIdHeader = (CallIdHeader) byeRequest.getHeader(CallIdHeader.NAME);  
752 - if (okEvent != null) {  
753 - sipSubscribe.addOkSubscribe(callIdHeader.getCallId(), okEvent);  
754 - }  
755 - CSeqHeader cSeqHeader = (CSeqHeader)byeRequest.getHeader(CSeqHeader.NAME);  
756 - cSeqHeader.setSeqNumber(redisCatchStorage.getCSEQ());  
757 - dialog.sendRequest(clientTransaction);  
758 -  
759 - } catch (SipException | ParseException e) {  
760 - e.printStackTrace();  
761 - } catch (InvalidArgumentException e) {  
762 - throw new RuntimeException(e);  
763 - }  
764 - }  
765 -  
766 - /**  
767 - * 语音广播  
768 - *  
769 - * @param device 视频设备  
770 - * @param channelId 预览通道  
771 - */  
772 - @Override  
773 - public boolean audioBroadcastCmd(Device device, String channelId) {  
774 - // 改为新的实现  
775 - return false;  
776 - }  
777 -  
778 - /**  
779 - * 语音广播  
780 - *  
781 - * @param device 视频设备  
782 - */  
783 - @Override  
784 - public boolean audioBroadcastCmd(Device device) {  
785 - try {  
786 - StringBuffer broadcastXml = new StringBuffer(200);  
787 - String charset = device.getCharset();  
788 - broadcastXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");  
789 - broadcastXml.append("<Notify>\r\n");  
790 - broadcastXml.append("<CmdType>Broadcast</CmdType>\r\n");  
791 - broadcastXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");  
792 - broadcastXml.append("<SourceID>" + sipConfig.getId() + "</SourceID>\r\n");  
793 - broadcastXml.append("<TargetID>" + device.getDeviceId() + "</TargetID>\r\n");  
794 - broadcastXml.append("</Notify>\r\n");  
795 -  
796 - CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()  
797 - : udpSipProvider.getNewCallId();  
798 -  
799 - Request request = headerProvider.createMessageRequest(device, broadcastXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null, callIdHeader);  
800 - transmitRequest(device, request);  
801 - return true;  
802 - } catch (SipException | ParseException | InvalidArgumentException e) {  
803 - e.printStackTrace();  
804 - }  
805 - return false;  
806 - }  
807 - @Override  
808 - public void audioBroadcastCmd(Device device, SipSubscribe.Event errorEvent) {  
809 - try {  
810 - StringBuffer broadcastXml = new StringBuffer(200);  
811 - String charset = device.getCharset();  
812 - broadcastXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");  
813 - broadcastXml.append("<Notify>\r\n");  
814 - broadcastXml.append("<CmdType>Broadcast</CmdType>\r\n");  
815 - broadcastXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");  
816 - broadcastXml.append("<SourceID>" + sipConfig.getId() + "</SourceID>\r\n");  
817 - broadcastXml.append("<TargetID>" + device.getDeviceId() + "</TargetID>\r\n");  
818 - broadcastXml.append("</Notify>\r\n");  
819 -  
820 - CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()  
821 - : udpSipProvider.getNewCallId();  
822 -  
823 - Request request = headerProvider.createMessageRequest(device, broadcastXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null, callIdHeader);  
824 - transmitRequest(device, request, errorEvent);  
825 - } catch (SipException | ParseException | InvalidArgumentException e) {  
826 - e.printStackTrace();  
827 - }  
828 - }  
829 -  
830 -  
831 - /**  
832 - * 音视频录像控制  
833 - *  
834 - * @param device 视频设备  
835 - * @param channelId 预览通道  
836 - * @param recordCmdStr 录像命令:Record / StopRecord  
837 - */  
838 - @Override  
839 - public boolean recordCmd(Device device, String channelId, String recordCmdStr, SipSubscribe.Event errorEvent) {  
840 - try {  
841 - StringBuffer cmdXml = new StringBuffer(200);  
842 - String charset = device.getCharset();  
843 - cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");  
844 - cmdXml.append("<Control>\r\n");  
845 - cmdXml.append("<CmdType>DeviceControl</CmdType>\r\n");  
846 - cmdXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");  
847 - if (ObjectUtils.isEmpty(channelId)) {  
848 - cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");  
849 - } else {  
850 - cmdXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n");  
851 - }  
852 - cmdXml.append("<RecordCmd>" + recordCmdStr + "</RecordCmd>\r\n");  
853 - cmdXml.append("</Control>\r\n");  
854 -  
855 - CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()  
856 - : udpSipProvider.getNewCallId();  
857 -  
858 - Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null, callIdHeader);  
859 - transmitRequest(device, request, errorEvent);  
860 - return true;  
861 - } catch (SipException | ParseException | InvalidArgumentException e) {  
862 - e.printStackTrace();  
863 - return false;  
864 - }  
865 - }  
866 -  
867 - /**  
868 - * 远程启动控制命令  
869 - *  
870 - * @param device 视频设备  
871 - */  
872 - @Override  
873 - public boolean teleBootCmd(Device device) {  
874 - try {  
875 - StringBuffer cmdXml = new StringBuffer(200);  
876 - String charset = device.getCharset();  
877 - cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");  
878 - cmdXml.append("<Control>\r\n");  
879 - cmdXml.append("<CmdType>DeviceControl</CmdType>\r\n");  
880 - cmdXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");  
881 - cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");  
882 - cmdXml.append("<TeleBoot>Boot</TeleBoot>\r\n");  
883 - cmdXml.append("</Control>\r\n");  
884 -  
885 - CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()  
886 - : udpSipProvider.getNewCallId();  
887 -  
888 - Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null, callIdHeader);  
889 - transmitRequest(device, request);  
890 - return true;  
891 - } catch (SipException | ParseException | InvalidArgumentException e) {  
892 - e.printStackTrace();  
893 - return false;  
894 - }  
895 - }  
896 -  
897 - /**  
898 - * 报警布防/撤防命令  
899 - *  
900 - * @param device 视频设备  
901 - * @param guardCmdStr "SetGuard"/"ResetGuard"  
902 - */  
903 - @Override  
904 - public boolean guardCmd(Device device, String guardCmdStr, SipSubscribe.Event errorEvent) {  
905 - try {  
906 - StringBuffer cmdXml = new StringBuffer(200);  
907 - String charset = device.getCharset();  
908 - cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");  
909 - cmdXml.append("<Control>\r\n");  
910 - cmdXml.append("<CmdType>DeviceControl</CmdType>\r\n");  
911 - cmdXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");  
912 - cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");  
913 - cmdXml.append("<GuardCmd>" + guardCmdStr + "</GuardCmd>\r\n");  
914 - cmdXml.append("</Control>\r\n");  
915 -  
916 - CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()  
917 - : udpSipProvider.getNewCallId();  
918 -  
919 - Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null, callIdHeader);  
920 - transmitRequest(device, request, errorEvent);  
921 - return true;  
922 - } catch (SipException | ParseException | InvalidArgumentException e) {  
923 - e.printStackTrace();  
924 - return false;  
925 - }  
926 - }  
927 -  
928 - /**  
929 - * 报警复位命令  
930 - *  
931 - * @param device 视频设备  
932 - */  
933 - @Override  
934 - public boolean alarmCmd(Device device, String alarmMethod, String alarmType, SipSubscribe.Event errorEvent) {  
935 - try {  
936 - StringBuffer cmdXml = new StringBuffer(200);  
937 - String charset = device.getCharset();  
938 - cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");  
939 - cmdXml.append("<Control>\r\n");  
940 - cmdXml.append("<CmdType>DeviceControl</CmdType>\r\n");  
941 - cmdXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");  
942 - cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");  
943 - cmdXml.append("<AlarmCmd>ResetAlarm</AlarmCmd>\r\n");  
944 - if (!ObjectUtils.isEmpty(alarmMethod) || !ObjectUtils.isEmpty(alarmType)) {  
945 - cmdXml.append("<Info>\r\n");  
946 - }  
947 - if (!ObjectUtils.isEmpty(alarmMethod)) {  
948 - cmdXml.append("<AlarmMethod>" + alarmMethod + "</AlarmMethod>\r\n");  
949 - }  
950 - if (!ObjectUtils.isEmpty(alarmType)) {  
951 - cmdXml.append("<AlarmType>" + alarmType + "</AlarmType>\r\n");  
952 - }  
953 - if (!ObjectUtils.isEmpty(alarmMethod) || !ObjectUtils.isEmpty(alarmType)) {  
954 - cmdXml.append("</Info>\r\n");  
955 - }  
956 - cmdXml.append("</Control>\r\n");  
957 -  
958 - CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()  
959 - : udpSipProvider.getNewCallId();  
960 -  
961 - Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null, callIdHeader);  
962 - transmitRequest(device, request, errorEvent);  
963 - return true;  
964 - } catch (SipException | ParseException | InvalidArgumentException e) {  
965 - e.printStackTrace();  
966 - return false;  
967 - }  
968 - }  
969 -  
970 - /**  
971 - * 强制关键帧命令,设备收到此命令应立刻发送一个IDR帧  
972 - *  
973 - * @param device 视频设备  
974 - * @param channelId 预览通道  
975 - */  
976 - @Override  
977 - public boolean iFrameCmd(Device device, String channelId) {  
978 - try {  
979 - StringBuffer cmdXml = new StringBuffer(200);  
980 - String charset = device.getCharset();  
981 - cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");  
982 - cmdXml.append("<Control>\r\n");  
983 - cmdXml.append("<CmdType>DeviceControl</CmdType>\r\n");  
984 - cmdXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");  
985 - if (ObjectUtils.isEmpty(channelId)) {  
986 - cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");  
987 - } else {  
988 - cmdXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n");  
989 - }  
990 - cmdXml.append("<IFameCmd>Send</IFameCmd>\r\n");  
991 - cmdXml.append("</Control>\r\n");  
992 -  
993 - CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()  
994 - : udpSipProvider.getNewCallId();  
995 -  
996 - Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null, callIdHeader);  
997 - transmitRequest(device, request);  
998 - return true;  
999 - } catch (SipException | ParseException | InvalidArgumentException e) {  
1000 - e.printStackTrace();  
1001 - return false;  
1002 - }  
1003 - }  
1004 -  
1005 - /**  
1006 - * 看守位控制命令  
1007 - *  
1008 - * @param device 视频设备  
1009 - * @param enabled 看守位使能:1 = 开启,0 = 关闭  
1010 - * @param resetTime 自动归位时间间隔,开启看守位时使用,单位:秒(s)  
1011 - * @param presetIndex 调用预置位编号,开启看守位时使用,取值范围0~255  
1012 - */  
1013 - @Override  
1014 - public boolean homePositionCmd(Device device, String channelId, String enabled, String resetTime, String presetIndex, SipSubscribe.Event errorEvent) {  
1015 - try {  
1016 - StringBuffer cmdXml = new StringBuffer(200);  
1017 - String charset = device.getCharset();  
1018 - cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");  
1019 - cmdXml.append("<Control>\r\n");  
1020 - cmdXml.append("<CmdType>DeviceControl</CmdType>\r\n");  
1021 - cmdXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");  
1022 - if (ObjectUtils.isEmpty(channelId)) {  
1023 - cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");  
1024 - } else {  
1025 - cmdXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n");  
1026 - }  
1027 - cmdXml.append("<HomePosition>\r\n");  
1028 - if (NumericUtil.isInteger(enabled) && (!enabled.equals("0"))) {  
1029 - cmdXml.append("<Enabled>1</Enabled>\r\n");  
1030 - if (NumericUtil.isInteger(resetTime)) {  
1031 - cmdXml.append("<ResetTime>" + resetTime + "</ResetTime>\r\n");  
1032 - } else {  
1033 - cmdXml.append("<ResetTime>0</ResetTime>\r\n");  
1034 - }  
1035 - if (NumericUtil.isInteger(presetIndex)) {  
1036 - cmdXml.append("<PresetIndex>" + presetIndex + "</PresetIndex>\r\n");  
1037 - } else {  
1038 - cmdXml.append("<PresetIndex>0</PresetIndex>\r\n");  
1039 - }  
1040 - } else {  
1041 - cmdXml.append("<Enabled>0</Enabled>\r\n");  
1042 - }  
1043 - cmdXml.append("</HomePosition>\r\n");  
1044 - cmdXml.append("</Control>\r\n");  
1045 -  
1046 - CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()  
1047 - : udpSipProvider.getNewCallId();  
1048 -  
1049 - Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null, callIdHeader);  
1050 - transmitRequest(device, request, errorEvent);  
1051 - return true;  
1052 - } catch (SipException | ParseException | InvalidArgumentException e) {  
1053 - e.printStackTrace();  
1054 - return false;  
1055 - }  
1056 - }  
1057 -  
1058 - /**  
1059 - * 设备配置命令  
1060 - *  
1061 - * @param device 视频设备  
1062 - */  
1063 - @Override  
1064 - public boolean deviceConfigCmd(Device device) {  
1065 - // TODO Auto-generated method stub  
1066 - return false;  
1067 - }  
1068 -  
1069 - /**  
1070 - * 设备配置命令:basicParam  
1071 - *  
1072 - * @param device 视频设备  
1073 - * @param channelId 通道编码(可选)  
1074 - * @param name 设备/通道名称(可选)  
1075 - * @param expiration 注册过期时间(可选)  
1076 - * @param heartBeatInterval 心跳间隔时间(可选)  
1077 - * @param heartBeatCount 心跳超时次数(可选)  
1078 - */  
1079 - @Override  
1080 - public boolean deviceBasicConfigCmd(Device device, String channelId, String name, String expiration,  
1081 - String heartBeatInterval, String heartBeatCount, SipSubscribe.Event errorEvent) {  
1082 - try {  
1083 - StringBuffer cmdXml = new StringBuffer(200);  
1084 - String charset = device.getCharset();  
1085 - cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");  
1086 - cmdXml.append("<Control>\r\n");  
1087 - cmdXml.append("<CmdType>DeviceConfig</CmdType>\r\n");  
1088 - cmdXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");  
1089 - if (ObjectUtils.isEmpty(channelId)) {  
1090 - cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");  
1091 - } else {  
1092 - cmdXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n");  
1093 - }  
1094 - cmdXml.append("<BasicParam>\r\n");  
1095 - if (!ObjectUtils.isEmpty(name)) {  
1096 - cmdXml.append("<Name>" + name + "</Name>\r\n");  
1097 - }  
1098 - if (NumericUtil.isInteger(expiration)) {  
1099 - if (Integer.valueOf(expiration) > 0) {  
1100 - cmdXml.append("<Expiration>" + expiration + "</Expiration>\r\n");  
1101 - }  
1102 - }  
1103 - if (NumericUtil.isInteger(heartBeatInterval)) {  
1104 - if (Integer.valueOf(heartBeatInterval) > 0) {  
1105 - cmdXml.append("<HeartBeatInterval>" + heartBeatInterval + "</HeartBeatInterval>\r\n");  
1106 - }  
1107 - }  
1108 - if (NumericUtil.isInteger(heartBeatCount)) {  
1109 - if (Integer.valueOf(heartBeatCount) > 0) {  
1110 - cmdXml.append("<HeartBeatCount>" + heartBeatCount + "</HeartBeatCount>\r\n");  
1111 - }  
1112 - }  
1113 - cmdXml.append("</BasicParam>\r\n");  
1114 - cmdXml.append("</Control>\r\n");  
1115 -  
1116 - CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()  
1117 - : udpSipProvider.getNewCallId();  
1118 -  
1119 - Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null, callIdHeader);  
1120 - transmitRequest(device, request, errorEvent);  
1121 - return true;  
1122 - } catch (SipException | ParseException | InvalidArgumentException e) {  
1123 - e.printStackTrace();  
1124 - return false;  
1125 - }  
1126 - }  
1127 -  
1128 - /**  
1129 - * 查询设备状态  
1130 - *  
1131 - * @param device 视频设备  
1132 - */  
1133 - @Override  
1134 - public boolean deviceStatusQuery(Device device, SipSubscribe.Event errorEvent) {  
1135 - try {  
1136 - String charset = device.getCharset();  
1137 - StringBuffer catalogXml = new StringBuffer(200);  
1138 - catalogXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");  
1139 - catalogXml.append("<Query>\r\n");  
1140 - catalogXml.append("<CmdType>DeviceStatus</CmdType>\r\n");  
1141 - catalogXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");  
1142 - catalogXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");  
1143 - catalogXml.append("</Query>\r\n");  
1144 -  
1145 - CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()  
1146 - : udpSipProvider.getNewCallId();  
1147 -  
1148 - Request request = headerProvider.createMessageRequest(device, catalogXml.toString(), null, SipUtils.getNewFromTag(), null, callIdHeader);  
1149 -  
1150 - transmitRequest(device, request, errorEvent);  
1151 - return true;  
1152 -  
1153 - } catch (SipException | ParseException | InvalidArgumentException e) {  
1154 - e.printStackTrace();  
1155 - return false;  
1156 - }  
1157 - }  
1158 -  
1159 - /**  
1160 - * 查询设备信息  
1161 - *  
1162 - * @param device 视频设备  
1163 - */  
1164 - @Override  
1165 - public boolean deviceInfoQuery(Device device) {  
1166 - try {  
1167 - StringBuffer catalogXml = new StringBuffer(200);  
1168 - String charset = device.getCharset();  
1169 - catalogXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");  
1170 - catalogXml.append("<Query>\r\n");  
1171 - catalogXml.append("<CmdType>DeviceInfo</CmdType>\r\n");  
1172 - catalogXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");  
1173 - catalogXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");  
1174 - catalogXml.append("</Query>\r\n");  
1175 -  
1176 - CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()  
1177 - : udpSipProvider.getNewCallId();  
1178 -  
1179 - Request request = headerProvider.createMessageRequest(device, catalogXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null, callIdHeader);  
1180 -  
1181 - transmitRequest(device, request);  
1182 -  
1183 - } catch (SipException | ParseException | InvalidArgumentException e) {  
1184 - e.printStackTrace();  
1185 - return false;  
1186 - }  
1187 - return true;  
1188 - }  
1189 -  
1190 - /**  
1191 - * 查询目录列表  
1192 - *  
1193 - * @param device 视频设备  
1194 - */  
1195 - @Override  
1196 - public boolean catalogQuery(Device device, int sn, SipSubscribe.Event errorEvent) {  
1197 - try {  
1198 - StringBuffer catalogXml = new StringBuffer(200);  
1199 - String charset = device.getCharset();  
1200 - catalogXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");  
1201 - catalogXml.append("<Query>\r\n");  
1202 - catalogXml.append(" <CmdType>Catalog</CmdType>\r\n");  
1203 - catalogXml.append(" <SN>" + sn + "</SN>\r\n");  
1204 - catalogXml.append(" <DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");  
1205 - catalogXml.append("</Query>\r\n");  
1206 -  
1207 - CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()  
1208 - : udpSipProvider.getNewCallId();  
1209 -  
1210 - Request request = headerProvider.createMessageRequest(device, catalogXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null, callIdHeader);  
1211 -  
1212 - transmitRequest(device, request, errorEvent);  
1213 - } catch (SipException | ParseException | InvalidArgumentException e) {  
1214 - e.printStackTrace();  
1215 - return false;  
1216 - }  
1217 - return true;  
1218 - }  
1219 -  
1220 - /**  
1221 - * 查询录像信息  
1222 - *  
1223 - * @param device 视频设备  
1224 - * @param startTime 开始时间,格式要求:yyyy-MM-dd HH:mm:ss  
1225 - * @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss  
1226 - */  
1227 - @Override  
1228 - public boolean recordInfoQuery(Device device, String channelId, String startTime, String endTime, int sn, Integer secrecy, String type, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) {  
1229 - if (secrecy == null) {  
1230 - secrecy = 0;  
1231 - }  
1232 - if (type == null) {  
1233 - type = "all";  
1234 - }  
1235 - try {  
1236 - StringBuffer recordInfoXml = new StringBuffer(200);  
1237 - String charset = device.getCharset();  
1238 - recordInfoXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");  
1239 - recordInfoXml.append("<Query>\r\n");  
1240 - recordInfoXml.append("<CmdType>RecordInfo</CmdType>\r\n");  
1241 - recordInfoXml.append("<SN>" + sn + "</SN>\r\n");  
1242 - recordInfoXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n");  
1243 - if (startTime != null) {  
1244 - recordInfoXml.append("<StartTime>" + DateUtil.yyyy_MM_dd_HH_mm_ssToISO8601(startTime) + "</StartTime>\r\n");  
1245 - }  
1246 - if (endTime != null) {  
1247 - recordInfoXml.append("<EndTime>" + DateUtil.yyyy_MM_dd_HH_mm_ssToISO8601(endTime) + "</EndTime>\r\n");  
1248 - }  
1249 - if (secrecy != null) {  
1250 - recordInfoXml.append("<Secrecy> "+ secrecy + " </Secrecy>\r\n");  
1251 - }  
1252 - if (type != null) {  
1253 - // 大华NVR要求必须增加一个值为all的文本元素节点Type  
1254 - recordInfoXml.append("<Type>" + type+"</Type>\r\n");  
1255 - }  
1256 - recordInfoXml.append("</Query>\r\n");  
1257 -  
1258 - CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()  
1259 - : udpSipProvider.getNewCallId();  
1260 -  
1261 - Request request = headerProvider.createMessageRequest(device, recordInfoXml.toString(),  
1262 - SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null, callIdHeader);  
1263 -  
1264 - transmitRequest(device, request, errorEvent, okEvent);  
1265 - } catch (SipException | ParseException | InvalidArgumentException e) {  
1266 - e.printStackTrace();  
1267 - return false;  
1268 - }  
1269 - return true;  
1270 - }  
1271 -  
1272 - /**  
1273 - * 查询报警信息  
1274 - *  
1275 - * @param device 视频设备  
1276 - * @param startPriority 报警起始级别(可选)  
1277 - * @param endPriority 报警终止级别(可选)  
1278 - * @param alarmMethod 报警方式条件(可选)  
1279 - * @param alarmType 报警类型  
1280 - * @param startTime 报警发生起始时间(可选)  
1281 - * @param endTime 报警发生终止时间(可选)  
1282 - * @return true = 命令发送成功  
1283 - */  
1284 - @Override  
1285 - public boolean alarmInfoQuery(Device device, String startPriority, String endPriority, String alarmMethod, String alarmType,  
1286 - String startTime, String endTime, SipSubscribe.Event errorEvent) {  
1287 - try {  
1288 - StringBuffer cmdXml = new StringBuffer(200);  
1289 - String charset = device.getCharset();  
1290 - cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");  
1291 - cmdXml.append("<Query>\r\n");  
1292 - cmdXml.append("<CmdType>Alarm</CmdType>\r\n");  
1293 - cmdXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");  
1294 - cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");  
1295 - if (!ObjectUtils.isEmpty(startPriority)) {  
1296 - cmdXml.append("<StartAlarmPriority>" + startPriority + "</StartAlarmPriority>\r\n");  
1297 - }  
1298 - if (!ObjectUtils.isEmpty(endPriority)) {  
1299 - cmdXml.append("<EndAlarmPriority>" + endPriority + "</EndAlarmPriority>\r\n");  
1300 - }  
1301 - if (!ObjectUtils.isEmpty(alarmMethod)) {  
1302 - cmdXml.append("<AlarmMethod>" + alarmMethod + "</AlarmMethod>\r\n");  
1303 - }  
1304 - if (!ObjectUtils.isEmpty(alarmType)) {  
1305 - cmdXml.append("<AlarmType>" + alarmType + "</AlarmType>\r\n");  
1306 - }  
1307 - if (!ObjectUtils.isEmpty(startTime)) {  
1308 - cmdXml.append("<StartAlarmTime>" + startTime + "</StartAlarmTime>\r\n");  
1309 - }  
1310 - if (!ObjectUtils.isEmpty(endTime)) {  
1311 - cmdXml.append("<EndAlarmTime>" + endTime + "</EndAlarmTime>\r\n");  
1312 - }  
1313 - cmdXml.append("</Query>\r\n");  
1314 -  
1315 - CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()  
1316 - : udpSipProvider.getNewCallId();  
1317 -  
1318 - Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null, callIdHeader);  
1319 - transmitRequest(device, request, errorEvent);  
1320 - return true;  
1321 - } catch (SipException | ParseException | InvalidArgumentException e) {  
1322 - e.printStackTrace();  
1323 - return false;  
1324 - }  
1325 - }  
1326 -  
1327 - /**  
1328 - * 查询设备配置  
1329 - *  
1330 - * @param device 视频设备  
1331 - * @param channelId 通道编码(可选)  
1332 - * @param configType 配置类型:  
1333 - */  
1334 - @Override  
1335 - public boolean deviceConfigQuery(Device device, String channelId, String configType, SipSubscribe.Event errorEvent) {  
1336 - try {  
1337 - StringBuffer cmdXml = new StringBuffer(200);  
1338 - String charset = device.getCharset();  
1339 - cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");  
1340 - cmdXml.append("<Query>\r\n");  
1341 - cmdXml.append("<CmdType>ConfigDownload</CmdType>\r\n");  
1342 - cmdXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");  
1343 - if (ObjectUtils.isEmpty(channelId)) {  
1344 - cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");  
1345 - } else {  
1346 - cmdXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n");  
1347 - }  
1348 - cmdXml.append("<ConfigType>" + configType + "</ConfigType>\r\n");  
1349 - cmdXml.append("</Query>\r\n");  
1350 -  
1351 - CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()  
1352 - : udpSipProvider.getNewCallId();  
1353 -  
1354 - Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null, callIdHeader);  
1355 - transmitRequest(device, request, errorEvent);  
1356 - return true;  
1357 - } catch (SipException | ParseException | InvalidArgumentException e) {  
1358 - e.printStackTrace();  
1359 - return false;  
1360 - }  
1361 - }  
1362 -  
1363 - /**  
1364 - * 查询设备预置位置  
1365 - *  
1366 - * @param device 视频设备  
1367 - */  
1368 - @Override  
1369 - public boolean presetQuery(Device device, String channelId, SipSubscribe.Event errorEvent) {  
1370 - try {  
1371 - StringBuffer cmdXml = new StringBuffer(200);  
1372 - String charset = device.getCharset();  
1373 - cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");  
1374 - cmdXml.append("<Query>\r\n");  
1375 - cmdXml.append("<CmdType>PresetQuery</CmdType>\r\n");  
1376 - cmdXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");  
1377 - if (ObjectUtils.isEmpty(channelId)) {  
1378 - cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");  
1379 - } else {  
1380 - cmdXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n");  
1381 - }  
1382 - cmdXml.append("</Query>\r\n");  
1383 -  
1384 - CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()  
1385 - : udpSipProvider.getNewCallId();  
1386 -  
1387 - Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null, callIdHeader);  
1388 - transmitRequest(device, request, errorEvent);  
1389 - return true;  
1390 - } catch (SipException | ParseException | InvalidArgumentException e) {  
1391 - e.printStackTrace();  
1392 - return false;  
1393 - }  
1394 - }  
1395 -  
1396 - /**  
1397 - * 查询移动设备位置数据  
1398 - *  
1399 - * @param device 视频设备  
1400 - */  
1401 - @Override  
1402 - public boolean mobilePostitionQuery(Device device, SipSubscribe.Event errorEvent) {  
1403 - try {  
1404 - StringBuffer mobilePostitionXml = new StringBuffer(200);  
1405 - String charset = device.getCharset();  
1406 - mobilePostitionXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");  
1407 - mobilePostitionXml.append("<Query>\r\n");  
1408 - mobilePostitionXml.append("<CmdType>MobilePosition</CmdType>\r\n");  
1409 - mobilePostitionXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");  
1410 - mobilePostitionXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");  
1411 - mobilePostitionXml.append("<Interval>60</Interval>\r\n");  
1412 - mobilePostitionXml.append("</Query>\r\n");  
1413 -  
1414 - CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()  
1415 - : udpSipProvider.getNewCallId();  
1416 -  
1417 - Request request = headerProvider.createMessageRequest(device, mobilePostitionXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null, callIdHeader);  
1418 -  
1419 - transmitRequest(device, request, errorEvent);  
1420 -  
1421 - } catch (SipException | ParseException | InvalidArgumentException e) {  
1422 - e.printStackTrace();  
1423 - return false;  
1424 - }  
1425 - return true;  
1426 - }  
1427 -  
1428 - /**  
1429 - * 订阅、取消订阅移动位置  
1430 - *  
1431 - * @param device 视频设备  
1432 - * @return true = 命令发送成功  
1433 - */  
1434 - @Override  
1435 - public SIPRequest mobilePositionSubscribe(Device device, SIPRequest requestOld, SipSubscribe.Event okEvent ,SipSubscribe.Event errorEvent) {  
1436 - try {  
1437 - StringBuffer subscribePostitionXml = new StringBuffer(200);  
1438 - String charset = device.getCharset();  
1439 - subscribePostitionXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");  
1440 - subscribePostitionXml.append("<Query>\r\n");  
1441 - subscribePostitionXml.append("<CmdType>MobilePosition</CmdType>\r\n");  
1442 - subscribePostitionXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");  
1443 - subscribePostitionXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");  
1444 - if (device.getSubscribeCycleForMobilePosition() > 0) {  
1445 - subscribePostitionXml.append("<Interval>" + device.getMobilePositionSubmissionInterval() + "</Interval>\r\n");  
1446 - }  
1447 - subscribePostitionXml.append("</Query>\r\n");  
1448 -  
1449 - CallIdHeader callIdHeader;  
1450 -  
1451 - if (requestOld != null) {  
1452 - callIdHeader = sipFactory.createHeaderFactory().createCallIdHeader(requestOld.getCallIdHeader().getCallId());  
1453 - }else {  
1454 - callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()  
1455 - : udpSipProvider.getNewCallId();  
1456 - }  
1457 - SIPRequest request = (SIPRequest)headerProvider.createSubscribeRequest(device, subscribePostitionXml.toString(), requestOld, device.getSubscribeCycleForMobilePosition(), "presence" ,callIdHeader); //Position;id=" + tm.substring(tm.length() - 4));  
1458 -  
1459 - transmitRequest(device, request, errorEvent, okEvent);  
1460 -  
1461 - return request;  
1462 -  
1463 - } catch ( NumberFormatException | ParseException | InvalidArgumentException | SipException e) {  
1464 - e.printStackTrace();  
1465 - return null;  
1466 - }  
1467 - }  
1468 -  
1469 - /**  
1470 - * 订阅、取消订阅报警信息  
1471 - *  
1472 - * @param device 视频设备  
1473 - * @param expires 订阅过期时间(0 = 取消订阅)  
1474 - * @param startPriority 报警起始级别(可选)  
1475 - * @param endPriority 报警终止级别(可选)  
1476 - * @param alarmMethod 报警方式条件(可选)  
1477 - * @param alarmType 报警类型  
1478 - * @param startTime 报警发生起始时间(可选)  
1479 - * @param endTime 报警发生终止时间(可选)  
1480 - * @return true = 命令发送成功  
1481 - */  
1482 - @Override  
1483 - public boolean alarmSubscribe(Device device, int expires, String startPriority, String endPriority, String alarmMethod, String alarmType, String startTime, String endTime) {  
1484 - try {  
1485 - StringBuffer cmdXml = new StringBuffer(200);  
1486 - String charset = device.getCharset();  
1487 - cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");  
1488 - cmdXml.append("<Query>\r\n");  
1489 - cmdXml.append("<CmdType>Alarm</CmdType>\r\n");  
1490 - cmdXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");  
1491 - cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");  
1492 - if (!ObjectUtils.isEmpty(startPriority)) {  
1493 - cmdXml.append("<StartAlarmPriority>" + startPriority + "</StartAlarmPriority>\r\n");  
1494 - }  
1495 - if (!ObjectUtils.isEmpty(endPriority)) {  
1496 - cmdXml.append("<EndAlarmPriority>" + endPriority + "</EndAlarmPriority>\r\n");  
1497 - }  
1498 - if (!ObjectUtils.isEmpty(alarmMethod)) {  
1499 - cmdXml.append("<AlarmMethod>" + alarmMethod + "</AlarmMethod>\r\n");  
1500 - }  
1501 - if (!ObjectUtils.isEmpty(alarmType)) {  
1502 - cmdXml.append("<AlarmType>" + alarmType + "</AlarmType>\r\n");  
1503 - }  
1504 - if (!ObjectUtils.isEmpty(startTime)) {  
1505 - cmdXml.append("<StartAlarmTime>" + startTime + "</StartAlarmTime>\r\n");  
1506 - }  
1507 - if (!ObjectUtils.isEmpty(endTime)) {  
1508 - cmdXml.append("<EndAlarmTime>" + endTime + "</EndAlarmTime>\r\n");  
1509 - }  
1510 - cmdXml.append("</Query>\r\n");  
1511 -  
1512 - CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()  
1513 - : udpSipProvider.getNewCallId();  
1514 -  
1515 - Request request = headerProvider.createSubscribeRequest(device, cmdXml.toString(), null, expires, "presence" , callIdHeader);  
1516 - transmitRequest(device, request);  
1517 -  
1518 - return true;  
1519 -  
1520 - } catch ( NumberFormatException | ParseException | InvalidArgumentException | SipException e) {  
1521 - e.printStackTrace();  
1522 - return false;  
1523 - }  
1524 - }  
1525 -  
1526 - @Override  
1527 - public SIPRequest catalogSubscribe(Device device, SIPRequest requestOld, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) {  
1528 - try {  
1529 - StringBuffer cmdXml = new StringBuffer(200);  
1530 - String charset = device.getCharset();  
1531 - cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");  
1532 - cmdXml.append("<Query>\r\n");  
1533 - cmdXml.append("<CmdType>Catalog</CmdType>\r\n");  
1534 - cmdXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");  
1535 - cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");  
1536 - cmdXml.append("</Query>\r\n");  
1537 -  
1538 - CallIdHeader callIdHeader ;  
1539 -  
1540 - if (requestOld != null) {  
1541 - callIdHeader = sipFactory.createHeaderFactory().createCallIdHeader(requestOld.getCallIdHeader().getCallId());  
1542 - }else {  
1543 - callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()  
1544 - : udpSipProvider.getNewCallId();  
1545 - }  
1546 -  
1547 - // 有效时间默认为60秒以上  
1548 - SIPRequest request = (SIPRequest)headerProvider.createSubscribeRequest(device, cmdXml.toString(), requestOld, device.getSubscribeCycleForCatalog(), "Catalog" ,  
1549 - callIdHeader);  
1550 - transmitRequest(device, request, errorEvent, okEvent);  
1551 - return request;  
1552 -  
1553 - } catch ( NumberFormatException | ParseException | InvalidArgumentException | SipException e) {  
1554 - e.printStackTrace();  
1555 - return null;  
1556 - }  
1557 - }  
1558 -  
1559 - @Override  
1560 - public boolean dragZoomCmd(Device device, String channelId, String cmdString) {  
1561 - try {  
1562 - StringBuffer dragXml = new StringBuffer(200);  
1563 - String charset = device.getCharset();  
1564 - dragXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");  
1565 - dragXml.append("<Control>\r\n");  
1566 - dragXml.append("<CmdType>DeviceControl</CmdType>\r\n");  
1567 - dragXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n");  
1568 - if (ObjectUtils.isEmpty(channelId)) {  
1569 - dragXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");  
1570 - } else {  
1571 - dragXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n");  
1572 - }  
1573 - dragXml.append(cmdString);  
1574 - dragXml.append("</Control>\r\n");  
1575 - CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()  
1576 - : udpSipProvider.getNewCallId();  
1577 - Request request = headerProvider.createMessageRequest(device, dragXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null, callIdHeader);  
1578 - logger.debug("拉框信令: " + request.toString());  
1579 - transmitRequest(device, request);  
1580 - return true;  
1581 - } catch (SipException | ParseException | InvalidArgumentException e) {  
1582 - e.printStackTrace();  
1583 - }  
1584 - return false;  
1585 - }  
1586 -  
1587 -  
1588 - private ClientTransaction transmitRequest(Device device, Request request) throws SipException {  
1589 - return transmitRequest(device, request, null, null);  
1590 - }  
1591 -  
1592 - private ClientTransaction transmitRequest(Device device, Request request, SipSubscribe.Event errorEvent) throws SipException {  
1593 - return transmitRequest(device, request, errorEvent, null);  
1594 - }  
1595 -  
1596 - private ClientTransaction transmitRequest(Device device, Request request, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent) throws SipException {  
1597 - ClientTransaction clientTransaction = null;  
1598 - if("TCP".equals(device.getTransport())) {  
1599 - clientTransaction = tcpSipProvider.getNewClientTransaction(request);  
1600 - } else if("UDP".equals(device.getTransport())) {  
1601 - clientTransaction = udpSipProvider.getNewClientTransaction(request);  
1602 - }  
1603 - if (request.getHeader(UserAgentHeader.NAME) == null) {  
1604 - try {  
1605 - request.addHeader(SipUtils.createUserAgentHeader(sipFactory, gitUtil));  
1606 - } catch (ParseException e) {  
1607 - logger.error("添加UserAgentHeader失败", e);  
1608 - }  
1609 - }  
1610 - CallIdHeader callIdHeader = (CallIdHeader)request.getHeader(CallIdHeader.NAME);  
1611 - // 添加错误订阅  
1612 - if (errorEvent != null) {  
1613 - sipSubscribe.addErrorSubscribe(callIdHeader.getCallId(), (eventResult -> {  
1614 - errorEvent.response(eventResult);  
1615 - sipSubscribe.removeErrorSubscribe(eventResult.callId);  
1616 - sipSubscribe.removeOkSubscribe(eventResult.callId);  
1617 - }));  
1618 - }  
1619 - // 添加订阅  
1620 - if (okEvent != null) {  
1621 - sipSubscribe.addOkSubscribe(callIdHeader.getCallId(), eventResult ->{  
1622 - okEvent.response(eventResult);  
1623 - sipSubscribe.removeOkSubscribe(eventResult.callId);  
1624 - sipSubscribe.removeErrorSubscribe(eventResult.callId);  
1625 - });  
1626 - }  
1627 -  
1628 - clientTransaction.sendRequest();  
1629 - return clientTransaction;  
1630 - }  
1631 -  
1632 - /**  
1633 - * 回放暂停  
1634 - */  
1635 - @Override  
1636 - public void playPauseCmd(Device device, StreamInfo streamInfo) {  
1637 - try {  
1638 - StringBuffer content = new StringBuffer(200);  
1639 - content.append("PAUSE RTSP/1.0\r\n");  
1640 - content.append("CSeq: " + getInfoCseq() + "\r\n");  
1641 - content.append("PauseTime: now\r\n");  
1642 - Request request = headerProvider.createInfoRequest(device, streamInfo, content.toString());  
1643 - if (request == null) {  
1644 - return;  
1645 - }  
1646 - logger.info(request.toString());  
1647 - ClientTransaction clientTransaction = null;  
1648 - if ("TCP".equals(device.getTransport())) {  
1649 - clientTransaction = tcpSipProvider.getNewClientTransaction(request);  
1650 - } else if ("UDP".equals(device.getTransport())) {  
1651 - clientTransaction = udpSipProvider.getNewClientTransaction(request);  
1652 - }  
1653 - if (clientTransaction != null) {  
1654 - clientTransaction.sendRequest();  
1655 - }  
1656 -  
1657 - } catch (SipException | ParseException | InvalidArgumentException e) {  
1658 - e.printStackTrace();  
1659 - }  
1660 - }  
1661 -  
1662 - /**  
1663 - * 回放恢复  
1664 - */  
1665 - @Override  
1666 - public void playResumeCmd(Device device, StreamInfo streamInfo) {  
1667 - try {  
1668 - StringBuffer content = new StringBuffer(200);  
1669 - content.append("PLAY RTSP/1.0\r\n");  
1670 - content.append("CSeq: " + getInfoCseq() + "\r\n");  
1671 - content.append("Range: npt=now-\r\n");  
1672 - Request request = headerProvider.createInfoRequest(device, streamInfo, content.toString());  
1673 - if (request == null) {  
1674 - return;  
1675 - }  
1676 - logger.info(request.toString());  
1677 - ClientTransaction clientTransaction = null;  
1678 - if ("TCP".equals(device.getTransport())) {  
1679 - clientTransaction = tcpSipProvider.getNewClientTransaction(request);  
1680 - } else if ("UDP".equals(device.getTransport())) {  
1681 - clientTransaction = udpSipProvider.getNewClientTransaction(request);  
1682 - }  
1683 -  
1684 - clientTransaction.sendRequest();  
1685 -  
1686 - } catch (SipException | ParseException | InvalidArgumentException e) {  
1687 - e.printStackTrace();  
1688 - }  
1689 - }  
1690 -  
1691 - /**  
1692 - * 回放拖动播放  
1693 - */  
1694 - @Override  
1695 - public void playSeekCmd(Device device, StreamInfo streamInfo, long seekTime) {  
1696 - try {  
1697 - StringBuffer content = new StringBuffer(200);  
1698 - content.append("PLAY RTSP/1.0\r\n");  
1699 - content.append("CSeq: " + getInfoCseq() + "\r\n");  
1700 - content.append("Range: npt=" + Math.abs(seekTime) + "-\r\n");  
1701 -  
1702 - Request request = headerProvider.createInfoRequest(device, streamInfo, content.toString());  
1703 - if (request == null) {  
1704 - return;  
1705 - }  
1706 - logger.info(request.toString());  
1707 - ClientTransaction clientTransaction = null;  
1708 - if ("TCP".equals(device.getTransport())) {  
1709 - clientTransaction = tcpSipProvider.getNewClientTransaction(request);  
1710 - } else if ("UDP".equals(device.getTransport())) {  
1711 - clientTransaction = udpSipProvider.getNewClientTransaction(request);  
1712 - }  
1713 -  
1714 - clientTransaction.sendRequest();  
1715 -  
1716 - } catch (SipException | ParseException | InvalidArgumentException e) {  
1717 - e.printStackTrace();  
1718 - }  
1719 - }  
1720 -  
1721 - /**  
1722 - * 回放倍速播放  
1723 - */  
1724 - @Override  
1725 - public void playSpeedCmd(Device device, StreamInfo streamInfo, Double speed) {  
1726 - try {  
1727 -  
1728 - StringBuffer content = new StringBuffer(200);  
1729 - content.append("PLAY RTSP/1.0\r\n");  
1730 - content.append("CSeq: " + getInfoCseq() + "\r\n");  
1731 - content.append("Scale: " + String.format("%.6f",speed) + "\r\n");  
1732 - Request request = headerProvider.createInfoRequest(device, streamInfo, content.toString());  
1733 - if (request == null) {  
1734 - return;  
1735 - }  
1736 - logger.info(request.toString());  
1737 - ClientTransaction clientTransaction = null;  
1738 - if ("TCP".equals(device.getTransport())) {  
1739 - clientTransaction = tcpSipProvider.getNewClientTransaction(request);  
1740 - } else if ("UDP".equals(device.getTransport())) {  
1741 - clientTransaction = udpSipProvider.getNewClientTransaction(request);  
1742 - }  
1743 -  
1744 - clientTransaction.sendRequest();  
1745 -  
1746 - } catch (SipException | ParseException | InvalidArgumentException e) {  
1747 - e.printStackTrace();  
1748 - }  
1749 - }  
1750 -  
1751 - private int getInfoCseq() {  
1752 - return (int) ((Math.random() * 9 + 1) * Math.pow(10, 8));  
1753 - }  
1754 -  
1755 - @Override  
1756 - public void playbackControlCmd(Device device, StreamInfo streamInfo, String content,SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) {  
1757 - try {  
1758 - Request request = headerProvider.createInfoRequest(device, streamInfo, content);  
1759 - if (request == null) {  
1760 - return;  
1761 - }  
1762 - ClientTransaction clientTransaction = null;  
1763 - if ("TCP".equals(device.getTransport())) {  
1764 - clientTransaction = tcpSipProvider.getNewClientTransaction(request);  
1765 - } else if ("UDP".equals(device.getTransport())) {  
1766 - clientTransaction = udpSipProvider.getNewClientTransaction(request);  
1767 - }  
1768 - CallIdHeader callIdHeader = (CallIdHeader)request.getHeader(CallIdHeader.NAME);  
1769 - if(errorEvent != null) {  
1770 - sipSubscribe.addErrorSubscribe(callIdHeader.getCallId(), (eventResult -> {  
1771 - errorEvent.response(eventResult);  
1772 - sipSubscribe.removeErrorSubscribe(eventResult.callId);  
1773 - sipSubscribe.removeOkSubscribe(eventResult.callId);  
1774 - }));  
1775 - }  
1776 -  
1777 - if(okEvent != null) {  
1778 - sipSubscribe.addOkSubscribe(callIdHeader.getCallId(), eventResult -> {  
1779 - okEvent.response(eventResult);  
1780 - sipSubscribe.removeOkSubscribe(eventResult.callId);  
1781 - sipSubscribe.removeErrorSubscribe(eventResult.callId);  
1782 - });  
1783 - }  
1784 - clientTransaction.sendRequest();  
1785 -  
1786 - } catch (SipException | ParseException | InvalidArgumentException e) {  
1787 - e.printStackTrace();  
1788 - }  
1789 - }  
1790 -  
1791 - @Override  
1792 - public boolean sendAlarmMessage(Device device, DeviceAlarm deviceAlarm) {  
1793 - if (device == null) {  
1794 - return false;  
1795 - }  
1796 - logger.info("[发送 报警通知] {}/{}->{},{}", device.getDeviceId(), deviceAlarm.getChannelId(),  
1797 - deviceAlarm.getLongitude(), deviceAlarm.getLatitude());  
1798 - try {  
1799 - String characterSet = device.getCharset();  
1800 - StringBuffer deviceStatusXml = new StringBuffer(600);  
1801 - deviceStatusXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n");  
1802 - deviceStatusXml.append("<Notify>\r\n");  
1803 - deviceStatusXml.append("<CmdType>Alarm</CmdType>\r\n");  
1804 - deviceStatusXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");  
1805 - deviceStatusXml.append("<DeviceID>" + deviceAlarm.getChannelId() + "</DeviceID>\r\n");  
1806 - deviceStatusXml.append("<AlarmPriority>" + deviceAlarm.getAlarmPriority() + "</AlarmPriority>\r\n");  
1807 - deviceStatusXml.append("<AlarmMethod>" + deviceAlarm.getAlarmMethod() + "</AlarmMethod>\r\n");  
1808 - deviceStatusXml.append("<AlarmTime>" + deviceAlarm.getAlarmTime() + "</AlarmTime>\r\n");  
1809 - deviceStatusXml.append("<AlarmDescription>" + deviceAlarm.getAlarmDescription() + "</AlarmDescription>\r\n");  
1810 - deviceStatusXml.append("<Longitude>" + deviceAlarm.getLongitude() + "</Longitude>\r\n");  
1811 - deviceStatusXml.append("<Latitude>" + deviceAlarm.getLatitude() + "</Latitude>\r\n");  
1812 - deviceStatusXml.append("<info>\r\n");  
1813 - deviceStatusXml.append("<AlarmType>" + deviceAlarm.getAlarmType() + "</AlarmType>\r\n");  
1814 - deviceStatusXml.append("</info>\r\n");  
1815 - deviceStatusXml.append("</Notify>\r\n");  
1816 -  
1817 - CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()  
1818 - : udpSipProvider.getNewCallId();  
1819 - Request request = headerProvider.createMessageRequest(device, deviceStatusXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null, callIdHeader);  
1820 - transmitRequest(device, request);  
1821 -  
1822 -  
1823 - } catch (SipException | ParseException e) {  
1824 - e.printStackTrace();  
1825 - return false;  
1826 - } catch (InvalidArgumentException e) {  
1827 - throw new RuntimeException(e);  
1828 - }  
1829 - return true;  
1830 - } 365 + CallIdHeader callIdHeader = device.getTransport().equalsIgnoreCase("TCP") ? tcpSipProvider.getNewCallId()
  366 + : udpSipProvider.getNewCallId();
  367 +
  368 + Request request = headerProvider.createInviteRequest(device, channelId, content.toString(), null, SipUtils.getNewFromTag(), null, ssrcInfo.getSsrc(), callIdHeader);
  369 + transmitRequest(device.getTransport(), request, (e -> {
  370 + streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream());
  371 + mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc());
  372 + errorEvent.response(e);
  373 + }), e -> {
  374 + // 这里为例避免一个通道的点播只有一个callID这个参数使用一个固定值
  375 + ResponseEvent responseEvent = (ResponseEvent) e.event;
  376 + SIPResponse response = (SIPResponse) responseEvent.getResponse();
  377 + streamSession.put(device.getDeviceId(), channelId, "play", stream, ssrcInfo.getSsrc(), mediaServerItem.getId(), response, VideoStreamSessionManager.SessionType.play);
  378 + okEvent.response(e);
  379 + });
  380 + }
  381 +
  382 + /**
  383 + * 请求回放视频流
  384 + *
  385 + * @param device 视频设备
  386 + * @param channelId 预览通道
  387 + * @param startTime 开始时间,格式要求:yyyy-MM-dd HH:mm:ss
  388 + * @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss
  389 + */
  390 + @Override
  391 + public void playbackStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId,
  392 + String startTime, String endTime, InviteStreamCallback inviteStreamCallback, InviteStreamCallback hookEvent,
  393 + SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException {
  394 +
  395 +
  396 + logger.info("{} 分配的ZLM为: {} [{}:{}]", ssrcInfo.getStream(), mediaServerItem.getId(), mediaServerItem.getIp(), ssrcInfo.getPort());
  397 +
  398 + StringBuffer content = new StringBuffer(200);
  399 + content.append("v=0\r\n");
  400 + content.append("o=" + channelId + " 0 0 IN IP4 " + mediaServerItem.getSdpIp() + "\r\n");
  401 + content.append("s=Playback\r\n");
  402 + content.append("u=" + channelId + ":0\r\n");
  403 + content.append("c=IN IP4 " + mediaServerItem.getSdpIp() + "\r\n");
  404 + content.append("t=" + DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(startTime) + " "
  405 + + DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(endTime) + "\r\n");
  406 +
  407 + String streamMode = device.getStreamMode();
  408 +
  409 + if (userSetting.isSeniorSdp()) {
  410 + if ("TCP-PASSIVE".equalsIgnoreCase(streamMode)) {
  411 + content.append("m=video " + ssrcInfo.getPort() + " TCP/RTP/AVP 96 126 125 99 34 98 97\r\n");
  412 + } else if ("TCP-ACTIVE".equalsIgnoreCase(streamMode)) {
  413 + content.append("m=video " + ssrcInfo.getPort() + " TCP/RTP/AVP 96 126 125 99 34 98 97\r\n");
  414 + } else if ("UDP".equalsIgnoreCase(streamMode)) {
  415 + content.append("m=video " + ssrcInfo.getPort() + " RTP/AVP 96 126 125 99 34 98 97\r\n");
  416 + }
  417 + content.append("a=recvonly\r\n");
  418 + content.append("a=rtpmap:96 PS/90000\r\n");
  419 + content.append("a=fmtp:126 profile-level-id=42e01e\r\n");
  420 + content.append("a=rtpmap:126 H264/90000\r\n");
  421 + content.append("a=rtpmap:125 H264S/90000\r\n");
  422 + content.append("a=fmtp:125 profile-level-id=42e01e\r\n");
  423 + content.append("a=rtpmap:99 H265/90000\r\n");
  424 + content.append("a=rtpmap:98 H264/90000\r\n");
  425 + content.append("a=rtpmap:97 MPEG4/90000\r\n");
  426 + if ("TCP-PASSIVE".equalsIgnoreCase(streamMode)) { // tcp被动模式
  427 + content.append("a=setup:passive\r\n");
  428 + content.append("a=connection:new\r\n");
  429 + } else if ("TCP-ACTIVE".equalsIgnoreCase(streamMode)) { // tcp主动模式
  430 + content.append("a=setup:active\r\n");
  431 + content.append("a=connection:new\r\n");
  432 + }
  433 + } else {
  434 + if ("TCP-PASSIVE".equalsIgnoreCase(streamMode)) {
  435 + content.append("m=video " + ssrcInfo.getPort() + " TCP/RTP/AVP 96 97 98 99\r\n");
  436 + } else if ("TCP-ACTIVE".equalsIgnoreCase(streamMode)) {
  437 + content.append("m=video " + ssrcInfo.getPort() + " TCP/RTP/AVP 96 97 98 99\r\n");
  438 + } else if ("UDP".equalsIgnoreCase(streamMode)) {
  439 + content.append("m=video " + ssrcInfo.getPort() + " RTP/AVP 96 97 98 99\r\n");
  440 + }
  441 + content.append("a=recvonly\r\n");
  442 + content.append("a=rtpmap:96 PS/90000\r\n");
  443 + content.append("a=rtpmap:97 MPEG4/90000\r\n");
  444 + content.append("a=rtpmap:98 H264/90000\r\n");
  445 + content.append("a=rtpmap:99 H265/90000\r\n");
  446 + if ("TCP-PASSIVE".equalsIgnoreCase(streamMode)) { // tcp被动模式
  447 + content.append("a=setup:passive\r\n");
  448 + content.append("a=connection:new\r\n");
  449 + } else if ("TCP-ACTIVE".equalsIgnoreCase(streamMode)) { // tcp主动模式
  450 + content.append("a=setup:active\r\n");
  451 + content.append("a=connection:new\r\n");
  452 + }
  453 + }
  454 +
  455 + content.append("y=" + ssrcInfo.getSsrc() + "\r\n");//ssrc
  456 +
  457 + CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
  458 + : udpSipProvider.getNewCallId();
  459 + HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", ssrcInfo.getStream(), true, "rtsp", mediaServerItem.getId());
  460 + // 添加订阅
  461 + subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, JSONObject json) -> {
  462 + if (hookEvent != null) {
  463 + InviteStreamInfo inviteStreamInfo = new InviteStreamInfo(mediaServerItemInUse, json, callIdHeader.getCallId(), "rtp", ssrcInfo.getStream());
  464 + hookEvent.call(inviteStreamInfo);
  465 + }
  466 + subscribe.removeSubscribe(hookSubscribe);
  467 + });
  468 + Request request = headerProvider.createPlaybackInviteRequest(device, channelId, content.toString(), null, SipUtils.getNewFromTag(), null, callIdHeader, ssrcInfo.getSsrc());
  469 +
  470 + transmitRequest(device.getTransport(), request, errorEvent, event -> {
  471 + ResponseEvent responseEvent = (ResponseEvent) event.event;
  472 + SIPResponse response = (SIPResponse) responseEvent.getResponse();
  473 + streamSession.put(device.getDeviceId(), channelId, callIdHeader.getCallId(), ssrcInfo.getStream(), ssrcInfo.getSsrc(), mediaServerItem.getId(), response, VideoStreamSessionManager.SessionType.playback);
  474 + okEvent.response(event);
  475 + });
  476 + if (inviteStreamCallback != null) {
  477 + inviteStreamCallback.call(new InviteStreamInfo(mediaServerItem, null, callIdHeader.getCallId(), "rtp", ssrcInfo.getStream()));
  478 + }
  479 + }
  480 +
  481 + /**
  482 + * 请求历史媒体下载
  483 + *
  484 + * @param device 视频设备
  485 + * @param channelId 预览通道
  486 + * @param startTime 开始时间,格式要求:yyyy-MM-dd HH:mm:ss
  487 + * @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss
  488 + * @param downloadSpeed 下载倍速参数
  489 + */
  490 + @Override
  491 + public void downloadStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId,
  492 + String startTime, String endTime, int downloadSpeed, InviteStreamCallback inviteStreamCallback, InviteStreamCallback hookEvent,
  493 + SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException {
  494 +
  495 + logger.info("{} 分配的ZLM为: {} [{}:{}]", ssrcInfo.getStream(), mediaServerItem.getId(), mediaServerItem.getIp(), ssrcInfo.getPort());
  496 +
  497 + StringBuffer content = new StringBuffer(200);
  498 + content.append("v=0\r\n");
  499 + content.append("o=" + channelId + " 0 0 IN IP4 " + mediaServerItem.getSdpIp() + "\r\n");
  500 + content.append("s=Download\r\n");
  501 + content.append("u=" + channelId + ":0\r\n");
  502 + content.append("c=IN IP4 " + mediaServerItem.getSdpIp() + "\r\n");
  503 + content.append("t=" + DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(startTime) + " "
  504 + + DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(endTime) + "\r\n");
  505 +
  506 + String streamMode = device.getStreamMode().toUpperCase();
  507 +
  508 + if (userSetting.isSeniorSdp()) {
  509 + if ("TCP-PASSIVE".equals(streamMode)) {
  510 + content.append("m=video " + ssrcInfo.getPort() + " TCP/RTP/AVP 96 126 125 99 34 98 97\r\n");
  511 + } else if ("TCP-ACTIVE".equals(streamMode)) {
  512 + content.append("m=video " + ssrcInfo.getPort() + " TCP/RTP/AVP 96 126 125 99 34 98 97\r\n");
  513 + } else if ("UDP".equals(streamMode)) {
  514 + content.append("m=video " + ssrcInfo.getPort() + " RTP/AVP 96 126 125 99 34 98 97\r\n");
  515 + }
  516 + content.append("a=recvonly\r\n");
  517 + content.append("a=rtpmap:96 PS/90000\r\n");
  518 + content.append("a=fmtp:126 profile-level-id=42e01e\r\n");
  519 + content.append("a=rtpmap:126 H264/90000\r\n");
  520 + content.append("a=rtpmap:125 H264S/90000\r\n");
  521 + content.append("a=fmtp:125 profile-level-id=42e01e\r\n");
  522 + content.append("a=rtpmap:99 MP4V-ES/90000\r\n");
  523 + content.append("a=fmtp:99 profile-level-id=3\r\n");
  524 + content.append("a=rtpmap:98 H264/90000\r\n");
  525 + content.append("a=rtpmap:97 MPEG4/90000\r\n");
  526 + if ("TCP-PASSIVE".equals(streamMode)) { // tcp被动模式
  527 + content.append("a=setup:passive\r\n");
  528 + content.append("a=connection:new\r\n");
  529 + } else if ("TCP-ACTIVE".equals(streamMode)) { // tcp主动模式
  530 + content.append("a=setup:active\r\n");
  531 + content.append("a=connection:new\r\n");
  532 + }
  533 + } else {
  534 + if ("TCP-PASSIVE".equals(streamMode)) {
  535 + content.append("m=video " + ssrcInfo.getPort() + " TCP/RTP/AVP 96 97 98 99\r\n");
  536 + } else if ("TCP-ACTIVE".equals(streamMode)) {
  537 + content.append("m=video " + ssrcInfo.getPort() + " TCP/RTP/AVP 96 97 98 99\r\n");
  538 + } else if ("UDP".equals(streamMode)) {
  539 + content.append("m=video " + ssrcInfo.getPort() + " RTP/AVP 96 97 98 99\r\n");
  540 + }
  541 + content.append("a=recvonly\r\n");
  542 + content.append("a=rtpmap:96 PS/90000\r\n");
  543 + content.append("a=rtpmap:97 MPEG4/90000\r\n");
  544 + content.append("a=rtpmap:98 H264/90000\r\n");
  545 + content.append("a=rtpmap:99 H265/90000\r\n");
  546 + if ("TCP-PASSIVE".equals(streamMode)) { // tcp被动模式
  547 + content.append("a=setup:passive\r\n");
  548 + content.append("a=connection:new\r\n");
  549 + } else if ("TCP-ACTIVE".equals(streamMode)) { // tcp主动模式
  550 + content.append("a=setup:active\r\n");
  551 + content.append("a=connection:new\r\n");
  552 + }
  553 + }
  554 + content.append("a=downloadspeed:" + downloadSpeed + "\r\n");
  555 +
  556 + content.append("y=" + ssrcInfo.getSsrc() + "\r\n");//ssrc
  557 +
  558 + CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
  559 + : udpSipProvider.getNewCallId();
  560 +
  561 + HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", ssrcInfo.getStream(), true, null, mediaServerItem.getId());
  562 + // 添加订阅
  563 + subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, JSONObject json) -> {
  564 + hookEvent.call(new InviteStreamInfo(mediaServerItem, json, callIdHeader.getCallId(), "rtp", ssrcInfo.getStream()));
  565 + subscribe.removeSubscribe(hookSubscribe);
  566 + hookSubscribe.getContent().put("regist", false);
  567 + hookSubscribe.getContent().put("schema", "rtsp");
  568 + // 添加流注销的订阅,注销了后向设备发送bye
  569 + subscribe.addSubscribe(hookSubscribe,
  570 + (MediaServerItem mediaServerItemForEnd, JSONObject jsonForEnd) -> {
  571 + logger.info("[录像]下载结束, 发送BYE");
  572 + try {
  573 + streamByeCmd(device, channelId, ssrcInfo.getStream(), callIdHeader.getCallId());
  574 + } catch (InvalidArgumentException | ParseException | SipException |
  575 + SsrcTransactionNotFoundException e) {
  576 + logger.error("[录像]下载结束, 发送BYE失败 {}", e.getMessage());
  577 + }
  578 + });
  579 + });
  580 +
  581 + Request request = headerProvider.createPlaybackInviteRequest(device, channelId, content.toString(), null, SipUtils.getNewFromTag(), null, callIdHeader, ssrcInfo.getSsrc());
  582 + if (inviteStreamCallback != null) {
  583 + inviteStreamCallback.call(new InviteStreamInfo(mediaServerItem, null, callIdHeader.getCallId(), "rtp", ssrcInfo.getStream()));
  584 + }
  585 + transmitRequest(device.getTransport(), request, errorEvent, okEvent -> {
  586 + ResponseEvent responseEvent = (ResponseEvent) okEvent.event;
  587 + SIPResponse response = (SIPResponse) responseEvent.getResponse();
  588 + streamSession.put(device.getDeviceId(), channelId, callIdHeader.getCallId(), ssrcInfo.getStream(), ssrcInfo.getSsrc(), mediaServerItem.getId(), response, VideoStreamSessionManager.SessionType.download);
  589 + });
  590 + }
  591 +
  592 + /**
  593 + * 视频流停止, 不使用回调
  594 + */
  595 + @Override
  596 + public void streamByeCmd(Device device, String channelId, String stream, String callId) throws InvalidArgumentException, ParseException, SipException, SsrcTransactionNotFoundException {
  597 + streamByeCmd(device, channelId, stream, callId, null);
  598 + }
  599 +
  600 + /**
  601 + * 视频流停止
  602 + */
  603 + @Override
  604 + public void streamByeCmd(Device device, String channelId, String stream, String callId, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException, SsrcTransactionNotFoundException {
  605 + SsrcTransaction ssrcTransaction = streamSession.getSsrcTransaction(device.getDeviceId(), channelId, callId, stream);
  606 + if (ssrcTransaction == null) {
  607 + throw new SsrcTransactionNotFoundException(device.getDeviceId(), channelId, callId, stream);
  608 + }
  609 +
  610 + mediaServerService.releaseSsrc(ssrcTransaction.getMediaServerId(), ssrcTransaction.getSsrc());
  611 + mediaServerService.closeRTPServer(ssrcTransaction.getMediaServerId(), ssrcTransaction.getStream());
  612 + streamSession.remove(ssrcTransaction.getDeviceId(), ssrcTransaction.getChannelId(), ssrcTransaction.getStream());
  613 +
  614 + Request byteRequest = headerProvider.createByteRequest(device, channelId, ssrcTransaction.getSipTransactionInfo());
  615 + transmitRequest(device.getTransport(), byteRequest, null, okEvent);
  616 + }
  617 +
  618 + /**
  619 + * 语音广播
  620 + *
  621 + * @param device 视频设备
  622 + * @param channelId 预览通道
  623 + */
  624 + @Override
  625 + public void audioBroadcastCmd(Device device, String channelId) {
  626 + }
  627 +
  628 + /**
  629 + * 语音广播
  630 + *
  631 + * @param device 视频设备
  632 + */
  633 + @Override
  634 + public void audioBroadcastCmd(Device device) throws InvalidArgumentException, SipException, ParseException {
  635 +
  636 + StringBuffer broadcastXml = new StringBuffer(200);
  637 + String charset = device.getCharset();
  638 + broadcastXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
  639 + broadcastXml.append("<Notify>\r\n");
  640 + broadcastXml.append("<CmdType>Broadcast</CmdType>\r\n");
  641 + broadcastXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n");
  642 + broadcastXml.append("<SourceID>" + sipConfig.getId() + "</SourceID>\r\n");
  643 + broadcastXml.append("<TargetID>" + device.getDeviceId() + "</TargetID>\r\n");
  644 + broadcastXml.append("</Notify>\r\n");
  645 +
  646 + CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
  647 + : udpSipProvider.getNewCallId();
  648 +
  649 + Request request = headerProvider.createMessageRequest(device, broadcastXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null, callIdHeader);
  650 + transmitRequest(device.getTransport(), request);
  651 +
  652 + }
  653 +
  654 + @Override
  655 + public void audioBroadcastCmd(Device device, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException {
  656 +
  657 + StringBuffer broadcastXml = new StringBuffer(200);
  658 + String charset = device.getCharset();
  659 + broadcastXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
  660 + broadcastXml.append("<Notify>\r\n");
  661 + broadcastXml.append("<CmdType>Broadcast</CmdType>\r\n");
  662 + broadcastXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n");
  663 + broadcastXml.append("<SourceID>" + sipConfig.getId() + "</SourceID>\r\n");
  664 + broadcastXml.append("<TargetID>" + device.getDeviceId() + "</TargetID>\r\n");
  665 + broadcastXml.append("</Notify>\r\n");
  666 +
  667 + CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
  668 + : udpSipProvider.getNewCallId();
  669 +
  670 + Request request = headerProvider.createMessageRequest(device, broadcastXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null, callIdHeader);
  671 + transmitRequest(device.getTransport(), request, errorEvent);
  672 +
  673 + }
  674 +
  675 +
  676 + /**
  677 + * 音视频录像控制
  678 + *
  679 + * @param device 视频设备
  680 + * @param channelId 预览通道
  681 + * @param recordCmdStr 录像命令:Record / StopRecord
  682 + */
  683 + @Override
  684 + public void recordCmd(Device device, String channelId, String recordCmdStr, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException {
  685 + StringBuffer cmdXml = new StringBuffer(200);
  686 + String charset = device.getCharset();
  687 + cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
  688 + cmdXml.append("<Control>\r\n");
  689 + cmdXml.append("<CmdType>DeviceControl</CmdType>\r\n");
  690 + cmdXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n");
  691 + if (ObjectUtils.isEmpty(channelId)) {
  692 + cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
  693 + } else {
  694 + cmdXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n");
  695 + }
  696 + cmdXml.append("<RecordCmd>" + recordCmdStr + "</RecordCmd>\r\n");
  697 + cmdXml.append("</Control>\r\n");
  698 +
  699 + CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
  700 + : udpSipProvider.getNewCallId();
  701 +
  702 + Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null, callIdHeader);
  703 + transmitRequest(device.getTransport(), request, errorEvent);
  704 + }
  705 +
  706 + /**
  707 + * 远程启动控制命令
  708 + *
  709 + * @param device 视频设备
  710 + */
  711 + @Override
  712 + public void teleBootCmd(Device device) throws InvalidArgumentException, SipException, ParseException {
  713 +
  714 + StringBuffer cmdXml = new StringBuffer(200);
  715 + String charset = device.getCharset();
  716 + cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
  717 + cmdXml.append("<Control>\r\n");
  718 + cmdXml.append("<CmdType>DeviceControl</CmdType>\r\n");
  719 + cmdXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n");
  720 + cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
  721 + cmdXml.append("<TeleBoot>Boot</TeleBoot>\r\n");
  722 + cmdXml.append("</Control>\r\n");
  723 +
  724 + CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
  725 + : udpSipProvider.getNewCallId();
  726 +
  727 + Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null, callIdHeader);
  728 + transmitRequest(device.getTransport(), request);
  729 + }
  730 +
  731 + /**
  732 + * 报警布防/撤防命令
  733 + *
  734 + * @param device 视频设备
  735 + * @param guardCmdStr "SetGuard"/"ResetGuard"
  736 + */
  737 + @Override
  738 + public void guardCmd(Device device, String guardCmdStr, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException {
  739 +
  740 + StringBuffer cmdXml = new StringBuffer(200);
  741 + String charset = device.getCharset();
  742 + cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
  743 + cmdXml.append("<Control>\r\n");
  744 + cmdXml.append("<CmdType>DeviceControl</CmdType>\r\n");
  745 + cmdXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n");
  746 + cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
  747 + cmdXml.append("<GuardCmd>" + guardCmdStr + "</GuardCmd>\r\n");
  748 + cmdXml.append("</Control>\r\n");
  749 +
  750 + CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
  751 + : udpSipProvider.getNewCallId();
  752 +
  753 + Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null, callIdHeader);
  754 + transmitRequest(device.getTransport(), request, errorEvent);
  755 + }
  756 +
  757 + /**
  758 + * 报警复位命令
  759 + *
  760 + * @param device 视频设备
  761 + */
  762 + @Override
  763 + public void alarmCmd(Device device, String alarmMethod, String alarmType, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException {
  764 +
  765 + StringBuffer cmdXml = new StringBuffer(200);
  766 + String charset = device.getCharset();
  767 + cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
  768 + cmdXml.append("<Control>\r\n");
  769 + cmdXml.append("<CmdType>DeviceControl</CmdType>\r\n");
  770 + cmdXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n");
  771 + cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
  772 + cmdXml.append("<AlarmCmd>ResetAlarm</AlarmCmd>\r\n");
  773 + if (!ObjectUtils.isEmpty(alarmMethod) || !ObjectUtils.isEmpty(alarmType)) {
  774 + cmdXml.append("<Info>\r\n");
  775 + }
  776 + if (!ObjectUtils.isEmpty(alarmMethod)) {
  777 + cmdXml.append("<AlarmMethod>" + alarmMethod + "</AlarmMethod>\r\n");
  778 + }
  779 + if (!ObjectUtils.isEmpty(alarmType)) {
  780 + cmdXml.append("<AlarmType>" + alarmType + "</AlarmType>\r\n");
  781 + }
  782 + if (!ObjectUtils.isEmpty(alarmMethod) || !ObjectUtils.isEmpty(alarmType)) {
  783 + cmdXml.append("</Info>\r\n");
  784 + }
  785 + cmdXml.append("</Control>\r\n");
  786 +
  787 + CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
  788 + : udpSipProvider.getNewCallId();
  789 +
  790 + Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null, callIdHeader);
  791 + transmitRequest(device.getTransport(), request, errorEvent);
  792 + }
  793 +
  794 + /**
  795 + * 强制关键帧命令,设备收到此命令应立刻发送一个IDR帧
  796 + *
  797 + * @param device 视频设备
  798 + * @param channelId 预览通道
  799 + */
  800 + @Override
  801 + public void iFrameCmd(Device device, String channelId) throws InvalidArgumentException, SipException, ParseException {
  802 +
  803 + StringBuffer cmdXml = new StringBuffer(200);
  804 + String charset = device.getCharset();
  805 + cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
  806 + cmdXml.append("<Control>\r\n");
  807 + cmdXml.append("<CmdType>DeviceControl</CmdType>\r\n");
  808 + cmdXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n");
  809 + if (ObjectUtils.isEmpty(channelId)) {
  810 + cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
  811 + } else {
  812 + cmdXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n");
  813 + }
  814 + cmdXml.append("<IFameCmd>Send</IFameCmd>\r\n");
  815 + cmdXml.append("</Control>\r\n");
  816 +
  817 + CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
  818 + : udpSipProvider.getNewCallId();
  819 +
  820 + Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null, callIdHeader);
  821 + transmitRequest(device.getTransport(), request);
  822 + }
  823 +
  824 + /**
  825 + * 看守位控制命令
  826 + *
  827 + * @param device 视频设备
  828 + * @param enabled 看守位使能:1 = 开启,0 = 关闭
  829 + * @param resetTime 自动归位时间间隔,开启看守位时使用,单位:秒(s)
  830 + * @param presetIndex 调用预置位编号,开启看守位时使用,取值范围0~255
  831 + */
  832 + @Override
  833 + public void homePositionCmd(Device device, String channelId, String enabled, String resetTime, String presetIndex, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException {
  834 +
  835 + StringBuffer cmdXml = new StringBuffer(200);
  836 + String charset = device.getCharset();
  837 + cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
  838 + cmdXml.append("<Control>\r\n");
  839 + cmdXml.append("<CmdType>DeviceControl</CmdType>\r\n");
  840 + cmdXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n");
  841 + if (ObjectUtils.isEmpty(channelId)) {
  842 + cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
  843 + } else {
  844 + cmdXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n");
  845 + }
  846 + cmdXml.append("<HomePosition>\r\n");
  847 + if (NumericUtil.isInteger(enabled) && (!enabled.equals("0"))) {
  848 + cmdXml.append("<Enabled>1</Enabled>\r\n");
  849 + if (NumericUtil.isInteger(resetTime)) {
  850 + cmdXml.append("<ResetTime>" + resetTime + "</ResetTime>\r\n");
  851 + } else {
  852 + cmdXml.append("<ResetTime>0</ResetTime>\r\n");
  853 + }
  854 + if (NumericUtil.isInteger(presetIndex)) {
  855 + cmdXml.append("<PresetIndex>" + presetIndex + "</PresetIndex>\r\n");
  856 + } else {
  857 + cmdXml.append("<PresetIndex>0</PresetIndex>\r\n");
  858 + }
  859 + } else {
  860 + cmdXml.append("<Enabled>0</Enabled>\r\n");
  861 + }
  862 + cmdXml.append("</HomePosition>\r\n");
  863 + cmdXml.append("</Control>\r\n");
  864 +
  865 + CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
  866 + : udpSipProvider.getNewCallId();
  867 +
  868 + Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null, callIdHeader);
  869 + transmitRequest(device.getTransport(), request, errorEvent);
  870 + }
  871 +
  872 + /**
  873 + * 设备配置命令
  874 + *
  875 + * @param device 视频设备
  876 + */
  877 + @Override
  878 + public void deviceConfigCmd(Device device) {
  879 + // TODO Auto-generated method stub
  880 + }
  881 +
  882 + /**
  883 + * 设备配置命令:basicParam
  884 + *
  885 + * @param device 视频设备
  886 + * @param channelId 通道编码(可选)
  887 + * @param name 设备/通道名称(可选)
  888 + * @param expiration 注册过期时间(可选)
  889 + * @param heartBeatInterval 心跳间隔时间(可选)
  890 + * @param heartBeatCount 心跳超时次数(可选)
  891 + */
  892 + @Override
  893 + public void deviceBasicConfigCmd(Device device, String channelId, String name, String expiration,
  894 + String heartBeatInterval, String heartBeatCount, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException {
  895 +
  896 + StringBuffer cmdXml = new StringBuffer(200);
  897 + String charset = device.getCharset();
  898 + cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
  899 + cmdXml.append("<Control>\r\n");
  900 + cmdXml.append("<CmdType>DeviceConfig</CmdType>\r\n");
  901 + cmdXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n");
  902 + if (ObjectUtils.isEmpty(channelId)) {
  903 + cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
  904 + } else {
  905 + cmdXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n");
  906 + }
  907 + cmdXml.append("<BasicParam>\r\n");
  908 + if (!ObjectUtils.isEmpty(name)) {
  909 + cmdXml.append("<Name>" + name + "</Name>\r\n");
  910 + }
  911 + if (NumericUtil.isInteger(expiration)) {
  912 + if (Integer.valueOf(expiration) > 0) {
  913 + cmdXml.append("<Expiration>" + expiration + "</Expiration>\r\n");
  914 + }
  915 + }
  916 + if (NumericUtil.isInteger(heartBeatInterval)) {
  917 + if (Integer.valueOf(heartBeatInterval) > 0) {
  918 + cmdXml.append("<HeartBeatInterval>" + heartBeatInterval + "</HeartBeatInterval>\r\n");
  919 + }
  920 + }
  921 + if (NumericUtil.isInteger(heartBeatCount)) {
  922 + if (Integer.valueOf(heartBeatCount) > 0) {
  923 + cmdXml.append("<HeartBeatCount>" + heartBeatCount + "</HeartBeatCount>\r\n");
  924 + }
  925 + }
  926 + cmdXml.append("</BasicParam>\r\n");
  927 + cmdXml.append("</Control>\r\n");
  928 +
  929 + CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
  930 + : udpSipProvider.getNewCallId();
  931 +
  932 + Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null, callIdHeader);
  933 + transmitRequest(device.getTransport(), request, errorEvent);
  934 + }
  935 +
  936 + /**
  937 + * 查询设备状态
  938 + *
  939 + * @param device 视频设备
  940 + */
  941 + @Override
  942 + public void deviceStatusQuery(Device device, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException {
  943 +
  944 + String charset = device.getCharset();
  945 + StringBuffer catalogXml = new StringBuffer(200);
  946 + catalogXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
  947 + catalogXml.append("<Query>\r\n");
  948 + catalogXml.append("<CmdType>DeviceStatus</CmdType>\r\n");
  949 + catalogXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n");
  950 + catalogXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
  951 + catalogXml.append("</Query>\r\n");
  952 +
  953 + CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
  954 + : udpSipProvider.getNewCallId();
  955 +
  956 + Request request = headerProvider.createMessageRequest(device, catalogXml.toString(), null, SipUtils.getNewFromTag(), null, callIdHeader);
  957 +
  958 + transmitRequest(device.getTransport(), request, errorEvent);
  959 + }
  960 +
  961 + /**
  962 + * 查询设备信息
  963 + *
  964 + * @param device 视频设备
  965 + */
  966 + @Override
  967 + public void deviceInfoQuery(Device device) throws InvalidArgumentException, SipException, ParseException {
  968 +
  969 + StringBuffer catalogXml = new StringBuffer(200);
  970 + String charset = device.getCharset();
  971 + catalogXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
  972 + catalogXml.append("<Query>\r\n");
  973 + catalogXml.append("<CmdType>DeviceInfo</CmdType>\r\n");
  974 + catalogXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n");
  975 + catalogXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
  976 + catalogXml.append("</Query>\r\n");
  977 +
  978 + CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
  979 + : udpSipProvider.getNewCallId();
  980 +
  981 + Request request = headerProvider.createMessageRequest(device, catalogXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null, callIdHeader);
  982 +
  983 + transmitRequest(device.getTransport(), request);
  984 +
  985 + }
  986 +
  987 + /**
  988 + * 查询目录列表
  989 + *
  990 + * @param device 视频设备
  991 + */
  992 + @Override
  993 + public void catalogQuery(Device device, int sn, SipSubscribe.Event errorEvent) throws SipException, InvalidArgumentException, ParseException {
  994 +
  995 + StringBuffer catalogXml = new StringBuffer(200);
  996 + String charset = device.getCharset();
  997 + catalogXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
  998 + catalogXml.append("<Query>\r\n");
  999 + catalogXml.append(" <CmdType>Catalog</CmdType>\r\n");
  1000 + catalogXml.append(" <SN>" + sn + "</SN>\r\n");
  1001 + catalogXml.append(" <DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
  1002 + catalogXml.append("</Query>\r\n");
  1003 +
  1004 + CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
  1005 + : udpSipProvider.getNewCallId();
  1006 +
  1007 + Request request = headerProvider.createMessageRequest(device, catalogXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null, callIdHeader);
  1008 +
  1009 + transmitRequest(device.getTransport(), request, errorEvent);
  1010 + }
  1011 +
  1012 + /**
  1013 + * 查询录像信息
  1014 + *
  1015 + * @param device 视频设备
  1016 + * @param startTime 开始时间,格式要求:yyyy-MM-dd HH:mm:ss
  1017 + * @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss
  1018 + */
  1019 + @Override
  1020 + 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 {
  1021 + if (secrecy == null) {
  1022 + secrecy = 0;
  1023 + }
  1024 + if (type == null) {
  1025 + type = "all";
  1026 + }
  1027 +
  1028 + StringBuffer recordInfoXml = new StringBuffer(200);
  1029 + String charset = device.getCharset();
  1030 + recordInfoXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
  1031 + recordInfoXml.append("<Query>\r\n");
  1032 + recordInfoXml.append("<CmdType>RecordInfo</CmdType>\r\n");
  1033 + recordInfoXml.append("<SN>" + sn + "</SN>\r\n");
  1034 + recordInfoXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n");
  1035 + if (startTime != null) {
  1036 + recordInfoXml.append("<StartTime>" + DateUtil.yyyy_MM_dd_HH_mm_ssToISO8601(startTime) + "</StartTime>\r\n");
  1037 + }
  1038 + if (endTime != null) {
  1039 + recordInfoXml.append("<EndTime>" + DateUtil.yyyy_MM_dd_HH_mm_ssToISO8601(endTime) + "</EndTime>\r\n");
  1040 + }
  1041 + if (secrecy != null) {
  1042 + recordInfoXml.append("<Secrecy> " + secrecy + " </Secrecy>\r\n");
  1043 + }
  1044 + if (type != null) {
  1045 + // 大华NVR要求必须增加一个值为all的文本元素节点Type
  1046 + recordInfoXml.append("<Type>" + type + "</Type>\r\n");
  1047 + }
  1048 + recordInfoXml.append("</Query>\r\n");
  1049 +
  1050 + CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
  1051 + : udpSipProvider.getNewCallId();
  1052 +
  1053 + Request request = headerProvider.createMessageRequest(device, recordInfoXml.toString(),
  1054 + SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null, callIdHeader);
  1055 +
  1056 + transmitRequest(device.getTransport(), request, errorEvent, okEvent);
  1057 + }
  1058 +
  1059 + /**
  1060 + * 查询报警信息
  1061 + *
  1062 + * @param device 视频设备
  1063 + * @param startPriority 报警起始级别(可选)
  1064 + * @param endPriority 报警终止级别(可选)
  1065 + * @param alarmMethod 报警方式条件(可选)
  1066 + * @param alarmType 报警类型
  1067 + * @param startTime 报警发生起始时间(可选)
  1068 + * @param endTime 报警发生终止时间(可选)
  1069 + * @return true = 命令发送成功
  1070 + */
  1071 + @Override
  1072 + public void alarmInfoQuery(Device device, String startPriority, String endPriority, String alarmMethod, String alarmType,
  1073 + String startTime, String endTime, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException {
  1074 +
  1075 + StringBuffer cmdXml = new StringBuffer(200);
  1076 + String charset = device.getCharset();
  1077 + cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
  1078 + cmdXml.append("<Query>\r\n");
  1079 + cmdXml.append("<CmdType>Alarm</CmdType>\r\n");
  1080 + cmdXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n");
  1081 + cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
  1082 + if (!ObjectUtils.isEmpty(startPriority)) {
  1083 + cmdXml.append("<StartAlarmPriority>" + startPriority + "</StartAlarmPriority>\r\n");
  1084 + }
  1085 + if (!ObjectUtils.isEmpty(endPriority)) {
  1086 + cmdXml.append("<EndAlarmPriority>" + endPriority + "</EndAlarmPriority>\r\n");
  1087 + }
  1088 + if (!ObjectUtils.isEmpty(alarmMethod)) {
  1089 + cmdXml.append("<AlarmMethod>" + alarmMethod + "</AlarmMethod>\r\n");
  1090 + }
  1091 + if (!ObjectUtils.isEmpty(alarmType)) {
  1092 + cmdXml.append("<AlarmType>" + alarmType + "</AlarmType>\r\n");
  1093 + }
  1094 + if (!ObjectUtils.isEmpty(startTime)) {
  1095 + cmdXml.append("<StartAlarmTime>" + startTime + "</StartAlarmTime>\r\n");
  1096 + }
  1097 + if (!ObjectUtils.isEmpty(endTime)) {
  1098 + cmdXml.append("<EndAlarmTime>" + endTime + "</EndAlarmTime>\r\n");
  1099 + }
  1100 + cmdXml.append("</Query>\r\n");
  1101 +
  1102 + CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
  1103 + : udpSipProvider.getNewCallId();
  1104 +
  1105 + Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null, callIdHeader);
  1106 + transmitRequest(device.getTransport(), request, errorEvent);
  1107 + }
  1108 +
  1109 + /**
  1110 + * 查询设备配置
  1111 + *
  1112 + * @param device 视频设备
  1113 + * @param channelId 通道编码(可选)
  1114 + * @param configType 配置类型:
  1115 + */
  1116 + @Override
  1117 + public void deviceConfigQuery(Device device, String channelId, String configType, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException {
  1118 +
  1119 + StringBuffer cmdXml = new StringBuffer(200);
  1120 + String charset = device.getCharset();
  1121 + cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
  1122 + cmdXml.append("<Query>\r\n");
  1123 + cmdXml.append("<CmdType>ConfigDownload</CmdType>\r\n");
  1124 + cmdXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n");
  1125 + if (ObjectUtils.isEmpty(channelId)) {
  1126 + cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
  1127 + } else {
  1128 + cmdXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n");
  1129 + }
  1130 + cmdXml.append("<ConfigType>" + configType + "</ConfigType>\r\n");
  1131 + cmdXml.append("</Query>\r\n");
  1132 +
  1133 + CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
  1134 + : udpSipProvider.getNewCallId();
  1135 +
  1136 + Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null, callIdHeader);
  1137 + transmitRequest(device.getTransport(), request, errorEvent);
  1138 + }
  1139 +
  1140 + /**
  1141 + * 查询设备预置位置
  1142 + *
  1143 + * @param device 视频设备
  1144 + */
  1145 + @Override
  1146 + public void presetQuery(Device device, String channelId, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException {
  1147 +
  1148 + StringBuffer cmdXml = new StringBuffer(200);
  1149 + String charset = device.getCharset();
  1150 + cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
  1151 + cmdXml.append("<Query>\r\n");
  1152 + cmdXml.append("<CmdType>PresetQuery</CmdType>\r\n");
  1153 + cmdXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n");
  1154 + if (ObjectUtils.isEmpty(channelId)) {
  1155 + cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
  1156 + } else {
  1157 + cmdXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n");
  1158 + }
  1159 + cmdXml.append("</Query>\r\n");
  1160 +
  1161 + CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
  1162 + : udpSipProvider.getNewCallId();
  1163 +
  1164 + Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null, callIdHeader);
  1165 + transmitRequest(device.getTransport(), request, errorEvent);
  1166 + }
  1167 +
  1168 + /**
  1169 + * 查询移动设备位置数据
  1170 + *
  1171 + * @param device 视频设备
  1172 + */
  1173 + @Override
  1174 + public void mobilePostitionQuery(Device device, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException {
  1175 +
  1176 + StringBuffer mobilePostitionXml = new StringBuffer(200);
  1177 + String charset = device.getCharset();
  1178 + mobilePostitionXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
  1179 + mobilePostitionXml.append("<Query>\r\n");
  1180 + mobilePostitionXml.append("<CmdType>MobilePosition</CmdType>\r\n");
  1181 + mobilePostitionXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n");
  1182 + mobilePostitionXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
  1183 + mobilePostitionXml.append("<Interval>60</Interval>\r\n");
  1184 + mobilePostitionXml.append("</Query>\r\n");
  1185 +
  1186 + CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
  1187 + : udpSipProvider.getNewCallId();
  1188 +
  1189 + Request request = headerProvider.createMessageRequest(device, mobilePostitionXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null, callIdHeader);
  1190 +
  1191 + transmitRequest(device.getTransport(), request, errorEvent);
  1192 +
  1193 + }
  1194 +
  1195 + /**
  1196 + * 订阅、取消订阅移动位置
  1197 + *
  1198 + * @param device 视频设备
  1199 + * @return true = 命令发送成功
  1200 + */
  1201 + @Override
  1202 + public SIPRequest mobilePositionSubscribe(Device device, SIPRequest requestOld, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException {
  1203 +
  1204 + StringBuffer subscribePostitionXml = new StringBuffer(200);
  1205 + String charset = device.getCharset();
  1206 + subscribePostitionXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
  1207 + subscribePostitionXml.append("<Query>\r\n");
  1208 + subscribePostitionXml.append("<CmdType>MobilePosition</CmdType>\r\n");
  1209 + subscribePostitionXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n");
  1210 + subscribePostitionXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
  1211 + if (device.getSubscribeCycleForMobilePosition() > 0) {
  1212 + subscribePostitionXml.append("<Interval>" + device.getMobilePositionSubmissionInterval() + "</Interval>\r\n");
  1213 + }
  1214 + subscribePostitionXml.append("</Query>\r\n");
  1215 +
  1216 + CallIdHeader callIdHeader;
  1217 +
  1218 + if (requestOld != null) {
  1219 + callIdHeader = sipFactory.createHeaderFactory().createCallIdHeader(requestOld.getCallIdHeader().getCallId());
  1220 + } else {
  1221 + callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
  1222 + : udpSipProvider.getNewCallId();
  1223 + }
  1224 + SIPRequest request = (SIPRequest) headerProvider.createSubscribeRequest(device, subscribePostitionXml.toString(), requestOld, device.getSubscribeCycleForMobilePosition(), "presence", callIdHeader); //Position;id=" + tm.substring(tm.length() - 4));
  1225 +
  1226 + transmitRequest(device.getTransport(), request, errorEvent, okEvent);
  1227 + return request;
  1228 + }
  1229 +
  1230 + /**
  1231 + * 订阅、取消订阅报警信息
  1232 + *
  1233 + * @param device 视频设备
  1234 + * @param expires 订阅过期时间(0 = 取消订阅)
  1235 + * @param startPriority 报警起始级别(可选)
  1236 + * @param endPriority 报警终止级别(可选)
  1237 + * @param alarmMethod 报警方式条件(可选)
  1238 + * @param alarmType 报警类型
  1239 + * @param startTime 报警发生起始时间(可选)
  1240 + * @param endTime 报警发生终止时间(可选)
  1241 + * @return true = 命令发送成功
  1242 + */
  1243 + @Override
  1244 + public void alarmSubscribe(Device device, int expires, String startPriority, String endPriority, String alarmMethod, String alarmType, String startTime, String endTime) throws InvalidArgumentException, SipException, ParseException {
  1245 +
  1246 + StringBuffer cmdXml = new StringBuffer(200);
  1247 + String charset = device.getCharset();
  1248 + cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
  1249 + cmdXml.append("<Query>\r\n");
  1250 + cmdXml.append("<CmdType>Alarm</CmdType>\r\n");
  1251 + cmdXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n");
  1252 + cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
  1253 + if (!ObjectUtils.isEmpty(startPriority)) {
  1254 + cmdXml.append("<StartAlarmPriority>" + startPriority + "</StartAlarmPriority>\r\n");
  1255 + }
  1256 + if (!ObjectUtils.isEmpty(endPriority)) {
  1257 + cmdXml.append("<EndAlarmPriority>" + endPriority + "</EndAlarmPriority>\r\n");
  1258 + }
  1259 + if (!ObjectUtils.isEmpty(alarmMethod)) {
  1260 + cmdXml.append("<AlarmMethod>" + alarmMethod + "</AlarmMethod>\r\n");
  1261 + }
  1262 + if (!ObjectUtils.isEmpty(alarmType)) {
  1263 + cmdXml.append("<AlarmType>" + alarmType + "</AlarmType>\r\n");
  1264 + }
  1265 + if (!ObjectUtils.isEmpty(startTime)) {
  1266 + cmdXml.append("<StartAlarmTime>" + startTime + "</StartAlarmTime>\r\n");
  1267 + }
  1268 + if (!ObjectUtils.isEmpty(endTime)) {
  1269 + cmdXml.append("<EndAlarmTime>" + endTime + "</EndAlarmTime>\r\n");
  1270 + }
  1271 + cmdXml.append("</Query>\r\n");
  1272 +
  1273 + CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
  1274 + : udpSipProvider.getNewCallId();
  1275 +
  1276 + Request request = headerProvider.createSubscribeRequest(device, cmdXml.toString(), null, expires, "presence", callIdHeader);
  1277 + transmitRequest(device.getTransport(), request);
  1278 +
  1279 + }
  1280 +
  1281 + @Override
  1282 + public SIPRequest catalogSubscribe(Device device, SIPRequest requestOld, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException {
  1283 +
  1284 + StringBuffer cmdXml = new StringBuffer(200);
  1285 + String charset = device.getCharset();
  1286 + cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
  1287 + cmdXml.append("<Query>\r\n");
  1288 + cmdXml.append("<CmdType>Catalog</CmdType>\r\n");
  1289 + cmdXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n");
  1290 + cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
  1291 + cmdXml.append("</Query>\r\n");
  1292 +
  1293 + CallIdHeader callIdHeader;
  1294 +
  1295 + if (requestOld != null) {
  1296 + callIdHeader = sipFactory.createHeaderFactory().createCallIdHeader(requestOld.getCallIdHeader().getCallId());
  1297 + } else {
  1298 + callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
  1299 + : udpSipProvider.getNewCallId();
  1300 + }
  1301 +
  1302 + // 有效时间默认为60秒以上
  1303 + SIPRequest request = (SIPRequest) headerProvider.createSubscribeRequest(device, cmdXml.toString(), requestOld, device.getSubscribeCycleForCatalog(), "Catalog",
  1304 + callIdHeader);
  1305 + transmitRequest(device.getTransport(), request, errorEvent, okEvent);
  1306 + return request;
  1307 + }
  1308 +
  1309 + @Override
  1310 + public void dragZoomCmd(Device device, String channelId, String cmdString) throws InvalidArgumentException, SipException, ParseException {
  1311 +
  1312 + StringBuffer dragXml = new StringBuffer(200);
  1313 + String charset = device.getCharset();
  1314 + dragXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
  1315 + dragXml.append("<Control>\r\n");
  1316 + dragXml.append("<CmdType>DeviceControl</CmdType>\r\n");
  1317 + dragXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n");
  1318 + if (ObjectUtils.isEmpty(channelId)) {
  1319 + dragXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
  1320 + } else {
  1321 + dragXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n");
  1322 + }
  1323 + dragXml.append(cmdString);
  1324 + dragXml.append("</Control>\r\n");
  1325 + CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
  1326 + : udpSipProvider.getNewCallId();
  1327 + Request request = headerProvider.createMessageRequest(device, dragXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null, callIdHeader);
  1328 + logger.debug("拉框信令: " + request.toString());
  1329 + transmitRequest(device.getTransport(), request);
  1330 + }
  1331 +
  1332 +
  1333 + @Override
  1334 + public void transmitRequest(String transport, Request request) throws SipException, ParseException {
  1335 + transmitRequest(transport, request, null, null);
  1336 + }
  1337 +
  1338 + @Override
  1339 + public void transmitRequest(String transport, Request request, SipSubscribe.Event errorEvent) throws SipException, ParseException {
  1340 + transmitRequest(transport, request, errorEvent, null);
  1341 + }
  1342 +
  1343 + @Override
  1344 + public void transmitRequest(String transport, Request request, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) throws SipException, ParseException {
  1345 +
  1346 + if (request.getHeader(UserAgentHeader.NAME) == null) {
  1347 + try {
  1348 + request.addHeader(SipUtils.createUserAgentHeader(sipFactory, gitUtil));
  1349 + } catch (ParseException e) {
  1350 + logger.error("添加UserAgentHeader失败", e);
  1351 + }
  1352 + }
  1353 +
  1354 + CallIdHeader callIdHeader = (CallIdHeader) request.getHeader(CallIdHeader.NAME);
  1355 + // 添加错误订阅
  1356 + if (errorEvent != null) {
  1357 + sipSubscribe.addErrorSubscribe(callIdHeader.getCallId(), (eventResult -> {
  1358 + errorEvent.response(eventResult);
  1359 + sipSubscribe.removeErrorSubscribe(eventResult.callId);
  1360 + sipSubscribe.removeOkSubscribe(eventResult.callId);
  1361 + }));
  1362 + }
  1363 + // 添加订阅
  1364 + if (okEvent != null) {
  1365 + sipSubscribe.addOkSubscribe(callIdHeader.getCallId(), eventResult -> {
  1366 + okEvent.response(eventResult);
  1367 + sipSubscribe.removeOkSubscribe(eventResult.callId);
  1368 + sipSubscribe.removeErrorSubscribe(eventResult.callId);
  1369 + });
  1370 + }
  1371 + if ("TCP".equals(transport)) {
  1372 + tcpSipProvider.sendRequest(request);
  1373 + } else if ("UDP".equals(transport)) {
  1374 + udpSipProvider.sendRequest(request);
  1375 + }
  1376 +
  1377 + }
  1378 +
  1379 +
  1380 + /**
  1381 + * 回放暂停
  1382 + */
  1383 + @Override
  1384 + public void playPauseCmd(Device device, StreamInfo streamInfo) throws InvalidArgumentException, ParseException, SipException {
  1385 + StringBuffer content = new StringBuffer(200);
  1386 + content.append("PAUSE RTSP/1.0\r\n");
  1387 + content.append("CSeq: " + getInfoCseq() + "\r\n");
  1388 + content.append("PauseTime: now\r\n");
  1389 +
  1390 + playbackControlCmd(device, streamInfo, content.toString(), null, null);
  1391 + }
  1392 +
  1393 +
  1394 + /**
  1395 + * 回放恢复
  1396 + */
  1397 + @Override
  1398 + public void playResumeCmd(Device device, StreamInfo streamInfo) throws InvalidArgumentException, ParseException, SipException {
  1399 + StringBuffer content = new StringBuffer(200);
  1400 + content.append("PLAY RTSP/1.0\r\n");
  1401 + content.append("CSeq: " + getInfoCseq() + "\r\n");
  1402 + content.append("Range: npt=now-\r\n");
  1403 +
  1404 + playbackControlCmd(device, streamInfo, content.toString(), null, null);
  1405 + }
  1406 +
  1407 + /**
  1408 + * 回放拖动播放
  1409 + */
  1410 + @Override
  1411 + public void playSeekCmd(Device device, StreamInfo streamInfo, long seekTime) throws InvalidArgumentException, ParseException, SipException {
  1412 + StringBuffer content = new StringBuffer(200);
  1413 + content.append("PLAY RTSP/1.0\r\n");
  1414 + content.append("CSeq: " + getInfoCseq() + "\r\n");
  1415 + content.append("Range: npt=" + Math.abs(seekTime) + "-\r\n");
  1416 +
  1417 + playbackControlCmd(device, streamInfo, content.toString(), null, null);
  1418 + }
  1419 +
  1420 + /**
  1421 + * 回放倍速播放
  1422 + */
  1423 + @Override
  1424 + public void playSpeedCmd(Device device, StreamInfo streamInfo, Double speed) throws InvalidArgumentException, ParseException, SipException {
  1425 + StringBuffer content = new StringBuffer(200);
  1426 + content.append("PLAY RTSP/1.0\r\n");
  1427 + content.append("CSeq: " + getInfoCseq() + "\r\n");
  1428 + content.append("Scale: " + String.format("%.6f", speed) + "\r\n");
  1429 +
  1430 + playbackControlCmd(device, streamInfo, content.toString(), null, null);
  1431 + }
  1432 +
  1433 + private int getInfoCseq() {
  1434 + return (int) ((Math.random() * 9 + 1) * Math.pow(10, 8));
  1435 + }
  1436 +
  1437 + @Override
  1438 + public void playbackControlCmd(Device device, StreamInfo streamInfo, String content, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) throws SipException, InvalidArgumentException, ParseException {
  1439 +
  1440 + SsrcTransaction ssrcTransaction = streamSession.getSsrcTransaction(device.getDeviceId(), streamInfo.getChannelId(), null, streamInfo.getStream());
  1441 + if (ssrcTransaction == null) {
  1442 + logger.info("[回放控制]未找到视频流信息,设备:{}, 流ID: {}", device.getDeviceId(), streamInfo.getStream());
  1443 + return;
  1444 + }
  1445 +
  1446 + SIPRequest request = headerProvider.createInfoRequest(device, streamInfo.getChannelId(), content.toString(), ssrcTransaction.getSipTransactionInfo());
  1447 + if (request == null) {
  1448 + logger.info("[回放控制]构建Request信息失败,设备:{}, 流ID: {}", device.getDeviceId(), streamInfo.getStream());
  1449 + return;
  1450 + }
  1451 +
  1452 + transmitRequest(device.getTransport(), request, errorEvent, okEvent);
  1453 + }
  1454 +
  1455 + @Override
  1456 + public void sendAlarmMessage(Device device, DeviceAlarm deviceAlarm) throws InvalidArgumentException, SipException, ParseException {
  1457 + if (device == null) {
  1458 + return;
  1459 + }
  1460 + logger.info("[发送 报警通知] {}/{}->{},{}", device.getDeviceId(), deviceAlarm.getChannelId(),
  1461 + deviceAlarm.getLongitude(), deviceAlarm.getLatitude());
  1462 +
  1463 + String characterSet = device.getCharset();
  1464 + StringBuffer deviceStatusXml = new StringBuffer(600);
  1465 + deviceStatusXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n");
  1466 + deviceStatusXml.append("<Notify>\r\n");
  1467 + deviceStatusXml.append("<CmdType>Alarm</CmdType>\r\n");
  1468 + deviceStatusXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n");
  1469 + deviceStatusXml.append("<DeviceID>" + deviceAlarm.getChannelId() + "</DeviceID>\r\n");
  1470 + deviceStatusXml.append("<AlarmPriority>" + deviceAlarm.getAlarmPriority() + "</AlarmPriority>\r\n");
  1471 + deviceStatusXml.append("<AlarmMethod>" + deviceAlarm.getAlarmMethod() + "</AlarmMethod>\r\n");
  1472 + deviceStatusXml.append("<AlarmTime>" + deviceAlarm.getAlarmTime() + "</AlarmTime>\r\n");
  1473 + deviceStatusXml.append("<AlarmDescription>" + deviceAlarm.getAlarmDescription() + "</AlarmDescription>\r\n");
  1474 + deviceStatusXml.append("<Longitude>" + deviceAlarm.getLongitude() + "</Longitude>\r\n");
  1475 + deviceStatusXml.append("<Latitude>" + deviceAlarm.getLatitude() + "</Latitude>\r\n");
  1476 + deviceStatusXml.append("<info>\r\n");
  1477 + deviceStatusXml.append("<AlarmType>" + deviceAlarm.getAlarmType() + "</AlarmType>\r\n");
  1478 + deviceStatusXml.append("</info>\r\n");
  1479 + deviceStatusXml.append("</Notify>\r\n");
  1480 +
  1481 + CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
  1482 + : udpSipProvider.getNewCallId();
  1483 + Request request = headerProvider.createMessageRequest(device, deviceStatusXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null, callIdHeader);
  1484 + transmitRequest(device.getTransport(), request);
  1485 +
  1486 +
  1487 + }
1831 } 1488 }
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;
@@ -30,13 +27,10 @@ import org.springframework.stereotype.Component; @@ -30,13 +27,10 @@ import org.springframework.stereotype.Component;
30 import org.springframework.util.ObjectUtils; 27 import org.springframework.util.ObjectUtils;
31 28
32 import javax.sip.*; 29 import javax.sip.*;
33 -import javax.sip.address.SipURI;  
34 import javax.sip.header.*; 30 import javax.sip.header.*;
35 import javax.sip.message.Request; 31 import javax.sip.message.Request;
36 -import java.lang.reflect.Field;  
37 import java.text.ParseException; 32 import java.text.ParseException;
38 import java.util.ArrayList; 33 import java.util.ArrayList;
39 -import java.util.HashSet;  
40 import java.util.List; 34 import java.util.List;
41 35
42 @Component 36 @Component
@@ -77,19 +71,18 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { @@ -77,19 +71,18 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
77 private SubscribeHolder subscribeHolder; 71 private SubscribeHolder subscribeHolder;
78 72
79 @Override 73 @Override
80 - public boolean register(ParentPlatform parentPlatform, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent) {  
81 - return register(parentPlatform, null, null, errorEvent, okEvent, false, true); 74 + public void register(ParentPlatform parentPlatform, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent) throws InvalidArgumentException, ParseException, SipException {
  75 + register(parentPlatform, null, null, errorEvent, okEvent, false, true);
82 } 76 }
83 77
84 @Override 78 @Override
85 - public boolean unregister(ParentPlatform parentPlatform, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent) {  
86 - return register(parentPlatform, null, null, errorEvent, okEvent, false, false); 79 + public void unregister(ParentPlatform parentPlatform, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent) throws InvalidArgumentException, ParseException, SipException {
  80 + register(parentPlatform, null, null, errorEvent, okEvent, false, false);
87 } 81 }
88 82
89 @Override 83 @Override
90 - public boolean register(ParentPlatform parentPlatform, @Nullable String callId, @Nullable WWWAuthenticateHeader www,  
91 - SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent, boolean registerAgain, boolean isRegister) {  
92 - try { 84 + public void register(ParentPlatform parentPlatform, @Nullable String callId, @Nullable WWWAuthenticateHeader www,
  85 + SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent, boolean registerAgain, boolean isRegister) throws SipException, InvalidArgumentException, ParseException {
93 Request request; 86 Request request;
94 if (!registerAgain ) { 87 if (!registerAgain ) {
95 CallIdHeader callIdHeader = null; 88 CallIdHeader callIdHeader = null;
@@ -126,23 +119,10 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { @@ -126,23 +119,10 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
126 } 119 }
127 120
128 transmitRequest(parentPlatform, request, null, okEvent); 121 transmitRequest(parentPlatform, request, null, okEvent);
129 - return true;  
130 - } catch (ParseException e) {  
131 - e.printStackTrace();  
132 - } catch (InvalidArgumentException e) {  
133 - e.printStackTrace();  
134 - } catch (PeerUnavailableException e) {  
135 - e.printStackTrace();  
136 - } catch (SipException e) {  
137 - e.printStackTrace();  
138 - }  
139 - return false;  
140 } 122 }
141 123
142 @Override 124 @Override
143 - public String keepalive(ParentPlatform parentPlatform,SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent) {  
144 - String callId = null;  
145 - try { 125 + public String keepalive(ParentPlatform parentPlatform,SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent) throws SipException, InvalidArgumentException, ParseException {
146 String characterSet = parentPlatform.getCharacterSet(); 126 String characterSet = parentPlatform.getCharacterSet();
147 StringBuffer keepaliveXml = new StringBuffer(200); 127 StringBuffer keepaliveXml = new StringBuffer(200);
148 keepaliveXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n"); 128 keepaliveXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n");
@@ -163,11 +143,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { @@ -163,11 +143,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
163 SipUtils.getNewViaTag(), 143 SipUtils.getNewViaTag(),
164 callIdHeader); 144 callIdHeader);
165 transmitRequest(parentPlatform, request, errorEvent, okEvent); 145 transmitRequest(parentPlatform, request, errorEvent, okEvent);
166 - callId = callIdHeader.getCallId();  
167 - } catch (ParseException | InvalidArgumentException | SipException e) {  
168 - e.printStackTrace();  
169 - }  
170 - return callId; 146 + return callIdHeader.getCallId();
171 } 147 }
172 148
173 private void transmitRequest(ParentPlatform parentPlatform, Request request) throws SipException { 149 private void transmitRequest(ParentPlatform parentPlatform, Request request) throws SipException {
@@ -206,39 +182,32 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { @@ -206,39 +182,32 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
206 * @return 182 * @return
207 */ 183 */
208 @Override 184 @Override
209 - public boolean catalogQuery(DeviceChannel channel, ParentPlatform parentPlatform, String sn, String fromTag, int size) { 185 + public void catalogQuery(DeviceChannel channel, ParentPlatform parentPlatform, String sn, String fromTag, int size) throws SipException, InvalidArgumentException, ParseException {
210 186
211 if ( parentPlatform ==null) { 187 if ( parentPlatform ==null) {
212 - return false; 188 + return ;
213 } 189 }
214 - try {  
215 - List<DeviceChannel> channels = new ArrayList<>();  
216 - if (channel != null) {  
217 - channels.add(channel);  
218 - }  
219 - String catalogXml = getCatalogXml(channels, sn, parentPlatform, size); 190 + List<DeviceChannel> channels = new ArrayList<>();
  191 + if (channel != null) {
  192 + channels.add(channel);
  193 + }
  194 + String catalogXml = getCatalogXml(channels, sn, parentPlatform, size);
220 195
221 - // callid  
222 - CallIdHeader callIdHeader = parentPlatform.getTransport().equalsIgnoreCase("TCP") ? tcpSipProvider.getNewCallId()  
223 - : udpSipProvider.getNewCallId(); 196 + // callid
  197 + CallIdHeader callIdHeader = parentPlatform.getTransport().equalsIgnoreCase("TCP") ? tcpSipProvider.getNewCallId()
  198 + : udpSipProvider.getNewCallId();
224 199
225 - Request request = headerProviderPlatformProvider.createMessageRequest(parentPlatform, catalogXml.toString(), fromTag, SipUtils.getNewViaTag(), callIdHeader);  
226 - transmitRequest(parentPlatform, request); 200 + Request request = headerProviderPlatformProvider.createMessageRequest(parentPlatform, catalogXml.toString(), fromTag, SipUtils.getNewViaTag(), callIdHeader);
  201 + transmitRequest(parentPlatform, request);
227 202
228 - } catch (SipException | ParseException | InvalidArgumentException e) {  
229 - e.printStackTrace();  
230 - return false;  
231 - }  
232 - return true;  
233 } 203 }
234 204
235 @Override 205 @Override
236 - public boolean catalogQuery(List<DeviceChannel> channels, ParentPlatform parentPlatform, String sn, String fromTag) { 206 + public void catalogQuery(List<DeviceChannel> channels, ParentPlatform parentPlatform, String sn, String fromTag) throws InvalidArgumentException, ParseException, SipException {
237 if ( parentPlatform ==null) { 207 if ( parentPlatform ==null) {
238 - return false; 208 + return ;
239 } 209 }
240 sendCatalogResponse(channels, parentPlatform, sn, fromTag, 0); 210 sendCatalogResponse(channels, parentPlatform, sn, fromTag, 0);
241 - return true;  
242 } 211 }
243 private String getCatalogXml(List<DeviceChannel> channels, String sn, ParentPlatform parentPlatform, int size) { 212 private String getCatalogXml(List<DeviceChannel> channels, String sn, ParentPlatform parentPlatform, int size) {
244 String characterSet = parentPlatform.getCharacterSet(); 213 String characterSet = parentPlatform.getCharacterSet();
@@ -300,30 +269,30 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { @@ -300,30 +269,30 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
300 return catalogXml.toString(); 269 return catalogXml.toString();
301 } 270 }
302 271
303 - private void sendCatalogResponse(List<DeviceChannel> channels, ParentPlatform parentPlatform, String sn, String fromTag, int index) { 272 + private void sendCatalogResponse(List<DeviceChannel> channels, ParentPlatform parentPlatform, String sn, String fromTag, int index) throws SipException, InvalidArgumentException, ParseException {
304 if (index >= channels.size()) { 273 if (index >= channels.size()) {
305 return; 274 return;
306 } 275 }
307 - try {  
308 - List<DeviceChannel> deviceChannels;  
309 - if (index + parentPlatform.getCatalogGroup() < channels.size()) {  
310 - deviceChannels = channels.subList(index, index + parentPlatform.getCatalogGroup());  
311 - }else {  
312 - deviceChannels = channels.subList(index, channels.size());  
313 - }  
314 - String catalogXml = getCatalogXml(deviceChannels, sn, parentPlatform, channels.size());  
315 - // callid  
316 - CallIdHeader callIdHeader = parentPlatform.getTransport().equalsIgnoreCase("TCP") ? tcpSipProvider.getNewCallId()  
317 - : udpSipProvider.getNewCallId(); 276 + List<DeviceChannel> deviceChannels;
  277 + if (index + parentPlatform.getCatalogGroup() < channels.size()) {
  278 + deviceChannels = channels.subList(index, index + parentPlatform.getCatalogGroup());
  279 + }else {
  280 + deviceChannels = channels.subList(index, channels.size());
  281 + }
  282 + String catalogXml = getCatalogXml(deviceChannels, sn, parentPlatform, channels.size());
  283 + // callid
  284 + CallIdHeader callIdHeader = parentPlatform.getTransport().equalsIgnoreCase("TCP") ? tcpSipProvider.getNewCallId()
  285 + : udpSipProvider.getNewCallId();
318 286
319 - Request request = headerProviderPlatformProvider.createMessageRequest(parentPlatform, catalogXml, fromTag, SipUtils.getNewViaTag(), callIdHeader);  
320 - transmitRequest(parentPlatform, request, null, eventResult -> {  
321 - int indexNext = index + parentPlatform.getCatalogGroup(); 287 + Request request = headerProviderPlatformProvider.createMessageRequest(parentPlatform, catalogXml, fromTag, SipUtils.getNewViaTag(), callIdHeader);
  288 + transmitRequest(parentPlatform, request, null, eventResult -> {
  289 + int indexNext = index + parentPlatform.getCatalogGroup();
  290 + try {
322 sendCatalogResponse(channels, parentPlatform, sn, fromTag, indexNext); 291 sendCatalogResponse(channels, parentPlatform, sn, fromTag, indexNext);
323 - });  
324 - } catch (SipException | ParseException | InvalidArgumentException e) {  
325 - e.printStackTrace();  
326 - } 292 + } catch (SipException | InvalidArgumentException | ParseException e) {
  293 + logger.error("[命令发送失败] 国标级联 目录查询回复: {}", e.getMessage());
  294 + }
  295 + });
327 } 296 }
328 297
329 /** 298 /**
@@ -334,36 +303,29 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { @@ -334,36 +303,29 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
334 * @return 303 * @return
335 */ 304 */
336 @Override 305 @Override
337 - public boolean deviceInfoResponse(ParentPlatform parentPlatform, String sn, String fromTag) { 306 + public void deviceInfoResponse(ParentPlatform parentPlatform, String sn, String fromTag) throws SipException, InvalidArgumentException, ParseException {
338 if (parentPlatform == null) { 307 if (parentPlatform == null) {
339 - return false;  
340 - }  
341 - try {  
342 - String characterSet = parentPlatform.getCharacterSet();  
343 - StringBuffer deviceInfoXml = new StringBuffer(600);  
344 - deviceInfoXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n");  
345 - deviceInfoXml.append("<Response>\r\n");  
346 - deviceInfoXml.append("<CmdType>DeviceInfo</CmdType>\r\n");  
347 - deviceInfoXml.append("<SN>" +sn + "</SN>\r\n");  
348 - deviceInfoXml.append("<DeviceID>" + parentPlatform.getDeviceGBId() + "</DeviceID>\r\n");  
349 - deviceInfoXml.append("<DeviceName>" + parentPlatform.getName() + "</DeviceName>\r\n");  
350 - deviceInfoXml.append("<Manufacturer>wvp</Manufacturer>\r\n");  
351 - deviceInfoXml.append("<Model>wvp-28181-2.0</Model>\r\n");  
352 - deviceInfoXml.append("<Firmware>2.0.202107</Firmware>\r\n");  
353 - deviceInfoXml.append("<Result>OK</Result>\r\n");  
354 - deviceInfoXml.append("</Response>\r\n");  
355 -  
356 - CallIdHeader callIdHeader = parentPlatform.getTransport().equalsIgnoreCase("TCP") ? tcpSipProvider.getNewCallId()  
357 - : udpSipProvider.getNewCallId();  
358 -  
359 - Request request = headerProviderPlatformProvider.createMessageRequest(parentPlatform, deviceInfoXml.toString(), fromTag, SipUtils.getNewViaTag(), callIdHeader);  
360 - transmitRequest(parentPlatform, request);  
361 -  
362 - } catch (SipException | ParseException | InvalidArgumentException e) {  
363 - e.printStackTrace();  
364 - return false; 308 + return;
365 } 309 }
366 - return true; 310 + String characterSet = parentPlatform.getCharacterSet();
  311 + StringBuffer deviceInfoXml = new StringBuffer(600);
  312 + deviceInfoXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n");
  313 + deviceInfoXml.append("<Response>\r\n");
  314 + deviceInfoXml.append("<CmdType>DeviceInfo</CmdType>\r\n");
  315 + deviceInfoXml.append("<SN>" +sn + "</SN>\r\n");
  316 + deviceInfoXml.append("<DeviceID>" + parentPlatform.getDeviceGBId() + "</DeviceID>\r\n");
  317 + deviceInfoXml.append("<DeviceName>" + parentPlatform.getName() + "</DeviceName>\r\n");
  318 + deviceInfoXml.append("<Manufacturer>wvp</Manufacturer>\r\n");
  319 + deviceInfoXml.append("<Model>wvp-28181-2.0</Model>\r\n");
  320 + deviceInfoXml.append("<Firmware>2.0.202107</Firmware>\r\n");
  321 + deviceInfoXml.append("<Result>OK</Result>\r\n");
  322 + deviceInfoXml.append("</Response>\r\n");
  323 +
  324 + CallIdHeader callIdHeader = parentPlatform.getTransport().equalsIgnoreCase("TCP") ? tcpSipProvider.getNewCallId()
  325 + : udpSipProvider.getNewCallId();
  326 +
  327 + Request request = headerProviderPlatformProvider.createMessageRequest(parentPlatform, deviceInfoXml.toString(), fromTag, SipUtils.getNewViaTag(), callIdHeader);
  328 + transmitRequest(parentPlatform, request);
367 } 329 }
368 330
369 /** 331 /**
@@ -374,129 +336,103 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { @@ -374,129 +336,103 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
374 * @return 336 * @return
375 */ 337 */
376 @Override 338 @Override
377 - public boolean deviceStatusResponse(ParentPlatform parentPlatform, String sn, String fromTag) { 339 + public void deviceStatusResponse(ParentPlatform parentPlatform, String sn, String fromTag) throws SipException, InvalidArgumentException, ParseException {
378 if (parentPlatform == null) { 340 if (parentPlatform == null) {
379 - return false; 341 + return ;
380 } 342 }
381 - try {  
382 - String characterSet = parentPlatform.getCharacterSet();  
383 - StringBuffer deviceStatusXml = new StringBuffer(600);  
384 - deviceStatusXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n");  
385 - deviceStatusXml.append("<Response>\r\n");  
386 - deviceStatusXml.append("<CmdType>DeviceStatus</CmdType>\r\n");  
387 - deviceStatusXml.append("<SN>" +sn + "</SN>\r\n");  
388 - deviceStatusXml.append("<DeviceID>" + parentPlatform.getDeviceGBId() + "</DeviceID>\r\n");  
389 - deviceStatusXml.append("<Result>OK</Result>\r\n");  
390 - deviceStatusXml.append("<Online>ONLINE</Online>\r\n");  
391 - deviceStatusXml.append("<Status>OK</Status>\r\n");  
392 - deviceStatusXml.append("</Response>\r\n");  
393 -  
394 - CallIdHeader callIdHeader = parentPlatform.getTransport().equalsIgnoreCase("TCP") ? tcpSipProvider.getNewCallId()  
395 - : udpSipProvider.getNewCallId();  
396 -  
397 - Request request = headerProviderPlatformProvider.createMessageRequest(parentPlatform, deviceStatusXml.toString(), fromTag, SipUtils.getNewViaTag(), callIdHeader);  
398 - transmitRequest(parentPlatform, request); 343 + String characterSet = parentPlatform.getCharacterSet();
  344 + StringBuffer deviceStatusXml = new StringBuffer(600);
  345 + deviceStatusXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n");
  346 + deviceStatusXml.append("<Response>\r\n");
  347 + deviceStatusXml.append("<CmdType>DeviceStatus</CmdType>\r\n");
  348 + deviceStatusXml.append("<SN>" +sn + "</SN>\r\n");
  349 + deviceStatusXml.append("<DeviceID>" + parentPlatform.getDeviceGBId() + "</DeviceID>\r\n");
  350 + deviceStatusXml.append("<Result>OK</Result>\r\n");
  351 + deviceStatusXml.append("<Online>ONLINE</Online>\r\n");
  352 + deviceStatusXml.append("<Status>OK</Status>\r\n");
  353 + deviceStatusXml.append("</Response>\r\n");
  354 +
  355 + CallIdHeader callIdHeader = parentPlatform.getTransport().equalsIgnoreCase("TCP") ? tcpSipProvider.getNewCallId()
  356 + : udpSipProvider.getNewCallId();
  357 +
  358 + Request request = headerProviderPlatformProvider.createMessageRequest(parentPlatform, deviceStatusXml.toString(), fromTag, SipUtils.getNewViaTag(), callIdHeader);
  359 + transmitRequest(parentPlatform, request);
399 360
400 - } catch (SipException | ParseException | InvalidArgumentException e) {  
401 - e.printStackTrace();  
402 - return false;  
403 - }  
404 - return true;  
405 } 361 }
406 362
407 @Override 363 @Override
408 - public boolean sendNotifyMobilePosition(ParentPlatform parentPlatform, GPSMsgInfo gpsMsgInfo, SubscribeInfo subscribeInfo) { 364 + public void sendNotifyMobilePosition(ParentPlatform parentPlatform, GPSMsgInfo gpsMsgInfo, SubscribeInfo subscribeInfo) throws InvalidArgumentException, ParseException, NoSuchFieldException, SipException, IllegalAccessException {
409 if (parentPlatform == null) { 365 if (parentPlatform == null) {
410 - return false; 366 + return;
411 } 367 }
412 if (logger.isDebugEnabled()) { 368 if (logger.isDebugEnabled()) {
413 logger.debug("[发送 移动位置订阅] {}/{}->{},{}", parentPlatform.getServerGBId(), gpsMsgInfo.getId(), gpsMsgInfo.getLng(), gpsMsgInfo.getLat()); 369 logger.debug("[发送 移动位置订阅] {}/{}->{},{}", parentPlatform.getServerGBId(), gpsMsgInfo.getId(), gpsMsgInfo.getLng(), gpsMsgInfo.getLat());
414 } 370 }
415 371
416 - try {  
417 - String characterSet = parentPlatform.getCharacterSet();  
418 - StringBuffer deviceStatusXml = new StringBuffer(600);  
419 - deviceStatusXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n");  
420 - deviceStatusXml.append("<Notify>\r\n");  
421 - deviceStatusXml.append("<CmdType>MobilePosition</CmdType>\r\n");  
422 - deviceStatusXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");  
423 - deviceStatusXml.append("<DeviceID>" + gpsMsgInfo.getId() + "</DeviceID>\r\n");  
424 - deviceStatusXml.append("<Time>" + gpsMsgInfo.getTime() + "</Time>\r\n");  
425 - deviceStatusXml.append("<Longitude>" + gpsMsgInfo.getLng() + "</Longitude>\r\n");  
426 - deviceStatusXml.append("<Latitude>" + gpsMsgInfo.getLat() + "</Latitude>\r\n");  
427 - deviceStatusXml.append("<Speed>" + gpsMsgInfo.getSpeed() + "</Speed>\r\n");  
428 - deviceStatusXml.append("<Direction>" + gpsMsgInfo.getDirection() + "</Direction>\r\n");  
429 - deviceStatusXml.append("<Altitude>" + gpsMsgInfo.getAltitude() + "</Altitude>\r\n");  
430 - deviceStatusXml.append("</Notify>\r\n");  
431 -  
432 - sendNotify(parentPlatform, deviceStatusXml.toString(), subscribeInfo, eventResult -> {  
433 - logger.error("发送NOTIFY通知消息失败。错误:{} {}", eventResult.statusCode, eventResult.msg);  
434 - }, null);  
435 -  
436 - } catch (SipException | ParseException e) {  
437 - e.printStackTrace();  
438 - return false;  
439 - } catch (NoSuchFieldException e) {  
440 - e.printStackTrace();  
441 - } catch (IllegalAccessException e) {  
442 - e.printStackTrace();  
443 - } catch (InvalidArgumentException e) {  
444 - e.printStackTrace();  
445 - }  
446 - return true; 372 + String characterSet = parentPlatform.getCharacterSet();
  373 + StringBuffer deviceStatusXml = new StringBuffer(600);
  374 + deviceStatusXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n");
  375 + deviceStatusXml.append("<Notify>\r\n");
  376 + deviceStatusXml.append("<CmdType>MobilePosition</CmdType>\r\n");
  377 + deviceStatusXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
  378 + deviceStatusXml.append("<DeviceID>" + gpsMsgInfo.getId() + "</DeviceID>\r\n");
  379 + deviceStatusXml.append("<Time>" + gpsMsgInfo.getTime() + "</Time>\r\n");
  380 + deviceStatusXml.append("<Longitude>" + gpsMsgInfo.getLng() + "</Longitude>\r\n");
  381 + deviceStatusXml.append("<Latitude>" + gpsMsgInfo.getLat() + "</Latitude>\r\n");
  382 + deviceStatusXml.append("<Speed>" + gpsMsgInfo.getSpeed() + "</Speed>\r\n");
  383 + deviceStatusXml.append("<Direction>" + gpsMsgInfo.getDirection() + "</Direction>\r\n");
  384 + deviceStatusXml.append("<Altitude>" + gpsMsgInfo.getAltitude() + "</Altitude>\r\n");
  385 + deviceStatusXml.append("</Notify>\r\n");
  386 +
  387 + sendNotify(parentPlatform, deviceStatusXml.toString(), subscribeInfo, eventResult -> {
  388 + logger.error("发送NOTIFY通知消息失败。错误:{} {}", eventResult.statusCode, eventResult.msg);
  389 + }, null);
  390 +
447 } 391 }
448 392
449 @Override 393 @Override
450 - public boolean sendAlarmMessage(ParentPlatform parentPlatform, DeviceAlarm deviceAlarm) { 394 + public void sendAlarmMessage(ParentPlatform parentPlatform, DeviceAlarm deviceAlarm) throws SipException, InvalidArgumentException, ParseException {
451 if (parentPlatform == null) { 395 if (parentPlatform == null) {
452 - return false; 396 + return;
453 } 397 }
454 logger.info("[发送报警通知] {}/{}->{},{}: {}", parentPlatform.getServerGBId(), deviceAlarm.getChannelId(), 398 logger.info("[发送报警通知] {}/{}->{},{}: {}", parentPlatform.getServerGBId(), deviceAlarm.getChannelId(),
455 deviceAlarm.getLongitude(), deviceAlarm.getLatitude(), JSONObject.toJSON(deviceAlarm)); 399 deviceAlarm.getLongitude(), deviceAlarm.getLatitude(), JSONObject.toJSON(deviceAlarm));
456 - try {  
457 - String characterSet = parentPlatform.getCharacterSet();  
458 - StringBuffer deviceStatusXml = new StringBuffer(600);  
459 - deviceStatusXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n");  
460 - deviceStatusXml.append("<Notify>\r\n");  
461 - deviceStatusXml.append("<CmdType>Alarm</CmdType>\r\n");  
462 - deviceStatusXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");  
463 - deviceStatusXml.append("<DeviceID>" + deviceAlarm.getChannelId() + "</DeviceID>\r\n");  
464 - deviceStatusXml.append("<AlarmPriority>" + deviceAlarm.getAlarmPriority() + "</AlarmPriority>\r\n");  
465 - deviceStatusXml.append("<AlarmMethod>" + deviceAlarm.getAlarmMethod() + "</AlarmMethod>\r\n");  
466 - deviceStatusXml.append("<AlarmTime>" + deviceAlarm.getAlarmTime() + "</AlarmTime>\r\n");  
467 - deviceStatusXml.append("<AlarmDescription>" + deviceAlarm.getAlarmDescription() + "</AlarmDescription>\r\n");  
468 - deviceStatusXml.append("<Longitude>" + deviceAlarm.getLongitude() + "</Longitude>\r\n");  
469 - deviceStatusXml.append("<Latitude>" + deviceAlarm.getLatitude() + "</Latitude>\r\n");  
470 - deviceStatusXml.append("<info>\r\n");  
471 - deviceStatusXml.append("<AlarmType>" + deviceAlarm.getAlarmType() + "</AlarmType>\r\n");  
472 - deviceStatusXml.append("</info>\r\n");  
473 - deviceStatusXml.append("</Notify>\r\n");  
474 -  
475 - CallIdHeader callIdHeader = parentPlatform.getTransport().equalsIgnoreCase("TCP") ? tcpSipProvider.getNewCallId()  
476 - : udpSipProvider.getNewCallId();  
477 -  
478 - Request request = headerProviderPlatformProvider.createMessageRequest(parentPlatform, deviceStatusXml.toString(), SipUtils.getNewFromTag(), SipUtils.getNewViaTag(), callIdHeader);  
479 - transmitRequest(parentPlatform, request); 400 + String characterSet = parentPlatform.getCharacterSet();
  401 + StringBuffer deviceStatusXml = new StringBuffer(600);
  402 + deviceStatusXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n");
  403 + deviceStatusXml.append("<Notify>\r\n");
  404 + deviceStatusXml.append("<CmdType>Alarm</CmdType>\r\n");
  405 + deviceStatusXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
  406 + deviceStatusXml.append("<DeviceID>" + deviceAlarm.getChannelId() + "</DeviceID>\r\n");
  407 + deviceStatusXml.append("<AlarmPriority>" + deviceAlarm.getAlarmPriority() + "</AlarmPriority>\r\n");
  408 + deviceStatusXml.append("<AlarmMethod>" + deviceAlarm.getAlarmMethod() + "</AlarmMethod>\r\n");
  409 + deviceStatusXml.append("<AlarmTime>" + deviceAlarm.getAlarmTime() + "</AlarmTime>\r\n");
  410 + deviceStatusXml.append("<AlarmDescription>" + deviceAlarm.getAlarmDescription() + "</AlarmDescription>\r\n");
  411 + deviceStatusXml.append("<Longitude>" + deviceAlarm.getLongitude() + "</Longitude>\r\n");
  412 + deviceStatusXml.append("<Latitude>" + deviceAlarm.getLatitude() + "</Latitude>\r\n");
  413 + deviceStatusXml.append("<info>\r\n");
  414 + deviceStatusXml.append("<AlarmType>" + deviceAlarm.getAlarmType() + "</AlarmType>\r\n");
  415 + deviceStatusXml.append("</info>\r\n");
  416 + deviceStatusXml.append("</Notify>\r\n");
  417 +
  418 + CallIdHeader callIdHeader = parentPlatform.getTransport().equalsIgnoreCase("TCP") ? tcpSipProvider.getNewCallId()
  419 + : udpSipProvider.getNewCallId();
  420 +
  421 + Request request = headerProviderPlatformProvider.createMessageRequest(parentPlatform, deviceStatusXml.toString(), SipUtils.getNewFromTag(), SipUtils.getNewViaTag(), callIdHeader);
  422 + transmitRequest(parentPlatform, request);
480 423
481 - } catch (SipException | ParseException e) {  
482 - e.printStackTrace();  
483 - return false;  
484 - } catch (InvalidArgumentException e) {  
485 - e.printStackTrace();  
486 - }  
487 - return true;  
488 } 424 }
489 425
490 @Override 426 @Override
491 - public boolean sendNotifyForCatalogAddOrUpdate(String type, ParentPlatform parentPlatform, List<DeviceChannel> deviceChannels, SubscribeInfo subscribeInfo, Integer index) { 427 + public void sendNotifyForCatalogAddOrUpdate(String type, ParentPlatform parentPlatform, List<DeviceChannel> deviceChannels, SubscribeInfo subscribeInfo, Integer index) throws InvalidArgumentException, ParseException, NoSuchFieldException, SipException, IllegalAccessException {
492 if (parentPlatform == null || deviceChannels == null || deviceChannels.size() == 0 || subscribeInfo == null) { 428 if (parentPlatform == null || deviceChannels == null || deviceChannels.size() == 0 || subscribeInfo == null) {
493 - return false; 429 + return;
494 } 430 }
495 if (index == null) { 431 if (index == null) {
496 index = 0; 432 index = 0;
497 } 433 }
498 if (index >= deviceChannels.size()) { 434 if (index >= deviceChannels.size()) {
499 - return true; 435 + return;
500 } 436 }
501 List<DeviceChannel> channels; 437 List<DeviceChannel> channels;
502 if (index + parentPlatform.getCatalogGroup() < deviceChannels.size()) { 438 if (index + parentPlatform.getCatalogGroup() < deviceChannels.size()) {
@@ -504,32 +440,25 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { @@ -504,32 +440,25 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
504 }else { 440 }else {
505 channels = deviceChannels.subList(index, deviceChannels.size()); 441 channels = deviceChannels.subList(index, deviceChannels.size());
506 } 442 }
507 - try {  
508 - Integer finalIndex = index;  
509 - String catalogXmlContent = getCatalogXmlContentForCatalogAddOrUpdate(parentPlatform, channels,  
510 - deviceChannels.size(), type, subscribeInfo);  
511 - sendNotify(parentPlatform, catalogXmlContent, subscribeInfo, eventResult -> {  
512 - logger.error("发送NOTIFY通知消息失败。错误:{} {}", eventResult.statusCode, eventResult.msg);  
513 - }, (eventResult -> { 443 + Integer finalIndex = index;
  444 + String catalogXmlContent = getCatalogXmlContentForCatalogAddOrUpdate(parentPlatform, channels,
  445 + deviceChannels.size(), type, subscribeInfo);
  446 + sendNotify(parentPlatform, catalogXmlContent, subscribeInfo, eventResult -> {
  447 + logger.error("发送NOTIFY通知消息失败。错误:{} {}", eventResult.statusCode, eventResult.msg);
  448 + }, (eventResult -> {
  449 + try {
514 sendNotifyForCatalogAddOrUpdate(type, parentPlatform, deviceChannels, subscribeInfo, 450 sendNotifyForCatalogAddOrUpdate(type, parentPlatform, deviceChannels, subscribeInfo,
515 finalIndex + parentPlatform.getCatalogGroup()); 451 finalIndex + parentPlatform.getCatalogGroup());
516 - }));  
517 - } catch (SipException | ParseException e) {  
518 - e.printStackTrace();  
519 - return false;  
520 - } catch (NoSuchFieldException e) {  
521 - e.printStackTrace();  
522 - } catch (IllegalAccessException e) {  
523 - e.printStackTrace();  
524 - } catch (InvalidArgumentException e) {  
525 - e.printStackTrace();  
526 - }  
527 - return true; 452 + } catch (InvalidArgumentException | ParseException | NoSuchFieldException | SipException |
  453 + IllegalAccessException e) {
  454 + logger.error("[命令发送失败] 国标级联 NOTIFY通知: {}", e.getMessage());
  455 + }
  456 + }));
528 } 457 }
529 458
530 - private ClientTransaction sendNotify(ParentPlatform parentPlatform, String catalogXmlContent, 459 + private void sendNotify(ParentPlatform parentPlatform, String catalogXmlContent,
531 SubscribeInfo subscribeInfo, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent ) 460 SubscribeInfo subscribeInfo, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent )
532 - throws NoSuchFieldException, IllegalAccessException, SipException, ParseException, InvalidArgumentException { 461 + throws SipException, ParseException, InvalidArgumentException {
533 MessageFactoryImpl messageFactory = (MessageFactoryImpl) sipFactory.createMessageFactory(); 462 MessageFactoryImpl messageFactory = (MessageFactoryImpl) sipFactory.createMessageFactory();
534 String characterSet = parentPlatform.getCharacterSet(); 463 String characterSet = parentPlatform.getCharacterSet();
535 // 设置编码, 防止中文乱码 464 // 设置编码, 防止中文乱码
@@ -537,50 +466,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { @@ -537,50 +466,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
537 466
538 SIPRequest notifyRequest = headerProviderPlatformProvider.createNotifyRequest(parentPlatform, catalogXmlContent, subscribeInfo); 467 SIPRequest notifyRequest = headerProviderPlatformProvider.createNotifyRequest(parentPlatform, catalogXmlContent, subscribeInfo);
539 468
540 - notifyRequest.getCSeqHeader().setSeqNumber(redisCatchStorage.getCSEQ());  
541 -  
542 - ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml");  
543 - notifyRequest.setContent(catalogXmlContent, contentTypeHeader);  
544 -  
545 - SubscriptionStateHeader subscriptionState = sipFactory.createHeaderFactory()  
546 - .createSubscriptionStateHeader(SubscriptionStateHeader.ACTIVE);  
547 - notifyRequest.addHeader(subscriptionState);  
548 -  
549 - EventHeader event = sipFactory.createHeaderFactory().createEventHeader(subscribeInfo.getEventType());  
550 - if (subscribeInfo.getEventId() != null) {  
551 - event.setEventId(subscribeInfo.getEventId());  
552 - }  
553 - notifyRequest.addHeader(event);  
554 - SipURI sipURI = (SipURI) notifyRequest.getRequestURI();  
555 - sipURI.setHost(parentPlatform.getServerIP());  
556 - sipURI.setPort(parentPlatform.getServerPort());  
557 -  
558 -// ClientTransaction transaction = subscribeInfo.getClientTransaction();  
559 -// if (transaction == null || transaction.getState().equals(TransactionState.COMPLETED)) {  
560 -// if ("TCP".equals(parentPlatform.getTransport())) {  
561 -// transaction = tcpSipProvider.getNewClientTransaction(notifyRequest);  
562 -// } else if ("UDP".equals(parentPlatform.getTransport())) {  
563 -// transaction = udpSipProvider.getNewClientTransaction(notifyRequest);  
564 -// }  
565 -// }  
566 -  
567 - ClientTransaction transaction = null;  
568 - if ("TCP".equals(parentPlatform.getTransport())) {  
569 - transaction = tcpSipProvider.getNewClientTransaction(notifyRequest);  
570 - } else if ("UDP".equals(parentPlatform.getTransport())) {  
571 - transaction = udpSipProvider.getNewClientTransaction(notifyRequest);  
572 - }  
573 -  
574 - // 添加错误订阅  
575 - if (errorEvent != null) {  
576 - sipSubscribe.addErrorSubscribe(subscribeInfo.getRequest().getCallIdHeader().getCallId(), errorEvent);  
577 - }  
578 - // 添加订阅  
579 - if (okEvent != null) {  
580 - sipSubscribe.addOkSubscribe(subscribeInfo.getRequest().getCallIdHeader().getCallId(), okEvent);  
581 - }  
582 - transaction.sendRequest();  
583 - return transaction; 469 + transmitRequest(parentPlatform, notifyRequest);
584 } 470 }
585 471
586 private String getCatalogXmlContentForCatalogAddOrUpdate(ParentPlatform parentPlatform, List<DeviceChannel> channels, int sumNum, String type, SubscribeInfo subscribeInfo) { 472 private String getCatalogXmlContentForCatalogAddOrUpdate(ParentPlatform parentPlatform, List<DeviceChannel> channels, int sumNum, String type, SubscribeInfo subscribeInfo) {
@@ -639,20 +525,21 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { @@ -639,20 +525,21 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
639 } 525 }
640 526
641 @Override 527 @Override
642 - public boolean sendNotifyForCatalogOther(String type, ParentPlatform parentPlatform, List<DeviceChannel> deviceChannels,  
643 - SubscribeInfo subscribeInfo, Integer index) { 528 + public void sendNotifyForCatalogOther(String type, ParentPlatform parentPlatform, List<DeviceChannel> deviceChannels,
  529 + SubscribeInfo subscribeInfo, Integer index) throws InvalidArgumentException, ParseException, NoSuchFieldException, SipException, IllegalAccessException {
644 if (parentPlatform == null 530 if (parentPlatform == null
645 || deviceChannels == null 531 || deviceChannels == null
646 || deviceChannels.size() == 0 532 || deviceChannels.size() == 0
647 || subscribeInfo == null) { 533 || subscribeInfo == null) {
648 - return false; 534 + logger.warn("[缺少必要参数]");
  535 + return;
649 } 536 }
650 537
651 if (index == null) { 538 if (index == null) {
652 index = 0; 539 index = 0;
653 } 540 }
654 if (index >= deviceChannels.size()) { 541 if (index >= deviceChannels.size()) {
655 - return true; 542 + return;
656 } 543 }
657 List<DeviceChannel> channels; 544 List<DeviceChannel> channels;
658 if (index + parentPlatform.getCatalogGroup() < deviceChannels.size()) { 545 if (index + parentPlatform.getCatalogGroup() < deviceChannels.size()) {
@@ -660,28 +547,19 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { @@ -660,28 +547,19 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
660 }else { 547 }else {
661 channels = deviceChannels.subList(index, deviceChannels.size()); 548 channels = deviceChannels.subList(index, deviceChannels.size());
662 } 549 }
663 - try {  
664 - Integer finalIndex = index;  
665 - String catalogXmlContent = getCatalogXmlContentForCatalogOther(parentPlatform, channels, type);  
666 - sendNotify(parentPlatform, catalogXmlContent, subscribeInfo, eventResult -> {  
667 - logger.error("发送NOTIFY通知消息失败。错误:{} {}", eventResult.statusCode, eventResult.msg);  
668 - }, (eventResult -> { 550 + Integer finalIndex = index;
  551 + String catalogXmlContent = getCatalogXmlContentForCatalogOther(parentPlatform, channels, type);
  552 + sendNotify(parentPlatform, catalogXmlContent, subscribeInfo, eventResult -> {
  553 + logger.error("发送NOTIFY通知消息失败。错误:{} {}", eventResult.statusCode, eventResult.msg);
  554 + }, eventResult -> {
  555 + try {
669 sendNotifyForCatalogOther(type, parentPlatform, deviceChannels, subscribeInfo, 556 sendNotifyForCatalogOther(type, parentPlatform, deviceChannels, subscribeInfo,
670 finalIndex + parentPlatform.getCatalogGroup()); 557 finalIndex + parentPlatform.getCatalogGroup());
671 - }));  
672 - } catch (SipException e) {  
673 - e.printStackTrace();  
674 - } catch (ParseException e) {  
675 - e.printStackTrace();  
676 - } catch (NoSuchFieldException e) {  
677 - e.printStackTrace();  
678 - } catch (IllegalAccessException e) {  
679 - e.printStackTrace();  
680 - } catch (InvalidArgumentException e) {  
681 - e.printStackTrace();  
682 - }  
683 -  
684 - return true; 558 + } catch (InvalidArgumentException | ParseException | NoSuchFieldException | SipException |
  559 + IllegalAccessException e) {
  560 + logger.error("[命令发送失败] 国标级联 NOTIFY通知: {}", e.getMessage());
  561 + }
  562 + });
685 } 563 }
686 564
687 private String getCatalogXmlContentForCatalogOther(ParentPlatform parentPlatform, List<DeviceChannel> channels, String type) { 565 private String getCatalogXmlContentForCatalogOther(ParentPlatform parentPlatform, List<DeviceChannel> channels, String type) {
@@ -711,113 +589,81 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { @@ -711,113 +589,81 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
711 return catalogXml.toString(); 589 return catalogXml.toString();
712 } 590 }
713 @Override 591 @Override
714 - public boolean recordInfo(DeviceChannel deviceChannel, ParentPlatform parentPlatform, String fromTag, RecordInfo recordInfo) { 592 + public void recordInfo(DeviceChannel deviceChannel, ParentPlatform parentPlatform, String fromTag, RecordInfo recordInfo) throws SipException, InvalidArgumentException, ParseException {
715 if ( parentPlatform ==null) { 593 if ( parentPlatform ==null) {
716 - return false; 594 + return ;
717 } 595 }
718 - try {  
719 - String characterSet = parentPlatform.getCharacterSet();  
720 - StringBuffer recordXml = new StringBuffer(600);  
721 - recordXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n");  
722 - recordXml.append("<Response>\r\n");  
723 - recordXml.append("<CmdType>RecordInfo</CmdType>\r\n");  
724 - recordXml.append("<SN>" +recordInfo.getSn() + "</SN>\r\n");  
725 - recordXml.append("<DeviceID>" + recordInfo.getDeviceId() + "</DeviceID>\r\n");  
726 - recordXml.append("<SumNum>" + recordInfo.getSumNum() + "</SumNum>\r\n");  
727 - if (recordInfo.getRecordList() == null ) {  
728 - recordXml.append("<RecordList Num=\"0\">\r\n");  
729 - }else {  
730 - recordXml.append("<RecordList Num=\"" + recordInfo.getRecordList().size()+"\">\r\n");  
731 - if (recordInfo.getRecordList().size() > 0) {  
732 - for (RecordItem recordItem : recordInfo.getRecordList()) {  
733 - recordXml.append("<Item>\r\n");  
734 - if (deviceChannel != null) {  
735 - recordXml.append("<DeviceID>" + recordItem.getDeviceId() + "</DeviceID>\r\n");  
736 - recordXml.append("<Name>" + recordItem.getName() + "</Name>\r\n");  
737 - recordXml.append("<StartTime>" + DateUtil.yyyy_MM_dd_HH_mm_ssToISO8601(recordItem.getStartTime()) + "</StartTime>\r\n");  
738 - recordXml.append("<EndTime>" + DateUtil.yyyy_MM_dd_HH_mm_ssToISO8601(recordItem.getEndTime()) + "</EndTime>\r\n");  
739 - recordXml.append("<Secrecy>" + recordItem.getSecrecy() + "</Secrecy>\r\n");  
740 - recordXml.append("<Type>" + recordItem.getType() + "</Type>\r\n");  
741 - if (!ObjectUtils.isEmpty(recordItem.getFileSize())) {  
742 - recordXml.append("<FileSize>" + recordItem.getFileSize() + "</FileSize>\r\n");  
743 - }  
744 - if (!ObjectUtils.isEmpty(recordItem.getFilePath())) {  
745 - recordXml.append("<FilePath>" + recordItem.getFilePath() + "</FilePath>\r\n");  
746 - } 596 + String characterSet = parentPlatform.getCharacterSet();
  597 + StringBuffer recordXml = new StringBuffer(600);
  598 + recordXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n");
  599 + recordXml.append("<Response>\r\n");
  600 + recordXml.append("<CmdType>RecordInfo</CmdType>\r\n");
  601 + recordXml.append("<SN>" +recordInfo.getSn() + "</SN>\r\n");
  602 + recordXml.append("<DeviceID>" + recordInfo.getDeviceId() + "</DeviceID>\r\n");
  603 + recordXml.append("<SumNum>" + recordInfo.getSumNum() + "</SumNum>\r\n");
  604 + if (recordInfo.getRecordList() == null ) {
  605 + recordXml.append("<RecordList Num=\"0\">\r\n");
  606 + }else {
  607 + recordXml.append("<RecordList Num=\"" + recordInfo.getRecordList().size()+"\">\r\n");
  608 + if (recordInfo.getRecordList().size() > 0) {
  609 + for (RecordItem recordItem : recordInfo.getRecordList()) {
  610 + recordXml.append("<Item>\r\n");
  611 + if (deviceChannel != null) {
  612 + recordXml.append("<DeviceID>" + recordItem.getDeviceId() + "</DeviceID>\r\n");
  613 + recordXml.append("<Name>" + recordItem.getName() + "</Name>\r\n");
  614 + recordXml.append("<StartTime>" + DateUtil.yyyy_MM_dd_HH_mm_ssToISO8601(recordItem.getStartTime()) + "</StartTime>\r\n");
  615 + recordXml.append("<EndTime>" + DateUtil.yyyy_MM_dd_HH_mm_ssToISO8601(recordItem.getEndTime()) + "</EndTime>\r\n");
  616 + recordXml.append("<Secrecy>" + recordItem.getSecrecy() + "</Secrecy>\r\n");
  617 + recordXml.append("<Type>" + recordItem.getType() + "</Type>\r\n");
  618 + if (!ObjectUtils.isEmpty(recordItem.getFileSize())) {
  619 + recordXml.append("<FileSize>" + recordItem.getFileSize() + "</FileSize>\r\n");
  620 + }
  621 + if (!ObjectUtils.isEmpty(recordItem.getFilePath())) {
  622 + recordXml.append("<FilePath>" + recordItem.getFilePath() + "</FilePath>\r\n");
747 } 623 }
748 - recordXml.append("</Item>\r\n");  
749 } 624 }
  625 + recordXml.append("</Item>\r\n");
750 } 626 }
751 } 627 }
  628 + }
752 629
753 - recordXml.append("</RecordList>\r\n");  
754 - recordXml.append("</Response>\r\n"); 630 + recordXml.append("</RecordList>\r\n");
  631 + recordXml.append("</Response>\r\n");
755 632
756 - // callid  
757 - CallIdHeader callIdHeader = parentPlatform.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()  
758 - : udpSipProvider.getNewCallId();  
759 - Request request = headerProviderPlatformProvider.createMessageRequest(parentPlatform, recordXml.toString(), fromTag, SipUtils.getNewViaTag(), callIdHeader);  
760 - transmitRequest(parentPlatform, request); 633 + // callid
  634 + CallIdHeader callIdHeader = parentPlatform.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
  635 + : udpSipProvider.getNewCallId();
  636 + Request request = headerProviderPlatformProvider.createMessageRequest(parentPlatform, recordXml.toString(), fromTag, SipUtils.getNewViaTag(), callIdHeader);
  637 + transmitRequest(parentPlatform, request);
761 638
762 - } catch (SipException | ParseException | InvalidArgumentException e) {  
763 - e.printStackTrace();  
764 - return false;  
765 - }  
766 - return true;  
767 } 639 }
768 640
769 @Override 641 @Override
770 - public boolean sendMediaStatusNotify(ParentPlatform platform, SendRtpItem sendRtpItem) {  
771 - if (sendRtpItem == null) {  
772 - return false;  
773 - }  
774 - if (platform == null) {  
775 - return false;  
776 - }  
777 -  
778 - try{  
779 -  
780 - String characterSet = platform.getCharacterSet();  
781 - StringBuffer mediaStatusXml = new StringBuffer(200);  
782 - mediaStatusXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n");  
783 - mediaStatusXml.append("<Notify>\r\n");  
784 - mediaStatusXml.append("<CmdType>MediaStatus</CmdType>\r\n");  
785 - mediaStatusXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");  
786 - mediaStatusXml.append("<DeviceID>" + sendRtpItem.getChannelId() + "</DeviceID>\r\n");  
787 - mediaStatusXml.append("<NotifyType>121</NotifyType>\r\n");  
788 - mediaStatusXml.append("</Notify>\r\n");  
789 -  
790 - SIPRequest messageRequest = (SIPRequest)headerProviderPlatformProvider.createMessageRequest(platform, mediaStatusXml.toString(),  
791 - sendRtpItem);  
792 -  
793 - ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml");  
794 - messageRequest.setContent(mediaStatusXml.toString(), contentTypeHeader);  
795 - SipURI sipURI = (SipURI) messageRequest.getRequestURI();  
796 - sipURI.setHost(platform.getServerIP());  
797 - sipURI.setPort(platform.getServerPort());  
798 - ClientTransaction clientTransaction;  
799 - if ("TCP".equals(platform.getTransport())) {  
800 - clientTransaction = tcpSipProvider.getNewClientTransaction(messageRequest);  
801 - }else {  
802 - clientTransaction = udpSipProvider.getNewClientTransaction(messageRequest);  
803 - }  
804 - clientTransaction.sendRequest();  
805 - } catch (SipException e) {  
806 - e.printStackTrace();  
807 - return false;  
808 - } catch (ParseException e) {  
809 - e.printStackTrace();  
810 - return false;  
811 - } catch (InvalidArgumentException e) {  
812 - throw new RuntimeException(e); 642 + public void sendMediaStatusNotify(ParentPlatform platform, SendRtpItem sendRtpItem) throws SipException, InvalidArgumentException, ParseException {
  643 + if (sendRtpItem == null || platform == null) {
  644 + return;
813 } 645 }
814 - return true;  
815 646
816 647
  648 + String characterSet = platform.getCharacterSet();
  649 + StringBuffer mediaStatusXml = new StringBuffer(200);
  650 + mediaStatusXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n");
  651 + mediaStatusXml.append("<Notify>\r\n");
  652 + mediaStatusXml.append("<CmdType>MediaStatus</CmdType>\r\n");
  653 + mediaStatusXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
  654 + mediaStatusXml.append("<DeviceID>" + sendRtpItem.getChannelId() + "</DeviceID>\r\n");
  655 + mediaStatusXml.append("<NotifyType>121</NotifyType>\r\n");
  656 + mediaStatusXml.append("</Notify>\r\n");
  657 +
  658 + SIPRequest messageRequest = (SIPRequest)headerProviderPlatformProvider.createMessageRequest(platform, mediaStatusXml.toString(),
  659 + sendRtpItem);
  660 +
  661 + transmitRequest(platform, messageRequest);
  662 +
817 } 663 }
818 664
819 @Override 665 @Override
820 - public void streamByeCmd(ParentPlatform platform, String callId) { 666 + public void streamByeCmd(ParentPlatform platform, String callId) throws SipException, InvalidArgumentException, ParseException {
821 if (platform == null) { 667 if (platform == null) {
822 return; 668 return;
823 } 669 }
@@ -828,7 +674,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { @@ -828,7 +674,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
828 } 674 }
829 675
830 @Override 676 @Override
831 - public void streamByeCmd(ParentPlatform platform, SendRtpItem sendRtpItem) { 677 + public void streamByeCmd(ParentPlatform platform, SendRtpItem sendRtpItem) throws SipException, InvalidArgumentException, ParseException {
832 if (sendRtpItem == null ) { 678 if (sendRtpItem == null ) {
833 logger.info("[向上级发送BYE], sendRtpItem 为NULL"); 679 logger.info("[向上级发送BYE], sendRtpItem 为NULL");
834 return; 680 return;
@@ -844,25 +690,10 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { @@ -844,25 +690,10 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
844 mediaServerService.releaseSsrc(mediaServerItem.getId(), sendRtpItem.getSsrc()); 690 mediaServerService.releaseSsrc(mediaServerItem.getId(), sendRtpItem.getSsrc());
845 zlmrtpServerFactory.closeRTPServer(mediaServerItem, sendRtpItem.getStreamId()); 691 zlmrtpServerFactory.closeRTPServer(mediaServerItem, sendRtpItem.getStreamId());
846 } 692 }
847 - try {  
848 -  
849 - SIPRequest byeRequest = headerProviderPlatformProvider.createByeRequest(platform, sendRtpItem);  
850 - if (byeRequest == null) {  
851 - logger.warn("[向上级发送bye]:无法创建 byeRequest");  
852 - }  
853 - ClientTransaction clientTransaction;  
854 - if ("TCP".equals(platform.getTransport())) {  
855 - clientTransaction = tcpSipProvider.getNewClientTransaction(byeRequest);  
856 - } else {  
857 - clientTransaction = udpSipProvider.getNewClientTransaction(byeRequest);  
858 - }  
859 - clientTransaction.sendRequest();  
860 - } catch (SipException e) {  
861 - e.printStackTrace();  
862 - } catch (ParseException e) {  
863 - e.printStackTrace();  
864 - } catch (InvalidArgumentException e) {  
865 - throw new RuntimeException(e); 693 + SIPRequest byeRequest = headerProviderPlatformProvider.createByeRequest(platform, sendRtpItem);
  694 + if (byeRequest == null) {
  695 + logger.warn("[向上级发送bye]:无法创建 byeRequest");
866 } 696 }
  697 + transmitRequest(platform,byeRequest);
867 } 698 }
868 } 699 }
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,7 +58,7 @@ public abstract class SIPRequestProcessorParent { @@ -57,7 +58,7 @@ 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 boolean isTcp = false; 63 boolean isTcp = false;
63 ViaHeader reqViaHeader = (ViaHeader) request.getHeader(ViaHeader.NAME); 64 ViaHeader reqViaHeader = (ViaHeader) request.getHeader(ViaHeader.NAME);
@@ -65,28 +66,28 @@ public abstract class SIPRequestProcessorParent { @@ -65,28 +66,28 @@ public abstract class SIPRequestProcessorParent {
65 if (transport.equalsIgnoreCase("TCP")) { 66 if (transport.equalsIgnoreCase("TCP")) {
66 isTcp = true; 67 isTcp = true;
67 } 68 }
68 - 69 + if (serverTransaction != null && serverTransaction.getOriginalRequest() == null) {
  70 + serverTransaction.setOriginalRequest((SIPRequest) evt.getRequest());
  71 + }
69 if (serverTransaction == null) { 72 if (serverTransaction == null) {
70 try { 73 try {
71 if (isTcp) { 74 if (isTcp) {
72 SipStackImpl stack = (SipStackImpl)tcpSipProvider.getSipStack(); 75 SipStackImpl stack = (SipStackImpl)tcpSipProvider.getSipStack();
73 - serverTransaction = (SIPServerTransaction) stack.findTransaction((SIPRequest)request, true); 76 + serverTransaction = (SIPServerTransactionImpl) stack.findTransaction((SIPRequest)request, true);
74 if (serverTransaction == null) { 77 if (serverTransaction == null) {
75 - serverTransaction = tcpSipProvider.getNewServerTransaction(request); 78 + serverTransaction = (SIPServerTransactionImpl)tcpSipProvider.getNewServerTransaction(request);
76 } 79 }
77 } else { 80 } else {
78 SipStackImpl stack = (SipStackImpl)udpSipProvider.getSipStack(); 81 SipStackImpl stack = (SipStackImpl)udpSipProvider.getSipStack();
79 - serverTransaction = (SIPServerTransaction) stack.findTransaction((SIPRequest)request, true); 82 + serverTransaction = (SIPServerTransactionImpl) stack.findTransaction((SIPRequest)request, true);
80 if (serverTransaction == null) { 83 if (serverTransaction == null) {
81 - serverTransaction = udpSipProvider.getNewServerTransaction(request); 84 + serverTransaction = (SIPServerTransactionImpl)udpSipProvider.getNewServerTransaction(request);
82 } 85 }
83 } 86 }
84 } catch (TransactionAlreadyExistsException e) { 87 } catch (TransactionAlreadyExistsException e) {
85 logger.error(e.getMessage()); 88 logger.error(e.getMessage());
86 } catch (TransactionUnavailableException e) { 89 } catch (TransactionUnavailableException e) {
87 logger.error(e.getMessage()); 90 logger.error(e.getMessage());
88 - }finally {  
89 -  
90 } 91 }
91 } 92 }
92 return serverTransaction; 93 return serverTransaction;
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/AckRequestProcessor.java
@@ -23,12 +23,15 @@ import org.springframework.beans.factory.InitializingBean; @@ -23,12 +23,15 @@ import org.springframework.beans.factory.InitializingBean;
23 import org.springframework.beans.factory.annotation.Autowired; 23 import org.springframework.beans.factory.annotation.Autowired;
24 import org.springframework.stereotype.Component; 24 import org.springframework.stereotype.Component;
25 25
  26 +import javax.sip.InvalidArgumentException;
26 import javax.sip.RequestEvent; 27 import javax.sip.RequestEvent;
  28 +import javax.sip.SipException;
27 import javax.sip.address.SipURI; 29 import javax.sip.address.SipURI;
28 import javax.sip.header.CallIdHeader; 30 import javax.sip.header.CallIdHeader;
29 import javax.sip.header.FromHeader; 31 import javax.sip.header.FromHeader;
30 import javax.sip.header.HeaderAddress; 32 import javax.sip.header.HeaderAddress;
31 import javax.sip.header.ToHeader; 33 import javax.sip.header.ToHeader;
  34 +import java.text.ParseException;
32 import java.util.*; 35 import java.util.*;
33 36
34 /** 37 /**
@@ -95,8 +98,8 @@ public class AckRequestProcessor extends SIPRequestProcessorParent implements In @@ -95,8 +98,8 @@ public class AckRequestProcessor extends SIPRequestProcessorParent implements In
95 SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(platformGbId, channelId, null, callIdHeader.getCallId()); 98 SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(platformGbId, channelId, null, callIdHeader.getCallId());
96 String is_Udp = sendRtpItem.isTcp() ? "0" : "1"; 99 String is_Udp = sendRtpItem.isTcp() ? "0" : "1";
97 MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId()); 100 MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId());
98 - logger.info("收到ACK,rtp/{}开始向上级推流, 目标 {}:{},SSRC={}", sendRtpItem.getStreamId(), sendRtpItem.getIp(), sendRtpItem.getPort(), sendRtpItem.getSsrc());  
99 - Map<String, Object> param = new HashMap<>(); 101 + logger.info("收到ACK,rtp/{}开始向上级推流, 目标={}:{},SSRC={}", sendRtpItem.getStreamId(), sendRtpItem.getIp(), sendRtpItem.getPort(), sendRtpItem.getSsrc());
  102 + Map<String, Object> param = new HashMap<>(12);
100 param.put("vhost","__defaultVhost__"); 103 param.put("vhost","__defaultVhost__");
101 param.put("app",sendRtpItem.getApp()); 104 param.put("app",sendRtpItem.getApp());
102 param.put("stream",sendRtpItem.getStreamId()); 105 param.put("stream",sendRtpItem.getStreamId());
@@ -139,7 +142,11 @@ public class AckRequestProcessor extends SIPRequestProcessorParent implements In @@ -139,7 +142,11 @@ public class AckRequestProcessor extends SIPRequestProcessorParent implements In
139 // TODO 可能是语音对讲 142 // TODO 可能是语音对讲
140 }else { 143 }else {
141 // 向上级平台 144 // 向上级平台
142 - commanderForPlatform.streamByeCmd(parentPlatform, callIdHeader.getCallId()); 145 + try {
  146 + commanderForPlatform.streamByeCmd(parentPlatform, callIdHeader.getCallId());
  147 + } catch (SipException | InvalidArgumentException | ParseException e) {
  148 + logger.error("[命令发送失败] 国标级联 发送BYE: {}", e.getMessage());
  149 + }
143 } 150 }
144 } 151 }
145 } 152 }
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,12 +13,11 @@ import com.genersoft.iot.vmp.gb28181.transmit.event.request.ISIPRequestProcessor @@ -12,12 +13,11 @@ 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.bean.MessageForPushChannel; 18 import com.genersoft.iot.vmp.service.bean.MessageForPushChannel;
17 import com.genersoft.iot.vmp.storager.IRedisCatchStorage; 19 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
18 import com.genersoft.iot.vmp.storager.IVideoManagerStorage; 20 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
19 -import com.genersoft.iot.vmp.utils.SerializeUtils;  
20 -import gov.nist.javax.sip.stack.SIPDialog;  
21 import org.slf4j.Logger; 21 import org.slf4j.Logger;
22 import org.slf4j.LoggerFactory; 22 import org.slf4j.LoggerFactory;
23 import org.springframework.beans.factory.InitializingBean; 23 import org.springframework.beans.factory.InitializingBean;
@@ -51,6 +51,9 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In @@ -51,6 +51,9 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In
51 private IRedisCatchStorage redisCatchStorage; 51 private IRedisCatchStorage redisCatchStorage;
52 52
53 @Autowired 53 @Autowired
  54 + private IDeviceService deviceService;
  55 +
  56 + @Autowired
54 private IVideoManagerStorage storager; 57 private IVideoManagerStorage storager;
55 58
56 @Autowired 59 @Autowired
@@ -77,9 +80,13 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In @@ -77,9 +80,13 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In
77 */ 80 */
78 @Override 81 @Override
79 public void process(RequestEvent evt) { 82 public void process(RequestEvent evt) {
  83 +
80 try { 84 try {
81 responseAck(getServerTransaction(evt), Response.OK); 85 responseAck(getServerTransaction(evt), Response.OK);
82 - CallIdHeader callIdHeader = (CallIdHeader)evt.getRequest().getHeader(CallIdHeader.NAME); 86 + } catch (SipException | InvalidArgumentException | ParseException e) {
  87 + logger.error("[回复BYE信息失败],{}", e.getMessage());
  88 + }
  89 + CallIdHeader callIdHeader = (CallIdHeader)evt.getRequest().getHeader(CallIdHeader.NAME);
83 String platformGbId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(FromHeader.NAME)).getAddress().getURI()).getUser(); 90 String platformGbId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(FromHeader.NAME)).getAddress().getURI()).getUser();
84 String channelId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(ToHeader.NAME)).getAddress().getURI()).getUser(); 91 String channelId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(ToHeader.NAME)).getAddress().getURI()).getUser();
85 SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(platformGbId, channelId, null, callIdHeader.getCallId()); 92 SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(platformGbId, channelId, null, callIdHeader.getCallId());
@@ -99,7 +106,17 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In @@ -99,7 +106,17 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In
99 if (totalReaderCount <= 0) { 106 if (totalReaderCount <= 0) {
100 logger.info("[收到bye] {} 无其它观看者,通知设备停止推流", streamId); 107 logger.info("[收到bye] {} 无其它观看者,通知设备停止推流", streamId);
101 if (sendRtpItem.getPlayType().equals(InviteStreamType.PLAY)) { 108 if (sendRtpItem.getPlayType().equals(InviteStreamType.PLAY)) {
102 - cmder.streamByeCmd(sendRtpItem.getDeviceId(), channelId, streamId, null); 109 + Device device = deviceService.queryDevice(sendRtpItem.getDeviceId());
  110 + if (device == null) {
  111 + logger.info("[收到bye] {} 通知设备停止推流时未找到设备信息", streamId);
  112 + }
  113 + try {
  114 + logger.warn("[停止点播] {}/{}", sendRtpItem.getDeviceId(), channelId);
  115 + cmder.streamByeCmd(device, channelId, streamId, null);
  116 + } catch (InvalidArgumentException | ParseException | SipException |
  117 + SsrcTransactionNotFoundException e) {
  118 + logger.error("[收到bye] {} 无其它观看者,通知设备停止推流, 发送BYE失败 {}",streamId, e.getMessage());
  119 + }
103 } 120 }
104 if (sendRtpItem.getPlayType().equals(InviteStreamType.PUSH)) { 121 if (sendRtpItem.getPlayType().equals(InviteStreamType.PUSH)) {
105 MessageForPushChannel messageForPushChannel = MessageForPushChannel.getInstance(0, 122 MessageForPushChannel messageForPushChannel = MessageForPushChannel.getInstance(0,
@@ -120,8 +137,7 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In @@ -120,8 +137,7 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In
120 } 137 }
121 SsrcTransaction ssrcTransactionForPlay = streamSession.getSsrcTransaction(device.getDeviceId(), channelId, "play", null); 138 SsrcTransaction ssrcTransactionForPlay = streamSession.getSsrcTransaction(device.getDeviceId(), channelId, "play", null);
122 if (ssrcTransactionForPlay != null){ 139 if (ssrcTransactionForPlay != null){
123 - SIPDialog dialogForPlay = (SIPDialog) SerializeUtils.deSerialize(ssrcTransactionForPlay.getDialog());  
124 - if (dialogForPlay.getCallId().getCallId().equals(callIdHeader.getCallId())){ 140 + if (ssrcTransactionForPlay.getCallId().equals(callIdHeader.getCallId())){
125 // 释放ssrc 141 // 释放ssrc
126 MediaServerItem mediaServerItem = mediaServerService.getOne(ssrcTransactionForPlay.getMediaServerId()); 142 MediaServerItem mediaServerItem = mediaServerService.getOne(ssrcTransactionForPlay.getMediaServerId());
127 if (mediaServerItem != null) { 143 if (mediaServerItem != null) {
@@ -140,12 +156,6 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In @@ -140,12 +156,6 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In
140 streamSession.remove(device.getDeviceId(), channelId, ssrcTransactionForPlayBack.getStream()); 156 streamSession.remove(device.getDeviceId(), channelId, ssrcTransactionForPlayBack.getStream());
141 } 157 }
142 } 158 }
143 - } catch (SipException e) {  
144 - e.printStackTrace();  
145 - } catch (InvalidArgumentException e) {  
146 - e.printStackTrace();  
147 - } catch (ParseException e) {  
148 - e.printStackTrace();  
149 - } 159 +
150 } 160 }
151 } 161 }
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java
@@ -341,7 +341,11 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements @@ -341,7 +341,11 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
341 logger.info("Ack 等待超时"); 341 logger.info("Ack 等待超时");
342 mediaServerService.releaseSsrc(mediaServerItemInUSe.getId(), ssrc); 342 mediaServerService.releaseSsrc(mediaServerItemInUSe.getId(), ssrc);
343 // 回复bye 343 // 回复bye
344 - cmderFroPlatform.streamByeCmd(platform, callIdHeader.getCallId()); 344 + try {
  345 + cmderFroPlatform.streamByeCmd(platform, callIdHeader.getCallId());
  346 + } catch (SipException | InvalidArgumentException | ParseException e) {
  347 + logger.error("[命令发送失败] 国标级联 发送BYE: {}", e.getMessage());
  348 + }
345 }, 60 * 1000); 349 }, 60 * 1000);
346 responseSdpAck(serverTransaction, content.toString(), platform); 350 responseSdpAck(serverTransaction, content.toString(), platform);
347 351
@@ -657,12 +661,8 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements @@ -657,12 +661,8 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
657 mediaListManager.removedChannelOnlineEventLister(gbStream.getApp(), gbStream.getStream()); 661 mediaListManager.removedChannelOnlineEventLister(gbStream.getApp(), gbStream.getStream());
658 try { 662 try {
659 responseAck(serverTransaction, Response.TEMPORARILY_UNAVAILABLE, response.getMsg()); 663 responseAck(serverTransaction, Response.TEMPORARILY_UNAVAILABLE, response.getMsg());
660 - } catch (SipException e) {  
661 - throw new RuntimeException(e);  
662 - } catch (InvalidArgumentException e) {  
663 - throw new RuntimeException(e);  
664 - } catch (ParseException e) {  
665 - throw new RuntimeException(e); 664 + } catch (SipException | InvalidArgumentException | ParseException e) {
  665 + logger.error("[命令发送失败] 国标级联 点播回复: {}", e.getMessage());
666 } 666 }
667 } 667 }
668 }); 668 });
@@ -729,12 +729,8 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements @@ -729,12 +729,8 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
729 mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId); 729 mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId);
730 } 730 }
731 } 731 }
732 - } catch (InvalidArgumentException e) {  
733 - throw new RuntimeException(e);  
734 - } catch (ParseException e) {  
735 - throw new RuntimeException(e);  
736 - } catch (SipException e) {  
737 - throw new RuntimeException(e); 732 + } catch (InvalidArgumentException | ParseException | SipException e) {
  733 + logger.error("[命令发送失败] 国标级联 点播回复: {}", e.getMessage());
738 } 734 }
739 735
740 736
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 63
64 64
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
@@ -87,89 +87,73 @@ public class CatalogResponseMessageHandler extends SIPRequestProcessorParent imp @@ -87,89 +87,73 @@ public class CatalogResponseMessageHandler extends SIPRequestProcessorParent imp
87 public void handForDevice(RequestEvent evt, Device device, Element element) { 87 public void handForDevice(RequestEvent evt, Device device, Element element) {
88 taskQueue.offer(new HandlerCatchData(evt, device, element)); 88 taskQueue.offer(new HandlerCatchData(evt, device, element));
89 // 回复200 OK 89 // 回复200 OK
  90 + ServerTransaction serverTransaction = getServerTransaction(evt);
90 try { 91 try {
91 - ServerTransaction serverTransaction = getServerTransaction(evt);  
92 responseAck(serverTransaction, Response.OK); 92 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 - } 93 + } catch (SipException | InvalidArgumentException | ParseException e) {
  94 + logger.error("[命令发送失败] 目录查询回复: {}", e.getMessage());
  95 + }
  96 + if (!taskQueueHandlerRun) {
  97 + taskQueueHandlerRun = true;
  98 + taskExecutor.execute(() -> {
  99 + while (!taskQueue.isEmpty()) {
  100 + HandlerCatchData take = taskQueue.poll();
  101 + Element rootElement = null;
  102 + try {
  103 + rootElement = getRootElement(take.getEvt(), take.getDevice().getCharset());
  104 + } catch (DocumentException e) {
  105 + logger.error("[xml解析] 失败: ", e);
  106 + continue;
  107 + }
  108 + if (rootElement == null) {
  109 + logger.warn("[ 收到通道 ] content cannot be null, {}", evt.getRequest());
  110 + continue;
  111 + }
  112 + Element deviceListElement = rootElement.element("DeviceList");
  113 + Element sumNumElement = rootElement.element("SumNum");
  114 + Element snElement = rootElement.element("SN");
  115 + int sumNum = Integer.parseInt(sumNumElement.getText());
  116 +
  117 + if (sumNum == 0) {
  118 + logger.info("[收到通道]设备:{}的: 0个", take.getDevice().getDeviceId());
  119 + // 数据已经完整接收
  120 + storager.cleanChannelsForDevice(take.getDevice().getDeviceId());
  121 + catalogDataCatch.setChannelSyncEnd(take.getDevice().getDeviceId(), null);
  122 + } else {
  123 + Iterator<Element> deviceListIterator = deviceListElement.elementIterator();
  124 + if (deviceListIterator != null) {
  125 + List<DeviceChannel> channelList = new ArrayList<>();
  126 + // 遍历DeviceList
  127 + while (deviceListIterator.hasNext()) {
  128 + Element itemDevice = deviceListIterator.next();
  129 + Element channelDeviceElement = itemDevice.element("DeviceID");
  130 + if (channelDeviceElement == null) {
  131 + continue;
148 } 132 }
  133 + DeviceChannel deviceChannel = XmlUtil.channelContentHander(itemDevice, device, null);
  134 + deviceChannel.setDeviceId(take.getDevice().getDeviceId());
149 135
  136 + channelList.add(deviceChannel);
  137 + }
  138 + int sn = Integer.parseInt(snElement.getText());
  139 + catalogDataCatch.put(take.getDevice().getDeviceId(), sn, sumNum, take.getDevice(), channelList);
  140 + logger.info("[收到通道]设备: {} -> {}个,{}/{}", take.getDevice().getDeviceId(), channelList.size(), catalogDataCatch.get(take.getDevice().getDeviceId()) == null ? 0 : catalogDataCatch.get(take.getDevice().getDeviceId()).size(), sumNum);
  141 + if (catalogDataCatch.get(take.getDevice().getDeviceId()).size() == sumNum) {
  142 + // 数据已经完整接收, 此时可能存在某个设备离线变上线的情况,但是考虑到性能,此处不做处理,
  143 + // 目前支持设备通道上线通知时和设备上线时向上级通知
  144 + boolean resetChannelsResult = storager.resetChannels(take.getDevice().getDeviceId(), catalogDataCatch.get(take.getDevice().getDeviceId()));
  145 + if (!resetChannelsResult) {
  146 + String errorMsg = "接收成功,写入失败,共" + sumNum + "条,已接收" + catalogDataCatch.get(take.getDevice().getDeviceId()).size() + "条";
  147 + catalogDataCatch.setChannelSyncEnd(take.getDevice().getDeviceId(), errorMsg);
  148 + } else {
  149 + catalogDataCatch.setChannelSyncEnd(take.getDevice().getDeviceId(), null);
  150 + }
150 } 151 }
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 } 152 }
  153 +
162 } 154 }
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; 155 + }
  156 + });
173 } 157 }
174 158
175 } 159 }
@@ -182,7 +166,7 @@ public class CatalogResponseMessageHandler extends SIPRequestProcessorParent imp @@ -182,7 +166,7 @@ public class CatalogResponseMessageHandler extends SIPRequestProcessorParent imp
182 public SyncStatus getChannelSyncProgress(String deviceId) { 166 public SyncStatus getChannelSyncProgress(String deviceId) {
183 if (catalogDataCatch.get(deviceId) == null) { 167 if (catalogDataCatch.get(deviceId) == null) {
184 return null; 168 return null;
185 - }else { 169 + } else {
186 return catalogDataCatch.getSyncStatus(deviceId); 170 return catalogDataCatch.getSyncStatus(deviceId);
187 } 171 }
188 } 172 }
@@ -190,7 +174,7 @@ public class CatalogResponseMessageHandler extends SIPRequestProcessorParent imp @@ -190,7 +174,7 @@ public class CatalogResponseMessageHandler extends SIPRequestProcessorParent imp
190 public boolean isSyncRunning(String deviceId) { 174 public boolean isSyncRunning(String deviceId) {
191 if (catalogDataCatch.get(deviceId) == null) { 175 if (catalogDataCatch.get(deviceId) == null) {
192 return false; 176 return false;
193 - }else { 177 + } else {
194 return catalogDataCatch.isSyncRunning(deviceId); 178 return catalogDataCatch.isSyncRunning(deviceId);
195 } 179 }
196 } 180 }
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,7 +147,7 @@ public class RecordInfoResponseMessageHandler extends SIPRequestProcessorParent @@ -147,7 +147,7 @@ public class RecordInfoResponseMessageHandler extends SIPRequestProcessorParent
147 } 147 }
148 } 148 }
149 } catch (DocumentException e) { 149 } catch (DocumentException e) {
150 - throw new RuntimeException(e); 150 + logger.error("xml解析异常: ", e);
151 } finally { 151 } finally {
152 taskQueueHandlerRun = false; 152 taskQueueHandlerRun = false;
153 } 153 }
@@ -155,13 +155,9 @@ public class RecordInfoResponseMessageHandler extends SIPRequestProcessorParent @@ -155,13 +155,9 @@ public class RecordInfoResponseMessageHandler extends SIPRequestProcessorParent
155 }); 155 });
156 } 156 }
157 157
158 - } catch (SipException e) {  
159 - e.printStackTrace();  
160 - } catch (InvalidArgumentException e) {  
161 - e.printStackTrace();  
162 - } catch (ParseException e) {  
163 - e.printStackTrace();  
164 - }finally { 158 + } catch (SipException | InvalidArgumentException | ParseException e) {
  159 + logger.error("[命令发送失败] 国标级联 国标录像: {}", e.getMessage());
  160 + } finally {
165 taskQueueHandlerRun = false; 161 taskQueueHandlerRun = false;
166 } 162 }
167 } 163 }
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,11 +2,17 @@ package com.genersoft.iot.vmp.service.impl; @@ -2,11 +2,17 @@ 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
  8 +import javax.sip.InvalidArgumentException;
7 import javax.sip.ResponseEvent; 9 import javax.sip.ResponseEvent;
  10 +import javax.sip.SipException;
8 11
9 import com.genersoft.iot.vmp.conf.exception.ControllerException; 12 import com.genersoft.iot.vmp.conf.exception.ControllerException;
  13 +import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException;
  14 +import com.genersoft.iot.vmp.gb28181.bean.*;
  15 +import com.genersoft.iot.vmp.service.IDeviceService;
10 import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; 16 import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
11 import org.slf4j.Logger; 17 import org.slf4j.Logger;
12 import org.slf4j.LoggerFactory; 18 import org.slf4j.LoggerFactory;
@@ -22,13 +28,6 @@ import com.alibaba.fastjson.JSONObject; @@ -22,13 +28,6 @@ import com.alibaba.fastjson.JSONObject;
22 import com.genersoft.iot.vmp.common.StreamInfo; 28 import com.genersoft.iot.vmp.common.StreamInfo;
23 import com.genersoft.iot.vmp.conf.DynamicTask; 29 import com.genersoft.iot.vmp.conf.DynamicTask;
24 import com.genersoft.iot.vmp.conf.UserSetting; 30 import com.genersoft.iot.vmp.conf.UserSetting;
25 -import com.genersoft.iot.vmp.gb28181.bean.Device;  
26 -import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;  
27 -import com.genersoft.iot.vmp.gb28181.bean.InviteStreamCallback;  
28 -import com.genersoft.iot.vmp.gb28181.bean.InviteStreamInfo;  
29 -import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;  
30 -import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem;  
31 -import com.genersoft.iot.vmp.gb28181.bean.SsrcTransaction;  
32 import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; 31 import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
33 import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; 32 import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
34 import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; 33 import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
@@ -92,6 +91,10 @@ public class PlayServiceImpl implements IPlayService { @@ -92,6 +91,10 @@ public class PlayServiceImpl implements IPlayService {
92 @Autowired 91 @Autowired
93 private VideoStreamSessionManager streamSession; 92 private VideoStreamSessionManager streamSession;
94 93
  94 +
  95 + @Autowired
  96 + private IDeviceService deviceService;
  97 +
95 @Autowired 98 @Autowired
96 private UserSetting userSetting; 99 private UserSetting userSetting;
97 100
@@ -261,14 +264,14 @@ public class PlayServiceImpl implements IPlayService { @@ -261,14 +264,14 @@ public class PlayServiceImpl implements IPlayService {
261 System.out.println("设置超时任务: " + timeOutTaskKey); 264 System.out.println("设置超时任务: " + timeOutTaskKey);
262 dynamicTask.startDelay( timeOutTaskKey,()->{ 265 dynamicTask.startDelay( timeOutTaskKey,()->{
263 266
264 - SIPDialog dialog = streamSession.getDialogByStream(device.getDeviceId(), channelId, finalSsrcInfo.getStream());  
265 - if (dialog != null) {  
266 - logger.info("[点播超时] 收流超时 deviceId: {}, channelId: {},端口:{}, SSRC: {}", device.getDeviceId(), channelId, finalSsrcInfo.getPort(), finalSsrcInfo.getSsrc());  
267 - timeoutCallback.run(1, "收流超时");  
268 - // 点播超时回复BYE 同时释放ssrc以及此次点播的资源  
269 - cmder.streamByeCmd(device.getDeviceId(), channelId, finalSsrcInfo.getStream(), null);  
270 - }else {  
271 - logger.info("[点播超时] 消息未响应 deviceId: {}, channelId: {},端口:{}, SSRC: {}", device.getDeviceId(), channelId, finalSsrcInfo.getPort(), finalSsrcInfo.getSsrc()); 267 + logger.info("[点播超时] 收流超时 deviceId: {}, channelId: {},端口:{}, SSRC: {}", device.getDeviceId(), channelId, finalSsrcInfo.getPort(), finalSsrcInfo.getSsrc());
  268 + timeoutCallback.run(1, "收流超时");
  269 + // 点播超时回复BYE 同时释放ssrc以及此次点播的资源
  270 + try {
  271 + cmder.streamByeCmd(device, channelId, finalSsrcInfo.getStream(), null);
  272 + } catch (InvalidArgumentException | ParseException | SipException e) {
  273 + logger.error("[点播超时], 发送BYE失败 {}", e.getMessage());
  274 + } catch (SsrcTransactionNotFoundException e) {
272 timeoutCallback.run(0, "点播超时"); 275 timeoutCallback.run(0, "点播超时");
273 mediaServerService.releaseSsrc(mediaServerItem.getId(), finalSsrcInfo.getSsrc()); 276 mediaServerService.releaseSsrc(mediaServerItem.getId(), finalSsrcInfo.getSsrc());
274 mediaServerService.closeRTPServer(mediaServerItem, finalSsrcInfo.getStream()); 277 mediaServerService.closeRTPServer(mediaServerItem, finalSsrcInfo.getStream());
@@ -282,73 +285,87 @@ public class PlayServiceImpl implements IPlayService { @@ -282,73 +285,87 @@ public class PlayServiceImpl implements IPlayService {
282 logger.info("[点播端口分配异常],deviceId={},channelId={},ssrcInfo={}", device.getDeviceId(), channelId, ssrcInfo); 285 logger.info("[点播端口分配异常],deviceId={},channelId={},ssrcInfo={}", device.getDeviceId(), channelId, ssrcInfo);
283 return; 286 return;
284 } 287 }
285 - cmder.playStreamCmd(mediaServerItem, ssrcInfo, device, channelId, (MediaServerItem mediaServerItemInuse, JSONObject response) -> {  
286 - logger.info("收到订阅消息: " + response.toJSONString());  
287 - System.out.println("停止超时任务: " + timeOutTaskKey);  
288 - dynamicTask.stop(timeOutTaskKey);  
289 - // hook响应  
290 - onPublishHandlerForPlay(mediaServerItemInuse, response, device.getDeviceId(), channelId, uuid);  
291 - hookEvent.response(mediaServerItemInuse, response);  
292 - logger.info("[点播成功] deviceId: {}, channelId: {}", device.getDeviceId(), channelId);  
293 -  
294 - }, (event) -> {  
295 - ResponseEvent responseEvent = (ResponseEvent)event.event;  
296 - String contentString = new String(responseEvent.getResponse().getRawContent());  
297 - // 获取ssrc  
298 - int ssrcIndex = contentString.indexOf("y=");  
299 - // 检查是否有y字段  
300 - if (ssrcIndex >= 0) {  
301 - //ssrc规定长度为10字节,不取余下长度以避免后续还有“f=”字段 TODO 后续对不规范的非10位ssrc兼容  
302 - String ssrcInResponse = contentString.substring(ssrcIndex + 2, ssrcIndex + 12);  
303 - // 查询到ssrc不一致且开启了ssrc校验则需要针对处理  
304 - if (ssrc.equals(ssrcInResponse)) {  
305 - return;  
306 - }  
307 - logger.info("[点播消息] 收到invite 200, 发现下级自定义了ssrc: {}", ssrcInResponse );  
308 - if (!mediaServerItem.isRtpEnable() || device.isSsrcCheck()) {  
309 - logger.info("[点播消息] SSRC修正 {}->{}", ssrc, ssrcInResponse);  
310 -  
311 - if (!mediaServerItem.getSsrcConfig().checkSsrc(ssrcInResponse)) {  
312 - // ssrc 不可用  
313 - // 释放ssrc  
314 - mediaServerService.releaseSsrc(mediaServerItem.getId(), finalSsrcInfo.getSsrc());  
315 - streamSession.remove(device.getDeviceId(), channelId, finalSsrcInfo.getStream());  
316 - event.msg = "下级自定义了ssrc,但是此ssrc不可用";  
317 - event.statusCode = 400;  
318 - errorEvent.response(event); 288 + try {
  289 + cmder.playStreamCmd(mediaServerItem, ssrcInfo, device, channelId, (MediaServerItem mediaServerItemInuse, JSONObject response) -> {
  290 + logger.info("收到订阅消息: " + response.toJSONString());
  291 + System.out.println("停止超时任务: " + timeOutTaskKey);
  292 + dynamicTask.stop(timeOutTaskKey);
  293 + // hook响应
  294 + onPublishHandlerForPlay(mediaServerItemInuse, response, device.getDeviceId(), channelId, uuid);
  295 + hookEvent.response(mediaServerItemInuse, response);
  296 + logger.info("[点播成功] deviceId: {}, channelId: {}", device.getDeviceId(), channelId);
  297 +
  298 + }, (event) -> {
  299 + ResponseEvent responseEvent = (ResponseEvent)event.event;
  300 + String contentString = new String(responseEvent.getResponse().getRawContent());
  301 + // 获取ssrc
  302 + int ssrcIndex = contentString.indexOf("y=");
  303 + // 检查是否有y字段
  304 + if (ssrcIndex >= 0) {
  305 + //ssrc规定长度为10字节,不取余下长度以避免后续还有“f=”字段 TODO 后续对不规范的非10位ssrc兼容
  306 + String ssrcInResponse = contentString.substring(ssrcIndex + 2, ssrcIndex + 12);
  307 + // 查询到ssrc不一致且开启了ssrc校验则需要针对处理
  308 + if (ssrc.equals(ssrcInResponse)) {
319 return; 309 return;
320 } 310 }
  311 + logger.info("[点播消息] 收到invite 200, 发现下级自定义了ssrc: {}", ssrcInResponse );
  312 + if (!mediaServerItem.isRtpEnable() || device.isSsrcCheck()) {
  313 + logger.info("[点播消息] SSRC修正 {}->{}", ssrc, ssrcInResponse);
  314 +
  315 + if (!mediaServerItem.getSsrcConfig().checkSsrc(ssrcInResponse)) {
  316 + // ssrc 不可用
  317 + // 释放ssrc
  318 + mediaServerService.releaseSsrc(mediaServerItem.getId(), finalSsrcInfo.getSsrc());
  319 + streamSession.remove(device.getDeviceId(), channelId, finalSsrcInfo.getStream());
  320 + event.msg = "下级自定义了ssrc,但是此ssrc不可用";
  321 + event.statusCode = 400;
  322 + errorEvent.response(event);
  323 + return;
  324 + }
321 325
322 - // 单端口模式streamId也有变化,需要重新设置监听  
323 - if (!mediaServerItem.isRtpEnable()) {  
324 - // 添加订阅  
325 - HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", stream, true, "rtsp", mediaServerItem.getId());  
326 - subscribe.removeSubscribe(hookSubscribe);  
327 - hookSubscribe.getContent().put("stream", String.format("%08x", Integer.parseInt(ssrcInResponse)).toUpperCase());  
328 - subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, JSONObject response)->{  
329 - logger.info("[ZLM HOOK] ssrc修正后收到订阅消息: " + response.toJSONString());  
330 - dynamicTask.stop(timeOutTaskKey);  
331 - // hook响应  
332 - onPublishHandlerForPlay(mediaServerItemInUse, response, device.getDeviceId(), channelId, uuid);  
333 - hookEvent.response(mediaServerItemInUse, response);  
334 - });  
335 - }  
336 - // 关闭rtp server  
337 - mediaServerService.closeRTPServer(mediaServerItem, finalSsrcInfo.getStream());  
338 - // 重新开启ssrc server  
339 - mediaServerService.openRTPServer(mediaServerItem, finalSsrcInfo.getStream(), ssrcInResponse, device.isSsrcCheck(), false, finalSsrcInfo.getPort()); 326 + // 单端口模式streamId也有变化,需要重新设置监听
  327 + if (!mediaServerItem.isRtpEnable()) {
  328 + // 添加订阅
  329 + HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", stream, true, "rtsp", mediaServerItem.getId());
  330 + subscribe.removeSubscribe(hookSubscribe);
  331 + hookSubscribe.getContent().put("stream", String.format("%08x", Integer.parseInt(ssrcInResponse)).toUpperCase());
  332 + subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, JSONObject response)->{
  333 + logger.info("[ZLM HOOK] ssrc修正后收到订阅消息: " + response.toJSONString());
  334 + dynamicTask.stop(timeOutTaskKey);
  335 + // hook响应
  336 + onPublishHandlerForPlay(mediaServerItemInUse, response, device.getDeviceId(), channelId, uuid);
  337 + hookEvent.response(mediaServerItemInUse, response);
  338 + });
  339 + }
  340 + // 关闭rtp server
  341 + mediaServerService.closeRTPServer(mediaServerItem, finalSsrcInfo.getStream());
  342 + // 重新开启ssrc server
  343 + mediaServerService.openRTPServer(mediaServerItem, finalSsrcInfo.getStream(), ssrcInResponse, device.isSsrcCheck(), false, finalSsrcInfo.getPort());
340 344
  345 + }
341 } 346 }
342 - }  
343 - }, (event) -> { 347 + }, (event) -> {
  348 + dynamicTask.stop(timeOutTaskKey);
  349 + mediaServerService.closeRTPServer(mediaServerItem, finalSsrcInfo.getStream());
  350 + // 释放ssrc
  351 + mediaServerService.releaseSsrc(mediaServerItem.getId(), finalSsrcInfo.getSsrc());
  352 +
  353 + streamSession.remove(device.getDeviceId(), channelId, finalSsrcInfo.getStream());
  354 + errorEvent.response(event);
  355 + });
  356 + } catch (InvalidArgumentException | SipException | ParseException e) {
  357 +
  358 + logger.error("[命令发送失败] 点播消息: {}", e.getMessage());
344 dynamicTask.stop(timeOutTaskKey); 359 dynamicTask.stop(timeOutTaskKey);
345 mediaServerService.closeRTPServer(mediaServerItem, finalSsrcInfo.getStream()); 360 mediaServerService.closeRTPServer(mediaServerItem, finalSsrcInfo.getStream());
346 // 释放ssrc 361 // 释放ssrc
347 mediaServerService.releaseSsrc(mediaServerItem.getId(), finalSsrcInfo.getSsrc()); 362 mediaServerService.releaseSsrc(mediaServerItem.getId(), finalSsrcInfo.getSsrc());
348 363
349 streamSession.remove(device.getDeviceId(), channelId, finalSsrcInfo.getStream()); 364 streamSession.remove(device.getDeviceId(), channelId, finalSsrcInfo.getStream());
350 - errorEvent.response(event);  
351 - }); 365 + SipSubscribe.EventResult eventResult = new SipSubscribe.EventResult(new CmdSendFailEvent(null));
  366 + eventResult.msg = "命令发送失败";
  367 + errorEvent.response(eventResult);
  368 + }
352 } 369 }
353 370
354 @Override 371 @Override
@@ -439,17 +456,18 @@ public class PlayServiceImpl implements IPlayService { @@ -439,17 +456,18 @@ public class PlayServiceImpl implements IPlayService {
439 playBackResult.setCode(ErrorCode.ERROR100.getCode()); 456 playBackResult.setCode(ErrorCode.ERROR100.getCode());
440 playBackResult.setMsg("回放超时"); 457 playBackResult.setMsg("回放超时");
441 playBackResult.setData(requestMessage); 458 playBackResult.setData(requestMessage);
442 - SIPDialog dialog = streamSession.getDialogByStream(deviceId, channelId, ssrcInfo.getStream());  
443 - // 点播超时回复BYE 同时释放ssrc以及此次点播的资源  
444 - if (dialog != null) { 459 +
  460 + try {
  461 + cmder.streamByeCmd(device, channelId, ssrcInfo.getStream(), null);
  462 + } catch (InvalidArgumentException | ParseException | SipException e) {
  463 + logger.error("[录像流]回放超时 发送BYE失败 {}", e.getMessage());
  464 + } catch (SsrcTransactionNotFoundException e) {
445 // 点播超时回复BYE 同时释放ssrc以及此次点播的资源 465 // 点播超时回复BYE 同时释放ssrc以及此次点播的资源
446 - cmder.streamByeCmd(device.getDeviceId(), channelId, ssrcInfo.getStream(), null);  
447 - }else {  
448 mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); 466 mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc());
449 mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream()); 467 mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream());
450 streamSession.remove(deviceId, channelId, ssrcInfo.getStream()); 468 streamSession.remove(deviceId, channelId, ssrcInfo.getStream());
451 } 469 }
452 - cmder.streamByeCmd(device.getDeviceId(), channelId, ssrcInfo.getStream(), null); 470 +
453 // 回复之前所有的点播请求 471 // 回复之前所有的点播请求
454 playBackCallback.call(playBackResult); 472 playBackCallback.call(playBackResult);
455 result.setResult(WVPResult.fail(ErrorCode.ERROR100.getCode(), "回放超时")); 473 result.setResult(WVPResult.fail(ErrorCode.ERROR100.getCode(), "回放超时"));
@@ -489,59 +507,67 @@ public class PlayServiceImpl implements IPlayService { @@ -489,59 +507,67 @@ public class PlayServiceImpl implements IPlayService {
489 playBackCallback.call(playBackResult); 507 playBackCallback.call(playBackResult);
490 }; 508 };
491 509
492 - cmder.playbackStreamCmd(mediaServerItem, ssrcInfo, device, channelId, startTime, endTime, infoCallBack,  
493 - hookEvent, eventResult -> {  
494 - if (eventResult.type == SipSubscribe.EventResultType.response) {  
495 - ResponseEvent responseEvent = (ResponseEvent)eventResult.event;  
496 - String contentString = new String(responseEvent.getResponse().getRawContent());  
497 - // 获取ssrc  
498 - int ssrcIndex = contentString.indexOf("y=");  
499 - // 检查是否有y字段  
500 - if (ssrcIndex >= 0) {  
501 - //ssrc规定长度为10字节,不取余下长度以避免后续还有“f=”字段 TODO 后续对不规范的非10位ssrc兼容  
502 - String ssrcInResponse = contentString.substring(ssrcIndex + 2, ssrcIndex + 12);  
503 - // 查询到ssrc不一致且开启了ssrc校验则需要针对处理  
504 - if (ssrcInfo.getSsrc().equals(ssrcInResponse)) {  
505 - return;  
506 - }  
507 - logger.info("[回放消息] 收到invite 200, 发现下级自定义了ssrc: {}", ssrcInResponse );  
508 - if (!mediaServerItem.isRtpEnable() || device.isSsrcCheck()) {  
509 - logger.info("[回放消息] SSRC修正 {}->{}", ssrcInfo.getSsrc(), ssrcInResponse);  
510 -  
511 - if (!mediaServerItem.getSsrcConfig().checkSsrc(ssrcInResponse)) {  
512 - // ssrc 不可用  
513 - // 释放ssrc  
514 - mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc());  
515 - streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream());  
516 - eventResult.msg = "下级自定义了ssrc,但是此ssrc不可用";  
517 - eventResult.statusCode = 400;  
518 - errorEvent.response(eventResult); 510 + try {
  511 + cmder.playbackStreamCmd(mediaServerItem, ssrcInfo, device, channelId, startTime, endTime, infoCallBack,
  512 + hookEvent, eventResult -> {
  513 + if (eventResult.type == SipSubscribe.EventResultType.response) {
  514 + ResponseEvent responseEvent = (ResponseEvent)eventResult.event;
  515 + String contentString = new String(responseEvent.getResponse().getRawContent());
  516 + // 获取ssrc
  517 + int ssrcIndex = contentString.indexOf("y=");
  518 + // 检查是否有y字段
  519 + if (ssrcIndex >= 0) {
  520 + //ssrc规定长度为10字节,不取余下长度以避免后续还有“f=”字段 TODO 后续对不规范的非10位ssrc兼容
  521 + String ssrcInResponse = contentString.substring(ssrcIndex + 2, ssrcIndex + 12);
  522 + // 查询到ssrc不一致且开启了ssrc校验则需要针对处理
  523 + if (ssrcInfo.getSsrc().equals(ssrcInResponse)) {
519 return; 524 return;
520 } 525 }
521 -  
522 - // 单端口模式streamId也有变化,需要重新设置监听  
523 - if (!mediaServerItem.isRtpEnable()) {  
524 - // 添加订阅  
525 - HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", ssrcInfo.getStream(), true, "rtsp", mediaServerItem.getId());  
526 - subscribe.removeSubscribe(hookSubscribe);  
527 - hookSubscribe.getContent().put("stream", String.format("%08x", Integer.parseInt(ssrcInResponse)).toUpperCase());  
528 - subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, JSONObject response)->{  
529 - logger.info("[ZLM HOOK] ssrc修正后收到订阅消息: " + response.toJSONString());  
530 - dynamicTask.stop(playBackTimeOutTaskKey);  
531 - // hook响应  
532 - onPublishHandlerForPlay(mediaServerItemInUse, response, device.getDeviceId(), channelId, uuid);  
533 - hookEvent.call(new InviteStreamInfo(mediaServerItem, null, eventResult.callId, "rtp", ssrcInfo.getStream()));  
534 - }); 526 + logger.info("[回放消息] 收到invite 200, 发现下级自定义了ssrc: {}", ssrcInResponse );
  527 + if (!mediaServerItem.isRtpEnable() || device.isSsrcCheck()) {
  528 + logger.info("[回放消息] SSRC修正 {}->{}", ssrcInfo.getSsrc(), ssrcInResponse);
  529 +
  530 + if (!mediaServerItem.getSsrcConfig().checkSsrc(ssrcInResponse)) {
  531 + // ssrc 不可用
  532 + // 释放ssrc
  533 + mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc());
  534 + streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream());
  535 + eventResult.msg = "下级自定义了ssrc,但是此ssrc不可用";
  536 + eventResult.statusCode = 400;
  537 + errorEvent.response(eventResult);
  538 + return;
  539 + }
  540 +
  541 + // 单端口模式streamId也有变化,需要重新设置监听
  542 + if (!mediaServerItem.isRtpEnable()) {
  543 + // 添加订阅
  544 + HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", ssrcInfo.getStream(), true, "rtsp", mediaServerItem.getId());
  545 + subscribe.removeSubscribe(hookSubscribe);
  546 + hookSubscribe.getContent().put("stream", String.format("%08x", Integer.parseInt(ssrcInResponse)).toUpperCase());
  547 + subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, JSONObject response)->{
  548 + logger.info("[ZLM HOOK] ssrc修正后收到订阅消息: " + response.toJSONString());
  549 + dynamicTask.stop(playBackTimeOutTaskKey);
  550 + // hook响应
  551 + onPublishHandlerForPlay(mediaServerItemInUse, response, device.getDeviceId(), channelId, uuid);
  552 + hookEvent.call(new InviteStreamInfo(mediaServerItem, null, eventResult.callId, "rtp", ssrcInfo.getStream()));
  553 + });
  554 + }
  555 + // 关闭rtp server
  556 + mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream());
  557 + // 重新开启ssrc server
  558 + mediaServerService.openRTPServer(mediaServerItem, ssrcInfo.getStream(), ssrcInResponse, device.isSsrcCheck(), true, ssrcInfo.getPort());
535 } 559 }
536 - // 关闭rtp server  
537 - mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream());  
538 - // 重新开启ssrc server  
539 - mediaServerService.openRTPServer(mediaServerItem, ssrcInfo.getStream(), ssrcInResponse, device.isSsrcCheck(), true, ssrcInfo.getPort());  
540 } 560 }
541 } 561 }
542 - }  
543 562
544 - }, errorEvent); 563 + }, errorEvent);
  564 + } catch (InvalidArgumentException | SipException | ParseException e) {
  565 + logger.error("[命令发送失败] 回放: {}", e.getMessage());
  566 +
  567 + SipSubscribe.EventResult eventResult = new SipSubscribe.EventResult(new CmdSendFailEvent(null));
  568 + eventResult.msg = "命令发送失败";
  569 + errorEvent.response(eventResult);
  570 + }
545 return result; 571 return result;
546 } 572 }
547 573
@@ -587,46 +613,57 @@ public class PlayServiceImpl implements IPlayService { @@ -587,46 +613,57 @@ public class PlayServiceImpl implements IPlayService {
587 downloadResult.setCode(ErrorCode.ERROR100.getCode()); 613 downloadResult.setCode(ErrorCode.ERROR100.getCode());
588 downloadResult.setMsg("录像下载请求超时"); 614 downloadResult.setMsg("录像下载请求超时");
589 hookCallBack.call(downloadResult); 615 hookCallBack.call(downloadResult);
590 - SIPDialog dialog = streamSession.getDialogByStream(deviceId, channelId, ssrcInfo.getStream()); 616 +
591 // 点播超时回复BYE 同时释放ssrc以及此次点播的资源 617 // 点播超时回复BYE 同时释放ssrc以及此次点播的资源
592 - if (dialog != null) {  
593 - // 点播超时回复BYE 同时释放ssrc以及此次点播的资源  
594 - cmder.streamByeCmd(device.getDeviceId(), channelId, ssrcInfo.getStream(), null);  
595 - }else { 618 + try {
  619 + cmder.streamByeCmd(device, channelId, ssrcInfo.getStream(), null);
  620 + } catch (InvalidArgumentException | ParseException | SipException e) {
  621 + logger.error("[录像流]录像下载请求超时, 发送BYE失败 {}", e.getMessage());
  622 + } catch (SsrcTransactionNotFoundException e) {
596 mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); 623 mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc());
597 mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream()); 624 mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream());
598 streamSession.remove(deviceId, channelId, ssrcInfo.getStream()); 625 streamSession.remove(deviceId, channelId, ssrcInfo.getStream());
599 } 626 }
600 - cmder.streamByeCmd(device.getDeviceId(), channelId, ssrcInfo.getStream(), null);  
601 // 回复之前所有的点播请求 627 // 回复之前所有的点播请求
602 hookCallBack.call(downloadResult); 628 hookCallBack.call(downloadResult);
603 }, userSetting.getPlayTimeout()); 629 }, userSetting.getPlayTimeout());
604 - cmder.downloadStreamCmd(mediaServerItem, ssrcInfo, device, channelId, startTime, endTime, downloadSpeed, infoCallBack,  
605 - inviteStreamInfo -> {  
606 - logger.info("收到订阅消息: " + inviteStreamInfo.getResponse().toJSONString());  
607 - dynamicTask.stop(downLoadTimeOutTaskKey);  
608 - StreamInfo streamInfo = onPublishHandler(inviteStreamInfo.getMediaServerItem(), inviteStreamInfo.getResponse(), deviceId, channelId);  
609 - streamInfo.setStartTime(startTime);  
610 - streamInfo.setEndTime(endTime);  
611 - redisCatchStorage.startDownload(streamInfo, inviteStreamInfo.getCallId());  
612 - wvpResult.setCode(ErrorCode.SUCCESS.getCode());  
613 - wvpResult.setMsg(ErrorCode.SUCCESS.getMsg());  
614 - wvpResult.setData(streamInfo);  
615 - downloadResult.setCode(ErrorCode.SUCCESS.getCode());  
616 - downloadResult.setMsg(ErrorCode.SUCCESS.getMsg());  
617 - downloadResult.setMediaServerItem(inviteStreamInfo.getMediaServerItem());  
618 - downloadResult.setResponse(inviteStreamInfo.getResponse());  
619 - hookCallBack.call(downloadResult);  
620 - }, event -> {  
621 - dynamicTask.stop(downLoadTimeOutTaskKey);  
622 - downloadResult.setCode(ErrorCode.ERROR100.getCode());  
623 - downloadResult.setMsg(String.format("录像下载失败, 错误码: %s, %s", event.statusCode, event.msg));  
624 - wvpResult.setCode(ErrorCode.ERROR100.getCode());  
625 - wvpResult.setMsg(String.format("录像下载失败, 错误码: %s, %s", event.statusCode, event.msg));  
626 - downloadResult.setEvent(event);  
627 - hookCallBack.call(downloadResult);  
628 - streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream());  
629 - }); 630 +
  631 + SipSubscribe.Event errorEvent = event -> {
  632 + dynamicTask.stop(downLoadTimeOutTaskKey);
  633 + downloadResult.setCode(ErrorCode.ERROR100.getCode());
  634 + downloadResult.setMsg(String.format("录像下载失败, 错误码: %s, %s", event.statusCode, event.msg));
  635 + wvpResult.setCode(ErrorCode.ERROR100.getCode());
  636 + wvpResult.setMsg(String.format("录像下载失败, 错误码: %s, %s", event.statusCode, event.msg));
  637 + downloadResult.setEvent(event);
  638 + hookCallBack.call(downloadResult);
  639 + streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream());
  640 + };
  641 +
  642 + try {
  643 + cmder.downloadStreamCmd(mediaServerItem, ssrcInfo, device, channelId, startTime, endTime, downloadSpeed, infoCallBack,
  644 + inviteStreamInfo -> {
  645 + logger.info("收到订阅消息: " + inviteStreamInfo.getResponse().toJSONString());
  646 + dynamicTask.stop(downLoadTimeOutTaskKey);
  647 + StreamInfo streamInfo = onPublishHandler(inviteStreamInfo.getMediaServerItem(), inviteStreamInfo.getResponse(), deviceId, channelId);
  648 + streamInfo.setStartTime(startTime);
  649 + streamInfo.setEndTime(endTime);
  650 + redisCatchStorage.startDownload(streamInfo, inviteStreamInfo.getCallId());
  651 + wvpResult.setCode(ErrorCode.SUCCESS.getCode());
  652 + wvpResult.setMsg(ErrorCode.SUCCESS.getMsg());
  653 + wvpResult.setData(streamInfo);
  654 + downloadResult.setCode(ErrorCode.SUCCESS.getCode());
  655 + downloadResult.setMsg(ErrorCode.SUCCESS.getMsg());
  656 + downloadResult.setMediaServerItem(inviteStreamInfo.getMediaServerItem());
  657 + downloadResult.setResponse(inviteStreamInfo.getResponse());
  658 + hookCallBack.call(downloadResult);
  659 + }, errorEvent);
  660 + } catch (InvalidArgumentException | SipException | ParseException e) {
  661 + logger.error("[命令发送失败] 录像下载: {}", e.getMessage());
  662 +
  663 + SipSubscribe.EventResult eventResult = new SipSubscribe.EventResult(new CmdSendFailEvent(null));
  664 + eventResult.msg = "命令发送失败";
  665 + errorEvent.response(eventResult);
  666 + }
630 return result; 667 return result;
631 } 668 }
632 669
@@ -705,7 +742,11 @@ public class PlayServiceImpl implements IPlayService { @@ -705,7 +742,11 @@ public class PlayServiceImpl implements IPlayService {
705 for (SendRtpItem sendRtpItem : sendRtpItems) { 742 for (SendRtpItem sendRtpItem : sendRtpItems) {
706 if (sendRtpItem.getMediaServerId().equals(mediaServerId)) { 743 if (sendRtpItem.getMediaServerId().equals(mediaServerId)) {
707 ParentPlatform platform = storager.queryParentPlatByServerGBId(sendRtpItem.getPlatformId()); 744 ParentPlatform platform = storager.queryParentPlatByServerGBId(sendRtpItem.getPlatformId());
708 - sipCommanderFroPlatform.streamByeCmd(platform, sendRtpItem.getCallId()); 745 + try {
  746 + sipCommanderFroPlatform.streamByeCmd(platform, sendRtpItem.getCallId());
  747 + } catch (SipException | InvalidArgumentException | ParseException e) {
  748 + logger.error("[命令发送失败] 国标级联 发送BYE: {}", e.getMessage());
  749 + }
709 } 750 }
710 } 751 }
711 } 752 }
@@ -714,8 +755,17 @@ public class PlayServiceImpl implements IPlayService { @@ -714,8 +755,17 @@ public class PlayServiceImpl implements IPlayService {
714 if (allSsrc.size() > 0) { 755 if (allSsrc.size() > 0) {
715 for (SsrcTransaction ssrcTransaction : allSsrc) { 756 for (SsrcTransaction ssrcTransaction : allSsrc) {
716 if(ssrcTransaction.getMediaServerId().equals(mediaServerId)) { 757 if(ssrcTransaction.getMediaServerId().equals(mediaServerId)) {
717 - cmder.streamByeCmd(ssrcTransaction.getDeviceId(), ssrcTransaction.getChannelId(),  
718 - ssrcTransaction.getStream(), null); 758 + Device device = deviceService.queryDevice(ssrcTransaction.getDeviceId());
  759 + if (device == null) {
  760 + continue;
  761 + }
  762 + try {
  763 + cmder.streamByeCmd(device, ssrcTransaction.getChannelId(),
  764 + ssrcTransaction.getStream(), null);
  765 + } catch (InvalidArgumentException | ParseException | SipException |
  766 + SsrcTransactionNotFoundException e) {
  767 + logger.error("[zlm离线]为正在使用此zlm的设备, 发送BYE失败 {}", e.getMessage());
  768 + }
719 } 769 }
720 } 770 }
721 } 771 }
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,9 @@ import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; @@ -16,7 +16,9 @@ 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.validation.constraints.NotNull; 19 +import javax.sip.InvalidArgumentException;
  20 +import javax.sip.SipException;
  21 +import java.text.ParseException;
20 import java.util.List; 22 import java.util.List;
21 import java.util.concurrent.ConcurrentLinkedQueue; 23 import java.util.concurrent.ConcurrentLinkedQueue;
22 24
@@ -78,16 +80,28 @@ public class RedisAlarmMsgListener implements MessageListener { @@ -78,16 +80,28 @@ public class RedisAlarmMsgListener implements MessageListener {
78 List<ParentPlatform> parentPlatforms = storage.queryEnableParentPlatformList(true); 80 List<ParentPlatform> parentPlatforms = storage.queryEnableParentPlatformList(true);
79 if (parentPlatforms.size() > 0) { 81 if (parentPlatforms.size() > 0) {
80 for (ParentPlatform parentPlatform : parentPlatforms) { 82 for (ParentPlatform parentPlatform : parentPlatforms) {
81 - commanderForPlatform.sendAlarmMessage(parentPlatform, deviceAlarm); 83 + try {
  84 + commanderForPlatform.sendAlarmMessage(parentPlatform, deviceAlarm);
  85 + } catch (SipException | InvalidArgumentException | ParseException e) {
  86 + logger.error("[命令发送失败] 国标级联 发送报警: {}", e.getMessage());
  87 + }
82 } 88 }
83 } 89 }
84 }else { 90 }else {
85 Device device = storage.queryVideoDevice(gbId); 91 Device device = storage.queryVideoDevice(gbId);
86 ParentPlatform platform = storage.queryParentPlatByServerGBId(gbId); 92 ParentPlatform platform = storage.queryParentPlatByServerGBId(gbId);
87 if (device != null && platform == null) { 93 if (device != null && platform == null) {
88 - commander.sendAlarmMessage(device, deviceAlarm); 94 + try {
  95 + commander.sendAlarmMessage(device, deviceAlarm);
  96 + } catch (InvalidArgumentException | SipException | ParseException e) {
  97 + logger.error("[命令发送失败] 发送报警: {}", e.getMessage());
  98 + }
89 }else if (device == null && platform != null){ 99 }else if (device == null && platform != null){
90 - commanderForPlatform.sendAlarmMessage(platform, deviceAlarm); 100 + try {
  101 + commanderForPlatform.sendAlarmMessage(platform, deviceAlarm);
  102 + } catch (InvalidArgumentException | SipException | ParseException e) {
  103 + logger.error("[命令发送失败] 发送报警: {}", e.getMessage());
  104 + }
91 }else { 105 }else {
92 logger.warn("无法确定" + gbId + "是平台还是设备"); 106 logger.warn("无法确定" + gbId + "是平台还是设备");
93 } 107 }
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;
@@ -36,6 +37,9 @@ import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; @@ -36,6 +37,9 @@ import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
36 import com.genersoft.iot.vmp.storager.IVideoManagerStorage; 37 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
37 import org.springframework.web.context.request.async.DeferredResult; 38 import org.springframework.web.context.request.async.DeferredResult;
38 39
  40 +import javax.sip.InvalidArgumentException;
  41 +import javax.sip.SipException;
  42 +import java.text.ParseException;
39 import java.util.List; 43 import java.util.List;
40 import java.util.UUID; 44 import java.util.UUID;
41 45
@@ -102,12 +106,23 @@ public class PlayController { @@ -102,12 +106,23 @@ public class PlayController {
102 throw new ControllerException(ErrorCode.ERROR400); 106 throw new ControllerException(ErrorCode.ERROR400);
103 } 107 }
104 108
  109 + Device device = storager.queryVideoDevice(deviceId);
  110 + if (device == null) {
  111 + throw new ControllerException(ErrorCode.ERROR100.getCode(), "设备[" + deviceId + "]不存在");
  112 + }
  113 +
105 StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channelId); 114 StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channelId);
106 if (streamInfo == null) { 115 if (streamInfo == null) {
107 throw new ControllerException(ErrorCode.ERROR100.getCode(), "点播未找到"); 116 throw new ControllerException(ErrorCode.ERROR100.getCode(), "点播未找到");
108 } 117 }
109 118
110 - cmder.streamByeCmd(deviceId, channelId, streamInfo.getStream(), null, null); 119 + try {
  120 + logger.warn("[停止点播] {}/{}", device.getDeviceId(), channelId);
  121 + cmder.streamByeCmd(device, channelId, streamInfo.getStream(), null, null);
  122 + } catch (InvalidArgumentException | SipException | ParseException | SsrcTransactionNotFoundException e) {
  123 + logger.error("[命令发送失败] 停止点播, 发送BYE: {}", e.getMessage());
  124 + throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
  125 + }
111 redisCatchStorage.stopPlay(streamInfo); 126 redisCatchStorage.stopPlay(streamInfo);
112 127
113 storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId()); 128 storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId());
@@ -221,18 +236,23 @@ public class PlayController { @@ -221,18 +236,23 @@ public class PlayController {
221 resultHolder.invokeResult(msg); 236 resultHolder.invokeResult(msg);
222 return result; 237 return result;
223 } 238 }
224 - cmder.audioBroadcastCmd(device, (event) -> {  
225 - RequestMessage msg = new RequestMessage();  
226 - msg.setKey(key);  
227 - msg.setId(uuid);  
228 - JSONObject json = new JSONObject();  
229 - json.put("DeviceID", deviceId);  
230 - json.put("CmdType", "Broadcast");  
231 - json.put("Result", "Failed");  
232 - json.put("Description", String.format("语音广播操作失败,错误码: %s, %s", event.statusCode, event.msg));  
233 - msg.setData(json);  
234 - resultHolder.invokeResult(msg);  
235 - }); 239 + try {
  240 + cmder.audioBroadcastCmd(device, (event) -> {
  241 + RequestMessage msg = new RequestMessage();
  242 + msg.setKey(key);
  243 + msg.setId(uuid);
  244 + JSONObject json = new JSONObject();
  245 + json.put("DeviceID", deviceId);
  246 + json.put("CmdType", "Broadcast");
  247 + json.put("Result", "Failed");
  248 + json.put("Description", String.format("语音广播操作失败,错误码: %s, %s", event.statusCode, event.msg));
  249 + msg.setData(json);
  250 + resultHolder.invokeResult(msg);
  251 + });
  252 + } catch (InvalidArgumentException | SipException | ParseException e) {
  253 + logger.error("[命令发送失败] 语音广播: {}", e.getMessage());
  254 + throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
  255 + }
236 256
237 result.onTimeout(() -> { 257 result.onTimeout(() -> {
238 logger.warn("语音广播操作超时, 设备未返回应答指令"); 258 logger.warn("语音广播操作超时, 设备未返回应答指令");
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 /**
@@ -177,7 +186,19 @@ public class ApiStreamController { @@ -177,7 +186,19 @@ public class ApiStreamController {
177 result.put("error","未找到流信息"); 186 result.put("error","未找到流信息");
178 return result; 187 return result;
179 } 188 }
180 - cmder.streamByeCmd(serial, code, streamInfo.getStream(), null); 189 + Device device = deviceService.queryDevice(serial);
  190 + if (device == null) {
  191 + JSONObject result = new JSONObject();
  192 + result.put("error","未找到设备");
  193 + return result;
  194 + }
  195 + try {
  196 + cmder.streamByeCmd(device, code, streamInfo.getStream(), null);
  197 + } catch (InvalidArgumentException | ParseException | SipException | SsrcTransactionNotFoundException e) {
  198 + JSONObject result = new JSONObject();
  199 + result.put("error","发送BYE失败:" + e.getMessage());
  200 + return result;
  201 + }
181 redisCatchStorage.stopPlay(streamInfo); 202 redisCatchStorage.stopPlay(streamInfo);
182 storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId()); 203 storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId());
183 return null; 204 return null;