Commit d7a1b94f905c5f28c9c8f2d48c3f9e28ebcf9cc4

Authored by 648540858
2 parents ab74d1cf a574ff09

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/event/request/impl/AckRequestProcessor.java
#	src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/ByeRequestProcessor.java
#	src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java
#	src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/BroadcastResponseMessageHandler.java
Showing 76 changed files with 1621 additions and 1308 deletions
src/main/java/com/genersoft/iot/vmp/conf/MediaConfig.java
... ... @@ -64,8 +64,8 @@ public class MediaConfig{
64 64 @Value("${media.secret}")
65 65 private String secret;
66 66  
67   - @Value("${media.stream-none-reader-delay-ms:10000}")
68   - private int streamNoneReaderDelayMS = 10000;
  67 + @Value("${media.stream-none-reader-delay-ms:15000}")
  68 + private int streamNoneReaderDelayMS = 15000;
69 69  
70 70 @Value("${media.rtp.enable}")
71 71 private boolean rtpEnable;
... ...
src/main/java/com/genersoft/iot/vmp/conf/UserSetting.java
... ... @@ -31,6 +31,8 @@ public class UserSetting {
31 31  
32 32 private Boolean logInDatebase = Boolean.TRUE;
33 33  
  34 + private Boolean usePushingAsStatus = Boolean.TRUE;
  35 +
34 36 private String serverId = "000000";
35 37  
36 38 private String thirdPartyGBIdReg = "[\\s\\S]*";
... ... @@ -136,4 +138,12 @@ public class UserSetting {
136 138 public void setPlatformPlayTimeout(int platformPlayTimeout) {
137 139 this.platformPlayTimeout = platformPlayTimeout;
138 140 }
  141 +
  142 + public Boolean isUsePushingAsStatus() {
  143 + return usePushingAsStatus;
  144 + }
  145 +
  146 + public void setUsePushingAsStatus(Boolean usePushingAsStatus) {
  147 + this.usePushingAsStatus = usePushingAsStatus;
  148 + }
139 149 }
... ...
src/main/java/com/genersoft/iot/vmp/conf/redis/RedisConfig.java
... ... @@ -3,7 +3,7 @@ package com.genersoft.iot.vmp.conf.redis;
3 3  
4 4 import com.alibaba.fastjson.parser.ParserConfig;
5 5 import com.genersoft.iot.vmp.common.VideoManagerConstants;
6   -import com.genersoft.iot.vmp.service.impl.*;
  6 +import com.genersoft.iot.vmp.service.redisMsg.*;
7 7 import org.springframework.beans.factory.annotation.Autowired;
8 8 import org.springframework.cache.annotation.CachingConfigurerSupport;
9 9 import org.springframework.context.annotation.Bean;
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/SipLayer.java
1 1 package com.genersoft.iot.vmp.gb28181;
2 2  
3 3 import com.genersoft.iot.vmp.conf.SipConfig;
  4 +import com.genersoft.iot.vmp.gb28181.conf.DefaultProperties;
4 5 import com.genersoft.iot.vmp.gb28181.transmit.ISIPProcessorObserver;
5 6 import gov.nist.javax.sip.SipProviderImpl;
6 7 import gov.nist.javax.sip.SipStackImpl;
... ... @@ -41,43 +42,7 @@ public class SipLayer{
41 42 @Bean("sipStack")
42 43 @DependsOn({"sipFactory"})
43 44 SipStack createSipStack() throws PeerUnavailableException {
44   - Properties properties = new Properties();
45   - properties.setProperty("javax.sip.STACK_NAME", "GB28181_SIP");
46   - properties.setProperty("javax.sip.IP_ADDRESS", sipConfig.getMonitorIp());
47   - /**
48   - * 完整配置参考 gov.nist.javax.sip.SipStackImpl,需要下载源码
49   - * gov/nist/javax/sip/SipStackImpl.class
50   - * sip消息的解析在 gov.nist.javax.sip.stack.UDPMessageChannel的processIncomingDataPacket方法
51   - */
52   -
53   -// * gov/nist/javax/sip/SipStackImpl.class
54   - if (logger.isDebugEnabled()) {
55   - properties.setProperty("gov.nist.javax.sip.LOG_MESSAGE_CONTENT", "false");
56   - }
57   - // 接收所有notify请求,即使没有订阅
58   - properties.setProperty("gov.nist.javax.sip.DELIVER_UNSOLICITED_NOTIFY", "true");
59   - properties.setProperty("gov.nist.javax.sip.AUTOMATIC_DIALOG_ERROR_HANDLING", "false");
60   - properties.setProperty("gov.nist.javax.sip.CANCEL_CLIENT_TRANSACTION_CHECKED", "false");
61   - // 为_NULL _对话框传递_终止的_事件
62   - properties.setProperty("gov.nist.javax.sip.DELIVER_TERMINATED_EVENT_FOR_NULL_DIALOG", "true");
63   - // 会话清理策略
64   - properties.setProperty("gov.nist.javax.sip.RELEASE_REFERENCES_STRATEGY", "Normal");
65   - // 处理由该服务器处理的基于底层TCP的保持生存超时
66   - properties.setProperty("gov.nist.javax.sip.RELIABLE_CONNECTION_KEEP_ALIVE_TIMEOUT", "60");
67   - // 获取实际内容长度,不使用header中的长度信息
68   - properties.setProperty("gov.nist.javax.sip.COMPUTE_CONTENT_LENGTH_FROM_MESSAGE_BODY", "true");
69   -
70   - /**
71   - * sip_server_log.log 和 sip_debug_log.log ERROR, INFO, WARNING, OFF, DEBUG, TRACE
72   - */
73   - properties.setProperty("gov.nist.javax.sip.TRACE_LEVEL", "ERROR");
74   -// properties.setProperty("gov.nist.javax.sip.SIP_MESSAGE_VALVE", "com.genersoft.iot.vmp.gb28181.session.SipMessagePreprocessing");
75   -// if (logger.isDebugEnabled()) {
76   -// properties.setProperty("gov.nist.javax.sip.TRACE_LEVEL", "DEBUG");
77   -// }
78   -
79   - sipStack = (SipStackImpl) sipFactory.createSipStack(properties);
80   -
  45 + sipStack = ( SipStackImpl )sipFactory.createSipStack(DefaultProperties.getProperties(sipConfig.getMonitorIp(), false));
81 46 return sipStack;
82 47 }
83 48  
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/bean/Device.java
... ... @@ -381,4 +381,5 @@ public class Device {
381 381 public void setTreeType(String treeType) {
382 382 this.treeType = treeType;
383 383 }
  384 +
384 385 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/bean/SendRtpItem.java
1 1 package com.genersoft.iot.vmp.gb28181.bean;
2 2  
  3 +import gov.nist.javax.sip.message.SIPRequest;
  4 +
3 5 public class SendRtpItem {
4 6  
5 7 /**
... ... @@ -77,11 +79,21 @@ public class SendRtpItem {
77 79 private String serverId;
78 80  
79 81 /**
80   - * invitecallId
  82 + * invitecallId
81 83 */
82 84 private String CallId;
83 85  
84 86 /**
  87 + * invite 的 fromTag
  88 + */
  89 + private String fromTag;
  90 +
  91 + /**
  92 + * invite 的 toTag
  93 + */
  94 + private String toTag;
  95 +
  96 + /**
85 97 * 发送时,rtp的pt(uint8_t),不传时默认为96
86 98 */
87 99 private int pt = 96;
... ... @@ -96,15 +108,12 @@ public class SendRtpItem {
96 108 */
97 109 private boolean onlyAudio = false;
98 110  
  111 +
99 112 /**
100 113 * 播放类型
101 114 */
102 115 private InviteStreamType playType;
103 116  
104   - private byte[] transaction;
105   -
106   - private byte[] dialog;
107   -
108 117 public String getIp() {
109 118 return ip;
110 119 }
... ... @@ -225,22 +234,6 @@ public class SendRtpItem {
225 234 this.playType = playType;
226 235 }
227 236  
228   - public byte[] getTransaction() {
229   - return transaction;
230   - }
231   -
232   - public void setTransaction(byte[] transaction) {
233   - this.transaction = transaction;
234   - }
235   -
236   - public byte[] getDialog() {
237   - return dialog;
238   - }
239   -
240   - public void setDialog(byte[] dialog) {
241   - this.dialog = dialog;
242   - }
243   -
244 237 public int getPt() {
245 238 return pt;
246 239 }
... ... @@ -272,4 +265,20 @@ public class SendRtpItem {
272 265 public void setServerId(String serverId) {
273 266 this.serverId = serverId;
274 267 }
  268 +
  269 + public String getFromTag() {
  270 + return fromTag;
  271 + }
  272 +
  273 + public void setFromTag(String fromTag) {
  274 + this.fromTag = fromTag;
  275 + }
  276 +
  277 + public String getToTag() {
  278 + return toTag;
  279 + }
  280 +
  281 + public void setToTag(String toTag) {
  282 + this.toTag = toTag;
  283 + }
275 284 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/bean/SipMsgInfo.java 0 → 100644
  1 +package com.genersoft.iot.vmp.gb28181.bean;
  2 +
  3 +import org.dom4j.Element;
  4 +
  5 +import javax.sip.RequestEvent;
  6 +
  7 +public class SipMsgInfo {
  8 + private RequestEvent evt;
  9 + private Device device;
  10 + private ParentPlatform platform;
  11 + private Element rootElement;
  12 +
  13 + public SipMsgInfo(RequestEvent evt, Device device, Element rootElement) {
  14 + this.evt = evt;
  15 + this.device = device;
  16 + this.rootElement = rootElement;
  17 + }
  18 +
  19 + public SipMsgInfo(RequestEvent evt, ParentPlatform platform, Element rootElement) {
  20 + this.evt = evt;
  21 + this.platform = platform;
  22 + this.rootElement = rootElement;
  23 + }
  24 +
  25 + public RequestEvent getEvt() {
  26 + return evt;
  27 + }
  28 +
  29 + public void setEvt(RequestEvent evt) {
  30 + this.evt = evt;
  31 + }
  32 +
  33 + public Device getDevice() {
  34 + return device;
  35 + }
  36 +
  37 + public void setDevice(Device device) {
  38 + this.device = device;
  39 + }
  40 +
  41 + public ParentPlatform getPlatform() {
  42 + return platform;
  43 + }
  44 +
  45 + public void setPlatform(ParentPlatform platform) {
  46 + this.platform = platform;
  47 + }
  48 +
  49 + public Element getRootElement() {
  50 + return rootElement;
  51 + }
  52 +
  53 + public void setRootElement(Element rootElement) {
  54 + this.rootElement = rootElement;
  55 + }
  56 +}
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/bean/SipTransactionInfo.java 0 → 100644
  1 +package com.genersoft.iot.vmp.gb28181.bean;
  2 +
  3 +import gov.nist.javax.sip.message.SIPRequest;
  4 +
  5 +public class SipTransactionInfo {
  6 +
  7 + private String callId;
  8 + private String fromTag;
  9 + private String toTag;
  10 + private String viaBranch;
  11 +
  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();
  17 + }
  18 +
  19 + public SipTransactionInfo() {
  20 + }
  21 +
  22 + public String getCallId() {
  23 + return callId;
  24 + }
  25 +
  26 + public void setCallId(String callId) {
  27 + this.callId = callId;
  28 + }
  29 +
  30 + public String getFromTag() {
  31 + return fromTag;
  32 + }
  33 +
  34 + public void setFromTag(String fromTag) {
  35 + this.fromTag = fromTag;
  36 + }
  37 +
  38 + public String getToTag() {
  39 + return toTag;
  40 + }
  41 +
  42 + public void setToTag(String toTag) {
  43 + this.toTag = toTag;
  44 + }
  45 +
  46 + public String getViaBranch() {
  47 + return viaBranch;
  48 + }
  49 +
  50 + public void setViaBranch(String viaBranch) {
  51 + this.viaBranch = viaBranch;
  52 + }
  53 +}
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/bean/SubscribeHolder.java
... ... @@ -5,6 +5,7 @@ import com.genersoft.iot.vmp.conf.DynamicTask;
5 5 import com.genersoft.iot.vmp.gb28181.task.ISubscribeTask;
6 6 import com.genersoft.iot.vmp.gb28181.task.impl.MobilePositionSubscribeHandlerTask;
7 7 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
  8 +import com.genersoft.iot.vmp.service.IPlatformService;
8 9 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
9 10 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
10 11 import org.springframework.beans.factory.annotation.Autowired;
... ... @@ -23,15 +24,6 @@ public class SubscribeHolder {
23 24 @Autowired
24 25 private DynamicTask dynamicTask;
25 26  
26   - @Autowired
27   - private IRedisCatchStorage redisCatchStorage;
28   -
29   - @Autowired
30   - private ISIPCommanderForPlatform sipCommanderForPlatform;
31   -
32   - @Autowired
33   - private IVideoManagerStorage storager;
34   -
35 27 private final String taskOverduePrefix = "subscribe_overdue_";
36 28  
37 29 private static ConcurrentHashMap<String, SubscribeInfo> catalogMap = new ConcurrentHashMap<>();
... ... @@ -62,15 +54,13 @@ public class SubscribeHolder {
62 54 }
63 55 // 添加任务处理订阅过期
64 56 dynamicTask.stop(taskOverdueKey);
65   -
66 57 }
67 58  
68 59 public void putMobilePositionSubscribe(String platformId, SubscribeInfo subscribeInfo) {
69 60 mobilePositionMap.put(platformId, subscribeInfo);
70 61 String key = VideoManagerConstants.SIP_SUBSCRIBE_PREFIX + "MobilePosition_" + platformId;
71 62 // 添加任务处理GPS定时推送
72   - dynamicTask.startCron(key, new MobilePositionSubscribeHandlerTask(redisCatchStorage, sipCommanderForPlatform,
73   - storager, platformId, subscribeInfo.getSn(), key, this, dynamicTask),
  63 + dynamicTask.startCron(key, new MobilePositionSubscribeHandlerTask(platformId),
74 64 subscribeInfo.getGpsInterval() * 1000);
75 65 String taskOverdueKey = taskOverduePrefix + "MobilePosition_" + platformId;
76 66 // 添加任务处理订阅过期
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/bean/SubscribeInfo.java
1 1 package com.genersoft.iot.vmp.gb28181.bean;
2 2  
3 3 import com.genersoft.iot.vmp.utils.SerializeUtils;
  4 +import gov.nist.javax.sip.message.SIPRequest;
  5 +import gov.nist.javax.sip.message.SIPResponse;
4 6  
  7 +import javax.sip.ClientTransaction;
5 8 import javax.sip.Dialog;
6 9 import javax.sip.RequestEvent;
7 10 import javax.sip.ServerTransaction;
... ... @@ -11,30 +14,24 @@ import javax.sip.message.Request;
11 14 public class SubscribeInfo {
12 15  
13 16  
14   - public SubscribeInfo(RequestEvent evt, String id) {
  17 + public SubscribeInfo(ServerTransaction serverTransaction, String id) {
15 18 this.id = id;
16   - Request request = evt.getRequest();
17   - ExpiresHeader expiresHeader = (ExpiresHeader)request.getHeader(ExpiresHeader.NAME);
18   - this.expires = expiresHeader.getExpires();
  19 + SIPRequest request = (SIPRequest)serverTransaction.getRequest();
  20 + this.request = request;
  21 + this.expires = request.getExpires().getExpires();
19 22 EventHeader eventHeader = (EventHeader)request.getHeader(EventHeader.NAME);
20 23 this.eventId = eventHeader.getEventId();
21 24 this.eventType = eventHeader.getEventType();
22   - this.transaction = evt.getServerTransaction();
23   - this.dialog = evt.getDialog();
24   - CallIdHeader callIdHeader = (CallIdHeader)evt.getRequest().getHeader(CallIdHeader.NAME);
25   - this.callId = callIdHeader.getCallId();
26   - }
27 25  
28   - public SubscribeInfo() {
29 26 }
30 27  
31 28 private String id;
  29 +
  30 + private SIPRequest request;
32 31 private int expires;
33   - private String callId;
34 32 private String eventId;
35 33 private String eventType;
36   - private ServerTransaction transaction;
37   - private Dialog dialog;
  34 + private SIPResponse response;
38 35  
39 36 /**
40 37 * 以下为可选字段
... ... @@ -43,29 +40,28 @@ public class SubscribeInfo {
43 40 private String sn;
44 41 private int gpsInterval;
45 42  
46   -
47 43 public String getId() {
48 44 return id;
49 45 }
50 46  
51   - public int getExpires() {
52   - return expires;
  47 + public void setId(String id) {
  48 + this.id = id;
53 49 }
54 50  
55   - public String getCallId() {
56   - return callId;
  51 + public SIPRequest getRequest() {
  52 + return request;
57 53 }
58 54  
59   - public void setId(String id) {
60   - this.id = id;
  55 + public void setRequest(SIPRequest request) {
  56 + this.request = request;
61 57 }
62 58  
63   - public void setExpires(int expires) {
64   - this.expires = expires;
  59 + public int getExpires() {
  60 + return expires;
65 61 }
66 62  
67   - public void setCallId(String callId) {
68   - this.callId = callId;
  63 + public void setExpires(int expires) {
  64 + this.expires = expires;
69 65 }
70 66  
71 67 public String getEventId() {
... ... @@ -84,20 +80,12 @@ public class SubscribeInfo {
84 80 this.eventType = eventType;
85 81 }
86 82  
87   - public ServerTransaction getTransaction() {
88   - return transaction;
89   - }
90   -
91   - public void setTransaction(ServerTransaction transaction) {
92   - this.transaction = transaction;
93   - }
94   -
95   - public Dialog getDialog() {
96   - return dialog;
  83 + public SIPResponse getResponse() {
  84 + return response;
97 85 }
98 86  
99   - public void setDialog(Dialog dialog) {
100   - this.dialog = dialog;
  87 + public void setResponse(SIPResponse response) {
  88 + this.response = response;
101 89 }
102 90  
103 91 public String getSn() {
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/conf/DefaultProperties.java 0 → 100644
  1 +package com.genersoft.iot.vmp.gb28181.conf;
  2 +
  3 +import java.util.Properties;
  4 +
  5 +/**
  6 + * 获取sip默认配置
  7 + * @author lin
  8 + */
  9 +public class DefaultProperties {
  10 +
  11 + public static Properties getProperties(String ip, boolean isDebug) {
  12 + Properties properties = new Properties();
  13 + properties.setProperty("javax.sip.STACK_NAME", "GB28181_SIP");
  14 + properties.setProperty("javax.sip.IP_ADDRESS", ip);
  15 + properties.setProperty("javax.sip.AUTOMATIC_DIALOG_SUPPORT", "off");
  16 + /**
  17 + * 完整配置参考 gov.nist.javax.sip.SipStackImpl,需要下载源码
  18 + * gov/nist/javax/sip/SipStackImpl.class
  19 + * sip消息的解析在 gov.nist.javax.sip.stack.UDPMessageChannel的processIncomingDataPacket方法
  20 + */
  21 +
  22 +// * gov/nist/javax/sip/SipStackImpl.class
  23 + if (isDebug) {
  24 + properties.setProperty("gov.nist.javax.sip.LOG_MESSAGE_CONTENT", "false");
  25 + }
  26 + // 接收所有notify请求,即使没有订阅
  27 + properties.setProperty("gov.nist.javax.sip.DELIVER_UNSOLICITED_NOTIFY", "true");
  28 + properties.setProperty("gov.nist.javax.sip.AUTOMATIC_DIALOG_ERROR_HANDLING", "false");
  29 + properties.setProperty("gov.nist.javax.sip.CANCEL_CLIENT_TRANSACTION_CHECKED", "false");
  30 + // 为_NULL _对话框传递_终止的_事件
  31 + properties.setProperty("gov.nist.javax.sip.DELIVER_TERMINATED_EVENT_FOR_NULL_DIALOG", "true");
  32 + // 会话清理策略
  33 + properties.setProperty("gov.nist.javax.sip.RELEASE_REFERENCES_STRATEGY", "Normal");
  34 + // 处理由该服务器处理的基于底层TCP的保持生存超时
  35 + properties.setProperty("gov.nist.javax.sip.RELIABLE_CONNECTION_KEEP_ALIVE_TIMEOUT", "60");
  36 + // 获取实际内容长度,不使用header中的长度信息
  37 + properties.setProperty("gov.nist.javax.sip.COMPUTE_CONTENT_LENGTH_FROM_MESSAGE_BODY", "true");
  38 +
  39 + /**
  40 + * sip_server_log.log 和 sip_debug_log.log ERROR, INFO, WARNING, OFF, DEBUG, TRACE
  41 + */
  42 + properties.setProperty("gov.nist.javax.sip.TRACE_LEVEL", "ERROR");
  43 +
  44 + return properties;
  45 + }
  46 +}
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/event/SipSubscribe.java
1 1 package com.genersoft.iot.vmp.gb28181.event;
2 2  
3 3 import com.genersoft.iot.vmp.gb28181.bean.DeviceNotFoundEvent;
  4 +import gov.nist.javax.sip.message.SIPRequest;
4 5 import org.slf4j.Logger;
5 6 import org.slf4j.LoggerFactory;
6 7 import org.springframework.scheduling.annotation.Scheduled;
... ... @@ -104,22 +105,27 @@ public class SipSubscribe {
104 105 this.type = EventResultType.timeout;
105 106 this.msg = "消息超时未回复";
106 107 this.statusCode = -1024;
107   - this.dialog = timeoutEvent.getClientTransaction().getDialog();
108   - this.callId = this.dialog != null?timeoutEvent.getClientTransaction().getDialog().getCallId().getCallId(): null;
  108 + if (timeoutEvent.isServerTransaction()) {
  109 + this.callId = ((SIPRequest)timeoutEvent.getServerTransaction().getRequest()).getCallIdHeader().getCallId();
  110 + }else {
  111 + this.callId = ((SIPRequest)timeoutEvent.getClientTransaction().getRequest()).getCallIdHeader().getCallId();
  112 + }
109 113 }else if (event instanceof TransactionTerminatedEvent) {
110 114 TransactionTerminatedEvent transactionTerminatedEvent = (TransactionTerminatedEvent)event;
111 115 this.type = EventResultType.transactionTerminated;
112 116 this.msg = "事务已结束";
113 117 this.statusCode = -1024;
114   - this.callId = transactionTerminatedEvent.getClientTransaction().getDialog().getCallId().getCallId();
115   - this.dialog = transactionTerminatedEvent.getClientTransaction().getDialog();
  118 + if (transactionTerminatedEvent.isServerTransaction()) {
  119 + this.callId = ((SIPRequest)transactionTerminatedEvent.getServerTransaction().getRequest()).getCallIdHeader().getCallId();
  120 + }else {
  121 + this.callId = ((SIPRequest)transactionTerminatedEvent.getClientTransaction().getRequest()).getCallIdHeader().getCallId();
  122 + }
116 123 }else if (event instanceof DialogTerminatedEvent) {
117 124 DialogTerminatedEvent dialogTerminatedEvent = (DialogTerminatedEvent)event;
118 125 this.type = EventResultType.dialogTerminated;
119 126 this.msg = "会话已结束";
120 127 this.statusCode = -1024;
121 128 this.callId = dialogTerminatedEvent.getDialog().getCallId().getCallId();
122   - this.dialog = dialogTerminatedEvent.getDialog();
123 129 }else if (event instanceof DeviceNotFoundEvent) {
124 130 DeviceNotFoundEvent deviceNotFoundEvent = (DeviceNotFoundEvent)event;
125 131 this.type = EventResultType.deviceNotFoundEvent;
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/task/ISubscribeTask.java
... ... @@ -7,6 +7,4 @@ import javax.sip.DialogState;
7 7 */
8 8 public interface ISubscribeTask extends Runnable{
9 9 void stop();
10   -
11   - DialogState getDialogState();
12 10 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/task/impl/CatalogSubscribeTask.java
... ... @@ -4,6 +4,7 @@ import com.genersoft.iot.vmp.conf.DynamicTask;
4 4 import com.genersoft.iot.vmp.gb28181.bean.Device;
5 5 import com.genersoft.iot.vmp.gb28181.task.ISubscribeTask;
6 6 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
  7 +import gov.nist.javax.sip.message.SIPRequest;
7 8 import org.slf4j.Logger;
8 9 import org.slf4j.LoggerFactory;
9 10 import org.springframework.scheduling.annotation.Async;
... ... @@ -12,6 +13,8 @@ import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
12 13 import javax.sip.Dialog;
13 14 import javax.sip.DialogState;
14 15 import javax.sip.ResponseEvent;
  16 +import javax.sip.header.ToHeader;
  17 +import java.text.ParseException;
15 18 import java.util.Timer;
16 19 import java.util.TimerTask;
17 20  
... ... @@ -23,7 +26,7 @@ public class CatalogSubscribeTask implements ISubscribeTask {
23 26 private final Logger logger = LoggerFactory.getLogger(CatalogSubscribeTask.class);
24 27 private Device device;
25 28 private final ISIPCommander sipCommander;
26   - private Dialog dialog;
  29 + private SIPRequest request;
27 30  
28 31 private DynamicTask dynamicTask;
29 32  
... ... @@ -41,24 +44,26 @@ public class CatalogSubscribeTask implements ISubscribeTask {
41 44 if (dynamicTask.get(taskKey) != null) {
42 45 dynamicTask.stop(taskKey);
43 46 }
44   - sipCommander.catalogSubscribe(device, dialog, eventResult -> {
45   - if (eventResult.dialog != null || eventResult.dialog.getState().equals(DialogState.CONFIRMED)) {
46   - dialog = eventResult.dialog;
47   - }
  47 + SIPRequest sipRequest = sipCommander.catalogSubscribe(device, request, eventResult -> {
48 48 ResponseEvent event = (ResponseEvent) eventResult.event;
49   - if (event.getResponse().getRawContent() != null) {
50   - // 成功
51   - logger.info("[目录订阅]成功: {}", device.getDeviceId());
52   - }else {
53   - // 成功
54   - logger.info("[目录订阅]成功: {}", device.getDeviceId());
  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;
55 57 }
56 58 },eventResult -> {
57   - dialog = null;
  59 + this.request = null;
58 60 // 失败
59 61 logger.warn("[目录订阅]失败,信令发送失败: {}-{} ", device.getDeviceId(), eventResult.msg);
60 62 dynamicTask.startDelay(taskKey, CatalogSubscribeTask.this, 2000);
61 63 });
  64 + if (sipRequest != null) {
  65 + this.request = sipRequest;
  66 + }
62 67 }
63 68  
64 69 @Override
... ... @@ -74,29 +79,19 @@ public class CatalogSubscribeTask implements ISubscribeTask {
74 79 if (dynamicTask.get(taskKey) != null) {
75 80 dynamicTask.stop(taskKey);
76 81 }
77   - if (dialog != null && dialog.getState().equals(DialogState.CONFIRMED)) {
78   - device.setSubscribeCycleForCatalog(0);
79   - sipCommander.catalogSubscribe(device, dialog, eventResult -> {
80   - ResponseEvent event = (ResponseEvent) eventResult.event;
81   - if (event.getResponse().getRawContent() != null) {
82   - // 成功
83   - logger.info("[取消目录订阅订阅]成功: {}", device.getDeviceId());
84   - }else {
85   - // 成功
86   - logger.info("[取消目录订阅订阅]成功: {}", device.getDeviceId());
87   - }
88   - },eventResult -> {
89   - // 失败
90   - logger.warn("[取消目录订阅订阅]失败,信令发送失败: {}-{} ", device.getDeviceId(), eventResult.msg);
91   - });
92   - }
93   - }
94   -
95   - @Override
96   - public DialogState getDialogState() {
97   - if (dialog == null) {
98   - return null;
99   - }
100   - return dialog.getState();
  82 + 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 + });
101 96 }
102 97 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/task/impl/MobilePositionSubscribeHandlerTask.java
... ... @@ -4,9 +4,11 @@ import com.genersoft.iot.vmp.conf.DynamicTask;
4 4 import com.genersoft.iot.vmp.gb28181.bean.*;
5 5 import com.genersoft.iot.vmp.gb28181.task.ISubscribeTask;
6 6 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
  7 +import com.genersoft.iot.vmp.service.IPlatformService;
7 8 import com.genersoft.iot.vmp.service.bean.GPSMsgInfo;
8 9 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
9 10 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
  11 +import com.genersoft.iot.vmp.utils.SpringBeanFactory;
10 12 import org.slf4j.Logger;
11 13 import org.slf4j.LoggerFactory;
12 14 import org.springframework.scheduling.annotation.Async;
... ... @@ -20,71 +22,23 @@ import java.util.List;
20 22 */
21 23 public class MobilePositionSubscribeHandlerTask implements ISubscribeTask {
22 24  
23   - private Logger logger = LoggerFactory.getLogger(MobilePositionSubscribeHandlerTask.class);
24 25  
25   - private IRedisCatchStorage redisCatchStorage;
26   - private IVideoManagerStorage storager;
27   - private ISIPCommanderForPlatform sipCommanderForPlatform;
28   - private SubscribeHolder subscribeHolder;
29   - private ParentPlatform platform;
  26 + private IPlatformService platformService;
  27 + private String platformId;
30 28  
31   - private String sn;
32   - private String key;
33 29  
34   - public MobilePositionSubscribeHandlerTask(IRedisCatchStorage redisCatchStorage,
35   - ISIPCommanderForPlatform sipCommanderForPlatform,
36   - IVideoManagerStorage storager,
37   - String platformId,
38   - String sn,
39   - String key,
40   - SubscribeHolder subscribeInfo,
41   - DynamicTask dynamicTask) {
42   - this.redisCatchStorage = redisCatchStorage;
43   - this.storager = storager;
44   - this.platform = storager.queryParentPlatByServerGBId(platformId);
45   - this.sn = sn;
46   - this.key = key;
47   - this.sipCommanderForPlatform = sipCommanderForPlatform;
48   - this.subscribeHolder = subscribeInfo;
  30 + public MobilePositionSubscribeHandlerTask(String platformId) {
  31 + this.platformService = SpringBeanFactory.getBean("platformServiceImpl");
  32 + this.platformId = platformId;
49 33 }
50 34  
51 35 @Override
52 36 public void run() {
53   -
54   - if (platform == null) {
55   - return;
56   - }
57   - SubscribeInfo subscribe = subscribeHolder.getMobilePositionSubscribe(platform.getServerGBId());
58   - if (subscribe != null) {
59   -
60   - // TODO 暂时只处理视频流的回复,后续增加对国标设备的支持
61   - List<DeviceChannel> gbStreams = storager.queryGbStreamListInPlatform(platform.getServerGBId());
62   - if (gbStreams.size() == 0) {
63   - return;
64   - }
65   - for (DeviceChannel deviceChannel : gbStreams) {
66   - String gbId = deviceChannel.getChannelId();
67   - GPSMsgInfo gpsMsgInfo = redisCatchStorage.getGpsMsgInfo(gbId);
68   - // 无最新位置不发送
69   - if (gpsMsgInfo != null) {
70   - // 经纬度都为0不发送
71   - if (gpsMsgInfo.getLng() == 0 && gpsMsgInfo.getLat() == 0) {
72   - continue;
73   - }
74   - // 发送GPS消息
75   - sipCommanderForPlatform.sendNotifyMobilePosition(platform, gpsMsgInfo, subscribe);
76   - }
77   - }
78   - }
  37 + platformService.sendNotifyMobilePosition(this.platformId);
79 38 }
80 39  
81 40 @Override
82 41 public void stop() {
83 42  
84 43 }
85   -
86   - @Override
87   - public DialogState getDialogState() {
88   - return null;
89   - }
90 44 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/task/impl/MobilePositionSubscribeTask.java
... ... @@ -4,6 +4,8 @@ import com.genersoft.iot.vmp.conf.DynamicTask;
4 4 import com.genersoft.iot.vmp.gb28181.bean.Device;
5 5 import com.genersoft.iot.vmp.gb28181.task.ISubscribeTask;
6 6 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
  7 +import gov.nist.javax.sip.message.SIPRequest;
  8 +import gov.nist.javax.sip.message.SIPResponse;
7 9 import org.dom4j.Element;
8 10 import org.slf4j.Logger;
9 11 import org.slf4j.LoggerFactory;
... ... @@ -12,6 +14,8 @@ import org.springframework.scheduling.annotation.Async;
12 14 import javax.sip.Dialog;
13 15 import javax.sip.DialogState;
14 16 import javax.sip.ResponseEvent;
  17 +import javax.sip.header.ToHeader;
  18 +import java.text.ParseException;
15 19 import java.util.Timer;
16 20 import java.util.TimerTask;
17 21  
... ... @@ -21,9 +25,10 @@ import java.util.TimerTask;
21 25 */
22 26 public class MobilePositionSubscribeTask implements ISubscribeTask {
23 27 private final Logger logger = LoggerFactory.getLogger(MobilePositionSubscribeTask.class);
24   - private Device device;
25   - private ISIPCommander sipCommander;
26   - private Dialog dialog;
  28 + private Device device;
  29 + private ISIPCommander sipCommander;
  30 +
  31 + private SIPRequest request;
27 32 private DynamicTask dynamicTask;
28 33 private String taskKey = "mobile-position-subscribe-timeout";
29 34  
... ... @@ -38,24 +43,26 @@ public class MobilePositionSubscribeTask implements ISubscribeTask {
38 43 if (dynamicTask.get(taskKey) != null) {
39 44 dynamicTask.stop(taskKey);
40 45 }
41   - sipCommander.mobilePositionSubscribe(device, dialog, eventResult -> {
42   - if (eventResult.dialog != null || eventResult.dialog.getState().equals(DialogState.CONFIRMED)) {
43   - dialog = eventResult.dialog;
44   - }
  46 + SIPRequest sipRequest = sipCommander.mobilePositionSubscribe(device, request, eventResult -> {
  47 + // 成功
  48 + logger.info("[移动位置订阅]成功: {}", device.getDeviceId());
45 49 ResponseEvent event = (ResponseEvent) eventResult.event;
46   - if (event.getResponse().getRawContent() != null) {
47   - // 成功
48   - logger.info("[移动位置订阅]成功: {}", device.getDeviceId());
49   - }else {
50   - // 成功
51   - logger.info("[移动位置订阅]成功: {}", device.getDeviceId());
  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;
52 56 }
53 57 },eventResult -> {
54   - dialog = null;
  58 + this.request = null;
55 59 // 失败
56 60 logger.warn("[移动位置订阅]失败,信令发送失败: {}-{} ", device.getDeviceId(), eventResult.msg);
57 61 dynamicTask.startDelay(taskKey, MobilePositionSubscribeTask.this, 2000);
58 62 });
  63 + if (sipRequest != null) {
  64 + this.request = sipRequest;
  65 + }
59 66  
60 67 }
61 68  
... ... @@ -71,29 +78,19 @@ public class MobilePositionSubscribeTask implements ISubscribeTask {
71 78 if (dynamicTask.get(taskKey) != null) {
72 79 dynamicTask.stop(taskKey);
73 80 }
74   - if (dialog != null && dialog.getState().equals(DialogState.CONFIRMED)) {
75   - logger.info("取消移动订阅时dialog状态为{}", dialog.getState());
76   - device.setSubscribeCycleForMobilePosition(0);
77   - sipCommander.mobilePositionSubscribe(device, dialog, eventResult -> {
78   - ResponseEvent event = (ResponseEvent) eventResult.event;
79   - if (event.getResponse().getRawContent() != null) {
80   - // 成功
81   - logger.info("[取消移动位置订阅]成功: {}", device.getDeviceId());
82   - }else {
83   - // 成功
84   - logger.info("[取消移动位置订阅]成功: {}", device.getDeviceId());
85   - }
86   - },eventResult -> {
87   - // 失败
88   - logger.warn("[取消移动位置订阅]失败,信令发送失败: {}-{} ", device.getDeviceId(), eventResult.msg);
89   - });
90   - }
91   - }
92   - @Override
93   - public DialogState getDialogState() {
94   - if (dialog == null) {
95   - return null;
96   - }
97   - return dialog.getState();
  81 + 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 + });
98 95 }
99 96 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorObserver.java
... ... @@ -69,12 +69,9 @@ public class SIPProcessorObserver implements ISIPProcessorObserver {
69 69 * @param requestEvent RequestEvent事件
70 70 */
71 71 @Override
72   - @Async
  72 + @Async("taskExecutor")
73 73 public void processRequest(RequestEvent requestEvent) {
74 74 String method = requestEvent.getRequest().getMethod();
75   - if ("NOTIFY".equalsIgnoreCase(requestEvent.getRequest().getMethod())) {
76   - System.out.println();
77   - }
78 75 ISIPRequestProcessor sipRequestProcessor = requestProcessorMap.get(method);
79 76 if (sipRequestProcessor == null) {
80 77 logger.warn("不支持方法{}的request", method);
... ... @@ -89,7 +86,7 @@ public class SIPProcessorObserver implements ISIPProcessorObserver {
89 86 * @param responseEvent responseEvent事件
90 87 */
91 88 @Override
92   - @Async
  89 + @Async("taskExecutor")
93 90 public void processResponse(ResponseEvent responseEvent) {
94 91 Response response = responseEvent.getResponse();
95 92 int status = response.getStatusCode();
... ... @@ -173,6 +170,12 @@ public class SIPProcessorObserver implements ISIPProcessorObserver {
173 170  
174 171 @Override
175 172 public void processTransactionTerminated(TransactionTerminatedEvent transactionTerminatedEvent) {
  173 +// if (transactionTerminatedEvent.isServerTransaction()) {
  174 +// ServerTransaction serverTransaction = transactionTerminatedEvent.getServerTransaction();
  175 +// serverTransaction.get
  176 +// }
  177 +
  178 +
176 179 // Transaction transaction = null;
177 180 // System.out.println("processTransactionTerminated");
178 181 // if (transactionTerminatedEvent.isServerTransaction()) {
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java
... ... @@ -7,6 +7,7 @@ import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe;
7 7 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
8 8 import com.genersoft.iot.vmp.service.bean.SSRCInfo;
9 9 import gov.nist.javax.sip.message.SIPRequest;
  10 +import gov.nist.javax.sip.message.SIPRequest;
10 11 import gov.nist.javax.sip.stack.SIPDialog;
11 12  
12 13 import javax.sip.Dialog;
... ... @@ -158,7 +159,7 @@ public interface ISIPCommander {
158 159 */
159 160 void playbackControlCmd(Device device, StreamInfo streamInfo, String content,SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent);
160 161  
161   -
  162 +
162 163 /**
163 164 * 语音广播
164 165 *
... ... @@ -311,7 +312,7 @@ public interface ISIPCommander {
311 312 * @param device 视频设备
312 313 * @return true = 命令发送成功
313 314 */
314   - boolean mobilePositionSubscribe(Device device, Dialog dialog, SipSubscribe.Event okEvent , SipSubscribe.Event errorEvent);
  315 + SIPRequest mobilePositionSubscribe(Device device, SIPRequest request, SipSubscribe.Event okEvent , SipSubscribe.Event errorEvent);
315 316  
316 317 /**
317 318 * 订阅、取消订阅报警信息
... ... @@ -331,7 +332,7 @@ public interface ISIPCommander {
331 332 * @param device 视频设备
332 333 * @return true = 命令发送成功
333 334 */
334   - boolean catalogSubscribe(Device device, Dialog dialog, SipSubscribe.Event okEvent ,SipSubscribe.Event errorEvent);
  335 + SIPRequest catalogSubscribe(Device device, SIPRequest request, SipSubscribe.Event okEvent ,SipSubscribe.Event errorEvent);
335 336  
336 337 /**
337 338 * 拉框控制命令
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommanderForPlatform.java
... ... @@ -117,4 +117,5 @@ public interface ISIPCommanderForPlatform {
117 117 * @param callId callId
118 118 */
119 119 void streamByeCmd(ParentPlatform platform, String callId);
  120 + void streamByeCmd(ParentPlatform platform, SendRtpItem sendRtpItem);
120 121 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderPlarformProvider.java
... ... @@ -2,10 +2,13 @@ package com.genersoft.iot.vmp.gb28181.transmit.cmd;
2 2  
3 3 import com.genersoft.iot.vmp.conf.SipConfig;
4 4 import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
  5 +import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem;
  6 +import com.genersoft.iot.vmp.gb28181.bean.SubscribeInfo;
5 7 import com.genersoft.iot.vmp.gb28181.utils.SipUtils;
6 8 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
7 9 import com.genersoft.iot.vmp.utils.GitUtil;
8 10 import gov.nist.javax.sip.message.MessageFactoryImpl;
  11 +import gov.nist.javax.sip.message.SIPRequest;
9 12 import org.springframework.beans.factory.annotation.Autowired;
10 13 import org.springframework.stereotype.Component;
11 14 import org.springframework.util.DigestUtils;
... ... @@ -154,8 +157,17 @@ public class SIPRequestHeaderPlarformProvider {
154 157 return registerRequest;
155 158 }
156 159  
  160 + public Request createMessageRequest(ParentPlatform parentPlatform, String content, SendRtpItem sendRtpItem) throws PeerUnavailableException, ParseException, InvalidArgumentException {
  161 + CallIdHeader callIdHeader = sipFactory.createHeaderFactory().createCallIdHeader(sendRtpItem.getCallId());
  162 + return createMessageRequest(parentPlatform, content, sendRtpItem.getToTag(), SipUtils.getNewViaTag(), sendRtpItem.getFromTag(), callIdHeader);
  163 + }
157 164  
158 165 public Request createMessageRequest(ParentPlatform parentPlatform, String content, String fromTag, String viaTag, CallIdHeader callIdHeader) throws PeerUnavailableException, ParseException, InvalidArgumentException {
  166 + return createMessageRequest(parentPlatform, content, fromTag, viaTag, null, callIdHeader);
  167 + }
  168 +
  169 +
  170 + public Request createMessageRequest(ParentPlatform parentPlatform, String content, String fromTag, String viaTag, String toTag, CallIdHeader callIdHeader) throws PeerUnavailableException, ParseException, InvalidArgumentException {
159 171 Request request = null;
160 172 String serverAddress = parentPlatform.getServerIP()+ ":" + parentPlatform.getServerPort();
161 173 // sipuri
... ... @@ -174,7 +186,7 @@ public class SIPRequestHeaderPlarformProvider {
174 186 // to
175 187 SipURI toSipURI = sipFactory.createAddressFactory().createSipURI(parentPlatform.getServerGBId(), serverAddress);
176 188 Address toAddress = sipFactory.createAddressFactory().createAddress(toSipURI);
177   - ToHeader toHeader = sipFactory.createHeaderFactory().createToHeader(toAddress, null);
  189 + ToHeader toHeader = sipFactory.createHeaderFactory().createToHeader(toAddress, toTag);
178 190  
179 191 // Forwards
180 192 MaxForwardsHeader maxForwards = sipFactory.createHeaderFactory().createMaxForwardsHeader(70);
... ... @@ -192,4 +204,107 @@ public class SIPRequestHeaderPlarformProvider {
192 204 request.setContent(content, contentTypeHeader);
193 205 return request;
194 206 }
  207 +
  208 + public SIPRequest createNotifyRequest(ParentPlatform parentPlatform, String content, SubscribeInfo subscribeInfo) throws PeerUnavailableException, ParseException, InvalidArgumentException {
  209 + SIPRequest request = null;
  210 + // sipuri
  211 + SipURI requestURI = sipFactory.createAddressFactory().createSipURI(parentPlatform.getServerGBId(), parentPlatform.getServerIP()+ ":" + parentPlatform.getServerPort());
  212 + // via
  213 + ArrayList<ViaHeader> viaHeaders = new ArrayList<>();
  214 + ViaHeader viaHeader = sipFactory.createHeaderFactory().createViaHeader(parentPlatform.getDeviceIp(), Integer.parseInt(parentPlatform.getDevicePort()),
  215 + parentPlatform.getTransport(), SipUtils.getNewViaTag());
  216 + viaHeader.setRPort();
  217 + viaHeaders.add(viaHeader);
  218 + // from
  219 + SipURI fromSipURI = sipFactory.createAddressFactory().createSipURI(parentPlatform.getDeviceGBId(),
  220 + parentPlatform.getDeviceIp() + ":" + parentPlatform.getDevicePort());
  221 + Address fromAddress = sipFactory.createAddressFactory().createAddress(fromSipURI);
  222 + FromHeader fromHeader = sipFactory.createHeaderFactory().createFromHeader(fromAddress, subscribeInfo.getResponse().getToTag());
  223 + // to
  224 + SipURI toSipURI = sipFactory.createAddressFactory().createSipURI(parentPlatform.getServerGBId(), parentPlatform.getServerGBDomain());
  225 + Address toAddress = sipFactory.createAddressFactory().createAddress(toSipURI);
  226 + ToHeader toHeader = sipFactory.createHeaderFactory().createToHeader(toAddress, subscribeInfo.getRequest().getFromTag());
  227 +
  228 + // Forwards
  229 + MaxForwardsHeader maxForwards = sipFactory.createHeaderFactory().createMaxForwardsHeader(70);
  230 + // ceq
  231 + CSeqHeader cSeqHeader = sipFactory.createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(), Request.NOTIFY);
  232 + MessageFactoryImpl messageFactory = (MessageFactoryImpl) sipFactory.createMessageFactory();
  233 + // 设置编码, 防止中文乱码
  234 + messageFactory.setDefaultContentEncodingCharset("gb2312");
  235 +
  236 + CallIdHeader callIdHeader = sipFactory.createHeaderFactory().createCallIdHeader(subscribeInfo.getRequest().getCallIdHeader().getCallId());
  237 +
  238 + request = (SIPRequest) messageFactory.createRequest(requestURI, Request.NOTIFY, callIdHeader, cSeqHeader, fromHeader,
  239 + toHeader, viaHeaders, maxForwards);
  240 +
  241 + request.addHeader(SipUtils.createUserAgentHeader(sipFactory, gitUtil));
  242 +
  243 + EventHeader event = sipFactory.createHeaderFactory().createEventHeader(subscribeInfo.getEventType());
  244 + if (subscribeInfo.getEventId() != null) {
  245 + event.setEventId(subscribeInfo.getEventId());
  246 + }
  247 +
  248 + request.addHeader(event);
  249 +
  250 + SubscriptionStateHeader active = sipFactory.createHeaderFactory().createSubscriptionStateHeader("active");
  251 + request.setHeader(active);
  252 +
  253 + String sipAddress = sipConfig.getIp() + ":" + sipConfig.getPort();
  254 + Address concatAddress = sipFactory.createAddressFactory().createAddress(sipFactory.createAddressFactory()
  255 + .createSipURI(parentPlatform.getDeviceGBId(), sipAddress));
  256 + request.addHeader(sipFactory.createHeaderFactory().createContactHeader(concatAddress));
  257 +
  258 + ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml");
  259 + request.setContent(content, contentTypeHeader);
  260 + return request;
  261 + }
  262 +
  263 + public SIPRequest createByeRequest(ParentPlatform platform, SendRtpItem sendRtpItem) throws PeerUnavailableException, ParseException, InvalidArgumentException {
  264 +
  265 + if (sendRtpItem == null ) {
  266 + return null;
  267 + }
  268 +
  269 + SIPRequest request = null;
  270 + // sipuri
  271 + SipURI requestURI = sipFactory.createAddressFactory().createSipURI(platform.getServerGBId(), platform.getServerIP()+ ":" + platform.getServerPort());
  272 + // via
  273 + ArrayList<ViaHeader> viaHeaders = new ArrayList<>();
  274 + ViaHeader viaHeader = sipFactory.createHeaderFactory().createViaHeader(platform.getDeviceIp(), Integer.parseInt(platform.getDevicePort()),
  275 + platform.getTransport(), SipUtils.getNewViaTag());
  276 + viaHeader.setRPort();
  277 + viaHeaders.add(viaHeader);
  278 + // from
  279 + SipURI fromSipURI = sipFactory.createAddressFactory().createSipURI(platform.getDeviceGBId(),
  280 + platform.getDeviceIp() + ":" + platform.getDevicePort());
  281 + Address fromAddress = sipFactory.createAddressFactory().createAddress(fromSipURI);
  282 + FromHeader fromHeader = sipFactory.createHeaderFactory().createFromHeader(fromAddress, sendRtpItem.getToTag());
  283 + // to
  284 + SipURI toSipURI = sipFactory.createAddressFactory().createSipURI(platform.getServerGBId(), platform.getServerGBDomain());
  285 + Address toAddress = sipFactory.createAddressFactory().createAddress(toSipURI);
  286 + ToHeader toHeader = sipFactory.createHeaderFactory().createToHeader(toAddress, sendRtpItem.getFromTag());
  287 +
  288 + // Forwards
  289 + MaxForwardsHeader maxForwards = sipFactory.createHeaderFactory().createMaxForwardsHeader(70);
  290 + // ceq
  291 + CSeqHeader cSeqHeader = sipFactory.createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(), Request.BYE);
  292 + MessageFactoryImpl messageFactory = (MessageFactoryImpl) sipFactory.createMessageFactory();
  293 + // 设置编码, 防止中文乱码
  294 + messageFactory.setDefaultContentEncodingCharset("gb2312");
  295 +
  296 + CallIdHeader callIdHeader = sipFactory.createHeaderFactory().createCallIdHeader(sendRtpItem.getCallId());
  297 +
  298 + request = (SIPRequest) messageFactory.createRequest(requestURI, Request.BYE, callIdHeader, cSeqHeader, fromHeader,
  299 + toHeader, viaHeaders, maxForwards);
  300 +
  301 + request.addHeader(SipUtils.createUserAgentHeader(sipFactory, gitUtil));
  302 +
  303 + String sipAddress = sipConfig.getIp() + ":" + sipConfig.getPort();
  304 + Address concatAddress = sipFactory.createAddressFactory().createAddress(sipFactory.createAddressFactory()
  305 + .createSipURI(platform.getDeviceGBId(), sipAddress));
  306 + request.addHeader(sipFactory.createHeaderFactory().createContactHeader(concatAddress));
  307 +
  308 + return request;
  309 + }
195 310 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java
... ... @@ -16,6 +16,7 @@ import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
16 16 import com.genersoft.iot.vmp.utils.GitUtil;
17 17 import gov.nist.javax.sip.SipProviderImpl;
18 18 import gov.nist.javax.sip.SipStackImpl;
  19 +import gov.nist.javax.sip.message.SIPRequest;
19 20 import gov.nist.javax.sip.stack.SIPDialog;
20 21 import org.springframework.beans.factory.annotation.Autowired;
21 22 import org.springframework.beans.factory.annotation.Qualifier;
... ... @@ -199,24 +200,24 @@ public class SIPRequestHeaderProvider {
199 200 return request;
200 201 }
201 202  
202   - public Request createSubscribeRequest(Device device, String content, String viaTag, String fromTag, String toTag, Integer expires, String event, CallIdHeader callIdHeader) throws ParseException, InvalidArgumentException, PeerUnavailableException {
  203 + public Request createSubscribeRequest(Device device, String content, SIPRequest requestOld, Integer expires, String event, CallIdHeader callIdHeader) throws ParseException, InvalidArgumentException, PeerUnavailableException {
203 204 Request request = null;
204 205 // sipuri
205 206 SipURI requestURI = sipFactory.createAddressFactory().createSipURI(device.getDeviceId(), device.getHostAddress());
206 207 // via
207 208 ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>();
208 209 ViaHeader viaHeader = sipFactory.createHeaderFactory().createViaHeader(sipConfig.getIp(), sipConfig.getPort(),
209   - device.getTransport(), viaTag);
  210 + device.getTransport(), SipUtils.getNewViaTag());
210 211 viaHeader.setRPort();
211 212 viaHeaders.add(viaHeader);
212 213 // from
213 214 SipURI fromSipURI = sipFactory.createAddressFactory().createSipURI(sipConfig.getId(), sipConfig.getDomain());
214 215 Address fromAddress = sipFactory.createAddressFactory().createAddress(fromSipURI);
215   - FromHeader fromHeader = sipFactory.createHeaderFactory().createFromHeader(fromAddress, fromTag);
  216 + FromHeader fromHeader = sipFactory.createHeaderFactory().createFromHeader(fromAddress, requestOld == null ? SipUtils.getNewFromTag() :requestOld.getFromTag());
216 217 // to
217 218 SipURI toSipURI = sipFactory.createAddressFactory().createSipURI(device.getDeviceId(), device.getHostAddress());
218 219 Address toAddress = sipFactory.createAddressFactory().createAddress(toSipURI);
219   - ToHeader toHeader = sipFactory.createHeaderFactory().createToHeader(toAddress, toTag);
  220 + ToHeader toHeader = sipFactory.createHeaderFactory().createToHeader(toAddress, requestOld == null ? null :requestOld.getToTag());
220 221  
221 222 // Forwards
222 223 MaxForwardsHeader maxForwards = sipFactory.createHeaderFactory().createMaxForwardsHeader(70);
... ... @@ -238,7 +239,7 @@ public class SIPRequestHeaderProvider {
238 239 // Event
239 240 EventHeader eventHeader = sipFactory.createHeaderFactory().createEventHeader(event);
240 241  
241   - int random = (int)Math.random() * 1000000000;
  242 + int random = (int) Math.floor(Math.random() * 10000);
242 243 eventHeader.setEventId(random + "");
243 244 request.addHeader(eventHeader);
244 245  
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
... ... @@ -26,6 +26,7 @@ import gov.nist.javax.sip.SipProviderImpl;
26 26 import gov.nist.javax.sip.SipStackImpl;
27 27 import gov.nist.javax.sip.message.MessageFactoryImpl;
28 28 import gov.nist.javax.sip.message.SIPRequest;
  29 +import gov.nist.javax.sip.stack.SIPClientTransaction;
29 30 import gov.nist.javax.sip.stack.SIPDialog;
30 31 import org.slf4j.Logger;
31 32 import org.slf4j.LoggerFactory;
... ... @@ -435,7 +436,14 @@ public class SIPCommander implements ISIPCommander {
435 436 }), e ->{
436 437 // 这里为例避免一个通道的点播只有一个callID这个参数使用一个固定值
437 438 streamSession.put(device.getDeviceId(), channelId ,"play", stream, ssrcInfo.getSsrc(), mediaServerItem.getId(), ((ResponseEvent)e.event).getClientTransaction(), VideoStreamSessionManager.SessionType.play);
438   - streamSession.put(device.getDeviceId(), channelId ,"play", e.dialog);
  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);
439 447 okEvent.response(e);
440 448 });
441 449  
... ... @@ -1446,7 +1454,7 @@ public class SIPCommander implements ISIPCommander {
1446 1454 * @return true = 命令发送成功
1447 1455 */
1448 1456 @Override
1449   - public boolean mobilePositionSubscribe(Device device, Dialog dialog, SipSubscribe.Event okEvent ,SipSubscribe.Event errorEvent) {
  1457 + public SIPRequest mobilePositionSubscribe(Device device, SIPRequest requestOld, SipSubscribe.Event okEvent ,SipSubscribe.Event errorEvent) {
1450 1458 try {
1451 1459 StringBuffer subscribePostitionXml = new StringBuffer(200);
1452 1460 String charset = device.getCharset();
... ... @@ -1456,38 +1464,27 @@ public class SIPCommander implements ISIPCommander {
1456 1464 subscribePostitionXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
1457 1465 subscribePostitionXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
1458 1466 if (device.getSubscribeCycleForMobilePosition() > 0) {
1459   - subscribePostitionXml.append("<Interval>" + String.valueOf(device.getMobilePositionSubmissionInterval()) + "</Interval>\r\n");
  1467 + subscribePostitionXml.append("<Interval>" + device.getMobilePositionSubmissionInterval() + "</Interval>\r\n");
1460 1468 }
1461 1469 subscribePostitionXml.append("</Query>\r\n");
1462 1470  
1463   - Request request;
1464   - if (dialog != null) {
1465   - SipURI requestURI = sipFactory.createAddressFactory().createSipURI(device.getDeviceId(), device.getHostAddress());
1466   - request = dialog.createRequest(Request.SUBSCRIBE);
1467   - ExpiresHeader expiresHeader = sipFactory.createHeaderFactory().createExpiresHeader(device.getSubscribeCycleForCatalog());
1468   - request.setExpires(expiresHeader);
1469   -
1470   - request.setRequestURI(requestURI);
  1471 + CallIdHeader callIdHeader;
1471 1472  
1472   - ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml");
1473   - request.setContent(subscribePostitionXml.toString(), contentTypeHeader);
1474   -
1475   - CSeqHeader cSeqHeader = (CSeqHeader)request.getHeader(CSeqHeader.NAME);
1476   - cSeqHeader.setSeqNumber(redisCatchStorage.getCSEQ());
1477   - request.removeHeader(CSeqHeader.NAME);
1478   - request.addHeader(cSeqHeader);
  1473 + if (requestOld != null) {
  1474 + callIdHeader = sipFactory.createHeaderFactory().createCallIdHeader(requestOld.getCallIdHeader().getCallId());
1479 1475 }else {
1480   - CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
  1476 + callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
1481 1477 : udpSipProvider.getNewCallId();
1482   - request = headerProvider.createSubscribeRequest(device, subscribePostitionXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null, device.getSubscribeCycleForMobilePosition(), "presence" ,callIdHeader); //Position;id=" + tm.substring(tm.length() - 4));
1483 1478 }
  1479 + SIPRequest request = (SIPRequest)headerProvider.createSubscribeRequest(device, subscribePostitionXml.toString(), requestOld, device.getSubscribeCycleForMobilePosition(), "presence" ,callIdHeader); //Position;id=" + tm.substring(tm.length() - 4));
  1480 +
1484 1481 transmitRequest(device, request, errorEvent, okEvent);
1485 1482  
1486   - return true;
  1483 + return request;
1487 1484  
1488 1485 } catch ( NumberFormatException | ParseException | InvalidArgumentException | SipException e) {
1489 1486 e.printStackTrace();
1490   - return false;
  1487 + return null;
1491 1488 }
1492 1489 }
1493 1490  
... ... @@ -1537,7 +1534,7 @@ public class SIPCommander implements ISIPCommander {
1537 1534 CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
1538 1535 : udpSipProvider.getNewCallId();
1539 1536  
1540   - Request request = headerProvider.createSubscribeRequest(device, cmdXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null, expires, "presence" , callIdHeader);
  1537 + Request request = headerProvider.createSubscribeRequest(device, cmdXml.toString(), null, expires, "presence" , callIdHeader);
1541 1538 transmitRequest(device, request);
1542 1539  
1543 1540 return true;
... ... @@ -1549,7 +1546,7 @@ public class SIPCommander implements ISIPCommander {
1549 1546 }
1550 1547  
1551 1548 @Override
1552   - public boolean catalogSubscribe(Device device, Dialog dialog, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) {
  1549 + public SIPRequest catalogSubscribe(Device device, SIPRequest requestOld, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) {
1553 1550 try {
1554 1551 StringBuffer cmdXml = new StringBuffer(200);
1555 1552 String charset = device.getCharset();
... ... @@ -1560,40 +1557,24 @@ public class SIPCommander implements ISIPCommander {
1560 1557 cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
1561 1558 cmdXml.append("</Query>\r\n");
1562 1559  
  1560 + CallIdHeader callIdHeader ;
1563 1561  
1564   - Request request;
1565   - if (dialog != null) {
1566   - SipURI requestURI = sipFactory.createAddressFactory().createSipURI(device.getDeviceId(), device.getHostAddress());
1567   - request = dialog.createRequest(Request.SUBSCRIBE);
1568   - ExpiresHeader expiresHeader = sipFactory.createHeaderFactory().createExpiresHeader(device.getSubscribeCycleForCatalog());
1569   - request.setExpires(expiresHeader);
1570   -
1571   - request.setRequestURI(requestURI);
1572   -
1573   - ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml");
1574   - request.setContent(cmdXml.toString(), contentTypeHeader);
1575   -
1576   - CSeqHeader cSeqHeader = (CSeqHeader)request.getHeader(CSeqHeader.NAME);
1577   - cSeqHeader.setSeqNumber(redisCatchStorage.getCSEQ());
1578   - request.removeHeader(CSeqHeader.NAME);
1579   - request.addHeader(cSeqHeader);
1580   -
  1562 + if (requestOld != null) {
  1563 + callIdHeader = sipFactory.createHeaderFactory().createCallIdHeader(requestOld.getCallIdHeader().getCallId());
1581 1564 }else {
1582   - CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
  1565 + callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
1583 1566 : udpSipProvider.getNewCallId();
1584   -
1585   - // 有效时间默认为60秒以上
1586   - request = headerProvider.createSubscribeRequest(device, cmdXml.toString(), SipUtils.getNewViaTag(),
1587   - SipUtils.getNewFromTag(), null, device.getSubscribeCycleForCatalog(), "Catalog" ,
1588   - callIdHeader);
1589   -
1590 1567 }
  1568 +
  1569 + // 有效时间默认为60秒以上
  1570 + SIPRequest request = (SIPRequest)headerProvider.createSubscribeRequest(device, cmdXml.toString(), requestOld, device.getSubscribeCycleForCatalog(), "Catalog" ,
  1571 + callIdHeader);
1591 1572 transmitRequest(device, request, errorEvent, okEvent);
1592   - return true;
  1573 + return request;
1593 1574  
1594 1575 } catch ( NumberFormatException | ParseException | InvalidArgumentException | SipException e) {
1595 1576 e.printStackTrace();
1596   - return false;
  1577 + return null;
1597 1578 }
1598 1579 }
1599 1580  
... ... @@ -1869,61 +1850,4 @@ public class SIPCommander implements ISIPCommander {
1869 1850 }
1870 1851 return true;
1871 1852 }
1872   -
1873   - private void sendNotify(Device device, String catalogXmlContent,
1874   - SubscribeInfo subscribeInfo, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent )
1875   - throws SipException, ParseException {
1876   - MessageFactoryImpl messageFactory = (MessageFactoryImpl) sipFactory.createMessageFactory();
1877   - String characterSet = device.getCharset();
1878   - // 设置编码, 防止中文乱码
1879   - messageFactory.setDefaultContentEncodingCharset(characterSet);
1880   - Dialog dialog = subscribeInfo.getDialog();
1881   - if (dialog == null || !dialog.getState().equals(DialogState.CONFIRMED)) {
1882   - return;
1883   - }
1884   - SIPRequest notifyRequest = (SIPRequest)dialog.createRequest(Request.NOTIFY);
1885   - ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml");
1886   - notifyRequest.setContent(catalogXmlContent, contentTypeHeader);
1887   -
1888   - SubscriptionStateHeader subscriptionState = sipFactory.createHeaderFactory()
1889   - .createSubscriptionStateHeader(SubscriptionStateHeader.ACTIVE);
1890   - notifyRequest.addHeader(subscriptionState);
1891   -
1892   - EventHeader event = sipFactory.createHeaderFactory().createEventHeader(subscribeInfo.getEventType());
1893   - if (subscribeInfo.getEventId() != null) {
1894   - event.setEventId(subscribeInfo.getEventId());
1895   - }
1896   - notifyRequest.addHeader(event);
1897   -
1898   - SipURI sipURI = (SipURI) notifyRequest.getRequestURI();
1899   - if (subscribeInfo.getTransaction() != null) {
1900   - SIPRequest request = (SIPRequest) subscribeInfo.getTransaction().getRequest();
1901   - sipURI.setHost(request.getRemoteAddress().getHostAddress());
1902   - sipURI.setPort(request.getRemotePort());
1903   - }else {
1904   - sipURI.setHost(device.getIp());
1905   - sipURI.setPort(device.getPort());
1906   - }
1907   -
1908   - ClientTransaction transaction = null;
1909   - if ("TCP".equals(device.getTransport())) {
1910   - transaction = tcpSipProvider.getNewClientTransaction(notifyRequest);
1911   - } else if ("UDP".equals(device.getTransport())) {
1912   - transaction = udpSipProvider.getNewClientTransaction(notifyRequest);
1913   - }
1914   - // 添加错误订阅
1915   - if (errorEvent != null) {
1916   - sipSubscribe.addErrorSubscribe(subscribeInfo.getCallId(), errorEvent);
1917   - }
1918   - // 添加订阅
1919   - if (okEvent != null) {
1920   - sipSubscribe.addOkSubscribe(subscribeInfo.getCallId(), okEvent);
1921   - }
1922   - if (transaction == null) {
1923   - logger.error("平台{}的Transport错误:{}",device.getDeviceId(), device.getTransport());
1924   - return;
1925   - }
1926   - dialog.sendRequest(transaction);
1927   -
1928   - }
1929 1853 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommanderFroPlatform.java
1 1 package com.genersoft.iot.vmp.gb28181.transmit.cmd.impl;
2 2  
  3 +import com.alibaba.fastjson.JSONObject;
3 4 import com.genersoft.iot.vmp.gb28181.bean.*;
4 5 import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
5 6 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
... ... @@ -47,7 +48,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
47 48 private final Logger logger = LoggerFactory.getLogger(SIPCommanderFroPlatform.class);
48 49  
49 50 @Autowired
50   - private SIPRequestHeaderPlarformProvider headerProviderPlarformProvider;
  51 + private SIPRequestHeaderPlarformProvider headerProviderPlatformProvider;
51 52  
52 53 @Autowired
53 54 private IRedisCatchStorage redisCatchStorage;
... ... @@ -74,6 +75,9 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
74 75 @Autowired
75 76 private SipFactory sipFactory;
76 77  
  78 + @Autowired
  79 + private SubscribeHolder subscribeHolder;
  80 +
77 81 @Override
78 82 public boolean register(ParentPlatform parentPlatform, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent) {
79 83 return register(parentPlatform, null, null, errorEvent, okEvent, false, true);
... ... @@ -98,7 +102,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
98 102 callIdHeader = udpSipProvider.getNewCallId();
99 103 }
100 104  
101   - request = headerProviderPlarformProvider.createRegisterRequest(parentPlatform,
  105 + request = headerProviderPlatformProvider.createRegisterRequest(parentPlatform,
102 106 redisCatchStorage.getCSEQ(), SipUtils.getNewFromTag(),
103 107 SipUtils.getNewViaTag(), callIdHeader, isRegister);
104 108 // 将 callid 写入缓存, 等注册成功可以更新状态
... ... @@ -120,7 +124,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
120 124 }else {
121 125 CallIdHeader callIdHeader = parentPlatform.getTransport().equalsIgnoreCase("TCP") ? tcpSipProvider.getNewCallId()
122 126 : udpSipProvider.getNewCallId();
123   - request = headerProviderPlarformProvider.createRegisterRequest(parentPlatform, SipUtils.getNewFromTag(), null, callId, www, callIdHeader, isRegister);
  127 + request = headerProviderPlatformProvider.createRegisterRequest(parentPlatform, SipUtils.getNewFromTag(), null, callId, www, callIdHeader, isRegister);
124 128 }
125 129  
126 130 transmitRequest(parentPlatform, request, null, okEvent);
... ... @@ -154,7 +158,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
154 158 CallIdHeader callIdHeader = parentPlatform.getTransport().equalsIgnoreCase("TCP") ? tcpSipProvider.getNewCallId()
155 159 : udpSipProvider.getNewCallId();
156 160  
157   - Request request = headerProviderPlarformProvider.createMessageRequest(
  161 + Request request = headerProviderPlatformProvider.createMessageRequest(
158 162 parentPlatform,
159 163 keepaliveXml.toString(),
160 164 SipUtils.getNewFromTag(),
... ... @@ -220,7 +224,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
220 224 CallIdHeader callIdHeader = parentPlatform.getTransport().equalsIgnoreCase("TCP") ? tcpSipProvider.getNewCallId()
221 225 : udpSipProvider.getNewCallId();
222 226  
223   - Request request = headerProviderPlarformProvider.createMessageRequest(parentPlatform, catalogXml.toString(), fromTag, SipUtils.getNewViaTag(), callIdHeader);
  227 + Request request = headerProviderPlatformProvider.createMessageRequest(parentPlatform, catalogXml.toString(), fromTag, SipUtils.getNewViaTag(), callIdHeader);
224 228 transmitRequest(parentPlatform, request);
225 229  
226 230 } catch (SipException | ParseException | InvalidArgumentException e) {
... ... @@ -314,7 +318,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
314 318 CallIdHeader callIdHeader = parentPlatform.getTransport().equalsIgnoreCase("TCP") ? tcpSipProvider.getNewCallId()
315 319 : udpSipProvider.getNewCallId();
316 320  
317   - Request request = headerProviderPlarformProvider.createMessageRequest(parentPlatform, catalogXml, fromTag, SipUtils.getNewViaTag(), callIdHeader);
  321 + Request request = headerProviderPlatformProvider.createMessageRequest(parentPlatform, catalogXml, fromTag, SipUtils.getNewViaTag(), callIdHeader);
318 322 transmitRequest(parentPlatform, request, null, eventResult -> {
319 323 int indexNext = index + parentPlatform.getCatalogGroup();
320 324 sendCatalogResponse(channels, parentPlatform, sn, fromTag, indexNext);
... ... @@ -354,7 +358,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
354 358 CallIdHeader callIdHeader = parentPlatform.getTransport().equalsIgnoreCase("TCP") ? tcpSipProvider.getNewCallId()
355 359 : udpSipProvider.getNewCallId();
356 360  
357   - Request request = headerProviderPlarformProvider.createMessageRequest(parentPlatform, deviceInfoXml.toString(), fromTag, SipUtils.getNewViaTag(), callIdHeader);
  361 + Request request = headerProviderPlatformProvider.createMessageRequest(parentPlatform, deviceInfoXml.toString(), fromTag, SipUtils.getNewViaTag(), callIdHeader);
358 362 transmitRequest(parentPlatform, request);
359 363  
360 364 } catch (SipException | ParseException | InvalidArgumentException e) {
... ... @@ -392,7 +396,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
392 396 CallIdHeader callIdHeader = parentPlatform.getTransport().equalsIgnoreCase("TCP") ? tcpSipProvider.getNewCallId()
393 397 : udpSipProvider.getNewCallId();
394 398  
395   - Request request = headerProviderPlarformProvider.createMessageRequest(parentPlatform, deviceStatusXml.toString(), fromTag, SipUtils.getNewViaTag(), callIdHeader);
  399 + Request request = headerProviderPlatformProvider.createMessageRequest(parentPlatform, deviceStatusXml.toString(), fromTag, SipUtils.getNewViaTag(), callIdHeader);
396 400 transmitRequest(parentPlatform, request);
397 401  
398 402 } catch (SipException | ParseException | InvalidArgumentException e) {
... ... @@ -427,11 +431,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
427 431 deviceStatusXml.append("<Altitude>" + gpsMsgInfo.getAltitude() + "</Altitude>\r\n");
428 432 deviceStatusXml.append("</Notify>\r\n");
429 433  
430   - CallIdHeader callIdHeader = parentPlatform.getTransport().equalsIgnoreCase("TCP") ? tcpSipProvider.getNewCallId()
431   - : udpSipProvider.getNewCallId();
432   - callIdHeader.setCallId(subscribeInfo.getCallId());
433   -
434   - sendNotify(parentPlatform, deviceStatusXml.toString(), subscribeInfo, eventResult -> {
  434 + sendNotify(parentPlatform, deviceStatusXml.toString(), subscribeInfo, eventResult -> {
435 435 logger.error("发送NOTIFY通知消息失败。错误:{} {}", eventResult.statusCode, eventResult.msg);
436 436 }, null);
437 437  
... ... @@ -453,8 +453,8 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
453 453 if (parentPlatform == null) {
454 454 return false;
455 455 }
456   - logger.info("[发送 报警订阅] {}/{}->{},{}", parentPlatform.getServerGBId(), deviceAlarm.getChannelId(),
457   - deviceAlarm.getLongitude(), deviceAlarm.getLatitude());
  456 + logger.info("[发送报警通知] {}/{}->{},{}: {}", parentPlatform.getServerGBId(), deviceAlarm.getChannelId(),
  457 + deviceAlarm.getLongitude(), deviceAlarm.getLatitude(), JSONObject.toJSON(deviceAlarm));
458 458 try {
459 459 String characterSet = parentPlatform.getCharacterSet();
460 460 StringBuffer deviceStatusXml = new StringBuffer(600);
... ... @@ -477,7 +477,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
477 477 CallIdHeader callIdHeader = parentPlatform.getTransport().equalsIgnoreCase("TCP") ? tcpSipProvider.getNewCallId()
478 478 : udpSipProvider.getNewCallId();
479 479  
480   - Request request = headerProviderPlarformProvider.createMessageRequest(parentPlatform, deviceStatusXml.toString(), SipUtils.getNewFromTag(), SipUtils.getNewViaTag(), callIdHeader);
  480 + Request request = headerProviderPlatformProvider.createMessageRequest(parentPlatform, deviceStatusXml.toString(), SipUtils.getNewFromTag(), SipUtils.getNewViaTag(), callIdHeader);
481 481 transmitRequest(parentPlatform, request);
482 482  
483 483 } catch (SipException | ParseException e) {
... ... @@ -529,18 +529,15 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
529 529 return true;
530 530 }
531 531  
532   - private void sendNotify(ParentPlatform parentPlatform, String catalogXmlContent,
  532 + private ClientTransaction sendNotify(ParentPlatform parentPlatform, String catalogXmlContent,
533 533 SubscribeInfo subscribeInfo, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent )
534 534 throws NoSuchFieldException, IllegalAccessException, SipException, ParseException, InvalidArgumentException {
535 535 MessageFactoryImpl messageFactory = (MessageFactoryImpl) sipFactory.createMessageFactory();
536 536 String characterSet = parentPlatform.getCharacterSet();
537 537 // 设置编码, 防止中文乱码
538 538 messageFactory.setDefaultContentEncodingCharset(characterSet);
539   - Dialog dialog = subscribeInfo.getDialog();
540   - if (dialog == null || !dialog.getState().equals(DialogState.CONFIRMED)) {
541   - return;
542   - }
543   - SIPRequest notifyRequest = (SIPRequest)dialog.createRequest(Request.NOTIFY);
  539 +
  540 + SIPRequest notifyRequest = headerProviderPlatformProvider.createNotifyRequest(parentPlatform, catalogXmlContent, subscribeInfo);
544 541  
545 542 notifyRequest.getCSeqHeader().setSeqNumber(redisCatchStorage.getCSEQ());
546 543  
... ... @@ -560,26 +557,32 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
560 557 sipURI.setHost(parentPlatform.getServerIP());
561 558 sipURI.setPort(parentPlatform.getServerPort());
562 559  
  560 +// ClientTransaction transaction = subscribeInfo.getClientTransaction();
  561 +// if (transaction == null || transaction.getState().equals(TransactionState.COMPLETED)) {
  562 +// if ("TCP".equals(parentPlatform.getTransport())) {
  563 +// transaction = tcpSipProvider.getNewClientTransaction(notifyRequest);
  564 +// } else if ("UDP".equals(parentPlatform.getTransport())) {
  565 +// transaction = udpSipProvider.getNewClientTransaction(notifyRequest);
  566 +// }
  567 +// }
  568 +
563 569 ClientTransaction transaction = null;
564 570 if ("TCP".equals(parentPlatform.getTransport())) {
565 571 transaction = tcpSipProvider.getNewClientTransaction(notifyRequest);
566 572 } else if ("UDP".equals(parentPlatform.getTransport())) {
567 573 transaction = udpSipProvider.getNewClientTransaction(notifyRequest);
568 574 }
  575 +
569 576 // 添加错误订阅
570 577 if (errorEvent != null) {
571   - sipSubscribe.addErrorSubscribe(subscribeInfo.getCallId(), errorEvent);
  578 + sipSubscribe.addErrorSubscribe(subscribeInfo.getRequest().getCallIdHeader().getCallId(), errorEvent);
572 579 }
573 580 // 添加订阅
574 581 if (okEvent != null) {
575   - sipSubscribe.addOkSubscribe(subscribeInfo.getCallId(), okEvent);
  582 + sipSubscribe.addOkSubscribe(subscribeInfo.getRequest().getCallIdHeader().getCallId(), okEvent);
576 583 }
577   - if (transaction == null) {
578   - logger.error("平台{}的Transport错误:{}",parentPlatform.getServerGBId(), parentPlatform.getTransport());
579   - return;
580   - }
581   - dialog.sendRequest(transaction);
582   -
  584 + transaction.sendRequest();
  585 + return transaction;
583 586 }
584 587  
585 588 private String getCatalogXmlContentForCatalogAddOrUpdate(ParentPlatform parentPlatform, List<DeviceChannel> channels, int sumNum, String type, SubscribeInfo subscribeInfo) {
... ... @@ -755,7 +758,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
755 758 // callid
756 759 CallIdHeader callIdHeader = parentPlatform.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
757 760 : udpSipProvider.getNewCallId();
758   - Request request = headerProviderPlarformProvider.createMessageRequest(parentPlatform, recordXml.toString(), fromTag, SipUtils.getNewViaTag(), callIdHeader);
  761 + Request request = headerProviderPlatformProvider.createMessageRequest(parentPlatform, recordXml.toString(), fromTag, SipUtils.getNewViaTag(), callIdHeader);
759 762 transmitRequest(parentPlatform, request);
760 763  
761 764 } catch (SipException | ParseException | InvalidArgumentException e) {
... ... @@ -774,36 +777,8 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
774 777 return false;
775 778 }
776 779  
777   - byte[] dialogByteArray = sendRtpItem.getDialog();
778   - if (dialogByteArray == null) {
779   - return false;
780   - }
781 780 try{
782   - SIPDialog dialog = (SIPDialog) SerializeUtils.deSerialize(dialogByteArray);
783   - SipStack sipStack;
784   - if ("TCP".equals(platform.getTransport())) {
785   - sipStack = tcpSipProvider.getSipStack();
786   - } else {
787   - sipStack = udpSipProvider.getSipStack();
788   - }
789   - SIPDialog sipDialog = ((SipStackImpl) sipStack).putDialog(dialog);
790   - if (dialog != sipDialog) {
791   - dialog = sipDialog;
792   - }
793   - if ("TCP".equals(platform.getTransport())) {
794   - dialog.setSipProvider(tcpSipProvider);
795   - } else {
796   - dialog.setSipProvider(udpSipProvider);
797   - }
798   -
799   - Field sipStackField = SIPDialog.class.getDeclaredField("sipStack");
800   - sipStackField.setAccessible(true);
801   - sipStackField.set(dialog, sipStack);
802   - Field eventListenersField = SIPDialog.class.getDeclaredField("eventListeners");
803   - eventListenersField.setAccessible(true);
804   - eventListenersField.set(dialog, new HashSet<>());
805 781  
806   - SIPRequest messageRequest = (SIPRequest)dialog.createRequest(Request.MESSAGE);
807 782 String characterSet = platform.getCharacterSet();
808 783 StringBuffer mediaStatusXml = new StringBuffer(200);
809 784 mediaStatusXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n");
... ... @@ -813,6 +788,10 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
813 788 mediaStatusXml.append("<DeviceID>" + sendRtpItem.getChannelId() + "</DeviceID>\r\n");
814 789 mediaStatusXml.append("<NotifyType>121</NotifyType>\r\n");
815 790 mediaStatusXml.append("</Notify>\r\n");
  791 +
  792 + SIPRequest messageRequest = (SIPRequest)headerProviderPlatformProvider.createMessageRequest(platform, mediaStatusXml.toString(),
  793 + sendRtpItem);
  794 +
816 795 ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml");
817 796 messageRequest.setContent(mediaStatusXml.toString(), contentTypeHeader);
818 797 SipURI sipURI = (SipURI) messageRequest.getRequestURI();
... ... @@ -824,17 +803,15 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
824 803 }else {
825 804 clientTransaction = udpSipProvider.getNewClientTransaction(messageRequest);
826 805 }
827   - dialog.sendRequest(clientTransaction);
  806 + clientTransaction.sendRequest();
828 807 } catch (SipException e) {
829 808 e.printStackTrace();
830 809 return false;
831 810 } catch (ParseException e) {
832 811 e.printStackTrace();
833 812 return false;
834   - } catch (NoSuchFieldException e) {
835   - e.printStackTrace();
836   - } catch (IllegalAccessException e) {
837   - e.printStackTrace();
  813 + } catch (InvalidArgumentException e) {
  814 + throw new RuntimeException(e);
838 815 }
839 816 return true;
840 817  
... ... @@ -848,61 +825,46 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
848 825 }
849 826 SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(platform.getServerGBId(), null, null, callId);
850 827 if (sendRtpItem != null) {
851   - String mediaServerId = sendRtpItem.getMediaServerId();
852   - MediaServerItem mediaServerItem = mediaServerService.getOne(mediaServerId);
853   - if (mediaServerItem != null) {
854   - mediaServerService.releaseSsrc(mediaServerItem.getId(), sendRtpItem.getSsrc());
855   - zlmrtpServerFactory.closeRTPServer(mediaServerItem, sendRtpItem.getStreamId());
856   - }
857   - byte[] dialogByteArray = sendRtpItem.getDialog();
858   - if (dialogByteArray != null) {
859   - SIPDialog dialog = (SIPDialog) SerializeUtils.deSerialize(dialogByteArray);
860   - SipStack sipStack;
861   - if ("TCP".equals(platform.getTransport())) {
862   - sipStack = tcpSipProvider.getSipStack();
863   - } else {
864   - sipStack = udpSipProvider.getSipStack();
865   - }
866   - SIPDialog sipDialog = ((SipStackImpl) sipStack).putDialog(dialog);
867   - if (dialog != sipDialog) {
868   - dialog = sipDialog;
869   - }
870   - try {
871   - if ("TCP".equals(platform.getTransport())) {
872   - dialog.setSipProvider(tcpSipProvider);
873   - } else {
874   - dialog.setSipProvider(udpSipProvider);
875   - }
876   - Field sipStackField = SIPDialog.class.getDeclaredField("sipStack");
877   - sipStackField.setAccessible(true);
878   - sipStackField.set(dialog, sipStack);
879   - Field eventListenersField = SIPDialog.class.getDeclaredField("eventListeners");
880   - eventListenersField.setAccessible(true);
881   - eventListenersField.set(dialog, new HashSet<>());
882   -
883   - Request byeRequest = dialog.createRequest(Request.BYE);
884   -
885   - SipURI byeURI = (SipURI) byeRequest.getRequestURI();
886   - byeURI.setHost(platform.getServerIP());
887   - byeURI.setPort(platform.getServerPort());
888   - ClientTransaction clientTransaction;
889   - if ("TCP".equals(platform.getTransport())) {
890   - clientTransaction = tcpSipProvider.getNewClientTransaction(byeRequest);
891   - } else {
892   - clientTransaction = udpSipProvider.getNewClientTransaction(byeRequest);
893   - }
894   - dialog.sendRequest(clientTransaction);
895   - } catch (SipException e) {
896   - e.printStackTrace();
897   - } catch (ParseException e) {
898   - e.printStackTrace();
899   - } catch (NoSuchFieldException e) {
900   - e.printStackTrace();
901   - } catch (IllegalAccessException e) {
902   - e.printStackTrace();
903   - }
  828 + streamByeCmd(platform, sendRtpItem);
  829 + }
  830 + }
  831 +
  832 + @Override
  833 + public void streamByeCmd(ParentPlatform platform, SendRtpItem sendRtpItem) {
  834 + if (sendRtpItem == null ) {
  835 + logger.info("[向上级发送BYE], sendRtpItem 为NULL");
  836 + return;
  837 + }
  838 + if (platform == null) {
  839 + logger.info("[向上级发送BYE], platform 为NULL");
  840 + return;
  841 + }
  842 + logger.info("[向上级发送BYE], {}/{}", platform.getServerGBId(), sendRtpItem.getChannelId());
  843 + String mediaServerId = sendRtpItem.getMediaServerId();
  844 + MediaServerItem mediaServerItem = mediaServerService.getOne(mediaServerId);
  845 + if (mediaServerItem != null) {
  846 + mediaServerService.releaseSsrc(mediaServerItem.getId(), sendRtpItem.getSsrc());
  847 + zlmrtpServerFactory.closeRTPServer(mediaServerItem, sendRtpItem.getStreamId());
  848 + }
  849 + try {
904 850  
  851 + SIPRequest byeRequest = headerProviderPlatformProvider.createByeRequest(platform, sendRtpItem);
  852 + if (byeRequest == null) {
  853 + logger.warn("[向上级发送bye]:无法创建 byeRequest");
  854 + }
  855 + ClientTransaction clientTransaction;
  856 + if ("TCP".equals(platform.getTransport())) {
  857 + clientTransaction = tcpSipProvider.getNewClientTransaction(byeRequest);
  858 + } else {
  859 + clientTransaction = udpSipProvider.getNewClientTransaction(byeRequest);
905 860 }
  861 + clientTransaction.sendRequest();
  862 + } catch (SipException e) {
  863 + e.printStackTrace();
  864 + } catch (ParseException e) {
  865 + e.printStackTrace();
  866 + } catch (InvalidArgumentException e) {
  867 + throw new RuntimeException(e);
906 868 }
907 869 }
908 870 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/SIPRequestProcessorParent.java
1 1 package com.genersoft.iot.vmp.gb28181.transmit.event.request;
2 2  
3 3 import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
  4 +import com.genersoft.iot.vmp.gb28181.utils.SipUtils;
4 5 import gov.nist.javax.sip.SipProviderImpl;
5 6 import gov.nist.javax.sip.SipStackImpl;
6 7 import gov.nist.javax.sip.message.SIPRequest;
  8 +import gov.nist.javax.sip.message.SIPResponse;
7 9 import gov.nist.javax.sip.stack.SIPServerTransaction;
8 10 import org.apache.commons.lang3.ArrayUtils;
9 11 import org.dom4j.Document;
... ... @@ -19,10 +21,7 @@ import javax.sip.*;
19 21 import javax.sip.address.Address;
20 22 import javax.sip.address.AddressFactory;
21 23 import javax.sip.address.SipURI;
22   -import javax.sip.header.ContentTypeHeader;
23   -import javax.sip.header.ExpiresHeader;
24   -import javax.sip.header.HeaderFactory;
25   -import javax.sip.header.ViaHeader;
  24 +import javax.sip.header.*;
26 25 import javax.sip.message.MessageFactory;
27 26 import javax.sip.message.Request;
28 27 import javax.sip.message.Response;
... ... @@ -59,9 +58,6 @@ public abstract class SIPRequestProcessorParent {
59 58 public ServerTransaction getServerTransaction(RequestEvent evt) {
60 59 Request request = evt.getRequest();
61 60 ServerTransaction serverTransaction = evt.getServerTransaction();
62   - if (serverTransaction != null) {
63   - System.out.println(serverTransaction.getState().toString());
64   - }
65 61 // 判断TCP还是UDP
66 62 ViaHeader reqViaHeader = (ViaHeader) request.getHeader(ViaHeader.NAME);
67 63 String transport = reqViaHeader.getTransport();
... ... @@ -120,105 +116,107 @@ public abstract class SIPRequestProcessorParent {
120 116 return null;
121 117 }
122 118  
  119 + class ResponseAckExtraParam{
  120 + String content;
  121 + ContentTypeHeader contentTypeHeader;
  122 + SipURI sipURI;
  123 + int expires = -1;
  124 + }
  125 +
123 126 /***
124 127 * 回复状态码
125 128 * 100 trying
126 129 * 200 OK
127 130 * 400
128 131 * 404
129   - * @param evt
130   - * @throws SipException
131   - * @throws InvalidArgumentException
132   - * @throws ParseException
133 132 */
134   - public void responseAck(RequestEvent evt, int statusCode) throws SipException, InvalidArgumentException, ParseException {
135   - Response response = getMessageFactory().createResponse(statusCode, evt.getRequest());
136   - ServerTransaction serverTransaction = getServerTransaction(evt);
137   - if (serverTransaction == null) {
138   - logger.warn("回复失败:{}", response);
139   - return;
  133 + public SIPResponse responseAck(ServerTransaction serverTransaction, int statusCode) throws SipException, InvalidArgumentException, ParseException {
  134 + return responseAck(serverTransaction, statusCode, null);
  135 + }
  136 +
  137 + public SIPResponse responseAck(ServerTransaction serverTransaction, int statusCode, String msg) throws SipException, InvalidArgumentException, ParseException {
  138 + return responseAck(serverTransaction, statusCode, msg, null);
  139 + }
  140 +
  141 + public SIPResponse responseAck(ServerTransaction serverTransaction, int statusCode, String msg, ResponseAckExtraParam responseAckExtraParam) throws SipException, InvalidArgumentException, ParseException {
  142 + ToHeader toHeader = (ToHeader) serverTransaction.getRequest().getHeader(ToHeader.NAME);
  143 + if (toHeader.getTag() == null) {
  144 + toHeader.setTag(SipUtils.getNewTag());
140 145 }
141   - serverTransaction.sendResponse(response);
142   - if (statusCode >= 200 && !"NOTIFY".equalsIgnoreCase(evt.getRequest().getMethod())) {
  146 + SIPResponse response = (SIPResponse)getMessageFactory().createResponse(statusCode, serverTransaction.getRequest());
  147 + if (msg != null) {
  148 + response.setReasonPhrase(msg);
  149 + }
  150 + if (responseAckExtraParam != null) {
  151 + if (responseAckExtraParam.sipURI != null && serverTransaction.getRequest().getMethod().equals(Request.INVITE)) {
  152 + logger.debug("responseSdpAck SipURI: {}:{}", responseAckExtraParam.sipURI.getHost(), responseAckExtraParam.sipURI.getPort());
  153 + Address concatAddress = SipFactory.getInstance().createAddressFactory().createAddress(
  154 + SipFactory.getInstance().createAddressFactory().createSipURI(responseAckExtraParam.sipURI.getUser(), responseAckExtraParam.sipURI.getHost()+":"+responseAckExtraParam.sipURI.getPort()
  155 + ));
  156 + response.addHeader(SipFactory.getInstance().createHeaderFactory().createContactHeader(concatAddress));
  157 + }
  158 + if (responseAckExtraParam.contentTypeHeader != null) {
  159 + response.setContent(responseAckExtraParam.content, responseAckExtraParam.contentTypeHeader);
  160 + }
143 161  
144   - if (serverTransaction.getDialog() != null) {
145   - serverTransaction.getDialog().delete();
  162 + if (serverTransaction.getRequest().getMethod().equals(Request.SUBSCRIBE)) {
  163 + if (responseAckExtraParam.expires == -1) {
  164 + logger.error("[参数不全] 2xx的SUBSCRIBE回复,必须设置Expires header");
  165 + }else {
  166 + ExpiresHeader expiresHeader = SipFactory.getInstance().createHeaderFactory().createExpiresHeader(responseAckExtraParam.expires);
  167 + response.addHeader(expiresHeader);
  168 + }
  169 + }
  170 + }else {
  171 + if (serverTransaction.getRequest().getMethod().equals(Request.SUBSCRIBE)) {
  172 + logger.error("[参数不全] 2xx的SUBSCRIBE回复,必须设置Expires header");
146 173 }
147 174 }
148   - }
149   -
150   - public void responseAck(RequestEvent evt, int statusCode, String msg) throws SipException, InvalidArgumentException, ParseException {
151   - Response response = getMessageFactory().createResponse(statusCode, evt.getRequest());
152   - response.setReasonPhrase(msg);
153   - ServerTransaction serverTransaction = getServerTransaction(evt);
154 175 serverTransaction.sendResponse(response);
155   - if (statusCode >= 200 && !"NOTIFY".equalsIgnoreCase(evt.getRequest().getMethod())) {
  176 + if (statusCode >= 200 && !"NOTIFY".equalsIgnoreCase(serverTransaction.getRequest().getMethod())) {
156 177 if (serverTransaction.getDialog() != null) {
157 178 serverTransaction.getDialog().delete();
158 179 }
159 180 }
  181 + return response;
160 182 }
161 183  
162 184 /**
163 185 * 回复带sdp的200
164   - * @param evt
165   - * @param sdp
166   - * @throws SipException
167   - * @throws InvalidArgumentException
168   - * @throws ParseException
169 186 */
170   - public void responseSdpAck(RequestEvent evt, String sdp, ParentPlatform platform) throws SipException, InvalidArgumentException, ParseException {
171   - Response response = getMessageFactory().createResponse(Response.OK, evt.getRequest());
172   - SipFactory sipFactory = SipFactory.getInstance();
173   - ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("APPLICATION", "SDP");
174   - response.setContent(sdp, contentTypeHeader);
  187 + public SIPResponse responseSdpAck(ServerTransaction serverTransaction, String sdp, ParentPlatform platform) throws SipException, InvalidArgumentException, ParseException {
  188 +
  189 + ContentTypeHeader contentTypeHeader = SipFactory.getInstance().createHeaderFactory().createContentTypeHeader("APPLICATION", "SDP");
175 190  
176 191 // 兼容国标中的使用编码@域名作为RequestURI的情况
177   - SipURI sipURI = (SipURI)evt.getRequest().getRequestURI();
  192 + SipURI sipURI = (SipURI)serverTransaction.getRequest().getRequestURI();
178 193 if (sipURI.getPort() == -1) {
179   - sipURI = sipFactory.createAddressFactory().createSipURI(platform.getServerGBId(), platform.getServerIP()+":"+platform.getServerPort());
  194 + sipURI = SipFactory.getInstance().createAddressFactory().createSipURI(platform.getServerGBId(), platform.getServerIP()+":"+platform.getServerPort());
180 195 }
181   - logger.debug("responseSdpAck SipURI: {}:{}", sipURI.getHost(), sipURI.getPort());
  196 + ResponseAckExtraParam responseAckExtraParam = new ResponseAckExtraParam();
  197 + responseAckExtraParam.contentTypeHeader = contentTypeHeader;
  198 + responseAckExtraParam.content = sdp;
  199 + responseAckExtraParam.sipURI = sipURI;
182 200  
183   - Address concatAddress = sipFactory.createAddressFactory().createAddress(
184   - sipFactory.createAddressFactory().createSipURI(sipURI.getUser(), sipURI.getHost()+":"+sipURI.getPort()
185   - ));
186   - response.addHeader(sipFactory.createHeaderFactory().createContactHeader(concatAddress));
187   - ServerTransaction serverTransaction = getServerTransaction(evt);
188   - if (serverTransaction == null) {
189   -
190   - }
191   - getServerTransaction(evt).sendResponse(response);
  201 + return responseAck(serverTransaction, Response.OK, null, responseAckExtraParam);
192 202 }
193 203  
194 204 /**
195 205 * 回复带xml的200
196   - * @param evt
197   - * @param xml
198   - * @throws SipException
199   - * @throws InvalidArgumentException
200   - * @throws ParseException
201 206 */
202   - public Response responseXmlAck(RequestEvent evt, String xml, ParentPlatform platform) throws SipException, InvalidArgumentException, ParseException {
203   - Response response = getMessageFactory().createResponse(Response.OK, evt.getRequest());
204   - SipFactory sipFactory = SipFactory.getInstance();
205   - ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml");
206   - response.setContent(xml, contentTypeHeader);
  207 + public SIPResponse responseXmlAck(ServerTransaction serverTransaction, String xml, ParentPlatform platform, Integer expires) throws SipException, InvalidArgumentException, ParseException {
  208 + ContentTypeHeader contentTypeHeader = SipFactory.getInstance().createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml");
207 209  
208   - // 兼容国标中的使用编码@域名作为RequestURI的情况
209   - SipURI sipURI = (SipURI)evt.getRequest().getRequestURI();
  210 + SipURI sipURI = (SipURI)serverTransaction.getRequest().getRequestURI();
210 211 if (sipURI.getPort() == -1) {
211   - sipURI = sipFactory.createAddressFactory().createSipURI(platform.getServerGBId(), platform.getServerIP()+":"+platform.getServerPort());
  212 + sipURI = SipFactory.getInstance().createAddressFactory().createSipURI(platform.getServerGBId(), platform.getServerIP()+":"+platform.getServerPort());
212 213 }
213   - logger.debug("responseXmlAck SipURI: {}:{}", sipURI.getHost(), sipURI.getPort());
214   -
215   - Address concatAddress = sipFactory.createAddressFactory().createAddress(
216   - sipFactory.createAddressFactory().createSipURI(sipURI.getUser(), sipURI.getHost()+":"+sipURI.getPort()
217   - ));
218   - response.addHeader(sipFactory.createHeaderFactory().createContactHeader(concatAddress));
219   - response.addHeader(evt.getRequest().getHeader(ExpiresHeader.NAME));
220   - getServerTransaction(evt).sendResponse(response);
221   - return response;
  214 + ResponseAckExtraParam responseAckExtraParam = new ResponseAckExtraParam();
  215 + responseAckExtraParam.contentTypeHeader = contentTypeHeader;
  216 + responseAckExtraParam.content = xml;
  217 + responseAckExtraParam.sipURI = sipURI;
  218 + responseAckExtraParam.expires = expires;
  219 + return responseAck(serverTransaction, Response.OK, null, responseAckExtraParam);
222 220 }
223 221  
224 222 public Element getRootElement(RequestEvent evt) throws DocumentException {
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/AckRequestProcessor.java
... ... @@ -16,7 +16,7 @@ import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
16 16 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
17 17 import com.genersoft.iot.vmp.service.IMediaServerService;
18 18 import com.genersoft.iot.vmp.service.bean.RequestPushStreamMsg;
19   -import com.genersoft.iot.vmp.service.impl.RedisGbPlayMsgListener;
  19 +import com.genersoft.iot.vmp.service.redisMsg.RedisGbPlayMsgListener;
20 20 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
21 21 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
22 22 import gov.nist.javax.sip.message.SIPRequest;
... ... @@ -29,6 +29,7 @@ import org.springframework.beans.factory.annotation.Autowired;
29 29 import org.springframework.stereotype.Component;
30 30  
31 31 import javax.sip.*;
  32 +import javax.sip.RequestEvent;
32 33 import javax.sip.address.SipURI;
33 34 import javax.sip.header.CallIdHeader;
34 35 import javax.sip.header.FromHeader;
... ... @@ -93,47 +94,41 @@ public class AckRequestProcessor extends SIPRequestProcessorParent implements In
93 94 */
94 95 @Override
95 96 public void process(RequestEvent evt) {
96   - Dialog dialog = evt.getDialog();
97   - CallIdHeader callIdHeader = (CallIdHeader) evt.getRequest().getHeader(CallIdHeader.NAME);
98   - if (dialog == null) {
99   - return;
  97 + CallIdHeader callIdHeader = (CallIdHeader)evt.getRequest().getHeader(CallIdHeader.NAME);
  98 +
  99 + String platformGbId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(FromHeader.NAME)).getAddress().getURI()).getUser();
  100 + logger.info("[收到ACK]: platformGbId->{}", platformGbId);
  101 + ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(platformGbId);
  102 + // 取消设置的超时任务
  103 + dynamicTask.stop(callIdHeader.getCallId());
  104 + String channelId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(ToHeader.NAME)).getAddress().getURI()).getUser();
  105 + SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(platformGbId, channelId, null, callIdHeader.getCallId());
  106 + String is_Udp = sendRtpItem.isTcp() ? "0" : "1";
  107 + MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId());
  108 + logger.info("收到ACK,rtp/{}开始向上级推流, 目标 {}:{},SSRC={}", sendRtpItem.getStreamId(), sendRtpItem.getIp(), sendRtpItem.getPort(), sendRtpItem.getSsrc());
  109 + Map<String, Object> param = new HashMap<>();
  110 + param.put("vhost","__defaultVhost__");
  111 + param.put("app",sendRtpItem.getApp());
  112 + param.put("stream",sendRtpItem.getStreamId());
  113 + param.put("ssrc", sendRtpItem.getSsrc());
  114 + param.put("src_port", sendRtpItem.getLocalPort());
  115 + param.put("pt", sendRtpItem.getPt());
  116 + param.put("use_ps", sendRtpItem.isUsePs() ? "1" : "0");
  117 + param.put("only_audio", sendRtpItem.isOnlyAudio() ? "1" : "0");
  118 + if (!sendRtpItem.isTcp() && parentPlatform.isRtcp()) {
  119 + // 开启rtcp保活
  120 + param.put("udp_rtcp_timeout", "1");
  121 + }
  122 +
  123 + JSONObject jsonObject;
  124 + if (sendRtpItem.isTcpActive()) {
  125 + jsonObject = zlmrtpServerFactory.startSendRtpPassive(mediaInfo, param);
  126 + } else {
  127 + param.put("is_udp", is_Udp);
  128 + param.put("dst_url", sendRtpItem.getIp());
  129 + param.put("dst_port", sendRtpItem.getPort());
  130 + jsonObject = zlmrtpServerFactory.startSendRtpStream(mediaInfo, param);
100 131 }
101   - if (dialog.getState() == DialogState.CONFIRMED) {
102   - String platformGbId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(FromHeader.NAME)).getAddress().getURI()).getUser();
103   - logger.info("ACK请求: platformGbId->{}", platformGbId);
104   - ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(platformGbId);
105   - // 取消设置的超时任务
106   - dynamicTask.stop(callIdHeader.getCallId());
107   -// String channelId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(ToHeader.NAME)).getAddress().getURI()).getUser();
108   - SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(platformGbId, null, null, callIdHeader.getCallId());
109   - String is_Udp = sendRtpItem.isTcp() ? "0" : "1";
110   - MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId());
111   - logger.info("[收到ACK],开始使用{}向上级推流 {}/{}->{}:{}({})", sendRtpItem.isTcp() ? "TCP" : "UDP",
112   - sendRtpItem.getApp(), sendRtpItem.getStreamId(),
113   - sendRtpItem.getIp(), sendRtpItem.getPort(),
114   - sendRtpItem.getSsrc());
115   - Map<String, Object> param = new HashMap<>();
116   - param.put("vhost", "__defaultVhost__");
117   - param.put("app", sendRtpItem.getApp());
118   - param.put("stream", sendRtpItem.getStreamId());
119   - param.put("ssrc", sendRtpItem.getSsrc());
120   - param.put("src_port", sendRtpItem.getLocalPort());
121   - param.put("pt", sendRtpItem.getPt());
122   - param.put("use_ps", sendRtpItem.isUsePs() ? "1" : "0");
123   - param.put("only_audio", sendRtpItem.isOnlyAudio() ? "1" : "0");
124   - if (!sendRtpItem.isTcp() && parentPlatform.isRtcp()) {
125   - // 开启rtcp保活
126   - param.put("udp_rtcp_timeout", "1");
127   - }
128   - JSONObject jsonObject;
129   - if (sendRtpItem.isTcpActive()) {
130   - jsonObject = zlmrtpServerFactory.startSendRtpPassive(mediaInfo, param);
131   - } else {
132   - param.put("is_udp", is_Udp);
133   - param.put("dst_url", sendRtpItem.getIp());
134   - param.put("dst_port", sendRtpItem.getPort());
135   - jsonObject = zlmrtpServerFactory.startSendRtpStream(mediaInfo, param);
136   - }
137 132  
138 133 if (jsonObject == null) {
139 134 logger.error("RTP推流失败: 请检查ZLM服务");
... ... @@ -155,12 +150,8 @@ public class AckRequestProcessor extends SIPRequestProcessorParent implements In
155 150 // 语音对讲
156 151 try {
157 152 cmder.streamByeCmd((SIPDialog) evt.getDialog(), sendRtpItem.getChannelId(), (SIPRequest) evt.getRequest(), null);
158   - } catch (SipException e) {
159   - throw new RuntimeException(e);
160   - } catch (ParseException e) {
161   - throw new RuntimeException(e);
162   - } catch (InvalidArgumentException e) {
163   - throw new RuntimeException(e);
  153 + } catch (SipException | ParseException | InvalidArgumentException e) {
  154 + logger.error("[命令发送失败] 停止语音对讲: {}", e.getMessage());
164 155 }
165 156 } else {
166 157 // 向上级平台
... ... @@ -188,12 +179,8 @@ public class AckRequestProcessor extends SIPRequestProcessorParent implements In
188 179 if (jsonObject == null) {
189 180 logger.error("RTP推流失败: 请检查ZLM服务");
190 181 } else if (jsonObject.getInteger("code") == 0) {
  182 + logger.info("调用ZLM推流接口, 结果: {}", jsonObject);
191 183 logger.info("RTP推流成功[ {}/{} ],{}->{}:{}, " ,param.get("app"), param.get("stream"), jsonObject.getString("local_port"), param.get("dst_url"), param.get("dst_port"));
192   - byte[] dialogByteArray = SerializeUtils.serialize(evt.getDialog());
193   - sendRtpItem.setDialog(dialogByteArray);
194   - byte[] transactionByteArray = SerializeUtils.serialize(evt.getServerTransaction());
195   - sendRtpItem.setTransaction(transactionByteArray);
196   - redisCatchStorage.updateSendRTPSever(sendRtpItem);
197 184 } else {
198 185 logger.error("RTP推流失败: {}, 参数:{}",jsonObject.getString("msg"),JSONObject.toJSON(param));
199 186 if (sendRtpItem.isOnlyAudio()) {
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/ByeRequestProcessor.java
... ... @@ -82,77 +82,69 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In
82 82 @Override
83 83 public void process(RequestEvent evt) {
84 84 try {
85   - responseAck(evt, Response.OK);
86   - Dialog dialog = evt.getDialog();
  85 + responseAck(getServerTransaction(evt), Response.OK);
87 86 CallIdHeader callIdHeader = (CallIdHeader)evt.getRequest().getHeader(CallIdHeader.NAME);
88   - if (dialog == null) {
89   - return;
90   - }
91   - if (dialog.getState().equals(DialogState.TERMINATED)) {
92   - String platformGbId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(FromHeader.NAME)).getAddress().getURI()).getUser();
93   - String channelId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(ToHeader.NAME)).getAddress().getURI()).getUser();
94   - SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(platformGbId, null, null, callIdHeader.getCallId());
95   - logger.info("收到bye, [{}/{}]", platformGbId, channelId);
96   - if (sendRtpItem != null ){
97   - String streamId = sendRtpItem.getStreamId();
98   - Map<String, Object> param = new HashMap<>();
99   - param.put("vhost","__defaultVhost__");
100   - param.put("app",sendRtpItem.getApp());
101   - param.put("stream",streamId);
102   - param.put("ssrc",sendRtpItem.getSsrc());
103   - logger.info("收到bye:停止向上级推流:" + streamId);
104   - MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId());
105   - zlmrtpServerFactory.stopSendRtpStream(mediaInfo, param);
106   - redisCatchStorage.deleteSendRTPServer(platformGbId, sendRtpItem.getChannelId(), callIdHeader.getCallId(), null);
107   - redisCatchStorage.deleteSendRTPServer(platformGbId, channelId, callIdHeader.getCallId(), null);
108   - zlmrtpServerFactory.stopSendRtpStream(mediaInfo, param);
109   - int totalReaderCount = zlmrtpServerFactory.totalReaderCount(mediaInfo, sendRtpItem.getApp(), streamId);
110   - if (totalReaderCount <= 0) {
111   - logger.info("收到bye: {} 无其它观看者,通知设备停止推流", streamId);
112   - if (sendRtpItem.getPlayType().equals(InviteStreamType.PLAY)) {
113   - cmder.streamByeCmd(sendRtpItem.getDeviceId(), sendRtpItem.getChannelId(), streamId, null);
114   - }
115   - if (sendRtpItem.isOnlyAudio()) {
116   - playService.stopAudioBroadcast(sendRtpItem.getDeviceId(), sendRtpItem.getChannelId());
117   - }
118   - if (sendRtpItem.getPlayType().equals(InviteStreamType.PUSH)) {
119   - MessageForPushChannel messageForPushChannel = MessageForPushChannel.getInstance(0,
120   - sendRtpItem.getApp(), sendRtpItem.getStreamId(), sendRtpItem.getChannelId(),
121   - sendRtpItem.getPlatformId(), null, null, sendRtpItem.getMediaServerId());
122   - redisCatchStorage.sendStreamPushRequestedMsg(messageForPushChannel);
123   - }
  87 + String platformGbId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(FromHeader.NAME)).getAddress().getURI()).getUser();
  88 + String channelId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(ToHeader.NAME)).getAddress().getURI()).getUser();
  89 + SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(platformGbId, channelId, null, callIdHeader.getCallId());
  90 + logger.info("[收到bye] {}/{}", platformGbId, channelId);
  91 + if (sendRtpItem != null){
  92 + String streamId = sendRtpItem.getStreamId();
  93 + Map<String, Object> param = new HashMap<>();
  94 + param.put("vhost","__defaultVhost__");
  95 + param.put("app",sendRtpItem.getApp());
  96 + param.put("stream",streamId);
  97 + param.put("ssrc",sendRtpItem.getSsrc());
  98 + logger.info("[收到bye] 停止向上级推流:{}", streamId);
  99 + MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId());
  100 + redisCatchStorage.deleteSendRTPServer(platformGbId, channelId, callIdHeader.getCallId(), null);
  101 + zlmrtpServerFactory.stopSendRtpStream(mediaInfo, param);
  102 + int totalReaderCount = zlmrtpServerFactory.totalReaderCount(mediaInfo, sendRtpItem.getApp(), streamId);
  103 + if (totalReaderCount <= 0) {
  104 + logger.info("[收到bye] {} 无其它观看者,通知设备停止推流", streamId);
  105 + if (sendRtpItem.getPlayType().equals(InviteStreamType.PLAY)) {
  106 + cmder.streamByeCmd(sendRtpItem.getDeviceId(), channelId, streamId, null);
124 107 }
125   - }
126   - // 可能是设备主动停止
127   - Device device = storager.queryVideoDeviceByChannelId(platformGbId);
128   - if (device != null) {
129   - storager.stopPlay(device.getDeviceId(), channelId);
130   - StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(device.getDeviceId(), channelId);
131   - if (streamInfo != null) {
132   - redisCatchStorage.stopPlay(streamInfo);
133   - mediaServerService.closeRTPServer(streamInfo.getMediaServerId(), streamInfo.getStream());
  108 + if (sendRtpItem.isOnlyAudio()) {
  109 + playService.stopAudioBroadcast(sendRtpItem.getDeviceId(), sendRtpItem.getChannelId());
134 110 }
135   - SsrcTransaction ssrcTransactionForPlay = streamSession.getSsrcTransaction(device.getDeviceId(), channelId, "play", null);
136   - if (ssrcTransactionForPlay != null){
137   - SIPDialog dialogForPlay = (SIPDialog) SerializeUtils.deSerialize(ssrcTransactionForPlay.getDialog());
138   - if (dialogForPlay.getCallId().getCallId().equals(callIdHeader.getCallId())){
139   - // 释放ssrc
140   - MediaServerItem mediaServerItem = mediaServerService.getOne(ssrcTransactionForPlay.getMediaServerId());
141   - if (mediaServerItem != null) {
142   - mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcTransactionForPlay.getSsrc());
143   - }
144   - streamSession.remove(device.getDeviceId(), channelId, ssrcTransactionForPlay.getStream());
145   - }
  111 + if (sendRtpItem.getPlayType().equals(InviteStreamType.PUSH)) {
  112 + MessageForPushChannel messageForPushChannel = MessageForPushChannel.getInstance(0,
  113 + sendRtpItem.getApp(), sendRtpItem.getStreamId(), sendRtpItem.getChannelId(),
  114 + sendRtpItem.getPlatformId(), null, null, sendRtpItem.getMediaServerId());
  115 + redisCatchStorage.sendStreamPushRequestedMsg(messageForPushChannel);
146 116 }
147   - SsrcTransaction ssrcTransactionForPlayBack = streamSession.getSsrcTransaction(device.getDeviceId(), channelId, callIdHeader.getCallId(), null);
148   - if (ssrcTransactionForPlayBack != null) {
  117 + }
  118 + }
  119 + // 可能是设备主动停止
  120 + Device device = storager.queryVideoDeviceByChannelId(platformGbId);
  121 + if (device != null) {
  122 + storager.stopPlay(device.getDeviceId(), channelId);
  123 + StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(device.getDeviceId(), channelId);
  124 + if (streamInfo != null) {
  125 + redisCatchStorage.stopPlay(streamInfo);
  126 + mediaServerService.closeRTPServer(streamInfo.getMediaServerId(), streamInfo.getStream());
  127 + }
  128 + SsrcTransaction ssrcTransactionForPlay = streamSession.getSsrcTransaction(device.getDeviceId(), channelId, "play", null);
  129 + if (ssrcTransactionForPlay != null){
  130 + SIPDialog dialogForPlay = (SIPDialog) SerializeUtils.deSerialize(ssrcTransactionForPlay.getDialog());
  131 + if (dialogForPlay.getCallId().getCallId().equals(callIdHeader.getCallId())){
149 132 // 释放ssrc
150   - MediaServerItem mediaServerItem = mediaServerService.getOne(ssrcTransactionForPlayBack.getMediaServerId());
  133 + MediaServerItem mediaServerItem = mediaServerService.getOne(ssrcTransactionForPlay.getMediaServerId());
151 134 if (mediaServerItem != null) {
152   - mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcTransactionForPlayBack.getSsrc());
  135 + mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcTransactionForPlay.getSsrc());
153 136 }
154   - streamSession.remove(device.getDeviceId(), channelId, ssrcTransactionForPlayBack.getStream());
  137 + streamSession.remove(device.getDeviceId(), channelId, ssrcTransactionForPlay.getStream());
  138 + }
  139 + }
  140 + SsrcTransaction ssrcTransactionForPlayBack = streamSession.getSsrcTransaction(device.getDeviceId(), channelId, callIdHeader.getCallId(), null);
  141 + if (ssrcTransactionForPlayBack != null) {
  142 + // 释放ssrc
  143 + MediaServerItem mediaServerItem = mediaServerService.getOne(ssrcTransactionForPlayBack.getMediaServerId());
  144 + if (mediaServerItem != null) {
  145 + mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcTransactionForPlayBack.getSsrc());
155 146 }
  147 + streamSession.remove(device.getDeviceId(), channelId, ssrcTransactionForPlayBack.getStream());
156 148 }
157 149 }
158 150 } catch (SipException e) {
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java
... ... @@ -14,7 +14,6 @@ import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver;
14 14 import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
15 15 import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
16 16 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
17   -import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
18 17 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform;
19 18 import com.genersoft.iot.vmp.gb28181.transmit.event.request.ISIPRequestProcessor;
20 19 import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
... ... @@ -32,7 +31,8 @@ import com.genersoft.iot.vmp.service.IStreamPushService;
32 31 import com.genersoft.iot.vmp.service.bean.MessageForPushChannel;
33 32 import com.genersoft.iot.vmp.service.bean.SSRCInfo;
34 33 import com.genersoft.iot.vmp.service.impl.RedisGbPlayMsgListener;
35   -import com.genersoft.iot.vmp.service.impl.RedisPushStreamResponseListener;
  34 +import com.genersoft.iot.vmp.service.redisMsg.RedisGbPlayMsgListener;
  35 +import com.genersoft.iot.vmp.service.redisMsg.RedisPushStreamResponseListener;
36 36 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
37 37 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
38 38 import com.genersoft.iot.vmp.utils.DateUtil;
... ... @@ -43,6 +43,8 @@ import gov.nist.javax.sdp.TimeDescriptionImpl;
43 43 import gov.nist.javax.sdp.fields.TimeField;
44 44 import gov.nist.javax.sip.message.SIPRequest;
45 45 import gov.nist.javax.sip.stack.SIPDialog;
  46 +import gov.nist.javax.sip.message.SIPRequest;
  47 +import gov.nist.javax.sip.message.SIPResponse;
46 48 import org.slf4j.Logger;
47 49 import org.slf4j.LoggerFactory;
48 50 import org.springframework.beans.factory.InitializingBean;
... ... @@ -160,17 +162,19 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
160 162 String channelId = SipUtils.getChannelIdFromRequest(request);
161 163 String requesterId = SipUtils.getUserIdFromFromHeader(request);
162 164 CallIdHeader callIdHeader = (CallIdHeader) request.getHeader(CallIdHeader.NAME);
  165 + ServerTransaction serverTransaction = getServerTransaction(evt);
163 166 if (requesterId == null || channelId == null) {
164 167 logger.info("无法从FromHeader的Address中获取到平台id,返回400");
165 168 // 参数不全, 发400,请求错误
166   - responseAck(evt, Response.BAD_REQUEST);
  169 + responseAck(serverTransaction, Response.BAD_REQUEST);
167 170 return;
168 171 }
169 172  
  173 +
170 174 // 查询请求是否来自上级平台\设备
171 175 ParentPlatform platform = storager.queryParentPlatByServerGBId(requesterId);
172 176 if (platform == null) {
173   - inviteFromDeviceHandle(evt, requesterId, channelId);
  177 + inviteFromDeviceHandle(serverTransaction, requesterId);
174 178 } else {
175 179 // 查询平台下是否有该通道
176 180 DeviceChannel channel = storager.queryChannelInParentPlatform(requesterId, channelId);
... ... @@ -182,12 +186,13 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
182 186 StreamProxyItem proxyByAppAndStream =null;
183 187 // 不是通道可能是直播流
184 188 if (channel != null && gbStream == null) {
185   - if (channel.getStatus() == 0) {
186   - logger.info("通道离线,返回400");
187   - responseAck(evt, Response.BAD_REQUEST, "channel [" + channel.getChannelId() + "] offline");
188   - return;
189   - }
190   - responseAck(evt, Response.CALL_IS_BEING_FORWARDED); // 通道存在,发181,呼叫转接中
  189 +// if (channel.getStatus() == 0) {
  190 +// logger.info("通道离线,返回400");
  191 +// responseAck(serverTransaction, Response.BAD_REQUEST, "channel [" + channel.getChannelId() + "] offline");
  192 +// return;
  193 +// }
  194 + // 通道存在,发100,TRYING
  195 + responseAck(serverTransaction, Response.TRYING);
191 196 } else if (channel == null && gbStream != null) {
192 197  
193 198 String mediaServerId = gbStream.getMediaServerId();
... ... @@ -195,13 +200,13 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
195 200 if (mediaServerItem == null) {
196 201 if ("proxy".equals(gbStream.getStreamType())) {
197 202 logger.info("[ app={}, stream={} ]找不到zlm {},返回410", gbStream.getApp(), gbStream.getStream(), mediaServerId);
198   - responseAck(evt, Response.GONE);
  203 + responseAck(serverTransaction, Response.GONE);
199 204 return;
200 205 } else {
201 206 streamPushItem = streamPushService.getPush(gbStream.getApp(), gbStream.getStream());
202 207 if (streamPushItem == null || streamPushItem.getServerId().equals(userSetting.getServerId())) {
203 208 logger.info("[ app={}, stream={} ]找不到zlm {},返回410", gbStream.getApp(), gbStream.getStream(), mediaServerId);
204   - responseAck(evt, Response.GONE);
  209 + responseAck(serverTransaction, Response.GONE);
205 210 return;
206 211 }
207 212 }
... ... @@ -210,25 +215,25 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
210 215 streamPushItem = streamPushService.getPush(gbStream.getApp(), gbStream.getStream());
211 216 if (streamPushItem == null) {
212 217 logger.info("[ app={}, stream={} ]找不到zlm {},返回410", gbStream.getApp(), gbStream.getStream(), mediaServerId);
213   - responseAck(evt, Response.GONE);
  218 + responseAck(serverTransaction, Response.GONE);
214 219 return;
215 220 }
216 221 }else if("proxy".equals(gbStream.getStreamType())){
217 222 proxyByAppAndStream = streamProxyService.getStreamProxyByAppAndStream(gbStream.getApp(), gbStream.getStream());
218 223 if (proxyByAppAndStream == null) {
219 224 logger.info("[ app={}, stream={} ]找不到zlm {},返回410", gbStream.getApp(), gbStream.getStream(), mediaServerId);
220   - responseAck(evt, Response.GONE);
  225 + responseAck(serverTransaction, Response.GONE);
221 226 return;
222 227 }
223 228 }
224 229 }
225   - responseAck(evt, Response.CALL_IS_BEING_FORWARDED); // 通道存在,发181,呼叫转接中
  230 + responseAck(serverTransaction, Response.CALL_IS_BEING_FORWARDED); // 通道存在,发181,呼叫转接中
226 231 } else if (catalog != null) {
227   - responseAck(evt, Response.BAD_REQUEST, "catalog channel can not play"); // 目录不支持点播
  232 + responseAck(serverTransaction, Response.BAD_REQUEST, "catalog channel can not play"); // 目录不支持点播
228 233 return;
229 234 } else {
230 235 logger.info("通道不存在,返回404");
231   - responseAck(evt, Response.NOT_FOUND); // 通道不存在,发404,资源不存在
  236 + responseAck(serverTransaction, Response.NOT_FOUND); // 通道不存在,发404,资源不存在
232 237 return;
233 238 }
234 239 // 解析sdp消息, 使用jainsip 自带的sdp解析方式
... ... @@ -241,7 +246,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
241 246 String ssrc;
242 247 SessionDescription sdp;
243 248 if (ssrcIndex >= 0) {
244   - //ssrc规定长度为10字节,不取余下长度以避免后续还有“f=”字段
  249 + //ssrc规定长度为10字节,不取余下长度以避免后续还有“f=”字段
245 250 ssrc = contentString.substring(ssrcIndex + 2, ssrcIndex + 12);
246 251 String substring = contentString.substring(0, contentString.indexOf("y="));
247 252 sdp = SdpFactory.getInstance().createSessionDescription(substring);
... ... @@ -288,9 +293,6 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
288 293 mediaTransmissionTCP = true;
289 294 if ("active".equalsIgnoreCase(setup)) {
290 295 tcpActive = true;
291   - // 不支持tcp主动
292   - responseAck(evt, Response.NOT_IMPLEMENTED, "tcp active not support"); // 目录不支持点播
293   - return;
294 296 } else if ("passive".equalsIgnoreCase(setup)) {
295 297 tcpActive = false;
296 298 }
... ... @@ -302,7 +304,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
302 304 if (port == -1) {
303 305 logger.info("不支持的媒体格式,返回415");
304 306 // 回复不支持的格式
305   - responseAck(evt, Response.UNSUPPORTED_MEDIA_TYPE); // 不支持的格式,发415
  307 + responseAck(serverTransaction, Response.UNSUPPORTED_MEDIA_TYPE); // 不支持的格式,发415
306 308 return;
307 309 }
308 310 String username = sdp.getOrigin().getUsername();
... ... @@ -315,24 +317,25 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
315 317 device = storager.queryVideoDeviceByPlatformIdAndChannelId(requesterId, channelId);
316 318 if (device == null) {
317 319 logger.warn("点播平台{}的通道{}时未找到设备信息", requesterId, channel);
318   - responseAck(evt, Response.SERVER_INTERNAL_ERROR);
  320 + responseAck(serverTransaction, Response.SERVER_INTERNAL_ERROR);
319 321 return;
320 322 }
321 323 mediaServerItem = playService.getNewMediaServerItem(device);
322 324 if (mediaServerItem == null) {
323 325 logger.warn("未找到可用的zlm");
324   - responseAck(evt, Response.BUSY_HERE);
  326 + responseAck(serverTransaction, Response.BUSY_HERE);
325 327 return;
326 328 }
327 329 SendRtpItem sendRtpItem = zlmrtpServerFactory.createSendRtpItem(mediaServerItem, addressStr, port, ssrc, requesterId,
328 330 device.getDeviceId(), channelId,
329 331 mediaTransmissionTCP);
  332 +
330 333 if (tcpActive != null) {
331 334 sendRtpItem.setTcpActive(tcpActive);
332 335 }
333 336 if (sendRtpItem == null) {
334 337 logger.warn("服务器端口资源不足");
335   - responseAck(evt, Response.BUSY_HERE);
  338 + responseAck(serverTransaction, Response.BUSY_HERE);
336 339 return;
337 340 }
338 341 sendRtpItem.setCallId(callIdHeader.getCallId());
... ... @@ -374,7 +377,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
374 377 // 回复bye
375 378 cmderFroPlatform.streamByeCmd(platform, callIdHeader.getCallId());
376 379 }, 60 * 1000);
377   - responseSdpAck(evt, content.toString(), platform);
  380 + responseSdpAck(serverTransaction, content.toString(), platform);
378 381  
379 382 } catch (SipException e) {
380 383 e.printStackTrace();
... ... @@ -389,8 +392,8 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
389 392 Response response = null;
390 393 try {
391 394 response = getMessageFactory().createResponse(event.statusCode, evt.getRequest());
392   - ServerTransaction serverTransaction = getServerTransaction(evt);
393 395 serverTransaction.sendResponse(response);
  396 + System.out.println("未知错误。直接转发设备点播的错误");
394 397 if (serverTransaction.getDialog() != null) {
395 398 serverTransaction.getDialog().delete();
396 399 }
... ... @@ -414,7 +417,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
414 417 }
415 418 redisCatchStorage.deleteSendRTPServer(platform.getServerGBId(), channelId, callIdHeader.getCallId(), null);
416 419 try {
417   - responseAck(evt, Response.REQUEST_TIMEOUT);
  420 + responseAck(serverTransaction, Response.REQUEST_TIMEOUT);
418 421 } catch (SipException e) {
419 422 e.printStackTrace();
420 423 } catch (InvalidArgumentException e) {
... ... @@ -452,6 +455,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
452 455 SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId, null, device.isSsrcCheck(), false);
453 456 logger.info(JSONObject.toJSONString(ssrcInfo));
454 457 sendRtpItem.setStreamId(ssrcInfo.getStream());
  458 +
455 459 // 写入redis, 超时时回复
456 460 redisCatchStorage.updateSendRTPSever(sendRtpItem);
457 461 playService.play(mediaServerItem, ssrcInfo, device, channelId, hookEvent, errorEvent, (code, msg) -> {
... ... @@ -472,26 +476,26 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
472 476 if("push".equals(gbStream.getStreamType())) {
473 477 if (streamPushItem != null && streamPushItem.isPushIng()) {
474 478 // 推流状态
475   - pushStream(evt, gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive,
  479 + pushStream(evt, serverTransaction, gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive,
476 480 mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId);
477 481 } else {
478 482 // 未推流 拉起
479   - notifyStreamOnline(evt, gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive,
  483 + notifyStreamOnline(evt, serverTransaction,gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive,
480 484 mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId);
481 485 }
482 486 }else if ("proxy".equals(gbStream.getStreamType())){
483 487 if(null != proxyByAppAndStream &&proxyByAppAndStream.isStatus()){
484   - pushProxyStream(evt, gbStream, platform, callIdHeader, mediaServerItem, port, tcpActive,
  488 + pushProxyStream(evt, serverTransaction, gbStream, platform, callIdHeader, mediaServerItem, port, tcpActive,
485 489 mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId);
486 490 }else{
487 491 //开启代理拉流
488 492 boolean start1 = streamProxyService.start(gbStream.getApp(), gbStream.getStream());
489 493 if(start1) {
490   - pushProxyStream(evt, gbStream, platform, callIdHeader, mediaServerItem, port, tcpActive,
  494 + pushProxyStream(evt, serverTransaction, gbStream, platform, callIdHeader, mediaServerItem, port, tcpActive,
491 495 mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId);
492 496 }else{
493 497 //失败后通知
494   - notifyStreamOnline(evt, gbStream, null, platform, callIdHeader, mediaServerItem, port, tcpActive,
  498 + notifyStreamOnline(evt, serverTransaction,gbStream, null, platform, callIdHeader, mediaServerItem, port, tcpActive,
495 499 mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId);
496 500 }
497 501 }
... ... @@ -514,7 +518,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
514 518 /**
515 519 * 安排推流
516 520 */
517   - private void pushProxyStream(RequestEvent evt, GbStream gbStream, ParentPlatform platform,
  521 + private void pushProxyStream(RequestEvent evt, ServerTransaction serverTransaction, GbStream gbStream, ParentPlatform platform,
518 522 CallIdHeader callIdHeader, MediaServerItem mediaServerItem,
519 523 int port, Boolean tcpActive, boolean mediaTransmissionTCP,
520 524 String channelId, String addressStr, String ssrc, String requesterId) throws InvalidArgumentException, ParseException, SipException {
... ... @@ -527,7 +531,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
527 531  
528 532 if (sendRtpItem == null) {
529 533 logger.warn("服务器端口资源不足");
530   - responseAck(evt, Response.BUSY_HERE);
  534 + responseAck(serverTransaction, Response.BUSY_HERE);
531 535 return;
532 536 }
533 537 if (tcpActive != null) {
... ... @@ -537,17 +541,19 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
537 541 // 写入redis, 超时时回复
538 542 sendRtpItem.setStatus(1);
539 543 sendRtpItem.setCallId(callIdHeader.getCallId());
540   - byte[] dialogByteArray = SerializeUtils.serialize(evt.getDialog());
541   - sendRtpItem.setDialog(dialogByteArray);
542   - byte[] transactionByteArray = SerializeUtils.serialize(evt.getServerTransaction());
543   - sendRtpItem.setTransaction(transactionByteArray);
  544 + SIPRequest request = (SIPRequest) evt.getRequest();
  545 + sendRtpItem.setFromTag(request.getFromTag());
  546 +
  547 + SIPResponse response = sendStreamAck(mediaServerItem, serverTransaction, sendRtpItem, platform, evt);
  548 + if (response != null) {
  549 + sendRtpItem.setToTag(response.getToTag());
  550 + }
544 551 redisCatchStorage.updateSendRTPSever(sendRtpItem);
545   - sendStreamAck(mediaServerItem, sendRtpItem, platform, evt);
546 552  
547 553 }
548 554  
549 555 }
550   - private void pushStream(RequestEvent evt, GbStream gbStream, StreamPushItem streamPushItem, ParentPlatform platform,
  556 + private void pushStream(RequestEvent evt, ServerTransaction serverTransaction, GbStream gbStream, StreamPushItem streamPushItem, ParentPlatform platform,
551 557 CallIdHeader callIdHeader, MediaServerItem mediaServerItem,
552 558 int port, Boolean tcpActive, boolean mediaTransmissionTCP,
553 559 String channelId, String addressStr, String ssrc, String requesterId) throws InvalidArgumentException, ParseException, SipException {
... ... @@ -562,7 +568,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
562 568  
563 569 if (sendRtpItem == null) {
564 570 logger.warn("服务器端口资源不足");
565   - responseAck(evt, Response.BUSY_HERE);
  571 + responseAck(serverTransaction, Response.BUSY_HERE);
566 572 return;
567 573 }
568 574 if (tcpActive != null) {
... ... @@ -572,39 +578,43 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
572 578 // 写入redis, 超时时回复
573 579 sendRtpItem.setStatus(1);
574 580 sendRtpItem.setCallId(callIdHeader.getCallId());
575   - byte[] dialogByteArray = SerializeUtils.serialize(evt.getDialog());
576   - sendRtpItem.setDialog(dialogByteArray);
577   - byte[] transactionByteArray = SerializeUtils.serialize(evt.getServerTransaction());
578   - sendRtpItem.setTransaction(transactionByteArray);
  581 +
  582 + SIPRequest request = (SIPRequest) evt.getRequest();
  583 + sendRtpItem.setFromTag(request.getFromTag());
  584 + SIPResponse response = sendStreamAck(mediaServerItem, serverTransaction, sendRtpItem, platform, evt);
  585 + if (response != null) {
  586 + sendRtpItem.setToTag(response.getToTag());
  587 + }
  588 +
579 589 redisCatchStorage.updateSendRTPSever(sendRtpItem);
580   - sendStreamAck(mediaServerItem, sendRtpItem, platform, evt);
  590 +
581 591 } else {
582 592 // 不在线 拉起
583   - notifyStreamOnline(evt, gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive,
  593 + notifyStreamOnline(evt, serverTransaction,gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive,
584 594 mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId);
585 595 }
586 596  
587 597 } else {
588 598 // 其他平台内容
589   - otherWvpPushStream(evt, gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive,
  599 + otherWvpPushStream(evt, serverTransaction, gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive,
590 600 mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId);
591 601 }
592 602 }
593 603 /**
594 604 * 通知流上线
595 605 */
596   - private void notifyStreamOnline(RequestEvent evt, GbStream gbStream, StreamPushItem streamPushItem, ParentPlatform platform,
  606 + private void notifyStreamOnline(RequestEvent evt, ServerTransaction serverTransaction, GbStream gbStream, StreamPushItem streamPushItem, ParentPlatform platform,
597 607 CallIdHeader callIdHeader, MediaServerItem mediaServerItem,
598 608 int port, Boolean tcpActive, boolean mediaTransmissionTCP,
599 609 String channelId, String addressStr, String ssrc, String requesterId) throws InvalidArgumentException, ParseException, SipException {
600 610 if ("proxy".equals(gbStream.getStreamType())) {
601 611 // TODO 控制启用以使设备上线
602 612 logger.info("[ app={}, stream={} ]通道未推流,启用流后开始推流", gbStream.getApp(), gbStream.getStream());
603   - responseAck(evt, Response.BAD_REQUEST, "channel [" + gbStream.getGbId() + "] offline");
  613 + responseAck(serverTransaction, Response.BAD_REQUEST, "channel [" + gbStream.getGbId() + "] offline");
604 614 } else if ("push".equals(gbStream.getStreamType())) {
605 615 if (!platform.isStartOfflinePush()) {
606 616 // 平台设置中关闭了拉起离线的推流则直接回复
607   - responseAck(evt, Response.TEMPORARILY_UNAVAILABLE, "channel stream not pushing");
  617 + responseAck(serverTransaction, Response.TEMPORARILY_UNAVAILABLE, "channel stream not pushing");
608 618 return;
609 619 }
610 620 // 发送redis消息以使设备上线
... ... @@ -619,7 +629,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
619 629 logger.info("[ app={}, stream={} ] 等待设备开始推流超时", gbStream.getApp(), gbStream.getStream());
620 630 try {
621 631 mediaListManager.removedChannelOnlineEventLister(gbStream.getApp(), gbStream.getStream());
622   - responseAck(evt, Response.REQUEST_TIMEOUT); // 超时
  632 + responseAck(serverTransaction, Response.REQUEST_TIMEOUT); // 超时
623 633 } catch (SipException e) {
624 634 e.printStackTrace();
625 635 } catch (InvalidArgumentException e) {
... ... @@ -642,7 +652,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
642 652 if (sendRtpItem == null) {
643 653 logger.warn("上级点时创建sendRTPItem失败,可能是服务器端口资源不足");
644 654 try {
645   - responseAck(evt, Response.BUSY_HERE);
  655 + responseAck(serverTransaction, Response.BUSY_HERE);
646 656 } catch (SipException e) {
647 657 e.printStackTrace();
648 658 } catch (InvalidArgumentException e) {
... ... @@ -659,15 +669,17 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
659 669 // 写入redis, 超时时回复
660 670 sendRtpItem.setStatus(1);
661 671 sendRtpItem.setCallId(callIdHeader.getCallId());
662   - byte[] dialogByteArray = SerializeUtils.serialize(evt.getDialog());
663   - sendRtpItem.setDialog(dialogByteArray);
664   - byte[] transactionByteArray = SerializeUtils.serialize(evt.getServerTransaction());
665   - sendRtpItem.setTransaction(transactionByteArray);
  672 +
  673 + SIPRequest request = (SIPRequest) evt.getRequest();
  674 + sendRtpItem.setFromTag(request.getFromTag());
  675 + SIPResponse response = sendStreamAck(mediaServerItem, serverTransaction, sendRtpItem, platform, evt);
  676 + if (response != null) {
  677 + sendRtpItem.setToTag(response.getToTag());
  678 + }
666 679 redisCatchStorage.updateSendRTPSever(sendRtpItem);
667   - sendStreamAck(mediaServerItem, sendRtpItem, platform, evt);
668 680 } else {
669 681 // 其他平台内容
670   - otherWvpPushStream(evt, gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive,
  682 + otherWvpPushStream(evt, serverTransaction, gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive,
671 683 mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId);
672 684 }
673 685 });
... ... @@ -678,7 +690,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
678 690 dynamicTask.stop(callIdHeader.getCallId());
679 691 mediaListManager.removedChannelOnlineEventLister(gbStream.getApp(), gbStream.getStream());
680 692 try {
681   - responseAck(evt, Response.TEMPORARILY_UNAVAILABLE, response.getMsg());
  693 + responseAck(serverTransaction, Response.TEMPORARILY_UNAVAILABLE, response.getMsg());
682 694 } catch (SipException e) {
683 695 throw new RuntimeException(e);
684 696 } catch (InvalidArgumentException e) {
... ... @@ -694,7 +706,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
694 706 /**
695 707 * 来自其他wvp的推流
696 708 */
697   - private void otherWvpPushStream(RequestEvent evt, GbStream gbStream, StreamPushItem streamPushItem, ParentPlatform platform,
  709 + private void otherWvpPushStream(RequestEvent evt, ServerTransaction serverTransaction, GbStream gbStream, StreamPushItem streamPushItem, ParentPlatform platform,
698 710 CallIdHeader callIdHeader, MediaServerItem mediaServerItem,
699 711 int port, Boolean tcpActive, boolean mediaTransmissionTCP,
700 712 String channelId, String addressStr, String ssrc, String requesterId) {
... ... @@ -707,7 +719,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
707 719 if (sendRtpItem == null || responseSendItemMsg.getMediaServerItem() == null) {
708 720 logger.warn("服务器端口资源不足");
709 721 try {
710   - responseAck(evt, Response.BUSY_HERE);
  722 + responseAck(serverTransaction, Response.BUSY_HERE);
711 723 } catch (SipException e) {
712 724 e.printStackTrace();
713 725 } catch (InvalidArgumentException e) {
... ... @@ -725,12 +737,14 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
725 737 // 写入redis, 超时时回复
726 738 sendRtpItem.setStatus(1);
727 739 sendRtpItem.setCallId(callIdHeader.getCallId());
728   - byte[] dialogByteArray = SerializeUtils.serialize(evt.getDialog());
729   - sendRtpItem.setDialog(dialogByteArray);
730   - byte[] transactionByteArray = SerializeUtils.serialize(evt.getServerTransaction());
731   - sendRtpItem.setTransaction(transactionByteArray);
  740 +
  741 + SIPRequest request = (SIPRequest) evt.getRequest();
  742 + sendRtpItem.setFromTag(request.getFromTag());
  743 + SIPResponse response = sendStreamAck(responseSendItemMsg.getMediaServerItem(), serverTransaction,sendRtpItem, platform, evt);
  744 + if (response != null) {
  745 + sendRtpItem.setToTag(response.getToTag());
  746 + }
732 747 redisCatchStorage.updateSendRTPSever(sendRtpItem);
733   - sendStreamAck(responseSendItemMsg.getMediaServerItem(), sendRtpItem, platform, evt);
734 748 }, (wvpResult) -> {
735 749 try {
736 750 // 错误
... ... @@ -740,12 +754,12 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
740 754 StreamPushItem currentStreamPushItem = streamPushService.getPush(streamPushItem.getApp(), streamPushItem.getStream());
741 755 if (currentStreamPushItem.isPushIng()) {
742 756 // 在线状态
743   - pushStream(evt, gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive,
  757 + pushStream(evt, serverTransaction, gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive,
744 758 mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId);
745 759  
746 760 } else {
747 761 // 不在线 拉起
748   - notifyStreamOnline(evt, gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive,
  762 + notifyStreamOnline(evt, serverTransaction, gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive,
749 763 mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId);
750 764 }
751 765 }
... ... @@ -759,7 +773,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
759 773  
760 774  
761 775 try {
762   - responseAck(evt, Response.BUSY_HERE);
  776 + responseAck(serverTransaction, Response.BUSY_HERE);
763 777 } catch (SipException e) {
764 778 e.printStackTrace();
765 779 } catch (InvalidArgumentException e) {
... ... @@ -771,7 +785,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
771 785 });
772 786 }
773 787  
774   - public void sendStreamAck(MediaServerItem mediaServerItem, SendRtpItem sendRtpItem, ParentPlatform platform, RequestEvent evt) {
  788 + public SIPResponse sendStreamAck(MediaServerItem mediaServerItem, ServerTransaction serverTransaction, SendRtpItem sendRtpItem, ParentPlatform platform, RequestEvent evt) {
775 789  
776 790 StringBuffer content = new StringBuffer(200);
777 791 content.append("v=0\r\n");
... ... @@ -794,7 +808,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
794 808 content.append("f=\r\n");
795 809  
796 810 try {
797   - responseSdpAck(evt, content.toString(), platform);
  811 + return responseSdpAck(serverTransaction, content.toString(), platform);
798 812 } catch (SipException e) {
799 813 e.printStackTrace();
800 814 } catch (InvalidArgumentException e) {
... ... @@ -802,24 +816,25 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
802 816 } catch (ParseException e) {
803 817 e.printStackTrace();
804 818 }
  819 + return null;
805 820 }
806 821  
807   - public void inviteFromDeviceHandle(RequestEvent evt, String requesterId, String channelId) throws InvalidArgumentException, ParseException, SipException, SdpException {
  822 + public void inviteFromDeviceHandle(ServerTransaction serverTransaction, String requesterId, String channelId) throws InvalidArgumentException, ParseException, SipException, SdpException {
808 823  
809 824 // 非上级平台请求,查询是否设备请求(通常为接收语音广播的设备)
810 825 Device device = redisCatchStorage.getDevice(requesterId);
811 826 AudioBroadcastCatch audioBroadcastCatch = audioBroadcastManager.get(requesterId, channelId);
812 827 if (audioBroadcastCatch == null) {
813 828 logger.warn("来自设备的Invite请求非语音广播,已忽略,requesterId: {}/{}", requesterId, channelId);
814   - responseAck(evt, Response.FORBIDDEN);
  829 + responseAck(serverTransaction, Response.FORBIDDEN);
815 830 return;
816 831 }
817   - Request request = evt.getRequest();
  832 + Request request = serverTransaction.getRequest();
818 833 if (device != null) {
819 834 logger.info("收到设备" + requesterId + "的语音广播Invite请求");
820   - responseAck(evt, Response.TRYING);
  835 + responseAck(serverTransaction, Response.TRYING);
821 836  
822   - String contentString = new String(request.getRawContent());
  837 + String contentString = new String(serverTransaction.getRequest().getRawContent());
823 838 // jainSip不支持y=字段, 移除移除以解析。
824 839 String substring = contentString;
825 840 String ssrc = "0000000404";
... ... @@ -867,7 +882,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
867 882 if (port == -1) {
868 883 logger.info("不支持的媒体格式,返回415");
869 884 // 回复不支持的格式
870   - responseAck(evt, Response.UNSUPPORTED_MEDIA_TYPE); // 不支持的格式,发415
  885 + responseAck(serverTransaction, Response.UNSUPPORTED_MEDIA_TYPE); // 不支持的格式,发415
871 886 return;
872 887 }
873 888 String addressStr = sdp.getOrigin().getAddress();
... ... @@ -876,7 +891,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
876 891 MediaServerItem mediaServerItem = playService.getNewMediaServerItem(device);
877 892 if (mediaServerItem == null) {
878 893 logger.warn("未找到可用的zlm");
879   - responseAck(evt, Response.BUSY_HERE);
  894 + responseAck(serverTransaction, Response.BUSY_HERE);
880 895 return;
881 896 }
882 897 SendRtpItem sendRtpItem = zlmrtpServerFactory.createSendRtpItem(mediaServerItem, addressStr, port, ssrc, requesterId,
... ... @@ -884,7 +899,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
884 899 mediaTransmissionTCP);
885 900 if (sendRtpItem == null) {
886 901 logger.warn("服务器端口资源不足");
887   - responseAck(evt, Response.BUSY_HERE);
  902 + responseAck(serverTransaction, Response.BUSY_HERE);
888 903 return;
889 904 }
890 905 sendRtpItem.setTcp(mediaTransmissionTCP);
... ... @@ -998,19 +1013,13 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
998 1013 parentPlatform.setServerPort(device.getPort());
999 1014 parentPlatform.setServerGBId(device.getDeviceId());
1000 1015  
1001   - responseSdpAck(evt, content.toString(), parentPlatform);
  1016 + responseSdpAck(serverTransaction, content.toString(), parentPlatform);
1002 1017 Dialog dialog = evt.getDialog();
1003 1018 audioBroadcastCatch.setDialog((SIPDialog) dialog);
1004 1019 audioBroadcastCatch.setRequest((SIPRequest) request);
1005 1020 audioBroadcastManager.update(audioBroadcastCatch);
1006   - } catch (SipException e) {
1007   - throw new RuntimeException(e);
1008   - } catch (InvalidArgumentException e) {
1009   - throw new RuntimeException(e);
1010   - } catch (ParseException e) {
1011   - throw new RuntimeException(e);
1012   - } catch (SdpParseException e) {
1013   - throw new RuntimeException(e);
  1021 + } catch (SipException | InvalidArgumentException | ParseException | SdpParseException e) {
  1022 + logger.error("[命令发送失败] 语音对讲: {}", e.getMessage());
1014 1023 }
1015 1024 });
1016 1025 // }
... ... @@ -1030,7 +1039,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
1030 1039 resultHolder.invokeAllResult(requestMessage);
1031 1040 } else {
1032 1041 logger.warn("来自无效设备/平台的请求");
1033   - responseAck(evt, Response.BAD_REQUEST);
  1042 + responseAck(serverTransaction, Response.BAD_REQUEST);
1034 1043 }
1035 1044 }
1036 1045 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/NotifyRequestProcessor.java
... ... @@ -34,6 +34,7 @@ import org.springframework.util.StringUtils;
34 34  
35 35 import javax.sip.InvalidArgumentException;
36 36 import javax.sip.RequestEvent;
  37 +import javax.sip.ServerTransaction;
37 38 import javax.sip.SipException;
38 39 import javax.sip.header.FromHeader;
39 40 import javax.sip.message.Response;
... ... @@ -78,7 +79,7 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements
78 79  
79 80 private boolean taskQueueHandlerRun = false;
80 81  
81   - private final ConcurrentLinkedQueue<HandlerCatchData> taskQueue = new ConcurrentLinkedQueue<>();
  82 + private ConcurrentLinkedQueue<HandlerCatchData> taskQueue = new ConcurrentLinkedQueue<>();
82 83  
83 84 @Qualifier("taskExecutor")
84 85 @Autowired
... ... @@ -94,7 +95,8 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements
94 95 public void process(RequestEvent evt) {
95 96 try {
96 97 taskQueue.offer(new HandlerCatchData(evt, null, null));
97   - responseAck(evt, Response.OK);
  98 + ServerTransaction serverTransaction = getServerTransaction(evt);
  99 + responseAck(serverTransaction, Response.OK);
98 100 if (!taskQueueHandlerRun) {
99 101 taskQueueHandlerRun = true;
100 102 taskExecutor.execute(()-> {
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/SubscribeRequestProcessor.java
... ... @@ -17,6 +17,12 @@ import com.genersoft.iot.vmp.gb28181.utils.XmlUtil;
17 17 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
18 18 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
19 19 import gov.nist.javax.sip.SipProviderImpl;
  20 +import gov.nist.javax.sip.message.SIPRequest;
  21 +import gov.nist.javax.sip.message.SIPResponse;
  22 +import gov.nist.javax.sip.stack.SIPClientTransaction;
  23 +import gov.nist.javax.sip.stack.SIPDialog;
  24 +import gov.nist.javax.sip.stack.SIPServerTransaction;
  25 +import gov.nist.javax.sip.stack.SIPServerTransactionImpl;
20 26 import org.dom4j.DocumentException;
21 27 import org.dom4j.Element;
22 28 import org.slf4j.Logger;
... ... @@ -49,22 +55,6 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme
49 55 @Autowired
50 56 private IVideoManagerStorage storager;
51 57  
52   - @Lazy
53   - @Autowired
54   - @Qualifier(value="tcpSipProvider")
55   - private SipProviderImpl tcpSipProvider;
56   -
57   - @Lazy
58   - @Autowired
59   - @Qualifier(value="udpSipProvider")
60   - private SipProviderImpl udpSipProvider;
61   -
62   - @Autowired
63   - private DynamicTask dynamicTask;
64   -
65   - @Autowired
66   - private UserSetting userSetting;
67   -
68 58 @Autowired
69 59 private SubscribeHolder subscribeHolder;
70 60  
... ... @@ -81,6 +71,7 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme
81 71 */
82 72 @Override
83 73 public void process(RequestEvent evt) {
  74 + ServerTransaction serverTransaction = getServerTransaction(evt);
84 75 Request request = evt.getRequest();
85 76 try {
86 77 Element rootElement = getRootElement(evt);
... ... @@ -90,12 +81,12 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme
90 81 }
91 82 String cmd = XmlUtil.getText(rootElement, "CmdType");
92 83 if (CmdType.MOBILE_POSITION.equals(cmd)) {
93   - processNotifyMobilePosition(evt, rootElement);
  84 + processNotifyMobilePosition(serverTransaction, rootElement);
94 85 // } else if (CmdType.ALARM.equals(cmd)) {
95 86 // logger.info("接收到Alarm订阅");
96   -// processNotifyAlarm(evt, rootElement);
  87 +// processNotifyAlarm(serverTransaction, rootElement);
97 88 } else if (CmdType.CATALOG.equals(cmd)) {
98   - processNotifyCatalogList(evt, rootElement);
  89 + processNotifyCatalogList(serverTransaction, rootElement);
99 90 } else {
100 91 logger.info("接收到消息:" + cmd);
101 92  
... ... @@ -108,7 +99,6 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme
108 99 ServerTransaction transaction = getServerTransaction(evt);
109 100 if (transaction != null) {
110 101 transaction.sendResponse(response);
111   - transaction.getDialog().delete();
112 102 transaction.terminate();
113 103 } else {
114 104 logger.info("processRequest serverTransactionId is null.");
... ... @@ -123,24 +113,20 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme
123 113 /**
124 114 * 处理移动位置订阅消息
125 115 */
126   - private void processNotifyMobilePosition(RequestEvent evt, Element rootElement) throws SipException {
127   - String platformId = SipUtils.getUserIdFromFromHeader(evt.getRequest());
  116 + private void processNotifyMobilePosition(ServerTransaction serverTransaction, Element rootElement) throws SipException {
  117 + if (serverTransaction == null) {
  118 + return;
  119 + }
  120 + String platformId = SipUtils.getUserIdFromFromHeader(serverTransaction.getRequest());
128 121 String deviceId = XmlUtil.getText(rootElement, "DeviceID");
129 122 ParentPlatform platform = storager.queryParentPlatByServerGBId(platformId);
130   - SubscribeInfo subscribeInfo = new SubscribeInfo(evt, platformId);
  123 + SubscribeInfo subscribeInfo = new SubscribeInfo(serverTransaction, platformId);
131 124 if (platform == null) {
132 125 return;
133 126 }
134   - if (evt.getServerTransaction() == null) {
135   - ServerTransaction serverTransaction = "TCP".equalsIgnoreCase(platform.getTransport()) ? tcpSipProvider.getNewServerTransaction(evt.getRequest())
136   - : udpSipProvider.getNewServerTransaction(evt.getRequest());
137   - subscribeInfo.setTransaction(serverTransaction);
138   - Dialog dialog = serverTransaction.getDialog();
139   - dialog.terminateOnBye(false);
140   - subscribeInfo.setDialog(dialog);
141   - }
  127 +
142 128 String sn = XmlUtil.getText(rootElement, "SN");
143   - logger.info("[回复 移动位置订阅]: {}", platformId);
  129 + logger.info("[回复上级的移动位置订阅请求]: {}", platformId);
144 130 StringBuilder resultXml = new StringBuilder(200);
145 131 resultXml.append("<?xml version=\"1.0\" ?>\r\n")
146 132 .append("<Response>\r\n")
... ... @@ -158,17 +144,19 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme
158 144 }else {
159 145 subscribeInfo.setGpsInterval(Integer.parseInt(interval));
160 146 }
161   -
162 147 subscribeInfo.setSn(sn);
163   - subscribeHolder.putMobilePositionSubscribe(platformId, subscribeInfo);
164   -
165   - }else if (subscribeInfo.getExpires() == 0) {
166   - subscribeHolder.removeMobilePositionSubscribe(platformId);
167 148 }
168 149  
169 150 try {
170 151 ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(platformId);
171   - responseXmlAck(evt, resultXml.toString(), parentPlatform);
  152 + SIPResponse response = responseXmlAck(serverTransaction, resultXml.toString(), parentPlatform, subscribeInfo.getExpires());
  153 + if (subscribeInfo.getExpires() == 0) {
  154 + subscribeHolder.removeMobilePositionSubscribe(platformId);
  155 + }else {
  156 + subscribeInfo.setResponse(response);
  157 + subscribeHolder.putMobilePositionSubscribe(platformId, subscribeInfo);
  158 + }
  159 +
172 160 } catch (SipException | InvalidArgumentException | ParseException e) {
173 161 e.printStackTrace();
174 162 }
... ... @@ -178,25 +166,20 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme
178 166  
179 167 }
180 168  
181   - private void processNotifyCatalogList(RequestEvent evt, Element rootElement) throws SipException {
182   -
183   - String platformId = SipUtils.getUserIdFromFromHeader(evt.getRequest());
  169 + private void processNotifyCatalogList(ServerTransaction serverTransaction, Element rootElement) throws SipException {
  170 + if (serverTransaction == null) {
  171 + return;
  172 + }
  173 + String platformId = SipUtils.getUserIdFromFromHeader(serverTransaction.getRequest());
184 174 String deviceId = XmlUtil.getText(rootElement, "DeviceID");
185 175 ParentPlatform platform = storager.queryParentPlatByServerGBId(platformId);
186 176 if (platform == null){
187 177 return;
188 178 }
189   - SubscribeInfo subscribeInfo = new SubscribeInfo(evt, platformId);
190   - if (evt.getServerTransaction() == null) {
191   - ServerTransaction serverTransaction = "TCP".equalsIgnoreCase(platform.getTransport()) ? tcpSipProvider.getNewServerTransaction(evt.getRequest())
192   - : udpSipProvider.getNewServerTransaction(evt.getRequest());
193   - subscribeInfo.setTransaction(serverTransaction);
194   - Dialog dialog = serverTransaction.getDialog();
195   - dialog.terminateOnBye(false);
196   - subscribeInfo.setDialog(dialog);
197   - }
  179 + SubscribeInfo subscribeInfo = new SubscribeInfo(serverTransaction, platformId);
  180 +
198 181 String sn = XmlUtil.getText(rootElement, "SN");
199   - logger.info("[回复 目录订阅]: {}/{}", platformId, deviceId);
  182 + logger.info("[回复上级的目录订阅请求]: {}/{}", platformId, deviceId);
200 183 StringBuilder resultXml = new StringBuilder(200);
201 184 resultXml.append("<?xml version=\"1.0\" ?>\r\n")
202 185 .append("<Response>\r\n")
... ... @@ -213,7 +196,13 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme
213 196 }
214 197 try {
215 198 ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(platformId);
216   - responseXmlAck(evt, resultXml.toString(), parentPlatform);
  199 + SIPResponse response = responseXmlAck(serverTransaction, resultXml.toString(), parentPlatform, subscribeInfo.getExpires());
  200 + if (subscribeInfo.getExpires() == 0) {
  201 + subscribeHolder.removeCatalogSubscribe(platformId);
  202 + }else {
  203 + subscribeInfo.setResponse(response);
  204 + subscribeHolder.putCatalogSubscribe(platformId, subscribeInfo);
  205 + }
217 206 } catch (SipException | InvalidArgumentException | ParseException e) {
218 207 e.printStackTrace();
219 208 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/info/InfoRequestProcessor.java
... ... @@ -19,6 +19,7 @@ import org.springframework.beans.factory.annotation.Autowired;
19 19 import org.springframework.stereotype.Component;
20 20 import javax.sip.InvalidArgumentException;
21 21 import javax.sip.RequestEvent;
  22 +import javax.sip.ServerTransaction;
22 23 import javax.sip.SipException;
23 24 import javax.sip.header.*;
24 25 import javax.sip.message.Response;
... ... @@ -65,9 +66,12 @@ public class InfoRequestProcessor extends SIPRequestProcessorParent implements I
65 66 CallIdHeader callIdHeader = (CallIdHeader)evt.getRequest().getHeader(CallIdHeader.NAME);
66 67 // 先从会话内查找
67 68 SsrcTransaction ssrcTransaction = sessionManager.getSsrcTransaction(null, null, callIdHeader.getCallId(), null);
68   - if (ssrcTransaction != null) { // 兼容海康 媒体通知 消息from字段不是设备ID的问题
  69 +
  70 + // 兼容海康 媒体通知 消息from字段不是设备ID的问题
  71 + if (ssrcTransaction != null) {
69 72 deviceId = ssrcTransaction.getDeviceId();
70 73 }
  74 + ServerTransaction serverTransaction = getServerTransaction(evt);
71 75 // 查询设备是否存在
72 76 Device device = redisCatchStorage.getDevice(deviceId);
73 77 // 查询上级平台是否存在
... ... @@ -86,7 +90,7 @@ public class InfoRequestProcessor extends SIPRequestProcessorParent implements I
86 90 }
87 91 if (device == null && parentPlatform == null) {
88 92 // 不存在则回复404
89   - responseAck(evt, Response.NOT_FOUND, "device "+ deviceId +" not found");
  93 + responseAck(serverTransaction, Response.NOT_FOUND, "device "+ deviceId +" not found");
90 94 logger.warn("[设备未找到 ]: {}", deviceId);
91 95 if (sipSubscribe.getErrorSubscribe(callIdHeader.getCallId()) != null){
92 96 SipSubscribe.EventResult eventResult = new SipSubscribe.EventResult(new DeviceNotFoundEvent(evt.getDialog()));
... ... @@ -101,14 +105,14 @@ public class InfoRequestProcessor extends SIPRequestProcessorParent implements I
101 105 String streamId = sendRtpItem.getStreamId();
102 106 StreamInfo streamInfo = redisCatchStorage.queryPlayback(null, null, streamId, null);
103 107 if (null == streamInfo) {
104   - responseAck(evt, Response.NOT_FOUND, "stream " + streamId + " not found");
  108 + responseAck(serverTransaction, Response.NOT_FOUND, "stream " + streamId + " not found");
105 109 return;
106 110 }
107 111 Device device1 = storager.queryVideoDevice(streamInfo.getDeviceID());
108 112 cmder.playbackControlCmd(device1,streamInfo,new String(evt.getRequest().getRawContent()),eventResult -> {
109 113 // 失败的回复
110 114 try {
111   - responseAck(evt, eventResult.statusCode, eventResult.msg);
  115 + responseAck(serverTransaction, eventResult.statusCode, eventResult.msg);
112 116 } catch (SipException e) {
113 117 e.printStackTrace();
114 118 } catch (InvalidArgumentException e) {
... ... @@ -119,7 +123,7 @@ public class InfoRequestProcessor extends SIPRequestProcessorParent implements I
119 123 }, eventResult -> {
120 124 // 成功的回复
121 125 try {
122   - responseAck(evt, eventResult.statusCode);
  126 + responseAck(serverTransaction, eventResult.statusCode);
123 127 } catch (SipException e) {
124 128 e.printStackTrace();
125 129 } catch (InvalidArgumentException e) {
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/MessageRequestProcessor.java
... ... @@ -23,6 +23,7 @@ import org.springframework.stereotype.Component;
23 23  
24 24 import javax.sip.InvalidArgumentException;
25 25 import javax.sip.RequestEvent;
  26 +import javax.sip.ServerTransaction;
26 27 import javax.sip.SipException;
27 28 import javax.sip.address.SipURI;
28 29 import javax.sip.header.CSeqHeader;
... ... @@ -79,6 +80,9 @@ public class MessageRequestProcessor extends SIPRequestProcessorParent implement
79 80 if (ssrcTransaction != null) {
80 81 deviceId = ssrcTransaction.getDeviceId();
81 82 }
  83 +
  84 + ServerTransaction serverTransaction = getServerTransaction(evt);
  85 +
82 86 // 查询设备是否存在
83 87 Device device = redisCatchStorage.getDevice(deviceId);
84 88 // 查询上级平台是否存在
... ... @@ -98,7 +102,7 @@ public class MessageRequestProcessor extends SIPRequestProcessorParent implement
98 102 }
99 103 if (device == null && parentPlatform == null) {
100 104 // 不存在则回复404
101   - responseAck(evt, Response.NOT_FOUND, "device "+ deviceId +" not found");
  105 + responseAck(serverTransaction, Response.NOT_FOUND, "device "+ deviceId +" not found");
102 106 logger.warn("[设备未找到 ]: {}", deviceId);
103 107 if (sipSubscribe.getErrorSubscribe(callIdHeader.getCallId()) != null){
104 108 SipSubscribe.EventResult eventResult = new SipSubscribe.EventResult(new DeviceNotFoundEvent(evt.getDialog()));
... ... @@ -110,13 +114,13 @@ public class MessageRequestProcessor extends SIPRequestProcessorParent implement
110 114 rootElement = getRootElement(evt);
111 115 if (rootElement == null) {
112 116 logger.error("处理MESSAGE请求 未获取到消息体{}", evt.getRequest());
113   - responseAck(evt, Response.BAD_REQUEST, "content is null");
  117 + responseAck(serverTransaction, Response.BAD_REQUEST, "content is null");
114 118 return;
115 119 }
116 120 } catch (DocumentException e) {
117 121 logger.warn("解析XML消息内容异常", e);
118 122 // 不存在则回复404
119   - responseAck(evt, Response.BAD_REQUEST, e.getMessage());
  123 + responseAck(serverTransaction, Response.BAD_REQUEST, e.getMessage());
120 124 }
121 125 String name = rootElement.getName();
122 126 IMessageHandler messageHandler = messageHandlerMap.get(name);
... ... @@ -129,7 +133,7 @@ public class MessageRequestProcessor extends SIPRequestProcessorParent implement
129 133 }else {
130 134 // 不支持的message
131 135 // 不存在则回复415
132   - responseAck(evt, Response.UNSUPPORTED_MEDIA_TYPE, "Unsupported message type, must Control/Notify/Query/Response");
  136 + responseAck(serverTransaction, Response.UNSUPPORTED_MEDIA_TYPE, "Unsupported message type, must Control/Notify/Query/Response");
133 137 }
134 138 }
135 139 } catch (SipException e) {
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/control/cmd/DeviceControlQueryMessageHandler.java
... ... @@ -61,6 +61,8 @@ public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent
61 61 @Override
62 62 public void handForPlatform(RequestEvent evt, ParentPlatform parentPlatform, Element rootElement) {
63 63  
  64 + ServerTransaction serverTransaction = getServerTransaction(evt);
  65 +
64 66 // 此处是上级发出的DeviceControl指令
65 67 String targetGBId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(ToHeader.NAME)).getAddress().getURI()).getUser();
66 68 String channelId = getText(rootElement, "DeviceID");
... ... @@ -107,7 +109,7 @@ public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent
107 109 Device deviceForPlatform = storager.queryVideoDeviceByPlatformIdAndChannelId(parentPlatform.getServerGBId(), channelId);
108 110 if (deviceForPlatform == null) {
109 111 try {
110   - responseAck(evt, Response.NOT_FOUND);
  112 + responseAck(serverTransaction, Response.NOT_FOUND);
111 113 return;
112 114 } catch (SipException e) {
113 115 e.printStackTrace();
... ... @@ -120,7 +122,7 @@ public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent
120 122 cmder.fronEndCmd(deviceForPlatform, channelId, cmdString, eventResult -> {
121 123 // 失败的回复
122 124 try {
123   - responseAck(evt, eventResult.statusCode, eventResult.msg);
  125 + responseAck(serverTransaction, eventResult.statusCode, eventResult.msg);
124 126 } catch (SipException e) {
125 127 e.printStackTrace();
126 128 } catch (InvalidArgumentException e) {
... ... @@ -131,7 +133,7 @@ public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent
131 133 }, eventResult -> {
132 134 // 成功的回复
133 135 try {
134   - responseAck(evt, eventResult.statusCode);
  136 + responseAck(serverTransaction, eventResult.statusCode);
135 137 } catch (SipException e) {
136 138 e.printStackTrace();
137 139 } catch (InvalidArgumentException e) {
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/AlarmNotifyMessageHandler.java
... ... @@ -21,6 +21,8 @@ import org.slf4j.Logger;
21 21 import org.slf4j.LoggerFactory;
22 22 import org.springframework.beans.factory.InitializingBean;
23 23 import org.springframework.beans.factory.annotation.Autowired;
  24 +import org.springframework.beans.factory.annotation.Qualifier;
  25 +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
24 26 import org.springframework.stereotype.Component;
25 27 import org.springframework.util.ObjectUtils;
26 28 import org.springframework.util.StringUtils;
... ... @@ -31,6 +33,7 @@ import javax.sip.SipException;
31 33 import javax.sip.message.Response;
32 34  
33 35 import java.text.ParseException;
  36 +import java.util.concurrent.ConcurrentLinkedQueue;
34 37  
35 38 import static com.genersoft.iot.vmp.gb28181.utils.XmlUtil.*;
36 39  
... ... @@ -67,6 +70,15 @@ public class AlarmNotifyMessageHandler extends SIPRequestProcessorParent impleme
67 70 @Autowired
68 71 private IDeviceChannelService deviceChannelService;
69 72  
  73 + private boolean taskQueueHandlerRun = false;
  74 +
  75 + private ConcurrentLinkedQueue<SipMsgInfo> taskQueue = new ConcurrentLinkedQueue<>();
  76 +
  77 + @Qualifier("taskExecutor")
  78 + @Autowired
  79 + private ThreadPoolTaskExecutor taskExecutor;
  80 +
  81 +
70 82 @Override
71 83 public void afterPropertiesSet() throws Exception {
72 84 notifyMessageHandler.addHandler(cmdType, this);
... ... @@ -75,114 +87,128 @@ public class AlarmNotifyMessageHandler extends SIPRequestProcessorParent impleme
75 87 @Override
76 88 public void handForDevice(RequestEvent evt, Device device, Element rootElement) {
77 89 logger.info("[收到报警通知]设备:{}", device.getDeviceId());
78   - // 回复200 OK
79   - try {
80   - responseAck(evt, Response.OK);
81   - } catch (SipException | InvalidArgumentException | ParseException e) {
82   - logger.error("[收到报警通知], 回复200OK失败", e);
83   - }
84 90  
85   - Element deviceIdElement = rootElement.element("DeviceID");
86   - String channelId = deviceIdElement.getText().toString();
87   -
88   - DeviceAlarm deviceAlarm = new DeviceAlarm();
89   - deviceAlarm.setCreateTime(DateUtil.getNow());
90   - deviceAlarm.setDeviceId(device.getDeviceId());
91   - deviceAlarm.setChannelId(channelId);
92   - deviceAlarm.setAlarmPriority(getText(rootElement, "AlarmPriority"));
93   - deviceAlarm.setAlarmMethod(getText(rootElement, "AlarmMethod"));
94   - String alarmTime = XmlUtil.getText(rootElement, "AlarmTime");
95   - if (alarmTime == null) {
96   - return;
97   - }
98   - deviceAlarm.setAlarmTime(DateUtil.ISO8601Toyyyy_MM_dd_HH_mm_ss(alarmTime));
99   - String alarmDescription = getText(rootElement, "AlarmDescription");
100   - if (alarmDescription == null) {
101   - deviceAlarm.setAlarmDescription("");
102   - } else {
103   - deviceAlarm.setAlarmDescription(alarmDescription);
104   - }
105   - String longitude = getText(rootElement, "Longitude");
106   - if (longitude != null && NumericUtil.isDouble(longitude)) {
107   - deviceAlarm.setLongitude(Double.parseDouble(longitude));
108   - } else {
109   - deviceAlarm.setLongitude(0.00);
110   - }
111   - String latitude = getText(rootElement, "Latitude");
112   - if (latitude != null && NumericUtil.isDouble(latitude)) {
113   - deviceAlarm.setLatitude(Double.parseDouble(latitude));
114   - } else {
115   - deviceAlarm.setLatitude(0.00);
116   - }
117   -
118   - if (!ObjectUtils.isEmpty(deviceAlarm.getAlarmMethod())) {
119   - if ( deviceAlarm.getAlarmMethod().contains(DeviceAlarmMethod.GPS.getVal() + "")) {
120   - MobilePosition mobilePosition = new MobilePosition();
121   - mobilePosition.setCreateTime(DateUtil.getNow());
122   - mobilePosition.setDeviceId(deviceAlarm.getDeviceId());
123   - mobilePosition.setTime(deviceAlarm.getAlarmTime());
124   - mobilePosition.setLongitude(deviceAlarm.getLongitude());
125   - mobilePosition.setLatitude(deviceAlarm.getLatitude());
126   - mobilePosition.setReportSource("GPS Alarm");
127   -
128   - // 更新device channel 的经纬度
129   - DeviceChannel deviceChannel = new DeviceChannel();
130   - deviceChannel.setDeviceId(device.getDeviceId());
131   - deviceChannel.setChannelId(channelId);
132   - deviceChannel.setLongitude(mobilePosition.getLongitude());
133   - deviceChannel.setLatitude(mobilePosition.getLatitude());
134   - deviceChannel.setGpsTime(mobilePosition.getTime());
135   -
136   - deviceChannel = deviceChannelService.updateGps(deviceChannel, device);
137   -
138   - mobilePosition.setLongitudeWgs84(deviceChannel.getLongitudeWgs84());
139   - mobilePosition.setLatitudeWgs84(deviceChannel.getLatitudeWgs84());
140   - mobilePosition.setLongitudeGcj02(deviceChannel.getLongitudeGcj02());
141   - mobilePosition.setLatitudeGcj02(deviceChannel.getLatitudeGcj02());
142   -
143   - if (userSetting.getSavePositionHistory()) {
144   - storager.insertMobilePosition(mobilePosition);
  91 + taskQueue.offer(new SipMsgInfo(evt, device, rootElement));
  92 + if (!taskQueueHandlerRun) {
  93 + taskQueueHandlerRun = true;
  94 + taskExecutor.execute(() -> {
  95 + logger.info("[处理报警通知]待处理数量:{}", taskQueue.size() );
  96 + while (!taskQueue.isEmpty()) {
  97 + SipMsgInfo sipMsgInfo = taskQueue.poll();
  98 + // 回复200 OK
  99 + try {
  100 + responseAck(getServerTransaction(sipMsgInfo.getEvt()), Response.OK);
  101 + } catch (SipException | InvalidArgumentException | ParseException e) {
  102 + logger.error("[处理报警通知], 回复200OK失败", e);
  103 + }
  104 +
  105 + Element deviceIdElement = sipMsgInfo.getRootElement().element("DeviceID");
  106 + String channelId = deviceIdElement.getText().toString();
  107 +
  108 + DeviceAlarm deviceAlarm = new DeviceAlarm();
  109 + deviceAlarm.setCreateTime(DateUtil.getNow());
  110 + deviceAlarm.setDeviceId(sipMsgInfo.getDevice().getDeviceId());
  111 + deviceAlarm.setChannelId(channelId);
  112 + deviceAlarm.setAlarmPriority(getText(sipMsgInfo.getRootElement(), "AlarmPriority"));
  113 + deviceAlarm.setAlarmMethod(getText(sipMsgInfo.getRootElement(), "AlarmMethod"));
  114 + String alarmTime = XmlUtil.getText(sipMsgInfo.getRootElement(), "AlarmTime");
  115 + if (alarmTime == null) {
  116 + continue;
  117 + }
  118 + deviceAlarm.setAlarmTime(DateUtil.ISO8601Toyyyy_MM_dd_HH_mm_ss(alarmTime));
  119 + String alarmDescription = getText(sipMsgInfo.getRootElement(), "AlarmDescription");
  120 + if (alarmDescription == null) {
  121 + deviceAlarm.setAlarmDescription("");
  122 + } else {
  123 + deviceAlarm.setAlarmDescription(alarmDescription);
  124 + }
  125 + String longitude = getText(sipMsgInfo.getRootElement(), "Longitude");
  126 + if (longitude != null && NumericUtil.isDouble(longitude)) {
  127 + deviceAlarm.setLongitude(Double.parseDouble(longitude));
  128 + } else {
  129 + deviceAlarm.setLongitude(0.00);
  130 + }
  131 + String latitude = getText(sipMsgInfo.getRootElement(), "Latitude");
  132 + if (latitude != null && NumericUtil.isDouble(latitude)) {
  133 + deviceAlarm.setLatitude(Double.parseDouble(latitude));
  134 + } else {
  135 + deviceAlarm.setLatitude(0.00);
  136 + }
  137 +
  138 + if (!ObjectUtils.isEmpty(deviceAlarm.getAlarmMethod())) {
  139 + if ( deviceAlarm.getAlarmMethod().contains(DeviceAlarmMethod.GPS.getVal() + "")) {
  140 + MobilePosition mobilePosition = new MobilePosition();
  141 + mobilePosition.setCreateTime(DateUtil.getNow());
  142 + mobilePosition.setDeviceId(deviceAlarm.getDeviceId());
  143 + mobilePosition.setTime(deviceAlarm.getAlarmTime());
  144 + mobilePosition.setLongitude(deviceAlarm.getLongitude());
  145 + mobilePosition.setLatitude(deviceAlarm.getLatitude());
  146 + mobilePosition.setReportSource("GPS Alarm");
  147 +
  148 + // 更新device channel 的经纬度
  149 + DeviceChannel deviceChannel = new DeviceChannel();
  150 + deviceChannel.setDeviceId(sipMsgInfo.getDevice().getDeviceId());
  151 + deviceChannel.setChannelId(channelId);
  152 + deviceChannel.setLongitude(mobilePosition.getLongitude());
  153 + deviceChannel.setLatitude(mobilePosition.getLatitude());
  154 + deviceChannel.setGpsTime(mobilePosition.getTime());
  155 +
  156 + deviceChannel = deviceChannelService.updateGps(deviceChannel, sipMsgInfo.getDevice());
  157 +
  158 + mobilePosition.setLongitudeWgs84(deviceChannel.getLongitudeWgs84());
  159 + mobilePosition.setLatitudeWgs84(deviceChannel.getLatitudeWgs84());
  160 + mobilePosition.setLongitudeGcj02(deviceChannel.getLongitudeGcj02());
  161 + mobilePosition.setLatitudeGcj02(deviceChannel.getLatitudeGcj02());
  162 +
  163 + if (userSetting.getSavePositionHistory()) {
  164 + storager.insertMobilePosition(mobilePosition);
  165 + }
  166 + storager.updateChannelPosition(deviceChannel);
  167 +
  168 + // 发送redis消息。 通知位置信息的变化
  169 + JSONObject jsonObject = new JSONObject();
  170 + jsonObject.put("time", mobilePosition.getTime());
  171 + jsonObject.put("serial", deviceChannel.getDeviceId());
  172 + jsonObject.put("code", deviceChannel.getChannelId());
  173 + jsonObject.put("longitude", mobilePosition.getLongitude());
  174 + jsonObject.put("latitude", mobilePosition.getLatitude());
  175 + jsonObject.put("altitude", mobilePosition.getAltitude());
  176 + jsonObject.put("direction", mobilePosition.getDirection());
  177 + jsonObject.put("speed", mobilePosition.getSpeed());
  178 + redisCatchStorage.sendMobilePositionMsg(jsonObject);
  179 + }
  180 + }
  181 + if (!ObjectUtils.isEmpty(deviceAlarm.getDeviceId())) {
  182 + if (deviceAlarm.getAlarmMethod().contains(DeviceAlarmMethod.Video.getVal() + "")) {
  183 + deviceAlarm.setAlarmType(getText(sipMsgInfo.getRootElement().element("Info"), "AlarmType"));
  184 + }
  185 + }
  186 + logger.info("[收到报警通知]内容:{}", JSONObject.toJSON(deviceAlarm));
  187 + if ("7".equals(deviceAlarm.getAlarmMethod()) ) {
  188 + // 发送给平台的报警信息。 发送redis通知
  189 + AlarmChannelMessage alarmChannelMessage = new AlarmChannelMessage();
  190 + alarmChannelMessage.setAlarmSn(Integer.parseInt(deviceAlarm.getAlarmMethod()));
  191 + alarmChannelMessage.setAlarmDescription(deviceAlarm.getAlarmDescription());
  192 + alarmChannelMessage.setGbId(channelId);
  193 + redisCatchStorage.sendAlarmMsg(alarmChannelMessage);
  194 + continue;
  195 + }
  196 +
  197 + logger.debug("存储报警信息、报警分类");
  198 + // 存储报警信息、报警分类
  199 + if (sipConfig.isAlarm()) {
  200 + deviceAlarmService.add(deviceAlarm);
  201 + }
  202 +
  203 + if (redisCatchStorage.deviceIsOnline(sipMsgInfo.getDevice().getDeviceId())) {
  204 + publisher.deviceAlarmEventPublish(deviceAlarm);
  205 + }
145 206 }
146   - storager.updateChannelPosition(deviceChannel);
147   -
148   - // 发送redis消息。 通知位置信息的变化
149   - JSONObject jsonObject = new JSONObject();
150   - jsonObject.put("time", mobilePosition.getTime());
151   - jsonObject.put("serial", deviceChannel.getDeviceId());
152   - jsonObject.put("code", deviceChannel.getChannelId());
153   - jsonObject.put("longitude", mobilePosition.getLongitude());
154   - jsonObject.put("latitude", mobilePosition.getLatitude());
155   - jsonObject.put("altitude", mobilePosition.getAltitude());
156   - jsonObject.put("direction", mobilePosition.getDirection());
157   - jsonObject.put("speed", mobilePosition.getSpeed());
158   - redisCatchStorage.sendMobilePositionMsg(jsonObject);
159   - }
160   - }
161   - if (!ObjectUtils.isEmpty(deviceAlarm.getDeviceId())) {
162   - if (deviceAlarm.getAlarmMethod().contains(DeviceAlarmMethod.Video.getVal() + "")) {
163   - deviceAlarm.setAlarmType(getText(rootElement.element("Info"), "AlarmType"));
164   - }
165   - }
166   -
167   - if ("7".equals(deviceAlarm.getAlarmMethod()) ) {
168   - // 发送给平台的报警信息。 发送redis通知
169   - AlarmChannelMessage alarmChannelMessage = new AlarmChannelMessage();
170   - alarmChannelMessage.setAlarmSn(Integer.parseInt(deviceAlarm.getAlarmMethod()));
171   - alarmChannelMessage.setAlarmDescription(deviceAlarm.getAlarmDescription());
172   - alarmChannelMessage.setGbId(channelId);
173   - redisCatchStorage.sendAlarmMsg(alarmChannelMessage);
174   - return;
  207 + taskQueueHandlerRun = false;
  208 + });
175 209 }
176 210  
177   - logger.debug("存储报警信息、报警分类");
178   - // 存储报警信息、报警分类
179   - if (sipConfig.isAlarm()) {
180   - deviceAlarmService.add(deviceAlarm);
181   - }
182 211  
183   - if (redisCatchStorage.deviceIsOnline(device.getDeviceId())) {
184   - publisher.deviceAlarmEventPublish(deviceAlarm);
185   - }
186 212 }
187 213  
188 214 @Override
... ... @@ -190,7 +216,7 @@ public class AlarmNotifyMessageHandler extends SIPRequestProcessorParent impleme
190 216 logger.info("收到来自平台[{}]的报警通知", parentPlatform.getServerGBId());
191 217 // 回复200 OK
192 218 try {
193   - responseAck(evt, Response.OK);
  219 + responseAck(getServerTransaction(evt), Response.OK);
194 220 } catch (SipException e) {
195 221 throw new RuntimeException(e);
196 222 } catch (InvalidArgumentException e) {
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/KeepaliveNotifyMessageHandler.java
... ... @@ -69,7 +69,7 @@ public class KeepaliveNotifyMessageHandler extends SIPRequestProcessorParent imp
69 69 }
70 70 device.setKeepaliveTime(DateUtil.getNow());
71 71 // 回复200 OK
72   - responseAck(evt, Response.OK);
  72 + responseAck(getServerTransaction(evt), Response.OK);
73 73 if (device.getOnline() == 1) {
74 74 deviceService.updateDevice(device);
75 75 }else {
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/MediaStatusNotifyMessageHandler.java
... ... @@ -66,7 +66,7 @@ public class MediaStatusNotifyMessageHandler extends SIPRequestProcessorParent i
66 66  
67 67 // 回复200 OK
68 68 try {
69   - responseAck(evt, Response.OK);
  69 + responseAck(getServerTransaction(evt), Response.OK);
70 70 } catch (SipException e) {
71 71 e.printStackTrace();
72 72 } catch (InvalidArgumentException e) {
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/MobilePositionNotifyMessageHandler.java
... ... @@ -17,6 +17,8 @@ import org.slf4j.Logger;
17 17 import org.slf4j.LoggerFactory;
18 18 import org.springframework.beans.factory.InitializingBean;
19 19 import org.springframework.beans.factory.annotation.Autowired;
  20 +import org.springframework.beans.factory.annotation.Qualifier;
  21 +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
20 22 import org.springframework.stereotype.Component;
21 23 import org.springframework.util.ObjectUtils;
22 24 import org.springframework.util.StringUtils;
... ... @@ -26,6 +28,7 @@ import javax.sip.RequestEvent;
26 28 import javax.sip.SipException;
27 29 import javax.sip.message.Response;
28 30 import java.text.ParseException;
  31 +import java.util.concurrent.ConcurrentLinkedQueue;
29 32  
30 33 import static com.genersoft.iot.vmp.gb28181.utils.XmlUtil.getText;
31 34  
... ... @@ -53,6 +56,14 @@ public class MobilePositionNotifyMessageHandler extends SIPRequestProcessorParen
53 56 @Autowired
54 57 private IDeviceChannelService deviceChannelService;
55 58  
  59 + private boolean taskQueueHandlerRun = false;
  60 +
  61 + private ConcurrentLinkedQueue<SipMsgInfo> taskQueue = new ConcurrentLinkedQueue<>();
  62 +
  63 + @Qualifier("taskExecutor")
  64 + @Autowired
  65 + private ThreadPoolTaskExecutor taskExecutor;
  66 +
56 67 @Override
57 68 public void afterPropertiesSet() throws Exception {
58 69 notifyMessageHandler.addHandler(cmdType, this);
... ... @@ -61,78 +72,91 @@ public class MobilePositionNotifyMessageHandler extends SIPRequestProcessorParen
61 72 @Override
62 73 public void handForDevice(RequestEvent evt, Device device, Element rootElement) {
63 74  
64   - try {
65   - rootElement = getRootElement(evt, device.getCharset());
66   - if (rootElement == null) {
67   - logger.warn("[ 移动设备位置数据通知 ] content cannot be null, {}", evt.getRequest());
68   - responseAck(evt, Response.BAD_REQUEST);
69   - return;
70   - }
71   - MobilePosition mobilePosition = new MobilePosition();
72   - mobilePosition.setCreateTime(DateUtil.getNow());
73   - if (!ObjectUtils.isEmpty(device.getName())) {
74   - mobilePosition.setDeviceName(device.getName());
75   - }
76   - mobilePosition.setDeviceId(device.getDeviceId());
77   - mobilePosition.setChannelId(getText(rootElement, "DeviceID"));
78   - mobilePosition.setTime(getText(rootElement, "Time"));
79   - mobilePosition.setLongitude(Double.parseDouble(getText(rootElement, "Longitude")));
80   - mobilePosition.setLatitude(Double.parseDouble(getText(rootElement, "Latitude")));
81   - if (NumericUtil.isDouble(getText(rootElement, "Speed"))) {
82   - mobilePosition.setSpeed(Double.parseDouble(getText(rootElement, "Speed")));
83   - } else {
84   - mobilePosition.setSpeed(0.0);
85   - }
86   - if (NumericUtil.isDouble(getText(rootElement, "Direction"))) {
87   - mobilePosition.setDirection(Double.parseDouble(getText(rootElement, "Direction")));
88   - } else {
89   - mobilePosition.setDirection(0.0);
90   - }
91   - if (NumericUtil.isDouble(getText(rootElement, "Altitude"))) {
92   - mobilePosition.setAltitude(Double.parseDouble(getText(rootElement, "Altitude")));
93   - } else {
94   - mobilePosition.setAltitude(0.0);
95   - }
96   - mobilePosition.setReportSource("Mobile Position");
97   -
98   -
99   - // 更新device channel 的经纬度
100   - DeviceChannel deviceChannel = new DeviceChannel();
101   - deviceChannel.setDeviceId(device.getDeviceId());
102   - deviceChannel.setChannelId(mobilePosition.getChannelId());
103   - deviceChannel.setLongitude(mobilePosition.getLongitude());
104   - deviceChannel.setLatitude(mobilePosition.getLatitude());
105   - deviceChannel.setGpsTime(mobilePosition.getTime());
106   -
107   - deviceChannel = deviceChannelService.updateGps(deviceChannel, device);
108   -
109   - mobilePosition.setLongitudeWgs84(deviceChannel.getLongitudeWgs84());
110   - mobilePosition.setLatitudeWgs84(deviceChannel.getLatitudeWgs84());
111   - mobilePosition.setLongitudeGcj02(deviceChannel.getLongitudeGcj02());
112   - mobilePosition.setLatitudeGcj02(deviceChannel.getLatitudeGcj02());
113   -
114   - if (userSetting.getSavePositionHistory()) {
115   - storager.insertMobilePosition(mobilePosition);
116   - }
117   - storager.updateChannelPosition(deviceChannel);
118   - //回复 200 OK
119   - responseAck(evt, Response.OK);
120   -
121   - // 发送redis消息。 通知位置信息的变化
122   - JSONObject jsonObject = new JSONObject();
123   - jsonObject.put("time", mobilePosition.getTime());
124   - jsonObject.put("serial", deviceChannel.getDeviceId());
125   - jsonObject.put("code", deviceChannel.getChannelId());
126   - jsonObject.put("longitude", mobilePosition.getLongitude());
127   - jsonObject.put("latitude", mobilePosition.getLatitude());
128   - jsonObject.put("altitude", mobilePosition.getAltitude());
129   - jsonObject.put("direction", mobilePosition.getDirection());
130   - jsonObject.put("speed", mobilePosition.getSpeed());
131   - redisCatchStorage.sendMobilePositionMsg(jsonObject);
132   -
133   - } catch (DocumentException | SipException | InvalidArgumentException | ParseException e) {
134   - e.printStackTrace();
  75 + taskQueue.offer(new SipMsgInfo(evt, device, rootElement));
  76 + if (!taskQueueHandlerRun) {
  77 + taskQueueHandlerRun = true;
  78 + taskExecutor.execute(() -> {
  79 + while (!taskQueue.isEmpty()) {
  80 + SipMsgInfo sipMsgInfo = taskQueue.poll();
  81 + try {
  82 + Element rootElementAfterCharset = getRootElement(sipMsgInfo.getEvt(), sipMsgInfo.getDevice().getCharset());
  83 + if (rootElementAfterCharset == null) {
  84 + logger.warn("[ 移动设备位置数据通知 ] content cannot be null, {}", sipMsgInfo.getEvt().getRequest());
  85 + responseAck(getServerTransaction(sipMsgInfo.getEvt()), Response.BAD_REQUEST);
  86 + continue;
  87 + }
  88 + MobilePosition mobilePosition = new MobilePosition();
  89 + mobilePosition.setCreateTime(DateUtil.getNow());
  90 + if (!ObjectUtils.isEmpty(sipMsgInfo.getDevice().getName())) {
  91 + mobilePosition.setDeviceName(sipMsgInfo.getDevice().getName());
  92 + }
  93 + mobilePosition.setDeviceId(sipMsgInfo.getDevice().getDeviceId());
  94 + mobilePosition.setChannelId(getText(rootElementAfterCharset, "DeviceID"));
  95 + mobilePosition.setTime(getText(rootElementAfterCharset, "Time"));
  96 + mobilePosition.setLongitude(Double.parseDouble(getText(rootElementAfterCharset, "Longitude")));
  97 + mobilePosition.setLatitude(Double.parseDouble(getText(rootElementAfterCharset, "Latitude")));
  98 + if (NumericUtil.isDouble(getText(rootElementAfterCharset, "Speed"))) {
  99 + mobilePosition.setSpeed(Double.parseDouble(getText(rootElementAfterCharset, "Speed")));
  100 + } else {
  101 + mobilePosition.setSpeed(0.0);
  102 + }
  103 + if (NumericUtil.isDouble(getText(rootElementAfterCharset, "Direction"))) {
  104 + mobilePosition.setDirection(Double.parseDouble(getText(rootElementAfterCharset, "Direction")));
  105 + } else {
  106 + mobilePosition.setDirection(0.0);
  107 + }
  108 + if (NumericUtil.isDouble(getText(rootElementAfterCharset, "Altitude"))) {
  109 + mobilePosition.setAltitude(Double.parseDouble(getText(rootElementAfterCharset, "Altitude")));
  110 + } else {
  111 + mobilePosition.setAltitude(0.0);
  112 + }
  113 + mobilePosition.setReportSource("Mobile Position");
  114 +
  115 +
  116 + // 更新device channel 的经纬度
  117 + DeviceChannel deviceChannel = new DeviceChannel();
  118 + deviceChannel.setDeviceId(sipMsgInfo.getDevice().getDeviceId());
  119 + deviceChannel.setChannelId(mobilePosition.getChannelId());
  120 + deviceChannel.setLongitude(mobilePosition.getLongitude());
  121 + deviceChannel.setLatitude(mobilePosition.getLatitude());
  122 + deviceChannel.setGpsTime(mobilePosition.getTime());
  123 +
  124 + deviceChannel = deviceChannelService.updateGps(deviceChannel, sipMsgInfo.getDevice());
  125 +
  126 + mobilePosition.setLongitudeWgs84(deviceChannel.getLongitudeWgs84());
  127 + mobilePosition.setLatitudeWgs84(deviceChannel.getLatitudeWgs84());
  128 + mobilePosition.setLongitudeGcj02(deviceChannel.getLongitudeGcj02());
  129 + mobilePosition.setLatitudeGcj02(deviceChannel.getLatitudeGcj02());
  130 +
  131 + if (userSetting.getSavePositionHistory()) {
  132 + storager.insertMobilePosition(mobilePosition);
  133 + }
  134 + storager.updateChannelPosition(deviceChannel);
  135 + //回复 200 OK
  136 + responseAck(getServerTransaction(sipMsgInfo.getEvt()), Response.OK);
  137 +
  138 + // 发送redis消息。 通知位置信息的变化
  139 + JSONObject jsonObject = new JSONObject();
  140 + jsonObject.put("time", mobilePosition.getTime());
  141 + jsonObject.put("serial", deviceChannel.getDeviceId());
  142 + jsonObject.put("code", deviceChannel.getChannelId());
  143 + jsonObject.put("longitude", mobilePosition.getLongitude());
  144 + jsonObject.put("latitude", mobilePosition.getLatitude());
  145 + jsonObject.put("altitude", mobilePosition.getAltitude());
  146 + jsonObject.put("direction", mobilePosition.getDirection());
  147 + jsonObject.put("speed", mobilePosition.getSpeed());
  148 + redisCatchStorage.sendMobilePositionMsg(jsonObject);
  149 +
  150 + } catch (DocumentException | SipException | InvalidArgumentException | ParseException e) {
  151 + e.printStackTrace();
  152 + }
  153 +
  154 + }
  155 + taskQueueHandlerRun = false;
  156 + });
135 157 }
  158 +
  159 +
136 160 }
137 161  
138 162 @Override
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/query/cmd/AlarmQueryMessageHandler.java
... ... @@ -58,7 +58,7 @@ public class AlarmQueryMessageHandler extends SIPRequestProcessorParent implemen
58 58  
59 59 logger.info("不支持alarm查询");
60 60 try {
61   - responseAck(evt, Response.NOT_FOUND, "not support alarm query");
  61 + responseAck(getServerTransaction(evt), Response.NOT_FOUND, "not support alarm query");
62 62 } catch (SipException e) {
63 63 e.printStackTrace();
64 64 } catch (InvalidArgumentException e) {
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/query/cmd/CatalogQueryMessageHandler.java
... ... @@ -66,7 +66,7 @@ public class CatalogQueryMessageHandler extends SIPRequestProcessorParent implem
66 66 FromHeader fromHeader = (FromHeader) evt.getRequest().getHeader(FromHeader.NAME);
67 67 try {
68 68 // 回复200 OK
69   - responseAck(evt, Response.OK);
  69 + responseAck(getServerTransaction(evt), Response.OK);
70 70 Element snElement = rootElement.element("SN");
71 71 String sn = snElement.getText();
72 72 // 准备回复通道信息
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/query/cmd/DeviceInfoQueryMessageHandler.java
... ... @@ -48,7 +48,7 @@ public class DeviceInfoQueryMessageHandler extends SIPRequestProcessorParent imp
48 48 FromHeader fromHeader = (FromHeader) evt.getRequest().getHeader(FromHeader.NAME);
49 49 try {
50 50 // 回复200 OK
51   - responseAck(evt, Response.OK);
  51 + responseAck(getServerTransaction(evt), Response.OK);
52 52 } catch (SipException e) {
53 53 e.printStackTrace();
54 54 } catch (InvalidArgumentException e) {
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/query/cmd/DeviceStatusQueryMessageHandler.java
... ... @@ -61,7 +61,7 @@ public class DeviceStatusQueryMessageHandler extends SIPRequestProcessorParent i
61 61 FromHeader fromHeader = (FromHeader) evt.getRequest().getHeader(FromHeader.NAME);
62 62 // 回复200 OK
63 63 try {
64   - responseAck(evt, Response.OK);
  64 + responseAck(getServerTransaction(evt), Response.OK);
65 65 } catch (SipException e) {
66 66 e.printStackTrace();
67 67 } catch (InvalidArgumentException e) {
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/query/cmd/RecordInfoQueryMessageHandler.java
... ... @@ -21,6 +21,7 @@ import org.springframework.stereotype.Component;
21 21  
22 22 import javax.sip.InvalidArgumentException;
23 23 import javax.sip.RequestEvent;
  24 +import javax.sip.ServerTransaction;
24 25 import javax.sip.SipException;
25 26 import javax.sip.header.FromHeader;
26 27 import javax.sip.message.Response;
... ... @@ -68,7 +69,7 @@ public class RecordInfoQueryMessageHandler extends SIPRequestProcessorParent imp
68 69 public void handForPlatform(RequestEvent evt, ParentPlatform parentPlatform, Element rootElement) {
69 70  
70 71 FromHeader fromHeader = (FromHeader) evt.getRequest().getHeader(FromHeader.NAME);
71   -
  72 + ServerTransaction serverTransaction = getServerTransaction(evt);
72 73 Element snElement = rootElement.element("SN");
73 74 int sn = Integer.parseInt(snElement.getText());
74 75 Element deviceIDElement = rootElement.element("DeviceID");
... ... @@ -108,7 +109,7 @@ public class RecordInfoQueryMessageHandler extends SIPRequestProcessorParent imp
108 109 DateUtil.ISO8601Toyyyy_MM_dd_HH_mm_ss(endTime), sn, secrecy, type, (eventResult -> {
109 110 // 回复200 OK
110 111 try {
111   - responseAck(evt, Response.OK);
  112 + responseAck(serverTransaction, Response.OK);
112 113 } catch (SipException e) {
113 114 e.printStackTrace();
114 115 } catch (InvalidArgumentException e) {
... ... @@ -119,7 +120,7 @@ public class RecordInfoQueryMessageHandler extends SIPRequestProcessorParent imp
119 120 }),(eventResult -> {
120 121 // 查询失败
121 122 try {
122   - responseAck(evt, eventResult.statusCode, eventResult.msg);
  123 + responseAck(serverTransaction, eventResult.statusCode, eventResult.msg);
123 124 } catch (SipException e) {
124 125 e.printStackTrace();
125 126 } catch (InvalidArgumentException e) {
... ... @@ -132,7 +133,7 @@ public class RecordInfoQueryMessageHandler extends SIPRequestProcessorParent imp
132 133 }else if (channelSources.get(1).getCount() > 0) { // 直播流
133 134 // TODO
134 135 try {
135   - responseAck(evt, Response.NOT_IMPLEMENTED); // 回复未实现
  136 + responseAck(serverTransaction, Response.NOT_IMPLEMENTED); // 回复未实现
136 137 } catch (SipException e) {
137 138 e.printStackTrace();
138 139 } catch (InvalidArgumentException e) {
... ... @@ -142,7 +143,7 @@ public class RecordInfoQueryMessageHandler extends SIPRequestProcessorParent imp
142 143 }
143 144 }else { // 错误的请求
144 145 try {
145   - responseAck(evt, Response.BAD_REQUEST);
  146 + responseAck(serverTransaction, Response.BAD_REQUEST);
146 147 } catch (SipException e) {
147 148 e.printStackTrace();
148 149 } catch (InvalidArgumentException e) {
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/BroadcastResponseMessageHandler.java
... ... @@ -21,6 +21,7 @@ import org.springframework.stereotype.Component;
21 21  
22 22 import javax.sip.InvalidArgumentException;
23 23 import javax.sip.RequestEvent;
  24 +import javax.sip.ServerTransaction;
24 25 import javax.sip.SipException;
25 26 import javax.sip.message.Response;
26 27 import java.text.ParseException;
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/CatalogResponseMessageHandler.java
... ... @@ -27,6 +27,7 @@ import org.springframework.util.StringUtils;
27 27  
28 28 import javax.sip.InvalidArgumentException;
29 29 import javax.sip.RequestEvent;
  30 +import javax.sip.ServerTransaction;
30 31 import javax.sip.SipException;
31 32 import javax.sip.message.Response;
32 33 import java.text.ParseException;
... ... @@ -87,7 +88,8 @@ public class CatalogResponseMessageHandler extends SIPRequestProcessorParent imp
87 88 taskQueue.offer(new HandlerCatchData(evt, device, element));
88 89 // 回复200 OK
89 90 try {
90   - responseAck(evt, Response.OK);
  91 + ServerTransaction serverTransaction = getServerTransaction(evt);
  92 + responseAck(serverTransaction, Response.OK);
91 93 if (!taskQueueHandlerRun) {
92 94 taskQueueHandlerRun = true;
93 95 taskExecutor.execute(()-> {
... ... @@ -103,7 +105,7 @@ public class CatalogResponseMessageHandler extends SIPRequestProcessorParent imp
103 105 Element sumNumElement = rootElement.element("SumNum");
104 106 Element snElement = rootElement.element("SN");
105 107 if (snElement == null || sumNumElement == null || deviceListElement == null) {
106   - responseAck(take.getEvt(), Response.BAD_REQUEST, "xml error");
  108 + responseAck(serverTransaction, Response.BAD_REQUEST, "xml error");
107 109 continue;
108 110 }
109 111 int sumNum = Integer.parseInt(sumNumElement.getText());
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/ConfigDownloadResponseMessageHandler.java
... ... @@ -52,7 +52,7 @@ public class ConfigDownloadResponseMessageHandler extends SIPRequestProcessorPar
52 52 String key = DeferredResultHolder.CALLBACK_CMD_CONFIGDOWNLOAD + device.getDeviceId() + channelId;
53 53 try {
54 54 // 回复200 OK
55   - responseAck(evt, Response.OK);
  55 + responseAck(getServerTransaction(evt), Response.OK);
56 56 // 此处是对本平台发出DeviceControl指令的应答
57 57 JSONObject json = new JSONObject();
58 58 XmlUtil.node2Json(element, json);
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/DeviceControlResponseMessageHandler.java
... ... @@ -46,7 +46,7 @@ public class DeviceControlResponseMessageHandler extends SIPRequestProcessorPare
46 46 public void handForDevice(RequestEvent evt, Device device, Element element) {
47 47 // 此处是对本平台发出DeviceControl指令的应答
48 48 try {
49   - responseAck(evt, Response.OK);
  49 + responseAck(getServerTransaction(evt), Response.OK);
50 50 JSONObject json = new JSONObject();
51 51 String channelId = getText(element, "DeviceID");
52 52 XmlUtil.node2Json(element, json);
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/DeviceInfoResponseMessageHandler.java
... ... @@ -25,6 +25,7 @@ import org.springframework.util.StringUtils;
25 25  
26 26 import javax.sip.InvalidArgumentException;
27 27 import javax.sip.RequestEvent;
  28 +import javax.sip.ServerTransaction;
28 29 import javax.sip.SipException;
29 30 import javax.sip.message.Response;
30 31 import java.text.ParseException;
... ... @@ -74,11 +75,12 @@ public class DeviceInfoResponseMessageHandler extends SIPRequestProcessorParent
74 75 logger.warn("[接收到DeviceInfo应答消息,但是设备已经离线]:" + (device != null ? device.getDeviceId():"" ));
75 76 return;
76 77 }
  78 + ServerTransaction serverTransaction = getServerTransaction(evt);
77 79 try {
78 80 rootElement = getRootElement(evt, device.getCharset());
79 81 if (rootElement == null) {
80 82 logger.warn("[ 接收到DeviceInfo应答消息 ] content cannot be null, {}", evt.getRequest());
81   - responseAck(evt, Response.BAD_REQUEST);
  83 + responseAck(serverTransaction, Response.BAD_REQUEST);
82 84 return;
83 85 }
84 86 Element deviceIdElement = rootElement.element("DeviceID");
... ... @@ -99,7 +101,7 @@ public class DeviceInfoResponseMessageHandler extends SIPRequestProcessorParent
99 101 msg.setData(device);
100 102 deferredResultHolder.invokeAllResult(msg);
101 103 // 回复200 OK
102   - responseAck(evt, Response.OK);
  104 + responseAck(serverTransaction, Response.OK);
103 105 } catch (DocumentException e) {
104 106 e.printStackTrace();
105 107 } catch (InvalidArgumentException e) {
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/DeviceStatusResponseMessageHandler.java
... ... @@ -59,7 +59,7 @@ public class DeviceStatusResponseMessageHandler extends SIPRequestProcessorParen
59 59 }
60 60 // 回复200 OK
61 61 try {
62   - responseAck(evt, Response.OK);
  62 + responseAck(getServerTransaction(evt), Response.OK);
63 63 } catch (SipException e) {
64 64 e.printStackTrace();
65 65 } catch (InvalidArgumentException e) {
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/MobilePositionResponseMessageHandler.java
... ... @@ -25,6 +25,7 @@ import org.springframework.util.StringUtils;
25 25  
26 26 import javax.sip.InvalidArgumentException;
27 27 import javax.sip.RequestEvent;
  28 +import javax.sip.ServerTransaction;
28 29 import javax.sip.SipException;
29 30 import javax.sip.message.Response;
30 31 import java.text.ParseException;
... ... @@ -64,11 +65,13 @@ public class MobilePositionResponseMessageHandler extends SIPRequestProcessorPar
64 65 @Override
65 66 public void handForDevice(RequestEvent evt, Device device, Element rootElement) {
66 67  
  68 + ServerTransaction serverTransaction = getServerTransaction(evt);
  69 +
67 70 try {
68 71 rootElement = getRootElement(evt, device.getCharset());
69 72 if (rootElement == null) {
70 73 logger.warn("[ 移动设备位置数据查询回复 ] content cannot be null, {}", evt.getRequest());
71   - responseAck(evt, Response.BAD_REQUEST);
  74 + responseAck(serverTransaction, Response.BAD_REQUEST);
72 75 return;
73 76 }
74 77 MobilePosition mobilePosition = new MobilePosition();
... ... @@ -130,7 +133,7 @@ public class MobilePositionResponseMessageHandler extends SIPRequestProcessorPar
130 133 jsonObject.put("speed", mobilePosition.getSpeed());
131 134 redisCatchStorage.sendMobilePositionMsg(jsonObject);
132 135 //回复 200 OK
133   - responseAck(evt, Response.OK);
  136 + responseAck(serverTransaction, Response.OK);
134 137 } catch (DocumentException | SipException | InvalidArgumentException | ParseException e) {
135 138 e.printStackTrace();
136 139 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/PresetQueryResponseMessageHandler.java
... ... @@ -17,6 +17,7 @@ import org.springframework.stereotype.Component;
17 17  
18 18 import javax.sip.InvalidArgumentException;
19 19 import javax.sip.RequestEvent;
  20 +import javax.sip.ServerTransaction;
20 21 import javax.sip.SipException;
21 22 import javax.sip.message.Response;
22 23 import java.text.ParseException;
... ... @@ -51,10 +52,13 @@ public class PresetQueryResponseMessageHandler extends SIPRequestProcessorParent
51 52 public void handForDevice(RequestEvent evt, Device device, Element element) {
52 53 Element rootElement = null;
53 54 try {
  55 +
  56 + ServerTransaction serverTransaction = getServerTransaction(evt);
  57 +
54 58 rootElement = getRootElement(evt, device.getCharset());
55 59 if (rootElement == null) {
56 60 logger.warn("[ 设备预置位查询应答 ] content cannot be null, {}", evt.getRequest());
57   - responseAck(evt, Response.BAD_REQUEST);
  61 + responseAck(serverTransaction, Response.BAD_REQUEST);
58 62 return;
59 63 }
60 64 Element presetListNumElement = rootElement.element("PresetList");
... ... @@ -63,7 +67,7 @@ public class PresetQueryResponseMessageHandler extends SIPRequestProcessorParent
63 67 String deviceId = getText(rootElement, "DeviceID");
64 68 String key = DeferredResultHolder.CALLBACK_CMD_PRESETQUERY + deviceId;
65 69 if (snElement == null || presetListNumElement == null) {
66   - responseAck(evt, Response.BAD_REQUEST, "xml error");
  70 + responseAck(serverTransaction, Response.BAD_REQUEST, "xml error");
67 71 return;
68 72 }
69 73 int sumNum = Integer.parseInt(presetListNumElement.attributeValue("Num"));
... ... @@ -93,7 +97,7 @@ public class PresetQueryResponseMessageHandler extends SIPRequestProcessorParent
93 97 requestMessage.setKey(key);
94 98 requestMessage.setData(presetQuerySipReqList);
95 99 deferredResultHolder.invokeAllResult(requestMessage);
96   - responseAck(evt, Response.OK);
  100 + responseAck(serverTransaction, Response.OK);
97 101 } catch (DocumentException e) {
98 102 e.printStackTrace();
99 103 } catch (InvalidArgumentException e) {
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/RecordInfoResponseMessageHandler.java
... ... @@ -72,7 +72,7 @@ public class RecordInfoResponseMessageHandler extends SIPRequestProcessorParent
72 72  
73 73 // 回复200 OK
74 74 try {
75   - responseAck(evt, Response.OK);
  75 + responseAck(getServerTransaction(evt), Response.OK);
76 76 taskQueue.offer(new HandlerCatchData(evt, device, rootElement));
77 77 if (!taskQueueHandlerRun) {
78 78 taskQueueHandlerRun = true;
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/response/impl/InviteResponseProcessor.java
... ... @@ -7,6 +7,8 @@ import com.genersoft.iot.vmp.gb28181.transmit.event.response.SIPResponseProcesso
7 7 import com.genersoft.iot.vmp.gb28181.utils.SipUtils;
8 8 import com.genersoft.iot.vmp.utils.GitUtil;
9 9 import gov.nist.javax.sip.ResponseEventExt;
  10 +import gov.nist.javax.sip.message.SIPResponse;
  11 +import gov.nist.javax.sip.stack.SIPClientTransaction;
10 12 import gov.nist.javax.sip.stack.SIPDialog;
11 13 import org.slf4j.Logger;
12 14 import org.slf4j.LoggerFactory;
... ... @@ -78,7 +80,7 @@ public class InviteResponseProcessor extends SIPResponseProcessorAbstract {
78 80 // 下发ack
79 81 if (statusCode == Response.OK) {
80 82 ResponseEventExt event = (ResponseEventExt)evt;
81   - SIPDialog dialog = (SIPDialog)evt.getDialog();
  83 + SIPDialog dialog = new SIPDialog((SIPClientTransaction) event.getClientTransaction(), (SIPResponse) event.getResponse());
82 84 CSeqHeader cseq = (CSeqHeader) response.getHeader(CSeqHeader.NAME);
83 85 Request reqAck = dialog.createAck(cseq.getSeqNumber());
84 86 SipURI requestURI = (SipURI) reqAck.getRequestURI();
... ...
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java
... ... @@ -103,7 +103,7 @@ public class ZLMHttpHookListener {
103 103 @PostMapping(value = "/on_server_keepalive", produces = "application/json;charset=UTF-8")
104 104 public JSONObject onServerKeepalive(@RequestBody JSONObject json){
105 105  
106   - logger.info("[ ZLM HOOK ] on_server_keepalive API调用,参数:" + json.toString());
  106 + logger.info("[ ZLM HOOK ]on_server_keepalive API调用,参数:" + json.toString());
107 107 String mediaServerId = json.getString("mediaServerId");
108 108 List<ZlmHttpHookSubscribe.Event> subscribes = this.subscribe.getSubscribes(HookType.on_server_keepalive);
109 109 if (subscribes != null && subscribes.size() > 0) {
... ... @@ -417,10 +417,11 @@ public class ZLMHttpHookListener {
417 417 String schema = item.getSchema();
418 418 List<MediaItem.MediaTrack> tracks = item.getTracks();
419 419 boolean regist = item.isRegist();
420   - if (item.getOriginType() == OriginType.RTMP_PUSH.ordinal()
421   - || item.getOriginType() == OriginType.RTSP_PUSH.ordinal()
422   - || item.getOriginType() == OriginType.RTC_PUSH.ordinal()) {
423   - if (regist) {
  420 + if (regist) {
  421 + if (item.getOriginType() == OriginType.RTMP_PUSH.ordinal()
  422 + || item.getOriginType() == OriginType.RTSP_PUSH.ordinal()
  423 + || item.getOriginType() == OriginType.RTC_PUSH.ordinal()) {
  424 +
424 425 StreamAuthorityInfo streamAuthorityInfo = redisCatchStorage.getStreamAuthorityInfo(app, stream);
425 426 if (streamAuthorityInfo == null) {
426 427 streamAuthorityInfo = StreamAuthorityInfo.getInstanceByHook(item);
... ... @@ -429,9 +430,9 @@ public class ZLMHttpHookListener {
429 430 streamAuthorityInfo.setOriginTypeStr(item.getOriginTypeStr());
430 431 }
431 432 redisCatchStorage.updateStreamAuthorityInfo(app, stream, streamAuthorityInfo);
432   - }else {
433   - redisCatchStorage.removeStreamAuthorityInfo(app, stream);
434 433 }
  434 + }else {
  435 + redisCatchStorage.removeStreamAuthorityInfo(app, stream);
435 436 }
436 437  
437 438 if ("rtsp".equals(schema)){
... ... @@ -451,15 +452,12 @@ public class ZLMHttpHookListener {
451 452 if (streamInfo!=null){
452 453 redisCatchStorage.stopPlay(streamInfo);
453 454 storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId());
454   - // 如果正在给上级推送,则发送bye
455   -
456 455 }else{
457 456 streamInfo = redisCatchStorage.queryPlayback(null, null, stream, null);
458 457 if (streamInfo != null) {
459 458 redisCatchStorage.stopPlayback(streamInfo.getDeviceID(), streamInfo.getChannelId(),
460 459 streamInfo.getStream(), null);
461 460 }
462   - // 如果正在给上级推送,则发送bye
463 461 }
464 462 }else {
465 463 if (!"rtp".equals(app)){
... ... @@ -509,6 +507,19 @@ public class ZLMHttpHookListener {
509 507 }
510 508 }
511 509 }
  510 + if (!regist) {
  511 + List<SendRtpItem> sendRtpItems = redisCatchStorage.querySendRTPServerByStream(stream);
  512 + if (sendRtpItems.size() > 0) {
  513 + for (SendRtpItem sendRtpItem : sendRtpItems) {
  514 + if (sendRtpItem.getApp().equals(app)) {
  515 + String platformId = sendRtpItem.getPlatformId();
  516 + ParentPlatform platform = storager.queryParentPlatByServerGBId(platformId);
  517 +
  518 + commanderFroPlatform.streamByeCmd(platform, sendRtpItem);
  519 + }
  520 + }
  521 + }
  522 + }
512 523 }
513 524  
514 525 JSONObject ret = new JSONObject();
... ...
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMMediaListManager.java
... ... @@ -17,6 +17,7 @@ import org.slf4j.LoggerFactory;
17 17 import org.springframework.beans.factory.annotation.Autowired;
18 18 import org.springframework.stereotype.Component;
19 19  
  20 +import java.text.ParseException;
20 21 import java.util.*;
21 22 import java.util.concurrent.ConcurrentHashMap;
22 23  
... ... @@ -83,7 +84,11 @@ public class ZLMMediaListManager {
83 84 }
84 85 if (transform != null) {
85 86 if (getChannelOnlineEventLister(transform.getApp(), transform.getStream()) != null) {
86   - getChannelOnlineEventLister(transform.getApp(), transform.getStream()).run(transform.getApp(), transform.getStream(), transform.getServerId());
  87 + try {
  88 + getChannelOnlineEventLister(transform.getApp(), transform.getStream()).run(transform.getApp(), transform.getStream(), transform.getServerId());
  89 + } catch (ParseException e) {
  90 + throw new RuntimeException(e);
  91 + }
87 92 removedChannelOnlineEventLister(transform.getApp(), transform.getStream());
88 93 }
89 94 }
... ... @@ -95,7 +100,11 @@ public class ZLMMediaListManager {
95 100 // 查看推流状态
96 101 if (zlmrtpServerFactory.isStreamReady(mediaServerItem, app, stream)) {
97 102 if (getChannelOnlineEventLister(app, stream) != null) {
98   - getChannelOnlineEventLister(app, stream).run(app, stream, mediaServerId);
  103 + try {
  104 + getChannelOnlineEventLister(app, stream).run(app, stream, mediaServerId);
  105 + } catch (ParseException e) {
  106 + throw new RuntimeException(e);
  107 + }
99 108 removedChannelOnlineEventLister(app, stream);
100 109 }
101 110 }
... ...
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRTPServerFactory.java
... ... @@ -98,7 +98,18 @@ public class ZLMRTPServerFactory {
98 98 result = rtpInfo.getInteger("local_port");
99 99 if (result == 0) {
100 100 // 此时说明rtpServer已经创建但是流还没有推上来
101   -
  101 + // 此时重新打开rtpServer
  102 + Map<String, Object> param = new HashMap<>();
  103 + param.put("stream_id", streamId);
  104 + JSONObject jsonObject = zlmresTfulUtils.closeRtpServer(mediaServerItem, param);
  105 + if (jsonObject != null ) {
  106 + System.out.println(jsonObject);
  107 + if (jsonObject.getInteger("code") == 0) {
  108 + return createRTPServer(mediaServerItem, streamId, ssrc, port);
  109 + }else {
  110 + logger.warn("[开启rtpServer], 重启RtpServer错误");
  111 + }
  112 + }
102 113 }
103 114 return result;
104 115 }
... ... @@ -326,12 +337,12 @@ public class ZLMRTPServerFactory {
326 337 Boolean result = false;
327 338 JSONObject jsonObject = zlmresTfulUtils.stopSendRtp(mediaServerItem, param);
328 339 if (jsonObject == null) {
329   - logger.error("停止RTP推流失败: 请检查ZLM服务");
  340 + logger.error("[停止RTP推流] 失败: 请检查ZLM服务");
330 341 } else if (jsonObject.getInteger("code") == 0) {
331 342 result= true;
332   - logger.info("停止RTP推流成功");
  343 + logger.info("[停止RTP推流] 成功");
333 344 } else {
334   - logger.error("停止RTP推流失败: {}, 参数:{}",jsonObject.getString("msg"),JSONObject.toJSON(param));
  345 + logger.error("[停止RTP推流] 失败: {}, 参数:{}->\r\n{}",jsonObject.getString("msg"),JSONObject.toJSON(param), jsonObject);
335 346 }
336 347 return result;
337 348 }
... ...
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRunner.java
... ... @@ -104,7 +104,7 @@ public class ZLMRunner implements CommandLineRunner {
104 104 }, 60 * 1000 );
105 105 }
106 106  
107   - @Async
  107 + @Async("taskExecutor")
108 108 public void connectZlmServer(MediaServerItem mediaServerItem){
109 109 String connectZlmServerTaskKey = "connect-zlm-" + mediaServerItem.getId();
110 110 ZLMServerConfig zlmServerConfigFirst = getMediaServerConfig(mediaServerItem);
... ...
src/main/java/com/genersoft/iot/vmp/media/zlm/ZlmHttpHookSubscribe.java
... ... @@ -137,8 +137,6 @@ public class ZlmHttpHookSubscribe {
137 137 @Scheduled(cron="0 0/5 * * * ?") //每5分钟执行一次
138 138 public void execute(){
139 139  
140   - logger.info("[hook订阅] 清理");
141   -
142 140 Instant instant = Instant.now().minusMillis(TimeUnit.MINUTES.toMillis(5));
143 141 int total = 0;
144 142 for (HookType hookType : allSubscribes.keySet()) {
... ... @@ -153,6 +151,5 @@ public class ZlmHttpHookSubscribe {
153 151 }
154 152 }
155 153 }
156   - logger.info("[hook订阅] 清理结束,共清理{}条过期数据", total);
157 154 }
158 155 }
... ...
src/main/java/com/genersoft/iot/vmp/media/zlm/dto/ChannelOnlineEvent.java
1 1 package com.genersoft.iot.vmp.media.zlm.dto;
2 2  
  3 +import java.text.ParseException;
  4 +
3 5 /**
4 6 * @author lin
5 7 */
6 8 public interface ChannelOnlineEvent {
7 9  
8   - void run(String app, String stream, String serverId);
  10 + void run(String app, String stream, String serverId) throws ParseException;
9 11 }
... ...
src/main/java/com/genersoft/iot/vmp/media/zlm/event/ZLMStatusEventListener.java
... ... @@ -36,7 +36,7 @@ public class ZLMStatusEventListener {
36 36 @Autowired
37 37 private IPlayService playService;
38 38  
39   - @Async
  39 + @Async("taskExecutor")
40 40 @EventListener
41 41 public void onApplicationEvent(ZLMOnlineEvent event) {
42 42 logger.info("[ZLM] 上线 ID:" + event.getMediaServerId());
... ... @@ -45,7 +45,7 @@ public class ZLMStatusEventListener {
45 45 playService.zlmServerOnline(event.getMediaServerId());
46 46 }
47 47  
48   - @Async
  48 + @Async("taskExecutor")
49 49 @EventListener
50 50 public void onApplicationEvent(ZLMOfflineEvent event) {
51 51  
... ...
src/main/java/com/genersoft/iot/vmp/service/IPlatformService.java
1 1 package com.genersoft.iot.vmp.service;
2 2  
  3 +import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
3 4 import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
  5 +import com.genersoft.iot.vmp.gb28181.bean.SubscribeInfo;
  6 +import com.genersoft.iot.vmp.service.bean.GPSMsgInfo;
4 7 import com.github.pagehelper.PageInfo;
5 8  
  9 +import java.util.List;
  10 +
6 11 /**
7 12 * 国标平台的业务类
8 13 * @author lin
... ... @@ -42,4 +47,10 @@ public interface IPlatformService {
42 47 * @param parentPlatform
43 48 */
44 49 void login(ParentPlatform parentPlatform);
  50 +
  51 + /**
  52 + * 向上级平台发送位置订阅
  53 + * @param platformId 平台
  54 + */
  55 + void sendNotifyMobilePosition(String platformId);
45 56 }
... ...
src/main/java/com/genersoft/iot/vmp/service/impl/PlatformChannelServiceImpl.java
... ... @@ -73,7 +73,9 @@ public class PlatformChannelServiceImpl implements IPlatformChannelService {
73 73 result = platformChannelMapper.addChannels(platformId, channelReducesToAdd);
74 74 // TODO 后续给平台增加控制开关以控制是否响应目录订阅
75 75 List<DeviceChannel> deviceChannelList = getDeviceChannelListByChannelReduceList(channelReducesToAdd, catalogId, platform);
76   - eventPublisher.catalogEventPublish(platformId, deviceChannelList, CatalogEvent.ADD);
  76 + if (deviceChannelList != null) {
  77 + eventPublisher.catalogEventPublish(platformId, deviceChannelList, CatalogEvent.ADD);
  78 + }
77 79 }
78 80  
79 81 return result;
... ... @@ -83,7 +85,7 @@ public class PlatformChannelServiceImpl implements IPlatformChannelService {
83 85 List<DeviceChannel> deviceChannelList = new ArrayList<>();
84 86 if (channelReduces.size() > 0){
85 87 PlatformCatalog catalog = catalogManager.select(catalogId);
86   - if (catalog == null && !catalogId.equals(platform.getServerGBId())) {
  88 + if (catalog == null && !catalogId.equals(platform.getDeviceGBId())) {
87 89 logger.warn("未查询到目录{}的信息", catalogId);
88 90 return null;
89 91 }
... ...
src/main/java/com/genersoft/iot/vmp/service/impl/PlatformServiceImpl.java
1 1 package com.genersoft.iot.vmp.service.impl;
2 2  
3 3 import com.genersoft.iot.vmp.conf.DynamicTask;
4   -import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
5   -import com.genersoft.iot.vmp.gb28181.bean.ParentPlatformCatch;
6   -import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem;
7   -import com.genersoft.iot.vmp.gb28181.bean.SubscribeHolder;
  4 +import com.genersoft.iot.vmp.conf.UserSetting;
  5 +import com.genersoft.iot.vmp.gb28181.bean.*;
8 6 import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
9 7 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform;
10 8 import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
11 9 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
12 10 import com.genersoft.iot.vmp.service.IMediaServerService;
13 11 import com.genersoft.iot.vmp.service.IPlatformService;
  12 +import com.genersoft.iot.vmp.service.bean.GPSMsgInfo;
14 13 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
  14 +import com.genersoft.iot.vmp.storager.dao.GbStreamMapper;
15 15 import com.genersoft.iot.vmp.storager.dao.ParentPlatformMapper;
16 16 import com.github.pagehelper.PageHelper;
17 17 import com.github.pagehelper.PageInfo;
... ... @@ -57,6 +57,12 @@ public class PlatformServiceImpl implements IPlatformService {
57 57 @Autowired
58 58 private SubscribeHolder subscribeHolder;
59 59  
  60 + @Autowired
  61 + private GbStreamMapper gbStreamMapper;
  62 +
  63 + @Autowired
  64 + private UserSetting userSetting;
  65 +
60 66  
61 67  
62 68 @Override
... ... @@ -228,4 +234,34 @@ public class PlatformServiceImpl implements IPlatformService {
228 234 60*1000);
229 235 }, null);
230 236 }
  237 +
  238 + @Override
  239 + public void sendNotifyMobilePosition(String platformId) {
  240 + ParentPlatform platform = platformMapper.getParentPlatByServerGBId(platformId);
  241 + if (platform == null) {
  242 + return;
  243 + }
  244 + SubscribeInfo subscribe = subscribeHolder.getMobilePositionSubscribe(platform.getServerGBId());
  245 + if (subscribe != null) {
  246 +
  247 + // TODO 暂时只处理视频流的回复,后续增加对国标设备的支持
  248 + List<DeviceChannel> gbStreams = gbStreamMapper.queryGbStreamListInPlatform(platform.getServerGBId(), userSetting.isUsePushingAsStatus());
  249 + if (gbStreams.size() == 0) {
  250 + return;
  251 + }
  252 + for (DeviceChannel deviceChannel : gbStreams) {
  253 + String gbId = deviceChannel.getChannelId();
  254 + GPSMsgInfo gpsMsgInfo = redisCatchStorage.getGpsMsgInfo(gbId);
  255 + // 无最新位置不发送
  256 + if (gpsMsgInfo != null) {
  257 + // 经纬度都为0不发送
  258 + if (gpsMsgInfo.getLng() == 0 && gpsMsgInfo.getLat() == 0) {
  259 + continue;
  260 + }
  261 + // 发送GPS消息
  262 + commanderForPlatform.sendNotifyMobilePosition(platform, gpsMsgInfo, subscribe);
  263 + }
  264 + }
  265 + }
  266 + }
231 267 }
... ...
src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
... ... @@ -177,6 +177,7 @@ public class PlayServiceImpl implements IPlayService {
177 177 }
178 178 });
179 179 });
  180 +
180 181 if (streamInfo != null) {
181 182 String streamId = streamInfo.getStream();
182 183 if (streamId == null) {
... ... @@ -281,7 +282,7 @@ public class PlayServiceImpl implements IPlayService {
281 282 if (ssrcInfo == null) {
282 283 ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId, device.isSsrcCheck(), false);
283 284 }
284   - logger.info("[点播开始] deviceId: {}, channelId: {}, SSRC: {}", device.getDeviceId(), channelId, ssrcInfo.getSsrc() );
  285 + logger.info("[点播开始] deviceId: {}, channelId: {},收流端口: {}, 收流模式:{}, SSRC: {}, SSRC校验:{}", device.getDeviceId(), channelId, ssrcInfo.getPort(), device.getStreamMode(), ssrcInfo.getSsrc(), device.isSsrcCheck() );
285 286 // 超时处理
286 287 String timeOutTaskKey = UUID.randomUUID().toString();
287 288 SSRCInfo finalSsrcInfo = ssrcInfo;
... ... @@ -290,12 +291,12 @@ public class PlayServiceImpl implements IPlayService {
290 291  
291 292 SIPDialog dialog = streamSession.getDialogByStream(device.getDeviceId(), channelId, finalSsrcInfo.getStream());
292 293 if (dialog != null) {
293   - logger.info("[点播超时] 收流超时 deviceId: {}, channelId: {}", device.getDeviceId(), channelId);
  294 + logger.info("[点播超时] 收流超时 deviceId: {}, channelId: {},端口:{}, SSRC: {}", device.getDeviceId(), channelId, finalSsrcInfo.getPort(), finalSsrcInfo.getSsrc());
294 295 timeoutCallback.run(1, "收流超时");
295 296 // 点播超时回复BYE 同时释放ssrc以及此次点播的资源
296 297 cmder.streamByeCmd(device.getDeviceId(), channelId, finalSsrcInfo.getStream(), null);
297 298 }else {
298   - logger.info("[点播超时] 消息未响应 deviceId: {}, channelId: {}", device.getDeviceId(), channelId);
  299 + logger.info("[点播超时] 消息未响应 deviceId: {}, channelId: {},端口:{}, SSRC: {}", device.getDeviceId(), channelId, finalSsrcInfo.getPort(), finalSsrcInfo.getSsrc());
299 300 timeoutCallback.run(0, "点播超时");
300 301 mediaServerService.releaseSsrc(mediaServerItem.getId(), finalSsrcInfo.getSsrc());
301 302 mediaServerService.closeRTPServer(mediaServerItem, finalSsrcInfo.getStream());
... ...
src/main/java/com/genersoft/iot/vmp/service/impl/RedisAlarmMsgListener.java renamed to src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisAlarmMsgListener.java
1   -package com.genersoft.iot.vmp.service.impl;
  1 +package com.genersoft.iot.vmp.service.redisMsg;
2 2  
3 3 import com.alibaba.fastjson.JSON;
4 4 import com.genersoft.iot.vmp.gb28181.bean.*;
5 5 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
6 6 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
7   -import com.genersoft.iot.vmp.service.IPlatformChannelService;
8   -import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
9 7 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
10 8 import com.genersoft.iot.vmp.utils.DateUtil;
11 9 import org.slf4j.Logger;
12 10 import org.slf4j.LoggerFactory;
13 11 import org.springframework.beans.factory.annotation.Autowired;
  12 +import org.springframework.beans.factory.annotation.Qualifier;
14 13 import org.springframework.data.redis.connection.Message;
15 14 import org.springframework.data.redis.connection.MessageListener;
  15 +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
16 16 import org.springframework.stereotype.Component;
17 17 import org.springframework.util.ObjectUtils;
18 18  
  19 +import javax.validation.constraints.NotNull;
19 20 import java.util.List;
  21 +import java.util.concurrent.ConcurrentLinkedQueue;
20 22  
21 23  
22 24 @Component
... ... @@ -33,45 +35,68 @@ public class RedisAlarmMsgListener implements MessageListener {
33 35 @Autowired
34 36 private IVideoManagerStorage storage;
35 37  
  38 + private boolean taskQueueHandlerRun = false;
  39 +
  40 + private ConcurrentLinkedQueue<Message> taskQueue = new ConcurrentLinkedQueue<>();
  41 +
  42 + @Qualifier("taskExecutor")
  43 + @Autowired
  44 + private ThreadPoolTaskExecutor taskExecutor;
  45 +
36 46 @Override
37   - public void onMessage(Message message, byte[] bytes) {
  47 + public void onMessage(@NotNull Message message, byte[] bytes) {
38 48 logger.info("收到来自REDIS的ALARM通知: {}", new String(message.getBody()));
39   - AlarmChannelMessage alarmChannelMessage = JSON.parseObject(message.getBody(), AlarmChannelMessage.class);
40   - if (alarmChannelMessage == null) {
41   - logger.warn("[REDIS的ALARM通知]消息解析失败");
42   - return;
43   - }
44   - String gbId = alarmChannelMessage.getGbId();
45   -
46   - DeviceAlarm deviceAlarm = new DeviceAlarm();
47   - deviceAlarm.setCreateTime(DateUtil.getNow());
48   - deviceAlarm.setChannelId(gbId);
49   - deviceAlarm.setAlarmDescription(alarmChannelMessage.getAlarmDescription());
50   - deviceAlarm.setAlarmMethod("" + alarmChannelMessage.getAlarmSn());
51   - deviceAlarm.setAlarmPriority("1");
52   - deviceAlarm.setAlarmTime(DateUtil.getNowForISO8601());
53   - deviceAlarm.setAlarmType("1");
54   - deviceAlarm.setLongitude(0);
55   - deviceAlarm.setLatitude(0);
56   -
57   - if (ObjectUtils.isEmpty(gbId)) {
58   - // 发送给所有的上级
59   - List<ParentPlatform> parentPlatforms = storage.queryEnableParentPlatformList(true);
60   - if (parentPlatforms.size() > 0) {
61   - for (ParentPlatform parentPlatform : parentPlatforms) {
62   - commanderForPlatform.sendAlarmMessage(parentPlatform, deviceAlarm);
  49 +
  50 + taskQueue.offer(message);
  51 + if (!taskQueueHandlerRun) {
  52 + taskQueueHandlerRun = true;
  53 + logger.info("[线程池信息]活动线程数:{}, 最大线程数: {}", taskExecutor.getActiveCount(), taskExecutor.getMaxPoolSize());
  54 + taskExecutor.execute(() -> {
  55 + while (!taskQueue.isEmpty()) {
  56 + Message msg = taskQueue.poll();
  57 +
  58 + AlarmChannelMessage alarmChannelMessage = JSON.parseObject(msg.getBody(), AlarmChannelMessage.class);
  59 + if (alarmChannelMessage == null) {
  60 + logger.warn("[REDIS的ALARM通知]消息解析失败");
  61 + continue;
  62 + }
  63 + String gbId = alarmChannelMessage.getGbId();
  64 +
  65 + DeviceAlarm deviceAlarm = new DeviceAlarm();
  66 + deviceAlarm.setCreateTime(DateUtil.getNow());
  67 + deviceAlarm.setChannelId(gbId);
  68 + deviceAlarm.setAlarmDescription(alarmChannelMessage.getAlarmDescription());
  69 + deviceAlarm.setAlarmMethod("" + alarmChannelMessage.getAlarmSn());
  70 + deviceAlarm.setAlarmPriority("1");
  71 + deviceAlarm.setAlarmTime(DateUtil.getNowForISO8601());
  72 + deviceAlarm.setAlarmType("1");
  73 + deviceAlarm.setLongitude(0);
  74 + deviceAlarm.setLatitude(0);
  75 +
  76 + if (ObjectUtils.isEmpty(gbId)) {
  77 + // 发送给所有的上级
  78 + List<ParentPlatform> parentPlatforms = storage.queryEnableParentPlatformList(true);
  79 + if (parentPlatforms.size() > 0) {
  80 + for (ParentPlatform parentPlatform : parentPlatforms) {
  81 + commanderForPlatform.sendAlarmMessage(parentPlatform, deviceAlarm);
  82 + }
  83 + }
  84 + }else {
  85 + Device device = storage.queryVideoDevice(gbId);
  86 + ParentPlatform platform = storage.queryParentPlatByServerGBId(gbId);
  87 + if (device != null && platform == null) {
  88 + commander.sendAlarmMessage(device, deviceAlarm);
  89 + }else if (device == null && platform != null){
  90 + commanderForPlatform.sendAlarmMessage(platform, deviceAlarm);
  91 + }else {
  92 + logger.warn("无法确定" + gbId + "是平台还是设备");
  93 + }
  94 + }
63 95 }
64   - }
65   - }else {
66   - Device device = storage.queryVideoDevice(gbId);
67   - ParentPlatform platform = storage.queryParentPlatByServerGBId(gbId);
68   - if (device != null && platform == null) {
69   - commander.sendAlarmMessage(device, deviceAlarm);
70   - }else if (device == null && platform != null){
71   - commanderForPlatform.sendAlarmMessage(platform, deviceAlarm);
72   - }else {
73   - logger.warn("无法确定" + gbId + "是平台还是设备");
74   - }
  96 + taskQueueHandlerRun = false;
  97 + });
75 98 }
  99 +
  100 +
76 101 }
77 102 }
... ...
src/main/java/com/genersoft/iot/vmp/service/impl/RedisGbPlayMsgListener.java renamed to src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisGbPlayMsgListener.java
1   -package com.genersoft.iot.vmp.service.impl;
  1 +package com.genersoft.iot.vmp.service.redisMsg;
2 2  
3 3 import com.alibaba.fastjson.JSON;
4 4 import com.alibaba.fastjson.JSONObject;
... ... @@ -19,14 +19,18 @@ import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
19 19 import org.slf4j.Logger;
20 20 import org.slf4j.LoggerFactory;
21 21 import org.springframework.beans.factory.annotation.Autowired;
  22 +import org.springframework.beans.factory.annotation.Qualifier;
22 23 import org.springframework.data.redis.connection.Message;
23 24 import org.springframework.data.redis.connection.MessageListener;
  25 +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
24 26 import org.springframework.stereotype.Component;
25 27  
  28 +import java.text.ParseException;
26 29 import java.util.HashMap;
27 30 import java.util.Map;
28 31 import java.util.UUID;
29 32 import java.util.concurrent.ConcurrentHashMap;
  33 +import java.util.concurrent.ConcurrentLinkedQueue;
30 34  
31 35  
32 36 /**
... ... @@ -84,9 +88,17 @@ public class RedisGbPlayMsgListener implements MessageListener {
84 88 @Autowired
85 89 private ZlmHttpHookSubscribe subscribe;
86 90  
  91 + private boolean taskQueueHandlerRun = false;
  92 +
  93 + private ConcurrentLinkedQueue<Message> taskQueue = new ConcurrentLinkedQueue<>();
  94 +
  95 + @Qualifier("taskExecutor")
  96 + @Autowired
  97 + private ThreadPoolTaskExecutor taskExecutor;
  98 +
87 99  
88 100 public interface PlayMsgCallback{
89   - void handler(ResponseSendItemMsg responseSendItemMsg);
  101 + void handler(ResponseSendItemMsg responseSendItemMsg) throws ParseException;
90 102 }
91 103  
92 104 public interface PlayMsgCallbackForStartSendRtpStream{
... ... @@ -99,90 +111,107 @@ public class RedisGbPlayMsgListener implements MessageListener {
99 111  
100 112 @Override
101 113 public void onMessage(Message message, byte[] bytes) {
102   - JSONObject msgJSON = JSON.parseObject(message.getBody(), JSONObject.class);
103   - WvpRedisMsg wvpRedisMsg = JSON.toJavaObject(msgJSON, WvpRedisMsg.class);
104   - if (!userSetting.getServerId().equals(wvpRedisMsg.getToId())) {
105   - return;
106   - }
107   - if (WvpRedisMsg.isRequest(wvpRedisMsg)) {
108   - logger.info("[收到REDIS通知] 请求: {}", new String(message.getBody()));
109   -
110   - switch (wvpRedisMsg.getCmd()){
111   - case WvpRedisMsgCmd.GET_SEND_ITEM:
112   - RequestSendItemMsg content = JSON.toJavaObject((JSONObject)wvpRedisMsg.getContent(), RequestSendItemMsg.class);
113   - requestSendItemMsgHand(content, wvpRedisMsg.getFromId(), wvpRedisMsg.getSerial());
114   - break;
115   - case WvpRedisMsgCmd.REQUEST_PUSH_STREAM:
116   - RequestPushStreamMsg param = JSON.toJavaObject((JSONObject)wvpRedisMsg.getContent(), RequestPushStreamMsg.class);;
117   - requestPushStreamMsgHand(param, wvpRedisMsg.getFromId(), wvpRedisMsg.getSerial());
118   - break;
119   - default:
120   - break;
121   - }
122 114  
123   - }else {
124   - logger.info("[收到REDIS通知] 回复: {}", new String(message.getBody()));
125   - switch (wvpRedisMsg.getCmd()){
126   - case WvpRedisMsgCmd.GET_SEND_ITEM:
127   -
128   - WVPResult content = JSON.toJavaObject((JSONObject)wvpRedisMsg.getContent(), WVPResult.class);
129   -
130   - String key = wvpRedisMsg.getSerial();
131   - switch (content.getCode()) {
132   - case 0:
133   - ResponseSendItemMsg responseSendItemMsg =JSON.toJavaObject((JSONObject)content.getData(), ResponseSendItemMsg.class);
134   - PlayMsgCallback playMsgCallback = callbacks.get(key);
135   - if (playMsgCallback != null) {
136   - callbacksForError.remove(key);
137   - playMsgCallback.handler(responseSendItemMsg);
138   - }
139   - break;
140   - case ERROR_CODE_MEDIA_SERVER_NOT_FOUND:
141   - case ERROR_CODE_OFFLINE:
142   - case ERROR_CODE_TIMEOUT:
143   - PlayMsgErrorCallback errorCallback = callbacksForError.get(key);
144   - if (errorCallback != null) {
145   - callbacks.remove(key);
146   - errorCallback.handler(content);
147   - }
148   - break;
149   - default:
150   - break;
  115 + taskQueue.offer(message);
  116 + if (!taskQueueHandlerRun) {
  117 + taskQueueHandlerRun = true;
  118 + taskExecutor.execute(() -> {
  119 + while (!taskQueue.isEmpty()) {
  120 + Message msg = taskQueue.poll();
  121 + JSONObject msgJSON = JSON.parseObject(msg.getBody(), JSONObject.class);
  122 + WvpRedisMsg wvpRedisMsg = JSON.toJavaObject(msgJSON, WvpRedisMsg.class);
  123 + if (!userSetting.getServerId().equals(wvpRedisMsg.getToId())) {
  124 + continue;
151 125 }
152   - break;
153   - case WvpRedisMsgCmd.REQUEST_PUSH_STREAM:
154   - WVPResult wvpResult = JSON.toJavaObject((JSONObject)wvpRedisMsg.getContent(), WVPResult.class);
155   - String serial = wvpRedisMsg.getSerial();
156   - switch (wvpResult.getCode()) {
157   - case 0:
158   - JSONObject jsonObject = (JSONObject)wvpResult.getData();
159   - PlayMsgCallbackForStartSendRtpStream playMsgCallback = callbacksForStartSendRtpStream.get(serial);
160   - if (playMsgCallback != null) {
161   - callbacksForError.remove(serial);
162   - playMsgCallback.handler(jsonObject);
163   - }
164   - break;
165   - case ERROR_CODE_MEDIA_SERVER_NOT_FOUND:
166   - case ERROR_CODE_OFFLINE:
167   - case ERROR_CODE_TIMEOUT:
168   - PlayMsgErrorCallback errorCallback = callbacksForError.get(serial);
169   - if (errorCallback != null) {
170   - callbacks.remove(serial);
171   - errorCallback.handler(wvpResult);
172   - }
173   - break;
174   - default:
175   - break;
  126 + if (WvpRedisMsg.isRequest(wvpRedisMsg)) {
  127 + logger.info("[收到REDIS通知] 请求: {}", new String(msg.getBody()));
  128 +
  129 + switch (wvpRedisMsg.getCmd()){
  130 + case WvpRedisMsgCmd.GET_SEND_ITEM:
  131 + RequestSendItemMsg content = JSON.toJavaObject((JSONObject)wvpRedisMsg.getContent(), RequestSendItemMsg.class);
  132 + requestSendItemMsgHand(content, wvpRedisMsg.getFromId(), wvpRedisMsg.getSerial());
  133 + break;
  134 + case WvpRedisMsgCmd.REQUEST_PUSH_STREAM:
  135 + RequestPushStreamMsg param = JSON.toJavaObject((JSONObject)wvpRedisMsg.getContent(), RequestPushStreamMsg.class);;
  136 + requestPushStreamMsgHand(param, wvpRedisMsg.getFromId(), wvpRedisMsg.getSerial());
  137 + break;
  138 + default:
  139 + break;
  140 + }
  141 +
  142 + }else {
  143 + logger.info("[收到REDIS通知] 回复: {}", new String(msg.getBody()));
  144 + switch (wvpRedisMsg.getCmd()){
  145 + case WvpRedisMsgCmd.GET_SEND_ITEM:
  146 +
  147 + WVPResult content = JSON.toJavaObject((JSONObject)wvpRedisMsg.getContent(), WVPResult.class);
  148 +
  149 + String key = wvpRedisMsg.getSerial();
  150 + switch (content.getCode()) {
  151 + case 0:
  152 + ResponseSendItemMsg responseSendItemMsg =JSON.toJavaObject((JSONObject)content.getData(), ResponseSendItemMsg.class);
  153 + PlayMsgCallback playMsgCallback = callbacks.get(key);
  154 + if (playMsgCallback != null) {
  155 + callbacksForError.remove(key);
  156 + try {
  157 + playMsgCallback.handler(responseSendItemMsg);
  158 + } catch (ParseException e) {
  159 + throw new RuntimeException(e);
  160 + }
  161 + }
  162 + break;
  163 + case ERROR_CODE_MEDIA_SERVER_NOT_FOUND:
  164 + case ERROR_CODE_OFFLINE:
  165 + case ERROR_CODE_TIMEOUT:
  166 + PlayMsgErrorCallback errorCallback = callbacksForError.get(key);
  167 + if (errorCallback != null) {
  168 + callbacks.remove(key);
  169 + errorCallback.handler(content);
  170 + }
  171 + break;
  172 + default:
  173 + break;
  174 + }
  175 + break;
  176 + case WvpRedisMsgCmd.REQUEST_PUSH_STREAM:
  177 + WVPResult wvpResult = JSON.toJavaObject((JSONObject)wvpRedisMsg.getContent(), WVPResult.class);
  178 + String serial = wvpRedisMsg.getSerial();
  179 + switch (wvpResult.getCode()) {
  180 + case 0:
  181 + JSONObject jsonObject = (JSONObject)wvpResult.getData();
  182 + PlayMsgCallbackForStartSendRtpStream playMsgCallback = callbacksForStartSendRtpStream.get(serial);
  183 + if (playMsgCallback != null) {
  184 + callbacksForError.remove(serial);
  185 + playMsgCallback.handler(jsonObject);
  186 + }
  187 + break;
  188 + case ERROR_CODE_MEDIA_SERVER_NOT_FOUND:
  189 + case ERROR_CODE_OFFLINE:
  190 + case ERROR_CODE_TIMEOUT:
  191 + PlayMsgErrorCallback errorCallback = callbacksForError.get(serial);
  192 + if (errorCallback != null) {
  193 + callbacks.remove(serial);
  194 + errorCallback.handler(wvpResult);
  195 + }
  196 + break;
  197 + default:
  198 + break;
  199 + }
  200 + break;
  201 + default:
  202 + break;
  203 + }
176 204 }
177   - break;
178   - default:
179   - break;
180   - }
  205 + }
  206 + taskQueueHandlerRun = false;
  207 + });
181 208 }
182 209  
183 210  
184 211  
185 212  
  213 +
  214 +
186 215 }
187 216  
188 217 /**
... ...
src/main/java/com/genersoft/iot/vmp/service/impl/RedisGpsMsgListener.java renamed to src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisGpsMsgListener.java
1   -package com.genersoft.iot.vmp.service.impl;
  1 +package com.genersoft.iot.vmp.service.redisMsg;
2 2  
3 3 import com.alibaba.fastjson.JSON;
4   -import com.genersoft.iot.vmp.gb28181.bean.HandlerCatchData;
5 4 import com.genersoft.iot.vmp.service.bean.GPSMsgInfo;
6 5 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
7 6 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
... ... @@ -36,7 +35,7 @@ public class RedisGpsMsgListener implements MessageListener {
36 35 @Autowired
37 36 private IVideoManagerStorage storager;
38 37  
39   - private final ConcurrentLinkedQueue<Message> taskQueue = new ConcurrentLinkedQueue<>();
  38 + private ConcurrentLinkedQueue<Message> taskQueue = new ConcurrentLinkedQueue<>();
40 39  
41 40 @Qualifier("taskExecutor")
42 41 @Autowired
... ...
src/main/java/com/genersoft/iot/vmp/service/impl/RedisPushStreamResponseListener.java renamed to src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisPushStreamResponseListener.java
1   -package com.genersoft.iot.vmp.service.impl;
  1 +package com.genersoft.iot.vmp.service.redisMsg;
2 2  
3 3 import com.alibaba.fastjson.JSON;
4   -import com.alibaba.fastjson.JSONObject;
5   -import com.genersoft.iot.vmp.media.zlm.dto.ChannelOnlineEvent;
6   -import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem;
7   -import com.genersoft.iot.vmp.service.IGbStreamService;
8   -import com.genersoft.iot.vmp.service.IMediaServerService;
9   -import com.genersoft.iot.vmp.service.IStreamPushService;
  4 +import com.genersoft.iot.vmp.service.bean.GPSMsgInfo;
10 5 import com.genersoft.iot.vmp.service.bean.MessageForPushChannelResponse;
11   -import com.genersoft.iot.vmp.utils.DateUtil;
12 6 import org.slf4j.Logger;
13 7 import org.slf4j.LoggerFactory;
  8 +import org.springframework.beans.factory.annotation.Autowired;
  9 +import org.springframework.beans.factory.annotation.Qualifier;
14 10 import org.springframework.data.redis.connection.Message;
15 11 import org.springframework.data.redis.connection.MessageListener;
  12 +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
16 13 import org.springframework.stereotype.Component;
17 14 import org.springframework.util.ObjectUtils;
18 15  
19   -import javax.annotation.Resource;
20   -import java.util.ArrayList;
21   -import java.util.List;
22 16 import java.util.Map;
23 17 import java.util.concurrent.ConcurrentHashMap;
  18 +import java.util.concurrent.ConcurrentLinkedQueue;
24 19  
25 20 /**
26 21 * 接收redis返回的推流结果
... ... @@ -31,6 +26,15 @@ public class RedisPushStreamResponseListener implements MessageListener {
31 26  
32 27 private final static Logger logger = LoggerFactory.getLogger(RedisPushStreamResponseListener.class);
33 28  
  29 + private boolean taskQueueHandlerRun = false;
  30 +
  31 + private ConcurrentLinkedQueue<Message> taskQueue = new ConcurrentLinkedQueue<>();
  32 +
  33 + @Qualifier("taskExecutor")
  34 + @Autowired
  35 + private ThreadPoolTaskExecutor taskExecutor;
  36 +
  37 +
34 38 private Map<String, PushStreamResponseEvent> responseEvents = new ConcurrentHashMap<>();
35 39  
36 40 public interface PushStreamResponseEvent{
... ... @@ -39,16 +43,25 @@ public class RedisPushStreamResponseListener implements MessageListener {
39 43  
40 44 @Override
41 45 public void onMessage(Message message, byte[] bytes) {
42   - //
43 46 logger.warn("[REDIS消息-请求推流结果]: {}", new String(message.getBody()));
44   - MessageForPushChannelResponse response = JSON.parseObject(new String(message.getBody()), MessageForPushChannelResponse.class);
45   - if (response == null || ObjectUtils.isEmpty(response.getApp()) || ObjectUtils.isEmpty(response.getStream())){
46   - logger.info("[REDIS消息-请求推流结果]:参数不全");
47   - return;
48   - }
49   - // 查看正在等待的invite消息
50   - if (responseEvents.get(response.getApp() + response.getStream()) != null) {
51   - responseEvents.get(response.getApp() + response.getStream()).run(response);
  47 + taskQueue.offer(message);
  48 + if (!taskQueueHandlerRun) {
  49 + taskQueueHandlerRun = true;
  50 + taskExecutor.execute(() -> {
  51 + while (!taskQueue.isEmpty()) {
  52 + Message msg = taskQueue.poll();
  53 + MessageForPushChannelResponse response = JSON.parseObject(new String(msg.getBody()), MessageForPushChannelResponse.class);
  54 + if (response == null || ObjectUtils.isEmpty(response.getApp()) || ObjectUtils.isEmpty(response.getStream())){
  55 + logger.info("[REDIS消息-请求推流结果]:参数不全");
  56 + continue;
  57 + }
  58 + // 查看正在等待的invite消息
  59 + if (responseEvents.get(response.getApp() + response.getStream()) != null) {
  60 + responseEvents.get(response.getApp() + response.getStream()).run(response);
  61 + }
  62 + }
  63 + taskQueueHandlerRun = false;
  64 + });
52 65 }
53 66 }
54 67  
... ...
src/main/java/com/genersoft/iot/vmp/service/impl/RedisPushStreamStatusListMsgListener.java renamed to src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisPushStreamStatusListMsgListener.java
1   -package com.genersoft.iot.vmp.service.impl;
  1 +package com.genersoft.iot.vmp.service.redisMsg;
2 2  
3 3 import com.alibaba.fastjson.JSON;
4 4 import com.alibaba.fastjson.JSONObject;
... ... @@ -6,15 +6,20 @@ import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem;
6 6 import com.genersoft.iot.vmp.service.IGbStreamService;
7 7 import com.genersoft.iot.vmp.service.IMediaServerService;
8 8 import com.genersoft.iot.vmp.service.IStreamPushService;
  9 +import com.genersoft.iot.vmp.service.bean.GPSMsgInfo;
9 10 import com.genersoft.iot.vmp.utils.DateUtil;
10 11 import org.slf4j.Logger;
11 12 import org.slf4j.LoggerFactory;
  13 +import org.springframework.beans.factory.annotation.Autowired;
  14 +import org.springframework.beans.factory.annotation.Qualifier;
12 15 import org.springframework.data.redis.connection.Message;
13 16 import org.springframework.data.redis.connection.MessageListener;
  17 +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
14 18 import org.springframework.stereotype.Component;
15 19  
16 20 import javax.annotation.Resource;
17 21 import java.util.*;
  22 +import java.util.concurrent.ConcurrentLinkedQueue;
18 23  
19 24 /**
20 25 * @Auther: JiangFeng
... ... @@ -33,49 +38,66 @@ public class RedisPushStreamStatusListMsgListener implements MessageListener {
33 38 @Resource
34 39 private IGbStreamService gbStreamService;
35 40  
  41 + private boolean taskQueueHandlerRun = false;
  42 +
  43 + private ConcurrentLinkedQueue<Message> taskQueue = new ConcurrentLinkedQueue<>();
  44 +
  45 + @Qualifier("taskExecutor")
  46 + @Autowired
  47 + private ThreadPoolTaskExecutor taskExecutor;
  48 +
36 49 @Override
37 50 public void onMessage(Message message, byte[] bytes) {
38   - //
39   - logger.warn("[REDIS消息-推流设备列表更新]: {}", new String(message.getBody()));
40   - List<StreamPushItem> streamPushItems = JSON.parseArray(new String(message.getBody()), StreamPushItem.class);
41   - //查询全部的app+stream 用于判断是添加还是修改
42   - List<String> allAppAndStream = streamPushService.getAllAppAndStream();
  51 + logger.info("[REDIS消息-推流设备列表更新]: {}", new String(message.getBody()));
43 52  
44   - /**
45   - * 用于存储更具APP+Stream过滤后的数据,可以直接存入stream_push表与gb_stream表
46   - */
47   - List<StreamPushItem> streamPushItemForSave = new ArrayList<>();
48   - List<StreamPushItem> streamPushItemForUpdate = new ArrayList<>();
49   - for (StreamPushItem streamPushItem : streamPushItems) {
50   - String app = streamPushItem.getApp();
51   - String stream = streamPushItem.getStream();
52   - boolean contains = allAppAndStream.contains(app + stream);
53   - //不存在就添加
54   - if (!contains) {
55   - streamPushItem.setStreamType("push");
56   - streamPushItem.setCreateTime(DateUtil.getNow());
57   - streamPushItem.setMediaServerId(mediaServerService.getDefaultMediaServer().getId());
58   - streamPushItem.setOriginType(2);
59   - streamPushItem.setOriginTypeStr("rtsp_push");
60   - streamPushItem.setTotalReaderCount("0");
61   - streamPushItemForSave.add(streamPushItem);
62   - } else {
63   - //存在就只修改 name和gbId
64   - streamPushItemForUpdate.add(streamPushItem);
65   - }
66   - }
67   - if (streamPushItemForSave.size() > 0) {
  53 + taskQueue.offer(message);
  54 + if (!taskQueueHandlerRun) {
  55 + taskQueueHandlerRun = true;
  56 + taskExecutor.execute(() -> {
  57 + while (!taskQueue.isEmpty()) {
  58 + Message msg = taskQueue.poll();
  59 + List<StreamPushItem> streamPushItems = JSON.parseArray(new String(msg.getBody()), StreamPushItem.class);
  60 + //查询全部的app+stream 用于判断是添加还是修改
  61 + List<String> allAppAndStream = streamPushService.getAllAppAndStream();
68 62  
69   - logger.info("添加{}条",streamPushItemForSave.size());
70   - logger.info(JSONObject.toJSONString(streamPushItemForSave));
71   - streamPushService.batchAdd(streamPushItemForSave);
  63 + /**
  64 + * 用于存储更具APP+Stream过滤后的数据,可以直接存入stream_push表与gb_stream表
  65 + */
  66 + List<StreamPushItem> streamPushItemForSave = new ArrayList<>();
  67 + List<StreamPushItem> streamPushItemForUpdate = new ArrayList<>();
  68 + for (StreamPushItem streamPushItem : streamPushItems) {
  69 + String app = streamPushItem.getApp();
  70 + String stream = streamPushItem.getStream();
  71 + boolean contains = allAppAndStream.contains(app + stream);
  72 + //不存在就添加
  73 + if (!contains) {
  74 + streamPushItem.setStreamType("push");
  75 + streamPushItem.setCreateTime(DateUtil.getNow());
  76 + streamPushItem.setMediaServerId(mediaServerService.getDefaultMediaServer().getId());
  77 + streamPushItem.setOriginType(2);
  78 + streamPushItem.setOriginTypeStr("rtsp_push");
  79 + streamPushItem.setTotalReaderCount("0");
  80 + streamPushItemForSave.add(streamPushItem);
  81 + } else {
  82 + //存在就只修改 name和gbId
  83 + streamPushItemForUpdate.add(streamPushItem);
  84 + }
  85 + }
  86 + if (streamPushItemForSave.size() > 0) {
72 87  
73   - }
74   - if(streamPushItemForUpdate.size()>0){
75   - logger.info("修改{}条",streamPushItemForUpdate.size());
76   - logger.info(JSONObject.toJSONString(streamPushItemForUpdate));
77   - gbStreamService.updateGbIdOrName(streamPushItemForUpdate);
78   - }
  88 + logger.info("添加{}条",streamPushItemForSave.size());
  89 + logger.info(JSONObject.toJSONString(streamPushItemForSave));
  90 + streamPushService.batchAdd(streamPushItemForSave);
79 91  
  92 + }
  93 + if(streamPushItemForUpdate.size()>0){
  94 + logger.info("修改{}条",streamPushItemForUpdate.size());
  95 + logger.info(JSONObject.toJSONString(streamPushItemForUpdate));
  96 + gbStreamService.updateGbIdOrName(streamPushItemForUpdate);
  97 + }
  98 + }
  99 + taskQueueHandlerRun = false;
  100 + });
  101 + }
80 102 }
81 103 }
... ...
src/main/java/com/genersoft/iot/vmp/service/impl/RedisPushStreamStatusMsgListener.java renamed to src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisPushStreamStatusMsgListener.java
1   -package com.genersoft.iot.vmp.service.impl;
  1 +package com.genersoft.iot.vmp.service.redisMsg;
2 2  
3 3 import com.alibaba.fastjson.JSON;
4   -import com.alibaba.fastjson.JSONObject;
5 4 import com.genersoft.iot.vmp.common.VideoManagerConstants;
6 5 import com.genersoft.iot.vmp.conf.DynamicTask;
7   -import com.genersoft.iot.vmp.conf.UserSetting;
8   -import com.genersoft.iot.vmp.gb28181.bean.GbStream;
9   -import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
10   -import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent;
11   -import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
12   -import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
13   -import com.genersoft.iot.vmp.media.zlm.ZLMMediaListManager;
14   -import com.genersoft.iot.vmp.media.zlm.dto.MediaItem;
15   -import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem;
16 6 import com.genersoft.iot.vmp.service.IStreamPushService;
17   -import com.genersoft.iot.vmp.service.bean.GPSMsgInfo;
18 7 import com.genersoft.iot.vmp.service.bean.PushStreamStatusChangeFromRedisDto;
19   -import com.genersoft.iot.vmp.service.bean.StreamPushItemFromRedis;
20 8 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
21   -import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
22 9 import org.slf4j.Logger;
23 10 import org.slf4j.LoggerFactory;
24 11 import org.springframework.beans.factory.annotation.Autowired;
... ... @@ -30,8 +17,6 @@ import org.springframework.data.redis.connection.MessageListener;
30 17 import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
31 18 import org.springframework.stereotype.Component;
32 19  
33   -import java.util.ArrayList;
34   -import java.util.List;
35 20 import java.util.concurrent.ConcurrentLinkedQueue;
36 21  
37 22  
... ... @@ -57,7 +42,7 @@ public class RedisPushStreamStatusMsgListener implements MessageListener, Applic
57 42  
58 43  
59 44  
60   - private final ConcurrentLinkedQueue<Message> taskQueue = new ConcurrentLinkedQueue<>();
  45 + private ConcurrentLinkedQueue<Message> taskQueue = new ConcurrentLinkedQueue<>();
61 46  
62 47 @Qualifier("taskExecutor")
63 48 @Autowired
... ... @@ -65,7 +50,6 @@ public class RedisPushStreamStatusMsgListener implements MessageListener, Applic
65 50  
66 51 @Override
67 52 public void onMessage(Message message, byte[] bytes) {
68   - // TODO 增加队列
69 53 logger.warn("[REDIS消息-推流设备状态变化]: {}", new String(message.getBody()));
70 54 taskQueue.offer(message);
71 55  
... ... @@ -77,7 +61,7 @@ public class RedisPushStreamStatusMsgListener implements MessageListener, Applic
77 61 PushStreamStatusChangeFromRedisDto statusChangeFromPushStream = JSON.parseObject(msg.getBody(), PushStreamStatusChangeFromRedisDto.class);
78 62 if (statusChangeFromPushStream == null) {
79 63 logger.warn("[REDIS消息]推流设备状态变化消息解析失败");
80   - return;
  64 + continue;
81 65 }
82 66 // 取消定时任务
83 67 dynamicTask.stop(VideoManagerConstants.VM_MSG_GET_ALL_ONLINE_REQUESTED);
... ...
src/main/java/com/genersoft/iot/vmp/service/impl/RedisStreamMsgListener.java renamed to src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisStreamMsgListener.java
1   -package com.genersoft.iot.vmp.service.impl;
  1 +package com.genersoft.iot.vmp.service.redisMsg;
2 2  
3 3 import com.alibaba.fastjson.JSON;
4 4 import com.alibaba.fastjson.JSONObject;
5 5 import com.genersoft.iot.vmp.conf.UserSetting;
6 6  
7   -import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
8   -import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
9 7 import com.genersoft.iot.vmp.media.zlm.ZLMMediaListManager;
10 8 import com.genersoft.iot.vmp.media.zlm.dto.MediaItem;
11   -import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
12 9 import org.slf4j.Logger;
13 10 import org.slf4j.LoggerFactory;
14 11 import org.springframework.beans.factory.annotation.Autowired;
  12 +import org.springframework.beans.factory.annotation.Qualifier;
15 13 import org.springframework.data.redis.connection.Message;
16 14 import org.springframework.data.redis.connection.MessageListener;
  15 +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
17 16 import org.springframework.stereotype.Component;
18 17  
  18 +import java.util.concurrent.ConcurrentLinkedQueue;
  19 +
19 20  
20 21 /**
21 22 * 接收其他wvp发送流变化通知
... ... @@ -32,41 +33,59 @@ public class RedisStreamMsgListener implements MessageListener {
32 33 @Autowired
33 34 private ZLMMediaListManager zlmMediaListManager;
34 35  
  36 + private boolean taskQueueHandlerRun = false;
  37 +
  38 + private ConcurrentLinkedQueue<Message> taskQueue = new ConcurrentLinkedQueue<>();
  39 +
  40 + @Qualifier("taskExecutor")
  41 + @Autowired
  42 + private ThreadPoolTaskExecutor taskExecutor;
  43 +
35 44 @Override
36 45 public void onMessage(Message message, byte[] bytes) {
37 46  
38   - JSONObject steamMsgJson = JSON.parseObject(message.getBody(), JSONObject.class);
39   - if (steamMsgJson == null) {
40   - logger.warn("[收到redis 流变化]消息解析失败");
41   - return;
42   - }
43   - String serverId = steamMsgJson.getString("serverId");
  47 + taskQueue.offer(message);
  48 + if (!taskQueueHandlerRun) {
  49 + taskQueueHandlerRun = true;
  50 + taskExecutor.execute(() -> {
  51 + while (!taskQueue.isEmpty()) {
  52 + Message msg = taskQueue.poll();
  53 + JSONObject steamMsgJson = JSON.parseObject(msg.getBody(), JSONObject.class);
  54 + if (steamMsgJson == null) {
  55 + logger.warn("[收到redis 流变化]消息解析失败");
  56 + continue;
  57 + }
  58 + String serverId = steamMsgJson.getString("serverId");
44 59  
45   - if (userSetting.getServerId().equals(serverId)) {
46   - // 自己发送的消息忽略即可
47   - return;
48   - }
49   - logger.info("[收到redis 流变化]: {}", new String(message.getBody()));
50   - String app = steamMsgJson.getString("app");
51   - String stream = steamMsgJson.getString("stream");
52   - boolean register = steamMsgJson.getBoolean("register");
53   - String mediaServerId = steamMsgJson.getString("mediaServerId");
54   - MediaItem mediaItem = new MediaItem();
55   - mediaItem.setSeverId(serverId);
56   - mediaItem.setApp(app);
57   - mediaItem.setStream(stream);
58   - mediaItem.setRegist(register);
59   - mediaItem.setMediaServerId(mediaServerId);
60   - mediaItem.setCreateStamp(System.currentTimeMillis()/1000);
61   - mediaItem.setAliveSecond(0L);
62   - mediaItem.setTotalReaderCount("0");
63   - mediaItem.setOriginType(0);
64   - mediaItem.setOriginTypeStr("0");
65   - mediaItem.setOriginTypeStr("unknown");
66   - if (register) {
67   - zlmMediaListManager.addPush(mediaItem);
68   - }else {
69   - zlmMediaListManager.removeMedia(app, stream);
  60 + if (userSetting.getServerId().equals(serverId)) {
  61 + // 自己发送的消息忽略即可
  62 + continue;
  63 + }
  64 + logger.info("[收到redis 流变化]: {}", new String(message.getBody()));
  65 + String app = steamMsgJson.getString("app");
  66 + String stream = steamMsgJson.getString("stream");
  67 + boolean register = steamMsgJson.getBoolean("register");
  68 + String mediaServerId = steamMsgJson.getString("mediaServerId");
  69 + MediaItem mediaItem = new MediaItem();
  70 + mediaItem.setSeverId(serverId);
  71 + mediaItem.setApp(app);
  72 + mediaItem.setStream(stream);
  73 + mediaItem.setRegist(register);
  74 + mediaItem.setMediaServerId(mediaServerId);
  75 + mediaItem.setCreateStamp(System.currentTimeMillis()/1000);
  76 + mediaItem.setAliveSecond(0L);
  77 + mediaItem.setTotalReaderCount("0");
  78 + mediaItem.setOriginType(0);
  79 + mediaItem.setOriginTypeStr("0");
  80 + mediaItem.setOriginTypeStr("unknown");
  81 + if (register) {
  82 + zlmMediaListManager.addPush(mediaItem);
  83 + }else {
  84 + zlmMediaListManager.removeMedia(app, stream);
  85 + }
  86 + }
  87 + taskQueueHandlerRun = false;
  88 + });
70 89 }
71 90 }
72 91 }
... ...
src/main/java/com/genersoft/iot/vmp/storager/dao/GbStreamMapper.java
... ... @@ -75,18 +75,23 @@ public interface GbStreamMapper {
75 75 "WHERE gs.gbId = '${gbId}' AND pgs.platformId = '${platformId}'")
76 76 GbStream queryStreamInPlatform(String platformId, String gbId);
77 77  
78   - @Select("select gt.gbId as channelId, gt.name, 'wvp-pro' as manufacture, st.status, gt.longitude, gt.latitude, pc.id as parentId," +
  78 + @Select("<script> "+
  79 + "select gt.gbId as channelId, gt.name, 'wvp-pro' as manufacture, st.status, gt.longitude, gt.latitude, pc.id as parentId," +
79 80 " '1' as registerWay, pc.civilCode, 'live' as model, 'wvp-pro' as owner, '0' as parental,'0' as secrecy" +
80 81 " from gb_stream gt " +
81 82 " left join (" +
82   - " select sp.status, sp.app, sp.stream from stream_push sp" +
  83 + " select " +
  84 + " <if test='usPushingAsStatus != true'> sp.status as status, </if>" +
  85 + " <if test='usPushingAsStatus == true'> sp.pushIng as status, </if>" +
  86 + "sp.app, sp.stream from stream_push sp" +
83 87 " union all" +
84 88 " select spxy.status, spxy.app, spxy.stream from stream_proxy spxy" +
85 89 " ) st on st.app = gt.app and st.stream = gt.stream" +
86 90 " left join platform_gb_stream pgs on gt.gbStreamId = pgs.gbStreamId" +
87 91 " left join platform_catalog pc on pgs.catalogId = pc.id and pgs.platformId = pc.platformId" +
88   - " where pgs.platformId=#{platformId}")
89   - List<DeviceChannel> queryGbStreamListInPlatform(String platformId);
  92 + " where pgs.platformId=#{platformId}" +
  93 + "</script>")
  94 + List<DeviceChannel> queryGbStreamListInPlatform(String platformId, boolean usPushingAsStatus);
90 95  
91 96  
92 97 @Select("SELECT gs.* FROM gb_stream gs LEFT JOIN platform_gb_stream pgs " +
... ...
src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java
... ... @@ -710,14 +710,14 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
710 710 @Override
711 711 public void sendMobilePositionMsg(JSONObject jsonObject) {
712 712 String key = VideoManagerConstants.VM_MSG_SUBSCRIBE_MOBILE_POSITION;
713   - logger.info("[redis发送通知]移动位置 {}: {}", key, jsonObject.toString());
  713 + logger.info("[redis发送通知] 移动位置 {}: {}", key, jsonObject.toString());
714 714 RedisUtil.convertAndSend(key, jsonObject);
715 715 }
716 716  
717 717 @Override
718 718 public void sendStreamPushRequestedMsg(MessageForPushChannel msg) {
719 719 String key = VideoManagerConstants.VM_MSG_STREAM_PUSH_REQUESTED;
720   - logger.info("[redis发送通知]推流被请求 {}: {}/{}", key, msg.getApp(), msg.getStream());
  720 + logger.info("[redis发送通知] 推流被请求 {}: {}/{}", key, msg.getApp(), msg.getStream());
721 721 RedisUtil.convertAndSend(key, (JSONObject)JSON.toJSON(msg));
722 722 }
723 723  
... ...
src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStorageImpl.java
... ... @@ -2,6 +2,7 @@ package com.genersoft.iot.vmp.storager.impl;
2 2  
3 3 import com.genersoft.iot.vmp.common.StreamInfo;
4 4 import com.genersoft.iot.vmp.conf.SipConfig;
  5 +import com.genersoft.iot.vmp.conf.UserSetting;
5 6 import com.genersoft.iot.vmp.gb28181.bean.*;
6 7 import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
7 8 import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent;
... ... @@ -84,6 +85,9 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage {
84 85 private GbStreamMapper gbStreamMapper;
85 86  
86 87 @Autowired
  88 + private UserSetting userSetting;
  89 +
  90 + @Autowired
87 91 private PlatformCatalogMapper catalogMapper;
88 92  
89 93 @Autowired
... ... @@ -614,7 +618,7 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage {
614 618 */
615 619 @Override
616 620 public List<DeviceChannel> queryGbStreamListInPlatform(String platformId) {
617   - return gbStreamMapper.queryGbStreamListInPlatform(platformId);
  621 + return gbStreamMapper.queryGbStreamListInPlatform(platformId, userSetting.isUsePushingAsStatus());
618 622 }
619 623  
620 624 /**
... ...
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceQuery.java
... ... @@ -413,24 +413,20 @@ public class DeviceQuery {
413 413 @GetMapping("/{deviceId}/subscribe_info")
414 414 @Operation(summary = "获取设备的订阅状态")
415 415 @Parameter(name = "deviceId", description = "设备国标编号", required = true)
416   - public WVPResult<Map<String, String>> getSubscribeInfo(@PathVariable String deviceId) {
  416 + public WVPResult<Map<String, Integer>> getSubscribeInfo(@PathVariable String deviceId) {
417 417 Set<String> allKeys = dynamicTask.getAllKeys();
418   - Map<String, String> dialogStateMap = new HashMap<>();
  418 + Map<String, Integer> dialogStateMap = new HashMap<>();
419 419 for (String key : allKeys) {
420 420 if (key.startsWith(deviceId)) {
421 421 ISubscribeTask subscribeTask = (ISubscribeTask)dynamicTask.get(key);
422   - DialogState dialogState = subscribeTask.getDialogState();
423   - if (dialogState == null) {
424   - continue;
425   - }
426 422 if (subscribeTask instanceof CatalogSubscribeTask) {
427   - dialogStateMap.put("catalog", dialogState.toString());
  423 + dialogStateMap.put("catalog", 1);
428 424 }else if (subscribeTask instanceof MobilePositionSubscribeTask) {
429   - dialogStateMap.put("mobilePosition", dialogState.toString());
  425 + dialogStateMap.put("mobilePosition", 1);
430 426 }
431 427 }
432 428 }
433   - WVPResult<Map<String, String>> wvpResult = new WVPResult<>();
  429 + WVPResult<Map<String, Integer>> wvpResult = new WVPResult<>();
434 430 wvpResult.setCode(0);
435 431 wvpResult.setData(dialogStateMap);
436 432 return wvpResult;
... ...
src/main/resources/all-application.yml
... ... @@ -188,6 +188,8 @@ user-settings:
188 188 record-sip: true
189 189 # 是否将日志存储进数据库
190 190 logInDatebase: true
  191 + # 使用推流状态作为推流通道状态
  192 + use-pushing-as-status: true
191 193  
192 194 # 关闭在线文档(生产环境建议关闭)
193 195 springdoc:
... ...
web_src/src/components/dialog/devicePlayer.vue
... ... @@ -411,6 +411,9 @@ export default {
411 411 console.log(this.videoUrl)
412 412 },
413 413 openDialog: function (tab, deviceId, channelId, param) {
  414 + if (this.showVideoDialog) {
  415 + return;
  416 + }
414 417 this.tabActiveName = tab;
415 418 this.channelId = channelId;
416 419 this.deviceId = deviceId;
... ...
web_src/src/components/dialog/recordDownload.vue
... ... @@ -84,12 +84,13 @@ export default {
84 84 method: 'get',
85 85 url: `/api/gb_record/download/progress/${this.deviceId}/${this.channelId}/${this.stream}`
86 86 }).then((res)=> {
  87 + console.log(res)
87 88 if (res.data.code === 0) {
88 89 this.streamInfo = res.data.data;
89 90 if (parseFloat(res.data.progress) == 1) {
90 91 this.percentage = 100;
91 92 }else {
92   - this.percentage = (res.data.progress*100).toFixed(1);
  93 + this.percentage = (parseFloat(res.data.data.progress)*100).toFixed(1);
93 94 }
94 95 if (callback)callback();
95 96 }
... ... @@ -175,6 +176,10 @@ export default {
175 176 }).then((res) => {
176 177 console.log(res)
177 178 if (res.data.code === 0) {
  179 + if (res.data.data.length === 0){
  180 + this.percentage = 0
  181 + return
  182 + }
178 183 this.percentage = parseFloat(res.data.data.percentage)*100
179 184 if (res.data.data[0].percentage === '1') {
180 185 this.getProgressForFileRun = false;
... ...