Commit 2ff3cdb6a1550941dbd36585749499064db4f8d5

Authored by 648540858
2 parents d7a1b94f 30979eb6

Merge branch 'wvp-28181-2.0'

# Conflicts:
#	src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java
#	src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
#	src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/SIPRequestProcessorParent.java
#	src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/AckRequestProcessor.java
#	src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
#	src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/PlayController.java
Showing 22 changed files with 1810 additions and 2103 deletions

Too many changes to show.

To preserve performance only 22 of 75 files are displayed.

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