Commit c1d7f867c2ffcb1364334a5e013eb8f208819ef5

Authored by 648540858
1 parent 41616f72

优化目录订阅以及国标级联目录订阅回复

Showing 25 changed files with 451 additions and 208 deletions
src/main/java/com/genersoft/iot/vmp/conf/MediaConfig.java
@@ -60,8 +60,8 @@ public class MediaConfig{ @@ -60,8 +60,8 @@ public class MediaConfig{
60 @Value("${media.secret}") 60 @Value("${media.secret}")
61 private String secret; 61 private String secret;
62 62
63 - @Value("${media.stream-none-reader-delay-ms:18000}")  
64 - private int streamNoneReaderDelayMS = 18000; 63 + @Value("${media.stream-none-reader-delay-ms:10000}")
  64 + private int streamNoneReaderDelayMS = 10000;
65 65
66 @Value("${media.rtp.enable}") 66 @Value("${media.rtp.enable}")
67 private boolean rtpEnable; 67 private boolean rtpEnable;
src/main/java/com/genersoft/iot/vmp/gb28181/SipLayer.java
@@ -47,7 +47,7 @@ public class SipLayer{ @@ -47,7 +47,7 @@ public class SipLayer{
47 Properties properties = new Properties(); 47 Properties properties = new Properties();
48 properties.setProperty("javax.sip.STACK_NAME", "GB28181_SIP"); 48 properties.setProperty("javax.sip.STACK_NAME", "GB28181_SIP");
49 properties.setProperty("javax.sip.IP_ADDRESS", sipConfig.getMonitorIp()); 49 properties.setProperty("javax.sip.IP_ADDRESS", sipConfig.getMonitorIp());
50 - properties.setProperty("gov.nist.javax.sip.LOG_MESSAGE_CONTENT", "false"); 50 + properties.setProperty("gov.nist.javax.sip.LOG_MESSAGE_CONTENT", "true");
51 /** 51 /**
52 * sip_server_log.log 和 sip_debug_log.log public static final int TRACE_NONE = 52 * sip_server_log.log 和 sip_debug_log.log public static final int TRACE_NONE =
53 * 0; public static final int TRACE_MESSAGES = 16; public static final int 53 * 0; public static final int TRACE_MESSAGES = 16; public static final int
@@ -57,6 +57,7 @@ public class SipLayer{ @@ -57,6 +57,7 @@ public class SipLayer{
57 properties.setProperty("gov.nist.javax.sip.SERVER_LOG", "sip_server_log"); 57 properties.setProperty("gov.nist.javax.sip.SERVER_LOG", "sip_server_log");
58 properties.setProperty("gov.nist.javax.sip.DEBUG_LOG", "sip_debug_log"); 58 properties.setProperty("gov.nist.javax.sip.DEBUG_LOG", "sip_debug_log");
59 sipStack = (SipStackImpl) sipFactory.createSipStack(properties); 59 sipStack = (SipStackImpl) sipFactory.createSipStack(properties);
  60 +
60 return sipStack; 61 return sipStack;
61 } 62 }
62 63
@@ -70,6 +71,7 @@ public class SipLayer{ @@ -70,6 +71,7 @@ public class SipLayer{
70 tcpSipProvider = (SipProviderImpl)sipStack.createSipProvider(tcpListeningPoint); 71 tcpSipProvider = (SipProviderImpl)sipStack.createSipProvider(tcpListeningPoint);
71 tcpSipProvider.setDialogErrorsAutomaticallyHandled(); 72 tcpSipProvider.setDialogErrorsAutomaticallyHandled();
72 tcpSipProvider.addSipListener(sipProcessorObserver); 73 tcpSipProvider.addSipListener(sipProcessorObserver);
  74 +// tcpSipProvider.setAutomaticDialogSupportEnabled(false);
73 logger.info("Sip Server TCP 启动成功 port {" + sipConfig.getMonitorIp() + ":" + sipConfig.getPort() + "}"); 75 logger.info("Sip Server TCP 启动成功 port {" + sipConfig.getMonitorIp() + ":" + sipConfig.getPort() + "}");
74 } catch (TransportNotSupportedException e) { 76 } catch (TransportNotSupportedException e) {
75 e.printStackTrace(); 77 e.printStackTrace();
@@ -93,6 +95,7 @@ public class SipLayer{ @@ -93,6 +95,7 @@ public class SipLayer{
93 udpListeningPoint = sipStack.createListeningPoint(sipConfig.getMonitorIp(), sipConfig.getPort(), "UDP"); 95 udpListeningPoint = sipStack.createListeningPoint(sipConfig.getMonitorIp(), sipConfig.getPort(), "UDP");
94 udpSipProvider = (SipProviderImpl)sipStack.createSipProvider(udpListeningPoint); 96 udpSipProvider = (SipProviderImpl)sipStack.createSipProvider(udpListeningPoint);
95 udpSipProvider.addSipListener(sipProcessorObserver); 97 udpSipProvider.addSipListener(sipProcessorObserver);
  98 +// udpSipProvider.setAutomaticDialogSupportEnabled(false);
96 } catch (TransportNotSupportedException e) { 99 } catch (TransportNotSupportedException e) {
97 e.printStackTrace(); 100 e.printStackTrace();
98 } catch (InvalidArgumentException e) { 101 } catch (InvalidArgumentException e) {
src/main/java/com/genersoft/iot/vmp/gb28181/auth/RegisterLogicHandler.java
@@ -27,18 +27,18 @@ public class RegisterLogicHandler { @@ -27,18 +27,18 @@ public class RegisterLogicHandler {
27 27
28 public void onRegister(Device device) { 28 public void onRegister(Device device) {
29 // 只有第一次注册时调用查询设备信息,如需更新调用更新API接口 29 // 只有第一次注册时调用查询设备信息,如需更新调用更新API接口
30 - // TODO 此处错误无法获取到通道  
31 - Device device1 = storager.queryVideoDevice(device.getDeviceId());  
32 - if (device.isFirsRegister()) {  
33 - logger.info("[{}] 首次注册,查询设备信息以及通道信息", device.getDeviceId());  
34 - try {  
35 - Thread.sleep(100);  
36 - cmder.deviceInfoQuery(device);  
37 - Thread.sleep(100);  
38 - cmder.catalogQuery(device, null);  
39 - } catch (InterruptedException e) {  
40 - e.printStackTrace();  
41 - }  
42 - } 30 +// // TODO 此处错误无法获取到通道
  31 +// Device device1 = storager.queryVideoDevice(device.getDeviceId());
  32 +// if (device.isFirsRegister()) {
  33 +// logger.info("[{}] 首次注册,查询设备信息以及通道信息", device.getDeviceId());
  34 +// try {
  35 +// Thread.sleep(100);
  36 +// cmder.deviceInfoQuery(device);
  37 +// Thread.sleep(100);
  38 +// cmder.catalogQuery(device, null);
  39 +// } catch (InterruptedException e) {
  40 +// e.printStackTrace();
  41 +// }
  42 +// }
43 } 43 }
44 } 44 }
src/main/java/com/genersoft/iot/vmp/gb28181/bean/SendRtpItem.java
@@ -220,4 +220,6 @@ public class SendRtpItem { @@ -220,4 +220,6 @@ public class SendRtpItem {
220 public void setDialog(byte[] dialog) { 220 public void setDialog(byte[] dialog) {
221 this.dialog = dialog; 221 this.dialog = dialog;
222 } 222 }
  223 +
  224 +
223 } 225 }
src/main/java/com/genersoft/iot/vmp/gb28181/bean/SubscribeHolder.java 0 → 100644
  1 +package com.genersoft.iot.vmp.gb28181.bean;
  2 +
  3 +import org.springframework.stereotype.Component;
  4 +
  5 +import java.util.concurrent.ConcurrentHashMap;
  6 +
  7 +@Component
  8 +public class SubscribeHolder {
  9 +
  10 + private static ConcurrentHashMap<String, SubscribeInfo> catalogMap = new ConcurrentHashMap<>();
  11 + private static ConcurrentHashMap<String, SubscribeInfo> mobilePositionMap = new ConcurrentHashMap<>();
  12 +
  13 +
  14 + public void putCatalogSubscribe(String platformId, SubscribeInfo subscribeInfo) {
  15 + catalogMap.put(platformId, subscribeInfo);
  16 + }
  17 +
  18 + public SubscribeInfo getCatalogSubscribe(String platformId) {
  19 + return catalogMap.get(platformId);
  20 + }
  21 +
  22 + public void removeCatalogSubscribe(String platformId) {
  23 + catalogMap.remove(platformId);
  24 + }
  25 +
  26 + public void putMobilePositionSubscribe(String platformId, SubscribeInfo subscribeInfo) {
  27 + mobilePositionMap.put(platformId, subscribeInfo);
  28 + }
  29 +
  30 + public SubscribeInfo getMobilePositionSubscribe(String platformId) {
  31 + return mobilePositionMap.get(platformId);
  32 + }
  33 +
  34 + public void removeMobilePositionSubscribe(String platformId) {
  35 + mobilePositionMap.remove(platformId);
  36 + }
  37 +}
src/main/java/com/genersoft/iot/vmp/gb28181/bean/SubscribeInfo.java
1 package com.genersoft.iot.vmp.gb28181.bean; 1 package com.genersoft.iot.vmp.gb28181.bean;
2 2
  3 +import com.genersoft.iot.vmp.utils.SerializeUtils;
  4 +
  5 +import javax.sip.Dialog;
3 import javax.sip.RequestEvent; 6 import javax.sip.RequestEvent;
  7 +import javax.sip.ServerTransaction;
4 import javax.sip.header.*; 8 import javax.sip.header.*;
5 import javax.sip.message.Request; 9 import javax.sip.message.Request;
6 10
7 public class SubscribeInfo { 11 public class SubscribeInfo {
8 12
9 - public SubscribeInfo() {  
10 - }  
11 13
12 public SubscribeInfo(RequestEvent evt, String id) { 14 public SubscribeInfo(RequestEvent evt, String id) {
13 this.id = id; 15 this.id = id;
@@ -23,6 +25,8 @@ public class SubscribeInfo { @@ -23,6 +25,8 @@ public class SubscribeInfo {
23 this.eventType = eventHeader.getEventType(); 25 this.eventType = eventHeader.getEventType();
24 ViaHeader viaHeader = (ViaHeader)request.getHeader(ViaHeader.NAME); 26 ViaHeader viaHeader = (ViaHeader)request.getHeader(ViaHeader.NAME);
25 this.branch = viaHeader.getBranch(); 27 this.branch = viaHeader.getBranch();
  28 + this.transaction = evt.getServerTransaction();
  29 + this.dialog = evt.getDialog();
26 } 30 }
27 31
28 private String id; 32 private String id;
@@ -33,6 +37,8 @@ public class SubscribeInfo { @@ -33,6 +37,8 @@ public class SubscribeInfo {
33 private String fromTag; 37 private String fromTag;
34 private String toTag; 38 private String toTag;
35 private String branch; 39 private String branch;
  40 + private ServerTransaction transaction;
  41 + private Dialog dialog;
36 42
37 public String getId() { 43 public String getId() {
38 return id; 44 return id;
@@ -97,4 +103,20 @@ public class SubscribeInfo { @@ -97,4 +103,20 @@ public class SubscribeInfo {
97 public void setBranch(String branch) { 103 public void setBranch(String branch) {
98 this.branch = branch; 104 this.branch = branch;
99 } 105 }
  106 +
  107 + public ServerTransaction getTransaction() {
  108 + return transaction;
  109 + }
  110 +
  111 + public void setTransaction(ServerTransaction transaction) {
  112 + this.transaction = transaction;
  113 + }
  114 +
  115 + public Dialog getDialog() {
  116 + return dialog;
  117 + }
  118 +
  119 + public void setDialog(Dialog dialog) {
  120 + this.dialog = dialog;
  121 + }
100 } 122 }
src/main/java/com/genersoft/iot/vmp/gb28181/event/EventPublisher.java
@@ -33,12 +33,20 @@ public class EventPublisher { @@ -33,12 +33,20 @@ public class EventPublisher {
33 @Autowired 33 @Autowired
34 private ApplicationEventPublisher applicationEventPublisher; 34 private ApplicationEventPublisher applicationEventPublisher;
35 35
36 - public void onlineEventPublish(Device device, String from) { 36 + public void onlineEventPublish(Device device, String from, int expires) {
37 OnlineEvent onEvent = new OnlineEvent(this); 37 OnlineEvent onEvent = new OnlineEvent(this);
38 onEvent.setDevice(device); 38 onEvent.setDevice(device);
39 onEvent.setFrom(from); 39 onEvent.setFrom(from);
  40 + onEvent.setExpires(expires);
40 applicationEventPublisher.publishEvent(onEvent); 41 applicationEventPublisher.publishEvent(onEvent);
41 } 42 }
  43 +
  44 + public void onlineEventPublish(Device device, String from) {
  45 + OnlineEvent onEvent = new OnlineEvent(this);
  46 + onEvent.setDevice(device);
  47 + onEvent.setFrom(from);
  48 + applicationEventPublisher.publishEvent(onEvent);
  49 + }
42 50
43 public void outlineEventPublish(String deviceId, String from){ 51 public void outlineEventPublish(String deviceId, String from){
44 OfflineEvent outEvent = new OfflineEvent(this); 52 OfflineEvent outEvent = new OfflineEvent(this);
@@ -107,6 +115,12 @@ public class EventPublisher { @@ -107,6 +115,12 @@ public class EventPublisher {
107 } 115 }
108 116
109 117
  118 + /**
  119 + *
  120 + * @param platformId
  121 + * @param deviceChannels
  122 + * @param type
  123 + */
110 public void catalogEventPublish(String platformId, List<DeviceChannel> deviceChannels, String type) { 124 public void catalogEventPublish(String platformId, List<DeviceChannel> deviceChannels, String type) {
111 CatalogEvent outEvent = new CatalogEvent(this); 125 CatalogEvent outEvent = new CatalogEvent(this);
112 List<DeviceChannel> channels = new ArrayList<>(); 126 List<DeviceChannel> channels = new ArrayList<>();
src/main/java/com/genersoft/iot/vmp/gb28181/event/offline/OfflineEventListener.java
@@ -91,7 +91,7 @@ public class OfflineEventListener implements ApplicationListener&lt;OfflineEvent&gt; { @@ -91,7 +91,7 @@ public class OfflineEventListener implements ApplicationListener&lt;OfflineEvent&gt; {
91 91
92 // 离线释放所有ssrc 92 // 离线释放所有ssrc
93 List<SsrcTransaction> ssrcTransactions = streamSession.getSsrcTransactionForAll(event.getDeviceId(), null, null, null); 93 List<SsrcTransaction> ssrcTransactions = streamSession.getSsrcTransactionForAll(event.getDeviceId(), null, null, null);
94 - if (ssrcTransactions.size() > 0) { 94 + if (ssrcTransactions != null && ssrcTransactions.size() > 0) {
95 for (SsrcTransaction ssrcTransaction : ssrcTransactions) { 95 for (SsrcTransaction ssrcTransaction : ssrcTransactions) {
96 mediaServerService.releaseSsrc(ssrcTransaction.getMediaServerId(), ssrcTransaction.getSsrc()); 96 mediaServerService.releaseSsrc(ssrcTransaction.getMediaServerId(), ssrcTransaction.getSsrc());
97 mediaServerService.closeRTPServer(event.getDeviceId(), ssrcTransaction.getChannelId(), ssrcTransaction.getStream()); 97 mediaServerService.closeRTPServer(event.getDeviceId(), ssrcTransaction.getChannelId(), ssrcTransaction.getStream());
src/main/java/com/genersoft/iot/vmp/gb28181/event/online/OnlineEvent.java
@@ -23,6 +23,8 @@ public class OnlineEvent extends ApplicationEvent { @@ -23,6 +23,8 @@ public class OnlineEvent extends ApplicationEvent {
23 23
24 private String from; 24 private String from;
25 25
  26 + private int expires;
  27 +
26 public Device getDevice() { 28 public Device getDevice() {
27 return device; 29 return device;
28 } 30 }
@@ -38,5 +40,12 @@ public class OnlineEvent extends ApplicationEvent { @@ -38,5 +40,12 @@ public class OnlineEvent extends ApplicationEvent {
38 public void setFrom(String from) { 40 public void setFrom(String from) {
39 this.from = from; 41 this.from = from;
40 } 42 }
41 - 43 +
  44 + public int getExpires() {
  45 + return expires;
  46 + }
  47 +
  48 + public void setExpires(int expires) {
  49 + this.expires = expires;
  50 + }
42 } 51 }
src/main/java/com/genersoft/iot/vmp/gb28181/event/online/OnlineEventListener.java
@@ -6,6 +6,7 @@ import com.genersoft.iot.vmp.gb28181.bean.Device; @@ -6,6 +6,7 @@ import com.genersoft.iot.vmp.gb28181.bean.Device;
6 import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; 6 import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
7 import com.genersoft.iot.vmp.gb28181.event.EventPublisher; 7 import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
8 import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent; 8 import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent;
  9 +import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
9 import com.genersoft.iot.vmp.service.IDeviceService; 10 import com.genersoft.iot.vmp.service.IDeviceService;
10 import com.genersoft.iot.vmp.storager.dao.dto.User; 11 import com.genersoft.iot.vmp.storager.dao.dto.User;
11 import org.slf4j.Logger; 12 import org.slf4j.Logger;
@@ -51,6 +52,9 @@ public class OnlineEventListener implements ApplicationListener&lt;OnlineEvent&gt; { @@ -51,6 +52,9 @@ public class OnlineEventListener implements ApplicationListener&lt;OnlineEvent&gt; {
51 @Autowired 52 @Autowired
52 private EventPublisher eventPublisher; 53 private EventPublisher eventPublisher;
53 54
  55 + @Autowired
  56 + private SIPCommander cmder;
  57 +
54 private SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 58 private SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
55 59
56 @Override 60 @Override
@@ -62,13 +66,21 @@ public class OnlineEventListener implements ApplicationListener&lt;OnlineEvent&gt; { @@ -62,13 +66,21 @@ public class OnlineEventListener implements ApplicationListener&lt;OnlineEvent&gt; {
62 Device device = event.getDevice(); 66 Device device = event.getDevice();
63 if (device == null) return; 67 if (device == null) return;
64 String key = VideoManagerConstants.KEEPLIVEKEY_PREFIX + userSetup.getServerId() + "_" + event.getDevice().getDeviceId(); 68 String key = VideoManagerConstants.KEEPLIVEKEY_PREFIX + userSetup.getServerId() + "_" + event.getDevice().getDeviceId();
65 - 69 + Device deviceInStore = storager.queryVideoDevice(device.getDeviceId());
  70 + device.setOnline(1);
  71 + // 处理上线监听
  72 + storager.updateDevice(device);
66 switch (event.getFrom()) { 73 switch (event.getFrom()) {
67 // 注册时触发的在线事件,先在redis中增加超时超时监听 74 // 注册时触发的在线事件,先在redis中增加超时超时监听
68 case VideoManagerConstants.EVENT_ONLINE_REGISTER: 75 case VideoManagerConstants.EVENT_ONLINE_REGISTER:
69 // 超时时间 76 // 超时时间
70 redis.set(key, event.getDevice().getDeviceId(), sipConfig.getKeepaliveTimeOut()); 77 redis.set(key, event.getDevice().getDeviceId(), sipConfig.getKeepaliveTimeOut());
71 device.setRegisterTime(format.format(System.currentTimeMillis())); 78 device.setRegisterTime(format.format(System.currentTimeMillis()));
  79 + if (deviceInStore == null) { //第一次上线
  80 + logger.info("[{}] 首次注册,查询设备信息以及通道信息", device.getDeviceId());
  81 + cmder.deviceInfoQuery(device);
  82 + cmder.catalogQuery(device, null);
  83 + }
72 break; 84 break;
73 // 设备主动发送心跳触发的在线事件 85 // 设备主动发送心跳触发的在线事件
74 case VideoManagerConstants.EVENT_ONLINE_KEEPLIVE: 86 case VideoManagerConstants.EVENT_ONLINE_KEEPLIVE:
@@ -87,19 +99,11 @@ public class OnlineEventListener implements ApplicationListener&lt;OnlineEvent&gt; { @@ -87,19 +99,11 @@ public class OnlineEventListener implements ApplicationListener&lt;OnlineEvent&gt; {
87 break; 99 break;
88 } 100 }
89 101
90 - device.setOnline(1);  
91 - Device deviceInStore = storager.queryVideoDevice(device.getDeviceId());  
92 - if (deviceInStore != null && deviceInStore.getOnline() == 0) {  
93 - List<DeviceChannel> deviceChannelList = storager.queryOnlineChannelsByDeviceId(device.getDeviceId());  
94 - eventPublisher.catalogEventPublish(null, deviceChannelList, CatalogEvent.ON);  
95 - }  
96 - // 处理上线监听  
97 - storager.updateDevice(device);  
98 - 102 + List<DeviceChannel> deviceChannelList = storager.queryOnlineChannelsByDeviceId(device.getDeviceId());
  103 + eventPublisher.catalogEventPublish(null, deviceChannelList, CatalogEvent.ON);
99 // 上线添加订阅 104 // 上线添加订阅
100 if (device.getSubscribeCycleForCatalog() > 0) { 105 if (device.getSubscribeCycleForCatalog() > 0) {
101 deviceService.addCatalogSubscribe(device); 106 deviceService.addCatalogSubscribe(device);
102 } 107 }
103 -  
104 } 108 }
105 } 109 }
src/main/java/com/genersoft/iot/vmp/gb28181/event/subscribe/catalog/CatalogEventLister.java
@@ -52,6 +52,9 @@ public class CatalogEventLister implements ApplicationListener&lt;CatalogEvent&gt; { @@ -52,6 +52,9 @@ public class CatalogEventLister implements ApplicationListener&lt;CatalogEvent&gt; {
52 @Autowired 52 @Autowired
53 private IGbStreamService gbStreamService; 53 private IGbStreamService gbStreamService;
54 54
  55 + @Autowired
  56 + private SubscribeHolder subscribeHolder;
  57 +
55 @Override 58 @Override
56 public void onApplicationEvent(CatalogEvent event) { 59 public void onApplicationEvent(CatalogEvent event) {
57 SubscribeInfo subscribe = null; 60 SubscribeInfo subscribe = null;
@@ -62,7 +65,8 @@ public class CatalogEventLister implements ApplicationListener&lt;CatalogEvent&gt; { @@ -62,7 +65,8 @@ public class CatalogEventLister implements ApplicationListener&lt;CatalogEvent&gt; {
62 parentPlatform = storager.queryParentPlatByServerGBId(event.getPlatformId()); 65 parentPlatform = storager.queryParentPlatByServerGBId(event.getPlatformId());
63 if (parentPlatform != null && !parentPlatform.isStatus())return; 66 if (parentPlatform != null && !parentPlatform.isStatus())return;
64 String key = VideoManagerConstants.SIP_SUBSCRIBE_PREFIX + userSetup.getServerId() + "_Catalog_" + event.getPlatformId(); 67 String key = VideoManagerConstants.SIP_SUBSCRIBE_PREFIX + userSetup.getServerId() + "_Catalog_" + event.getPlatformId();
65 - subscribe = redisCatchStorage.getSubscribe(key); 68 +// subscribe = redisCatchStorage.getSubscribe(key);
  69 + subscribe = subscribeHolder.getCatalogSubscribe(event.getPlatformId());
66 70
67 if (subscribe == null) { 71 if (subscribe == null) {
68 logger.debug("发送订阅消息时发现订阅信息已经不存在"); 72 logger.debug("发送订阅消息时发现订阅信息已经不存在");
@@ -114,7 +118,8 @@ public class CatalogEventLister implements ApplicationListener&lt;CatalogEvent&gt; { @@ -114,7 +118,8 @@ public class CatalogEventLister implements ApplicationListener&lt;CatalogEvent&gt; {
114 if (parentPlatforms != null && parentPlatforms.size() > 0) { 118 if (parentPlatforms != null && parentPlatforms.size() > 0) {
115 for (ParentPlatform platform : parentPlatforms) { 119 for (ParentPlatform platform : parentPlatforms) {
116 String key = VideoManagerConstants.SIP_SUBSCRIBE_PREFIX + userSetup.getServerId() + "_Catalog_" + platform.getServerGBId(); 120 String key = VideoManagerConstants.SIP_SUBSCRIBE_PREFIX + userSetup.getServerId() + "_Catalog_" + platform.getServerGBId();
117 - SubscribeInfo subscribeInfo = redisCatchStorage.getSubscribe(key); 121 +// SubscribeInfo subscribeInfo = redisCatchStorage.getSubscribe(key);
  122 + SubscribeInfo subscribeInfo = subscribeHolder.getCatalogSubscribe(platform.getServerGBId());
118 if (subscribeInfo == null) continue; 123 if (subscribeInfo == null) continue;
119 logger.info("[Catalog事件: {}]平台:{},影响通道{}", event.getType(), platform.getServerGBId(), gbId); 124 logger.info("[Catalog事件: {}]平台:{},影响通道{}", event.getType(), platform.getServerGBId(), gbId);
120 List<DeviceChannel> deviceChannelList = new ArrayList<>(); 125 List<DeviceChannel> deviceChannelList = new ArrayList<>();
@@ -153,8 +158,9 @@ public class CatalogEventLister implements ApplicationListener&lt;CatalogEvent&gt; { @@ -153,8 +158,9 @@ public class CatalogEventLister implements ApplicationListener&lt;CatalogEvent&gt; {
153 List<ParentPlatform> parentPlatforms = parentPlatformMap.get(gbId); 158 List<ParentPlatform> parentPlatforms = parentPlatformMap.get(gbId);
154 if (parentPlatforms != null && parentPlatforms.size() > 0) { 159 if (parentPlatforms != null && parentPlatforms.size() > 0) {
155 for (ParentPlatform platform : parentPlatforms) { 160 for (ParentPlatform platform : parentPlatforms) {
156 - String key = VideoManagerConstants.SIP_SUBSCRIBE_PREFIX + userSetup.getServerId() + "_Catalog_" + platform.getServerGBId();  
157 - SubscribeInfo subscribeInfo = redisCatchStorage.getSubscribe(key); 161 +// String key = VideoManagerConstants.SIP_SUBSCRIBE_PREFIX + userSetup.getServerId() + "_Catalog_" + platform.getServerGBId();
  162 +// SubscribeInfo subscribeInfo = redisCatchStorage.getSubscribe(key);
  163 + SubscribeInfo subscribeInfo = subscribeHolder.getCatalogSubscribe(event.getPlatformId());
158 if (subscribeInfo == null) continue; 164 if (subscribeInfo == null) continue;
159 logger.info("[Catalog事件: {}]平台:{},影响通道{}", event.getType(), platform.getServerGBId(), gbId); 165 logger.info("[Catalog事件: {}]平台:{},影响通道{}", event.getType(), platform.getServerGBId(), gbId);
160 List<DeviceChannel> deviceChannelList = new ArrayList<>(); 166 List<DeviceChannel> deviceChannelList = new ArrayList<>();
src/main/java/com/genersoft/iot/vmp/gb28181/task/GPSSubscribeTask.java
@@ -2,6 +2,7 @@ package com.genersoft.iot.vmp.gb28181.task; @@ -2,6 +2,7 @@ package com.genersoft.iot.vmp.gb28181.task;
2 2
3 import com.genersoft.iot.vmp.gb28181.bean.GbStream; 3 import com.genersoft.iot.vmp.gb28181.bean.GbStream;
4 import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; 4 import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
  5 +import com.genersoft.iot.vmp.gb28181.bean.SubscribeHolder;
5 import com.genersoft.iot.vmp.gb28181.bean.SubscribeInfo; 6 import com.genersoft.iot.vmp.gb28181.bean.SubscribeInfo;
6 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform; 7 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
7 import com.genersoft.iot.vmp.service.bean.GPSMsgInfo; 8 import com.genersoft.iot.vmp.service.bean.GPSMsgInfo;
@@ -16,25 +17,28 @@ public class GPSSubscribeTask implements Runnable{ @@ -16,25 +17,28 @@ public class GPSSubscribeTask implements Runnable{
16 private IRedisCatchStorage redisCatchStorage; 17 private IRedisCatchStorage redisCatchStorage;
17 private IVideoManagerStorager storager; 18 private IVideoManagerStorager storager;
18 private ISIPCommanderForPlatform sipCommanderForPlatform; 19 private ISIPCommanderForPlatform sipCommanderForPlatform;
  20 + private SubscribeHolder subscribeHolder;
19 private String platformId; 21 private String platformId;
20 private String sn; 22 private String sn;
21 private String key; 23 private String key;
22 24
23 private final SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 25 private final SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
24 26
25 - public GPSSubscribeTask(IRedisCatchStorage redisCatchStorage, ISIPCommanderForPlatform sipCommanderForPlatform, IVideoManagerStorager storager, String platformId, String sn, String key) { 27 + public GPSSubscribeTask(IRedisCatchStorage redisCatchStorage, ISIPCommanderForPlatform sipCommanderForPlatform, IVideoManagerStorager storager, String platformId, String sn, String key, SubscribeHolder subscribeInfo) {
26 this.redisCatchStorage = redisCatchStorage; 28 this.redisCatchStorage = redisCatchStorage;
27 this.storager = storager; 29 this.storager = storager;
28 this.platformId = platformId; 30 this.platformId = platformId;
29 this.sn = sn; 31 this.sn = sn;
30 this.key = key; 32 this.key = key;
31 this.sipCommanderForPlatform = sipCommanderForPlatform; 33 this.sipCommanderForPlatform = sipCommanderForPlatform;
  34 + this.subscribeHolder = subscribeInfo;
32 } 35 }
33 36
34 @Override 37 @Override
35 public void run() { 38 public void run() {
36 39
37 - SubscribeInfo subscribe = redisCatchStorage.getSubscribe(key); 40 + SubscribeInfo subscribe = subscribeHolder.getMobilePositionSubscribe(platformId);
  41 +
38 if (subscribe != null) { 42 if (subscribe != null) {
39 ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(platformId); 43 ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(platformId);
40 if (parentPlatform == null || parentPlatform.isStatus()) { 44 if (parentPlatform == null || parentPlatform.isStatus()) {
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorObserver.java
@@ -94,6 +94,7 @@ public class SIPProcessorObserver implements ISIPProcessorObserver { @@ -94,6 +94,7 @@ public class SIPProcessorObserver implements ISIPProcessorObserver {
94 Response response = responseEvent.getResponse(); 94 Response response = responseEvent.getResponse();
95 logger.debug("\n收到响应:\n{}", responseEvent.getResponse()); 95 logger.debug("\n收到响应:\n{}", responseEvent.getResponse());
96 int status = response.getStatusCode(); 96 int status = response.getStatusCode();
  97 +
97 if (((status >= 200) && (status < 300)) || status == 401) { // Success! 98 if (((status >= 200) && (status < 300)) || status == 401) { // Success!
98 CSeqHeader cseqHeader = (CSeqHeader) responseEvent.getResponse().getHeader(CSeqHeader.NAME); 99 CSeqHeader cseqHeader = (CSeqHeader) responseEvent.getResponse().getHeader(CSeqHeader.NAME);
99 String method = cseqHeader.getMethod(); 100 String method = cseqHeader.getMethod();
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderPlarformProvider.java
@@ -236,57 +236,57 @@ public class SIPRequestHeaderPlarformProvider { @@ -236,57 +236,57 @@ public class SIPRequestHeaderPlarformProvider {
236 return request; 236 return request;
237 } 237 }
238 238
239 - public Request createNotifyRequest(ParentPlatform parentPlatform, String content, CallIdHeader callIdHeader, String viaTag, SubscribeInfo subscribeInfo) throws PeerUnavailableException, ParseException, InvalidArgumentException {  
240 - Request request = null;  
241 - // sipuri  
242 - SipURI requestURI = sipFactory.createAddressFactory().createSipURI(parentPlatform.getServerGBId(), parentPlatform.getServerIP()+ ":" + parentPlatform.getServerPort());  
243 - // via  
244 - ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>();  
245 - ViaHeader viaHeader = sipFactory.createHeaderFactory().createViaHeader(parentPlatform.getDeviceIp(), Integer.parseInt(parentPlatform.getDevicePort()),  
246 - parentPlatform.getTransport(), subscribeInfo.getBranch());  
247 - viaHeader.setRPort();  
248 - viaHeaders.add(viaHeader);  
249 - // from  
250 - SipURI fromSipURI = sipFactory.createAddressFactory().createSipURI(parentPlatform.getDeviceGBId(),  
251 - parentPlatform.getDeviceIp() + ":" + parentPlatform.getDevicePort());  
252 - Address fromAddress = sipFactory.createAddressFactory().createAddress(fromSipURI);  
253 - FromHeader fromHeader = sipFactory.createHeaderFactory().createFromHeader(fromAddress, subscribeInfo.getToTag());  
254 - // to  
255 - SipURI toSipURI = sipFactory.createAddressFactory().createSipURI(parentPlatform.getServerGBId(), parentPlatform.getServerGBDomain());  
256 - Address toAddress = sipFactory.createAddressFactory().createAddress(toSipURI);  
257 - ToHeader toHeader = sipFactory.createHeaderFactory().createToHeader(toAddress, subscribeInfo.getFromTag());  
258 -  
259 - // Forwards  
260 - MaxForwardsHeader maxForwards = sipFactory.createHeaderFactory().createMaxForwardsHeader(70);  
261 - // ceq  
262 - CSeqHeader cSeqHeader = sipFactory.createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(Request.NOTIFY), Request.NOTIFY);  
263 - MessageFactoryImpl messageFactory = (MessageFactoryImpl) sipFactory.createMessageFactory();  
264 - // 设置编码, 防止中文乱码  
265 - messageFactory.setDefaultContentEncodingCharset("gb2312");  
266 - request = messageFactory.createRequest(requestURI, Request.NOTIFY, callIdHeader, cSeqHeader, fromHeader,  
267 - toHeader, viaHeaders, maxForwards);  
268 - List<String> agentParam = new ArrayList<>();  
269 - agentParam.add("wvp-pro");  
270 - UserAgentHeader userAgentHeader = sipFactory.createHeaderFactory().createUserAgentHeader(agentParam);  
271 - request.addHeader(userAgentHeader);  
272 -  
273 - EventHeader event = sipFactory.createHeaderFactory().createEventHeader(subscribeInfo.getEventType());  
274 - if (subscribeInfo.getEventId() != null) {  
275 - event.setEventId(subscribeInfo.getEventId());  
276 - }  
277 -  
278 - request.addHeader(event);  
279 -  
280 - SubscriptionStateHeader active = sipFactory.createHeaderFactory().createSubscriptionStateHeader("active");  
281 - request.setHeader(active);  
282 -  
283 - String sipAddress = sipConfig.getIp() + ":" + sipConfig.getPort();  
284 - Address concatAddress = sipFactory.createAddressFactory().createAddress(sipFactory.createAddressFactory()  
285 - .createSipURI(parentPlatform.getDeviceGBId(), sipAddress));  
286 - request.addHeader(sipFactory.createHeaderFactory().createContactHeader(concatAddress));  
287 -  
288 - ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml");  
289 - request.setContent(content, contentTypeHeader);  
290 - return request;  
291 - } 239 +// public Request createNotifyRequest(ParentPlatform parentPlatform, String content, CallIdHeader callIdHeader, String viaTag, String fromTag, SubscribeInfo subscribeInfo) throws PeerUnavailableException, ParseException, InvalidArgumentException {
  240 +// Request request = null;
  241 +// // sipuri
  242 +// SipURI requestURI = sipFactory.createAddressFactory().createSipURI(parentPlatform.getServerGBId(), parentPlatform.getServerIP()+ ":" + parentPlatform.getServerPort());
  243 +// // via
  244 +// ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>();
  245 +// ViaHeader viaHeader = sipFactory.createHeaderFactory().createViaHeader(parentPlatform.getDeviceIp(), Integer.parseInt(parentPlatform.getDevicePort()),
  246 +// parentPlatform.getTransport(), viaTag);
  247 +// viaHeader.setRPort();
  248 +// viaHeaders.add(viaHeader);
  249 +// // from
  250 +// SipURI fromSipURI = sipFactory.createAddressFactory().createSipURI(parentPlatform.getDeviceGBId(),
  251 +// parentPlatform.getDeviceIp() + ":" + parentPlatform.getDevicePort());
  252 +// Address fromAddress = sipFactory.createAddressFactory().createAddress(fromSipURI);
  253 +// FromHeader fromHeader = sipFactory.createHeaderFactory().createFromHeader(fromAddress, fromTag);
  254 +// // to
  255 +// SipURI toSipURI = sipFactory.createAddressFactory().createSipURI(parentPlatform.getServerGBId(), parentPlatform.getServerGBDomain());
  256 +// Address toAddress = sipFactory.createAddressFactory().createAddress(toSipURI);
  257 +// ToHeader toHeader = sipFactory.createHeaderFactory().createToHeader(toAddress, subscribeInfo.getFromTag());
  258 +//
  259 +// // Forwards
  260 +// MaxForwardsHeader maxForwards = sipFactory.createHeaderFactory().createMaxForwardsHeader(70);
  261 +// // ceq
  262 +// CSeqHeader cSeqHeader = sipFactory.createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(Request.NOTIFY), Request.NOTIFY);
  263 +// MessageFactoryImpl messageFactory = (MessageFactoryImpl) sipFactory.createMessageFactory();
  264 +// // 设置编码, 防止中文乱码
  265 +// messageFactory.setDefaultContentEncodingCharset("gb2312");
  266 +// request = messageFactory.createRequest(requestURI, Request.NOTIFY, callIdHeader, cSeqHeader, fromHeader,
  267 +// toHeader, viaHeaders, maxForwards);
  268 +// List<String> agentParam = new ArrayList<>();
  269 +// agentParam.add("wvp-pro");
  270 +// UserAgentHeader userAgentHeader = sipFactory.createHeaderFactory().createUserAgentHeader(agentParam);
  271 +// request.addHeader(userAgentHeader);
  272 +//
  273 +// EventHeader event = sipFactory.createHeaderFactory().createEventHeader(subscribeInfo.getEventType());
  274 +// if (subscribeInfo.getEventId() != null) {
  275 +// event.setEventId(subscribeInfo.getEventId());
  276 +// }
  277 +//
  278 +// request.addHeader(event);
  279 +//
  280 +// SubscriptionStateHeader active = sipFactory.createHeaderFactory().createSubscriptionStateHeader("active");
  281 +// request.setHeader(active);
  282 +//
  283 +// String sipAddress = sipConfig.getIp() + ":" + sipConfig.getPort();
  284 +// Address concatAddress = sipFactory.createAddressFactory().createAddress(sipFactory.createAddressFactory()
  285 +// .createSipURI(parentPlatform.getDeviceGBId(), sipAddress));
  286 +// request.addHeader(sipFactory.createHeaderFactory().createContactHeader(concatAddress));
  287 +//
  288 +// ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml");
  289 +// request.setContent(content, contentTypeHeader);
  290 +// return request;
  291 +// }
292 } 292 }
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java
@@ -215,6 +215,9 @@ public class SIPRequestHeaderProvider { @@ -215,6 +215,9 @@ public class SIPRequestHeaderProvider {
215 215
216 // Event 216 // Event
217 EventHeader eventHeader = sipFactory.createHeaderFactory().createEventHeader(event); 217 EventHeader eventHeader = sipFactory.createHeaderFactory().createEventHeader(event);
  218 +
  219 + int random = (int)Math.random() * 1000000000;
  220 + eventHeader.setEventId(random + "");
218 request.addHeader(eventHeader); 221 request.addHeader(eventHeader);
219 222
220 ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml"); 223 ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml");
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
@@ -1518,7 +1518,7 @@ public class SIPCommander implements ISIPCommander { @@ -1518,7 +1518,7 @@ public class SIPCommander implements ISIPCommander {
1518 1518
1519 // 有效时间默认为60秒以上 1519 // 有效时间默认为60秒以上
1520 Request request = headerProvider.createSubscribeRequest(device, cmdXml.toString(), "z9hG4bK-viaPos-" + tm, 1520 Request request = headerProvider.createSubscribeRequest(device, cmdXml.toString(), "z9hG4bK-viaPos-" + tm,
1521 - "fromTagPos" + tm, null, device.getSubscribeCycleForCatalog() + 60, "Catalog" , 1521 + "fromTagPos" + tm, null, device.getSubscribeCycleForCatalog(), "Catalog" ,
1522 callIdHeader); 1522 callIdHeader);
1523 transmitRequest(device, request, errorEvent, okEvent); 1523 transmitRequest(device, request, errorEvent, okEvent);
1524 1524
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommanderFroPlatform.java
@@ -27,9 +27,7 @@ import org.springframework.util.StringUtils; @@ -27,9 +27,7 @@ import org.springframework.util.StringUtils;
27 27
28 import javax.sip.*; 28 import javax.sip.*;
29 import javax.sip.address.SipURI; 29 import javax.sip.address.SipURI;
30 -import javax.sip.header.CallIdHeader;  
31 -import javax.sip.header.ViaHeader;  
32 -import javax.sip.header.WWWAuthenticateHeader; 30 +import javax.sip.header.*;
33 import javax.sip.message.Request; 31 import javax.sip.message.Request;
34 import java.lang.reflect.Field; 32 import java.lang.reflect.Field;
35 import java.text.ParseException; 33 import java.text.ParseException;
@@ -68,6 +66,9 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { @@ -68,6 +66,9 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
68 @Qualifier(value="udpSipProvider") 66 @Qualifier(value="udpSipProvider")
69 private SipProviderImpl udpSipProvider; 67 private SipProviderImpl udpSipProvider;
70 68
  69 + @Autowired
  70 + private SipFactory sipFactory;
  71 +
71 @Override 72 @Override
72 public boolean register(ParentPlatform parentPlatform, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent) { 73 public boolean register(ParentPlatform parentPlatform, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent) {
73 return register(parentPlatform, null, null, errorEvent, okEvent, false); 74 return register(parentPlatform, null, null, errorEvent, okEvent, false);
@@ -88,7 +89,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { @@ -88,7 +89,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
88 public boolean register(ParentPlatform parentPlatform, @Nullable String callId, @Nullable WWWAuthenticateHeader www, 89 public boolean register(ParentPlatform parentPlatform, @Nullable String callId, @Nullable WWWAuthenticateHeader www,
89 SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent, boolean registerAgain) { 90 SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent, boolean registerAgain) {
90 try { 91 try {
91 - Request request = null; 92 + Request request;
92 String tm = Long.toString(System.currentTimeMillis()); 93 String tm = Long.toString(System.currentTimeMillis());
93 if (!registerAgain ) { 94 if (!registerAgain ) {
94 // //callid 95 // //callid
@@ -364,16 +365,18 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { @@ -364,16 +365,18 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
364 : udpSipProvider.getNewCallId(); 365 : udpSipProvider.getNewCallId();
365 callIdHeader.setCallId(subscribeInfo.getCallId()); 366 callIdHeader.setCallId(subscribeInfo.getCallId());
366 367
367 - String tm = Long.toString(System.currentTimeMillis());  
368 -  
369 - Request request = headerProviderPlarformProvider.createNotifyRequest(parentPlatform,  
370 - deviceStatusXml.toString(),callIdHeader,  
371 - "z9hG4bK-" + UUID.randomUUID().toString().replace("-", ""), subscribeInfo);  
372 - transmitRequest(parentPlatform, request); 368 +//
  369 + sendNotify(parentPlatform, deviceStatusXml.toString(), subscribeInfo, eventResult -> {
  370 + logger.error("发送NOTIFY通知消息失败。错误:{} {}", eventResult.statusCode, eventResult.msg);
  371 + }, null);
373 372
374 - } catch (SipException | ParseException | InvalidArgumentException e) { 373 + } catch (SipException | ParseException e) {
375 e.printStackTrace(); 374 e.printStackTrace();
376 return false; 375 return false;
  376 + } catch (NoSuchFieldException e) {
  377 + e.printStackTrace();
  378 + } catch (IllegalAccessException e) {
  379 + e.printStackTrace();
377 } 380 }
378 return true; 381 return true;
379 } 382 }
@@ -386,37 +389,89 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { @@ -386,37 +389,89 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
386 if (index == null) { 389 if (index == null) {
387 index = 0; 390 index = 0;
388 } 391 }
389 - 392 + if (index >= deviceChannels.size()) {
  393 + return true;
  394 + }
390 try { 395 try {
391 - if (index > deviceChannels.size() - 1) {  
392 - return true;  
393 - }  
394 - Request request = getCatalogNotifyRequestForCatalogAddOrUpdate(parentPlatform, deviceChannels.get(index), deviceChannels.size(), type, subscribeInfo);  
395 - index += 1;  
396 Integer finalIndex = index; 396 Integer finalIndex = index;
397 - transmitRequest(parentPlatform, request, null, (eventResult -> {  
398 - sendNotifyForCatalogAddOrUpdate(type, parentPlatform, deviceChannels, subscribeInfo, finalIndex); 397 + String catalogXmlContent = getCatalogXmlContentForCatalogAddOrUpdate(parentPlatform, deviceChannels.get(index ), deviceChannels.size(), type, subscribeInfo);
  398 + sendNotify(parentPlatform, catalogXmlContent, subscribeInfo, eventResult -> {
  399 + logger.error("发送NOTIFY通知消息失败。错误:{} {}", eventResult.statusCode, eventResult.msg);
  400 + }, (eventResult -> {
  401 + sendNotifyForCatalogAddOrUpdate(type, parentPlatform, deviceChannels, subscribeInfo, finalIndex + 1);
399 })); 402 }));
400 - } catch (SipException | ParseException | InvalidArgumentException e) { 403 + } catch (SipException | ParseException e) {
401 e.printStackTrace(); 404 e.printStackTrace();
402 return false; 405 return false;
  406 + } catch (NoSuchFieldException e) {
  407 + e.printStackTrace();
  408 + } catch (IllegalAccessException e) {
  409 + e.printStackTrace();
403 } 410 }
404 return true; 411 return true;
405 } 412 }
406 413
407 - private Request getCatalogNotifyRequestForCatalogAddOrUpdate(ParentPlatform parentPlatform, DeviceChannel channel, int size, String type,  
408 - SubscribeInfo subscribeInfo) throws ParseException, InvalidArgumentException,  
409 - PeerUnavailableException {  
410 - String catalogXmlContent = getCatalogXmlContentForCatalogAddOrUpdate(parentPlatform, channel, size, type, subscribeInfo);  
411 -  
412 - CallIdHeader callIdHeader = parentPlatform.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()  
413 - : udpSipProvider.getNewCallId();  
414 - callIdHeader.setCallId(subscribeInfo.getCallId());  
415 - Request request = headerProviderPlarformProvider.createNotifyRequest(parentPlatform, catalogXmlContent,  
416 - callIdHeader, "z9hG4bK-" + UUID.randomUUID().toString().replace("-", ""), subscribeInfo);  
417 - return request; 414 + private void sendNotify(ParentPlatform parentPlatform, String catalogXmlContent,
  415 + SubscribeInfo subscribeInfo, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent )
  416 + throws NoSuchFieldException, IllegalAccessException, SipException, ParseException {
  417 + Dialog dialog = subscribeInfo.getDialog();
  418 + Request notifyRequest = dialog.createRequest(Request.NOTIFY);
  419 +
  420 + ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml");
  421 +
  422 + notifyRequest.setContent(catalogXmlContent, contentTypeHeader);
  423 +
  424 + SubscriptionStateHeader subscriptionState = sipFactory.createHeaderFactory()
  425 + .createSubscriptionStateHeader(SubscriptionStateHeader.ACTIVE);
  426 + notifyRequest.addHeader(subscriptionState);
  427 +
  428 + EventHeader event = sipFactory.createHeaderFactory().createEventHeader(subscribeInfo.getEventType());
  429 + if (subscribeInfo.getEventId() != null) {
  430 + event.setEventId(subscribeInfo.getEventId());
  431 + }
  432 + notifyRequest.addHeader(event);
  433 +
  434 + SipURI sipURI = (SipURI) notifyRequest.getRequestURI();
  435 + SIPRequest request = (SIPRequest) subscribeInfo.getTransaction().getRequest();
  436 + sipURI.setHost(request.getRemoteAddress().getHostName());
  437 + sipURI.setPort(request.getRemotePort());
  438 + ClientTransaction transaction = null;
  439 + if ("TCP".equals(parentPlatform.getTransport())) {
  440 + transaction = tcpSipProvider.getNewClientTransaction(notifyRequest);
  441 + } else if ("UDP".equals(parentPlatform.getTransport())) {
  442 + transaction = udpSipProvider.getNewClientTransaction(notifyRequest);
  443 + }
  444 + // 添加错误订阅
  445 + if (errorEvent != null) {
  446 + sipSubscribe.addErrorSubscribe(subscribeInfo.getCallId(), errorEvent);
  447 + }
  448 + // 添加订阅
  449 + if (okEvent != null) {
  450 + sipSubscribe.addOkSubscribe(subscribeInfo.getCallId(), okEvent);
  451 + }
  452 + if (transaction == null) {
  453 + logger.error("平台{}的Transport错误:{}",parentPlatform.getServerGBId(), parentPlatform.getTransport());
  454 + return;
  455 + }
  456 + dialog.sendRequest(transaction);
  457 +
418 } 458 }
419 459
  460 +// private Request getCatalogNotifyRequestForCatalogAddOrUpdate(ParentPlatform parentPlatform, DeviceChannel channel, int size, String type,
  461 +// SubscribeInfo subscribeInfo) throws ParseException, InvalidArgumentException,
  462 +// PeerUnavailableException, NoSuchFieldException, IllegalAccessException {
  463 +// String catalogXmlContent = getCatalogXmlContentForCatalogAddOrUpdate(parentPlatform, channel, size, type, subscribeInfo);
  464 +//
  465 +// CallIdHeader callIdHeader = parentPlatform.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
  466 +// : udpSipProvider.getNewCallId();
  467 +// callIdHeader.setCallId(subscribeInfo.getCallId());
  468 +// String tm = Long.toString(System.currentTimeMillis());
  469 +//
  470 +// Request request = headerProviderPlarformProvider.createNotifyRequest(parentPlatform, catalogXmlContent,
  471 +// callIdHeader, "z9hG4bK-" + UUID.randomUUID().toString().replace("-", ""),"FromRegister" + tm, subscribeInfo);
  472 +// return request;
  473 +// }
  474 +
420 private String getCatalogXmlContentForCatalogAddOrUpdate(ParentPlatform parentPlatform, DeviceChannel channel, int sumNum, String type, SubscribeInfo subscribeInfo) { 475 private String getCatalogXmlContentForCatalogAddOrUpdate(ParentPlatform parentPlatform, DeviceChannel channel, int sumNum, String type, SubscribeInfo subscribeInfo) {
421 StringBuffer catalogXml = new StringBuffer(600); 476 StringBuffer catalogXml = new StringBuffer(600);
422 if (parentPlatform.getServerGBId().equals(channel.getParentId())) { 477 if (parentPlatform.getServerGBId().equals(channel.getParentId())) {
@@ -465,34 +520,31 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { @@ -465,34 +520,31 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
465 if (index == null) { 520 if (index == null) {
466 index = 0; 521 index = 0;
467 } 522 }
468 -  
469 - if (index > deviceChannels.size() - 1) { 523 + if (index >= deviceChannels.size()) {
470 return true; 524 return true;
471 } 525 }
472 try { 526 try {
473 - String catalogXml = getCatalogXmlContentForCatalogOther(deviceChannels.get(index), type, parentPlatform);  
474 - CallIdHeader callIdHeader = parentPlatform.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()  
475 - : udpSipProvider.getNewCallId();  
476 - Request request = headerProviderPlarformProvider.createNotifyRequest(parentPlatform, catalogXml,  
477 - callIdHeader,  
478 - "z9hG4bK-" + UUID.randomUUID().toString().replace("-", ""), subscribeInfo);  
479 - index += 1;  
480 Integer finalIndex = index; 527 Integer finalIndex = index;
481 - transmitRequest(parentPlatform, request, null, eventResult -> {  
482 - sendNotifyForCatalogOther(type, parentPlatform, deviceChannels, subscribeInfo, finalIndex);  
483 - }); 528 + String catalogXmlContent = getCatalogXmlContentForCatalogOther(parentPlatform, deviceChannels.get(index), type);
  529 + sendNotify(parentPlatform, catalogXmlContent, subscribeInfo, eventResult -> {
  530 + logger.error("发送NOTIFY通知消息失败。错误:{} {}", eventResult.statusCode, eventResult.msg);
  531 + }, (eventResult -> {
  532 + sendNotifyForCatalogOther(type, parentPlatform, deviceChannels, subscribeInfo, finalIndex + 1);
  533 + }));
484 } catch (SipException e) { 534 } catch (SipException e) {
485 e.printStackTrace(); 535 e.printStackTrace();
486 - } catch (InvalidArgumentException e) {  
487 - e.printStackTrace();  
488 } catch (ParseException e) { 536 } catch (ParseException e) {
489 e.printStackTrace(); 537 e.printStackTrace();
  538 + } catch (NoSuchFieldException e) {
  539 + e.printStackTrace();
  540 + } catch (IllegalAccessException e) {
  541 + e.printStackTrace();
490 } 542 }
491 543
492 return true; 544 return true;
493 } 545 }
494 546
495 - private String getCatalogXmlContentForCatalogOther(DeviceChannel channel, String type, ParentPlatform parentPlatform) { 547 + private String getCatalogXmlContentForCatalogOther(ParentPlatform parentPlatform, DeviceChannel channel, String type) {
496 if (parentPlatform.getServerGBId().equals(channel.getParentId())) { 548 if (parentPlatform.getServerGBId().equals(channel.getParentId())) {
497 channel.setParentId(parentPlatform.getDeviceGBId()); 549 channel.setParentId(parentPlatform.getDeviceGBId());
498 } 550 }
@@ -594,6 +646,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { @@ -594,6 +646,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
594 byte[] transactionByteArray = sendRtpItem.getTransaction(); 646 byte[] transactionByteArray = sendRtpItem.getTransaction();
595 ClientTransaction clientTransaction = (ClientTransaction) SerializeUtils.deSerialize(transactionByteArray); 647 ClientTransaction clientTransaction = (ClientTransaction) SerializeUtils.deSerialize(transactionByteArray);
596 Request byeRequest = dialog.createRequest(Request.BYE); 648 Request byeRequest = dialog.createRequest(Request.BYE);
  649 +
597 SipURI byeURI = (SipURI) byeRequest.getRequestURI(); 650 SipURI byeURI = (SipURI) byeRequest.getRequestURI();
598 SIPRequest request = (SIPRequest) clientTransaction.getRequest(); 651 SIPRequest request = (SIPRequest) clientTransaction.getRequest();
599 byeURI.setHost(request.getRemoteAddress().getHostName()); 652 byeURI.setHost(request.getRemoteAddress().getHostName());
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/NotifyRequestProcessor.java
@@ -233,6 +233,7 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements @@ -233,6 +233,7 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements
233 */ 233 */
234 private void processNotifyCatalogList(RequestEvent evt) { 234 private void processNotifyCatalogList(RequestEvent evt) {
235 try { 235 try {
  236 + System.out.println(343434);
236 FromHeader fromHeader = (FromHeader) evt.getRequest().getHeader(FromHeader.NAME); 237 FromHeader fromHeader = (FromHeader) evt.getRequest().getHeader(FromHeader.NAME);
237 String deviceId = SipUtils.getUserIdFromFromHeader(fromHeader); 238 String deviceId = SipUtils.getUserIdFromFromHeader(fromHeader);
238 239
@@ -309,12 +310,6 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements @@ -309,12 +310,6 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements
309 310
310 } 311 }
311 312
312 - // RequestMessage msg = new RequestMessage();  
313 - // msg.setDeviceId(deviceId);  
314 - // msg.setType(DeferredResultHolder.CALLBACK_CMD_CATALOG);  
315 - // msg.setData(device);  
316 - // deferredResultHolder.invokeResult(msg);  
317 -  
318 if (offLineDetector.isOnline(deviceId)) { 313 if (offLineDetector.isOnline(deviceId)) {
319 publisher.onlineEventPublish(device, VideoManagerConstants.EVENT_ONLINE_MESSAGE); 314 publisher.onlineEventPublish(device, VideoManagerConstants.EVENT_ONLINE_MESSAGE);
320 } 315 }
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java
@@ -81,7 +81,7 @@ public class RegisterRequestProcessor extends SIPRequestProcessorParent implemen @@ -81,7 +81,7 @@ public class RegisterRequestProcessor extends SIPRequestProcessorParent implemen
81 String requestAddress = evtExt.getRemoteIpAddress() + ":" + evtExt.getRemotePort(); 81 String requestAddress = evtExt.getRemoteIpAddress() + ":" + evtExt.getRemotePort();
82 logger.info("[{}] 收到注册请求,开始处理", requestAddress); 82 logger.info("[{}] 收到注册请求,开始处理", requestAddress);
83 Request request = evt.getRequest(); 83 Request request = evt.getRequest();
84 - 84 + ExpiresHeader expiresHeader = (ExpiresHeader) request.getHeader(Expires.NAME);
85 Response response = null; 85 Response response = null;
86 boolean passwordCorrect = false; 86 boolean passwordCorrect = false;
87 // 注册标志 0:未携带授权头或者密码错误 1:注册成功 2:注销成功 87 // 注册标志 0:未携带授权头或者密码错误 1:注册成功 2:注销成功
@@ -128,7 +128,7 @@ public class RegisterRequestProcessor extends SIPRequestProcessorParent implemen @@ -128,7 +128,7 @@ public class RegisterRequestProcessor extends SIPRequestProcessorParent implemen
128 dateHeader.setDate(wvpSipDate); 128 dateHeader.setDate(wvpSipDate);
129 response.addHeader(dateHeader); 129 response.addHeader(dateHeader);
130 130
131 - ExpiresHeader expiresHeader = (ExpiresHeader) request.getHeader(Expires.NAME); 131 +
132 if (expiresHeader == null) { 132 if (expiresHeader == null) {
133 response = getMessageFactory().createResponse(Response.BAD_REQUEST, request); 133 response = getMessageFactory().createResponse(Response.BAD_REQUEST, request);
134 ServerTransaction serverTransaction = getServerTransaction(evt); 134 ServerTransaction serverTransaction = getServerTransaction(evt);
@@ -193,9 +193,7 @@ public class RegisterRequestProcessor extends SIPRequestProcessorParent implemen @@ -193,9 +193,7 @@ public class RegisterRequestProcessor extends SIPRequestProcessorParent implemen
193 // 保存到redis 193 // 保存到redis
194 if (registerFlag == 1 ) { 194 if (registerFlag == 1 ) {
195 logger.info("[{}] 注册成功! deviceId:" + device.getDeviceId(), requestAddress); 195 logger.info("[{}] 注册成功! deviceId:" + device.getDeviceId(), requestAddress);
196 - publisher.onlineEventPublish(device, VideoManagerConstants.EVENT_ONLINE_REGISTER);  
197 - // 重新注册更新设备和通道,以免设备替换或更新后信息无法更新  
198 - handler.onRegister(device); 196 + publisher.onlineEventPublish(device, VideoManagerConstants.EVENT_ONLINE_REGISTER, expiresHeader.getExpires());
199 } else if (registerFlag == 2) { 197 } else if (registerFlag == 2) {
200 logger.info("[{}] 注销成功! deviceId:" + device.getDeviceId(), requestAddress); 198 logger.info("[{}] 注销成功! deviceId:" + device.getDeviceId(), requestAddress);
201 publisher.outlineEventPublish(device.getDeviceId(), VideoManagerConstants.EVENT_OUTLINE_UNREGISTER); 199 publisher.outlineEventPublish(device.getDeviceId(), VideoManagerConstants.EVENT_OUTLINE_UNREGISTER);
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/SubscribeRequestProcessor.java
@@ -5,6 +5,7 @@ import com.genersoft.iot.vmp.conf.DynamicTask; @@ -5,6 +5,7 @@ import com.genersoft.iot.vmp.conf.DynamicTask;
5 import com.genersoft.iot.vmp.conf.UserSetup; 5 import com.genersoft.iot.vmp.conf.UserSetup;
6 import com.genersoft.iot.vmp.gb28181.bean.CmdType; 6 import com.genersoft.iot.vmp.gb28181.bean.CmdType;
7 import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; 7 import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
  8 +import com.genersoft.iot.vmp.gb28181.bean.SubscribeHolder;
8 import com.genersoft.iot.vmp.gb28181.bean.SubscribeInfo; 9 import com.genersoft.iot.vmp.gb28181.bean.SubscribeInfo;
9 import com.genersoft.iot.vmp.gb28181.task.GPSSubscribeTask; 10 import com.genersoft.iot.vmp.gb28181.task.GPSSubscribeTask;
10 import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver; 11 import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver;
@@ -15,18 +16,19 @@ import com.genersoft.iot.vmp.gb28181.utils.SipUtils; @@ -15,18 +16,19 @@ import com.genersoft.iot.vmp.gb28181.utils.SipUtils;
15 import com.genersoft.iot.vmp.gb28181.utils.XmlUtil; 16 import com.genersoft.iot.vmp.gb28181.utils.XmlUtil;
16 import com.genersoft.iot.vmp.storager.IRedisCatchStorage; 17 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
17 import com.genersoft.iot.vmp.storager.IVideoManagerStorager; 18 import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
  19 +import com.genersoft.iot.vmp.utils.SerializeUtils;
  20 +import gov.nist.javax.sip.SipProviderImpl;
18 import org.dom4j.DocumentException; 21 import org.dom4j.DocumentException;
19 import org.dom4j.Element; 22 import org.dom4j.Element;
20 import org.slf4j.Logger; 23 import org.slf4j.Logger;
21 import org.slf4j.LoggerFactory; 24 import org.slf4j.LoggerFactory;
22 import org.springframework.beans.factory.InitializingBean; 25 import org.springframework.beans.factory.InitializingBean;
23 import org.springframework.beans.factory.annotation.Autowired; 26 import org.springframework.beans.factory.annotation.Autowired;
  27 +import org.springframework.beans.factory.annotation.Qualifier;
  28 +import org.springframework.context.annotation.Lazy;
24 import org.springframework.stereotype.Component; 29 import org.springframework.stereotype.Component;
25 30
26 -import javax.sip.InvalidArgumentException;  
27 -import javax.sip.RequestEvent;  
28 -import javax.sip.ServerTransaction;  
29 -import javax.sip.SipException; 31 +import javax.sip.*;
30 import javax.sip.header.ExpiresHeader; 32 import javax.sip.header.ExpiresHeader;
31 import javax.sip.header.ToHeader; 33 import javax.sip.header.ToHeader;
32 import javax.sip.message.Request; 34 import javax.sip.message.Request;
@@ -54,12 +56,26 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme @@ -54,12 +56,26 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme
54 @Autowired 56 @Autowired
55 private IVideoManagerStorager storager; 57 private IVideoManagerStorager storager;
56 58
  59 + @Lazy
  60 + @Autowired
  61 + @Qualifier(value="tcpSipProvider")
  62 + private SipProviderImpl tcpSipProvider;
  63 +
  64 + @Lazy
  65 + @Autowired
  66 + @Qualifier(value="udpSipProvider")
  67 + private SipProviderImpl udpSipProvider;
  68 +
57 @Autowired 69 @Autowired
58 private DynamicTask dynamicTask; 70 private DynamicTask dynamicTask;
59 71
60 @Autowired 72 @Autowired
61 private UserSetup userSetup; 73 private UserSetup userSetup;
62 74
  75 +
  76 + @Autowired
  77 + private SubscribeHolder subscribeHolder;
  78 +
63 @Override 79 @Override
64 public void afterPropertiesSet() throws Exception { 80 public void afterPropertiesSet() throws Exception {
65 // 添加消息处理的订阅 81 // 添加消息处理的订阅
@@ -136,16 +152,17 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme @@ -136,16 +152,17 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme
136 .append("</Response>\r\n"); 152 .append("</Response>\r\n");
137 153
138 if (subscribeInfo.getExpires() > 0) { 154 if (subscribeInfo.getExpires() > 0) {
139 - if (redisCatchStorage.getSubscribe(key) != null) { 155 + if (subscribeHolder.getMobilePositionSubscribe(platformId) != null) {
140 dynamicTask.stop(key); 156 dynamicTask.stop(key);
141 } 157 }
142 String interval = XmlUtil.getText(rootElement, "Interval"); // GPS上报时间间隔 158 String interval = XmlUtil.getText(rootElement, "Interval"); // GPS上报时间间隔
143 - dynamicTask.startCron(key, new GPSSubscribeTask(redisCatchStorage, sipCommanderForPlatform, storager, platformId, sn, key), Integer.parseInt(interval));  
144 -  
145 - redisCatchStorage.updateSubscribe(key, subscribeInfo); 159 + dynamicTask.startCron(key, new GPSSubscribeTask(redisCatchStorage, sipCommanderForPlatform, storager, platformId, sn, key, subscribeHolder), Integer.parseInt(interval));
  160 + subscribeHolder.putMobilePositionSubscribe(platformId, subscribeInfo);
  161 +// redisCatchStorage.updateSubscribe(key, subscribeInfo);
146 }else if (subscribeInfo.getExpires() == 0) { 162 }else if (subscribeInfo.getExpires() == 0) {
147 dynamicTask.stop(key); 163 dynamicTask.stop(key);
148 - redisCatchStorage.delSubscribe(key); 164 +// redisCatchStorage.delSubscribe(key);
  165 + subscribeHolder.removeMobilePositionSubscribe(platformId);
149 } 166 }
150 167
151 try { 168 try {
@@ -168,10 +185,19 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme @@ -168,10 +185,19 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme
168 185
169 } 186 }
170 187
171 - private void processNotifyCatalogList(RequestEvent evt, Element rootElement) { 188 + private void processNotifyCatalogList(RequestEvent evt, Element rootElement) throws SipException {
172 String platformId = SipUtils.getUserIdFromFromHeader(evt.getRequest()); 189 String platformId = SipUtils.getUserIdFromFromHeader(evt.getRequest());
173 String deviceID = XmlUtil.getText(rootElement, "DeviceID"); 190 String deviceID = XmlUtil.getText(rootElement, "DeviceID");
  191 + ParentPlatform platform = storager.queryParentPlatByServerGBId(platformId);
174 SubscribeInfo subscribeInfo = new SubscribeInfo(evt, platformId); 192 SubscribeInfo subscribeInfo = new SubscribeInfo(evt, platformId);
  193 + if (evt.getServerTransaction() == null) {
  194 + ServerTransaction serverTransaction = platform.getTransport().equals("TCP") ? tcpSipProvider.getNewServerTransaction(evt.getRequest())
  195 + : udpSipProvider.getNewServerTransaction(evt.getRequest());
  196 + subscribeInfo.setTransaction(serverTransaction);
  197 + Dialog dialog = serverTransaction.getDialog();
  198 + dialog.terminateOnBye(false);
  199 + subscribeInfo.setDialog(dialog);
  200 + }
175 String sn = XmlUtil.getText(rootElement, "SN"); 201 String sn = XmlUtil.getText(rootElement, "SN");
176 String key = VideoManagerConstants.SIP_SUBSCRIBE_PREFIX + userSetup.getServerId() + "_Catalog_" + platformId; 202 String key = VideoManagerConstants.SIP_SUBSCRIBE_PREFIX + userSetup.getServerId() + "_Catalog_" + platformId;
177 logger.info("接收到{}的Catalog订阅", platformId); 203 logger.info("接收到{}的Catalog订阅", platformId);
@@ -185,9 +211,11 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme @@ -185,9 +211,11 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme
185 .append("</Response>\r\n"); 211 .append("</Response>\r\n");
186 212
187 if (subscribeInfo.getExpires() > 0) { 213 if (subscribeInfo.getExpires() > 0) {
188 - redisCatchStorage.updateSubscribe(key, subscribeInfo); 214 +// redisCatchStorage.updateSubscribe(key, subscribeInfo);
  215 + subscribeHolder.putCatalogSubscribe(platformId, subscribeInfo);
189 }else if (subscribeInfo.getExpires() == 0) { 216 }else if (subscribeInfo.getExpires() == 0) {
190 - redisCatchStorage.delSubscribe(key); 217 +// redisCatchStorage.delSubscribe(key);
  218 + subscribeHolder.removeCatalogSubscribe(platformId);
191 } 219 }
192 220
193 try { 221 try {
@@ -195,7 +223,8 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme @@ -195,7 +223,8 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme
195 Response response = responseXmlAck(evt, resultXml.toString(), parentPlatform); 223 Response response = responseXmlAck(evt, resultXml.toString(), parentPlatform);
196 ToHeader toHeader = (ToHeader)response.getHeader(ToHeader.NAME); 224 ToHeader toHeader = (ToHeader)response.getHeader(ToHeader.NAME);
197 subscribeInfo.setToTag(toHeader.getTag()); 225 subscribeInfo.setToTag(toHeader.getTag());
198 - redisCatchStorage.updateSubscribe(key, subscribeInfo); 226 +// redisCatchStorage.updateSubscribe(key, subscribeInfo);
  227 + subscribeHolder.putCatalogSubscribe(platformId, subscribeInfo);
199 228
200 } catch (SipException e) { 229 } catch (SipException e) {
201 e.printStackTrace(); 230 e.printStackTrace();
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/MessageRequestProcessor.java
@@ -21,6 +21,7 @@ import org.springframework.stereotype.Component; @@ -21,6 +21,7 @@ import org.springframework.stereotype.Component;
21 import javax.sip.InvalidArgumentException; 21 import javax.sip.InvalidArgumentException;
22 import javax.sip.RequestEvent; 22 import javax.sip.RequestEvent;
23 import javax.sip.SipException; 23 import javax.sip.SipException;
  24 +import javax.sip.header.CSeqHeader;
24 import javax.sip.header.CallIdHeader; 25 import javax.sip.header.CallIdHeader;
25 import javax.sip.message.Response; 26 import javax.sip.message.Response;
26 import java.text.ParseException; 27 import java.text.ParseException;
@@ -64,6 +65,11 @@ public class MessageRequestProcessor extends SIPRequestProcessorParent implement @@ -64,6 +65,11 @@ public class MessageRequestProcessor extends SIPRequestProcessorParent implement
64 String deviceId = SipUtils.getUserIdFromFromHeader(evt.getRequest()); 65 String deviceId = SipUtils.getUserIdFromFromHeader(evt.getRequest());
65 CallIdHeader callIdHeader = (CallIdHeader)evt.getRequest().getHeader(CallIdHeader.NAME); 66 CallIdHeader callIdHeader = (CallIdHeader)evt.getRequest().getHeader(CallIdHeader.NAME);
66 // 查询设备是否存在 67 // 查询设备是否存在
  68 + CSeqHeader cseqHeader = (CSeqHeader) evt.getRequest().getHeader(CSeqHeader.NAME);
  69 + String method = cseqHeader.getMethod();
  70 + if (method.equals("MESSAGE")) {
  71 + System.out.println();
  72 + }
67 Device device = redisCatchStorage.getDevice(deviceId); 73 Device device = redisCatchStorage.getDevice(deviceId);
68 // 查询上级平台是否存在 74 // 查询上级平台是否存在
69 ParentPlatform parentPlatform = storage.queryParentPlatByServerGBId(deviceId); 75 ParentPlatform parentPlatform = storage.queryParentPlatByServerGBId(deviceId);
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/CatalogResponseMessageHandler.java
@@ -85,41 +85,54 @@ public class CatalogResponseMessageHandler extends SIPRequestProcessorParent imp @@ -85,41 +85,54 @@ public class CatalogResponseMessageHandler extends SIPRequestProcessorParent imp
85 return; 85 return;
86 } 86 }
87 int sumNum = Integer.parseInt(sumNumElement.getText()); 87 int sumNum = Integer.parseInt(sumNumElement.getText());
88 - Iterator<Element> deviceListIterator = deviceListElement.elementIterator();  
89 - if (deviceListIterator != null) {  
90 - List<DeviceChannel> channelList = new ArrayList<>();  
91 - // 遍历DeviceList  
92 - while (deviceListIterator.hasNext()) {  
93 - Element itemDevice = deviceListIterator.next();  
94 - Element channelDeviceElement = itemDevice.element("DeviceID");  
95 - if (channelDeviceElement == null) {  
96 - continue; 88 + if (sumNum == 0) {
  89 + // 数据已经完整接收
  90 + storager.cleanChannelsForDevice(device.getDeviceId());
  91 + RequestMessage msg = new RequestMessage();
  92 + msg.setKey(key);
  93 + WVPResult<Object> result = new WVPResult<>();
  94 + result.setCode(0);
  95 + result.setData(device);
  96 + msg.setData(result);
  97 + result.setMsg("更新成功,共0条");
  98 + deferredResultHolder.invokeAllResult(msg);
  99 + catalogDataCatch.del(key);
  100 + }else {
  101 + Iterator<Element> deviceListIterator = deviceListElement.elementIterator();
  102 + if (deviceListIterator != null) {
  103 + List<DeviceChannel> channelList = new ArrayList<>();
  104 + // 遍历DeviceList
  105 + while (deviceListIterator.hasNext()) {
  106 + Element itemDevice = deviceListIterator.next();
  107 + Element channelDeviceElement = itemDevice.element("DeviceID");
  108 + if (channelDeviceElement == null) {
  109 + continue;
  110 + }
  111 + DeviceChannel deviceChannel = XmlUtil.channelContentHander(itemDevice);
  112 + deviceChannel.setDeviceId(device.getDeviceId());
  113 + logger.debug("收到来自设备【{}】的通道: {}【{}】", device.getDeviceId(), deviceChannel.getName(), deviceChannel.getChannelId());
  114 + channelList.add(deviceChannel);
97 } 115 }
98 - DeviceChannel deviceChannel = XmlUtil.channelContentHander(itemDevice);  
99 - deviceChannel.setDeviceId(device.getDeviceId());  
100 - logger.debug("收到来自设备【{}】的通道: {}【{}】", device.getDeviceId(), deviceChannel.getName(), deviceChannel.getChannelId());  
101 - channelList.add(deviceChannel);  
102 - }  
103 116
104 - catalogDataCatch.put(key, sumNum, device, channelList);  
105 - if (catalogDataCatch.get(key).size() == sumNum) {  
106 - // 数据已经完整接收  
107 - boolean resetChannelsResult = storager.resetChannels(device.getDeviceId(), catalogDataCatch.get(key));  
108 - RequestMessage msg = new RequestMessage();  
109 - msg.setKey(key);  
110 - WVPResult<Object> result = new WVPResult<>();  
111 - result.setCode(0);  
112 - result.setData(device);  
113 - if (resetChannelsResult) {  
114 - result.setMsg("更新成功,共" + sumNum + "条,已更新" + catalogDataCatch.get(key).size() + "条");  
115 - }else {  
116 - result.setMsg("接收成功,写入失败,共" + sumNum + "条,已接收" + catalogDataCatch.get(key).size() + "条"); 117 + catalogDataCatch.put(key, sumNum, device, channelList);
  118 + if (catalogDataCatch.get(key).size() == sumNum) {
  119 + // 数据已经完整接收
  120 + boolean resetChannelsResult = storager.resetChannels(device.getDeviceId(), catalogDataCatch.get(key));
  121 + RequestMessage msg = new RequestMessage();
  122 + msg.setKey(key);
  123 + WVPResult<Object> result = new WVPResult<>();
  124 + result.setCode(0);
  125 + result.setData(device);
  126 + if (resetChannelsResult || sumNum ==0) {
  127 + result.setMsg("更新成功,共" + sumNum + "条,已更新" + catalogDataCatch.get(key).size() + "条");
  128 + }else {
  129 + result.setMsg("接收成功,写入失败,共" + sumNum + "条,已接收" + catalogDataCatch.get(key).size() + "条");
  130 + }
  131 + msg.setData(result);
  132 + deferredResultHolder.invokeAllResult(msg);
  133 + catalogDataCatch.del(key);
117 } 134 }
118 - msg.setData(result);  
119 - deferredResultHolder.invokeAllResult(msg);  
120 - catalogDataCatch.del(key);  
121 } 135 }
122 -  
123 // 回复200 OK 136 // 回复200 OK
124 responseAck(evt, Response.OK); 137 responseAck(evt, Response.OK);
125 if (offLineDetector.isOnline(device.getDeviceId())) { 138 if (offLineDetector.isOnline(device.getDeviceId())) {
src/main/java/com/genersoft/iot/vmp/service/impl/DeviceServiceImpl.java
@@ -31,8 +31,8 @@ public class DeviceServiceImpl implements IDeviceService { @@ -31,8 +31,8 @@ public class DeviceServiceImpl implements IDeviceService {
31 return false; 31 return false;
32 } 32 }
33 if (dynamicTask.contains(device.getDeviceId())) { 33 if (dynamicTask.contains(device.getDeviceId())) {
34 - logger.info("[添加目录订阅] 设备{}的目录订阅以存在", device.getDeviceId());  
35 - return false; 34 + // 存在则停止现有的,开启新的
  35 + dynamicTask.stop(device.getDeviceId());
36 } 36 }
37 logger.info("[添加目录订阅] 设备{}", device.getDeviceId()); 37 logger.info("[添加目录订阅] 设备{}", device.getDeviceId());
38 // 添加目录订阅 38 // 添加目录订阅
src/main/java/com/genersoft/iot/vmp/service/impl/MediaServerServiceImpl.java
@@ -513,6 +513,14 @@ public class MediaServerServiceImpl implements IMediaServerService { @@ -513,6 +513,14 @@ public class MediaServerServiceImpl implements IMediaServerService {
513 param.put("hook.on_server_keepalive",String.format("%s/on_server_keepalive", hookPrex)); 513 param.put("hook.on_server_keepalive",String.format("%s/on_server_keepalive", hookPrex));
514 param.put("hook.timeoutSec","20"); 514 param.put("hook.timeoutSec","20");
515 param.put("general.streamNoneReaderDelayMS","-1".equals(mediaServerItem.getStreamNoneReaderDelayMS())?"3600000":mediaServerItem.getStreamNoneReaderDelayMS() ); 515 param.put("general.streamNoneReaderDelayMS","-1".equals(mediaServerItem.getStreamNoneReaderDelayMS())?"3600000":mediaServerItem.getStreamNoneReaderDelayMS() );
  516 + // 推流断开后可以在超时时间内重新连接上继续推流,这样播放器会接着播放。
  517 + // 置0关闭此特性(推流断开会导致立即断开播放器)
  518 + // 此参数不应大于播放器超时时间
  519 + // 优化此消息以更快的收到流注销事件
  520 + param.put("general.continue_push_ms", "3000" );
  521 + // 最多等待未初始化的Track时间,单位毫秒,超时之后会忽略未初始化的Track, 设置此选项优化那些音频错误的不规范流,
  522 + // 等zlm支持给每个rtpServer设置关闭音频的时候可以不设置此选项
  523 + param.put("general.wait_track_ready_ms", "3000" );
516 524
517 JSONObject responseJSON = zlmresTfulUtils.setServerConfig(mediaServerItem, param); 525 JSONObject responseJSON = zlmresTfulUtils.setServerConfig(mediaServerItem, param);
518 526
@@ -620,6 +628,8 @@ public class MediaServerServiceImpl implements IMediaServerService { @@ -620,6 +628,8 @@ public class MediaServerServiceImpl implements IMediaServerService {
620 public void updateMediaServerKeepalive(String mediaServerId, JSONObject data) { 628 public void updateMediaServerKeepalive(String mediaServerId, JSONObject data) {
621 MediaServerItem mediaServerItem = getOne(mediaServerId); 629 MediaServerItem mediaServerItem = getOne(mediaServerId);
622 if (mediaServerItem == null) { 630 if (mediaServerItem == null) {
  631 + // zlm连接重试
  632 +
623 logger.warn("[更新ZLM 保活信息]失败,未找到流媒体信息"); 633 logger.warn("[更新ZLM 保活信息]失败,未找到流媒体信息");
624 return; 634 return;
625 } 635 }
src/main/java/com/genersoft/iot/vmp/service/impl/StreamPushServiceImpl.java
1 package com.genersoft.iot.vmp.service.impl; 1 package com.genersoft.iot.vmp.service.impl;
2 2
3 import com.alibaba.fastjson.JSON; 3 import com.alibaba.fastjson.JSON;
  4 +import com.alibaba.fastjson.JSONArray;
4 import com.alibaba.fastjson.JSONObject; 5 import com.alibaba.fastjson.JSONObject;
5 import com.alibaba.fastjson.TypeReference; 6 import com.alibaba.fastjson.TypeReference;
6 import com.genersoft.iot.vmp.common.StreamInfo; 7 import com.genersoft.iot.vmp.common.StreamInfo;
7 import com.genersoft.iot.vmp.conf.UserSetup; 8 import com.genersoft.iot.vmp.conf.UserSetup;
8 -import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;  
9 -import com.genersoft.iot.vmp.gb28181.bean.GbStream;  
10 -import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;  
11 -import com.genersoft.iot.vmp.gb28181.bean.PlatformCatalog; 9 +import com.genersoft.iot.vmp.gb28181.bean.*;
12 import com.genersoft.iot.vmp.gb28181.event.EventPublisher; 10 import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
13 import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent; 11 import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent;
14 import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe; 12 import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe;
@@ -23,6 +21,8 @@ import com.genersoft.iot.vmp.storager.dao.*; @@ -23,6 +21,8 @@ import com.genersoft.iot.vmp.storager.dao.*;
23 import com.genersoft.iot.vmp.vmanager.bean.StreamPushExcelDto; 21 import com.genersoft.iot.vmp.vmanager.bean.StreamPushExcelDto;
24 import com.github.pagehelper.PageHelper; 22 import com.github.pagehelper.PageHelper;
25 import com.github.pagehelper.PageInfo; 23 import com.github.pagehelper.PageInfo;
  24 +import org.slf4j.Logger;
  25 +import org.slf4j.LoggerFactory;
26 import org.springframework.beans.factory.annotation.Autowired; 26 import org.springframework.beans.factory.annotation.Autowired;
27 import org.springframework.stereotype.Service; 27 import org.springframework.stereotype.Service;
28 import org.springframework.util.StringUtils; 28 import org.springframework.util.StringUtils;
@@ -33,6 +33,8 @@ import java.util.stream.Collectors; @@ -33,6 +33,8 @@ import java.util.stream.Collectors;
33 @Service 33 @Service
34 public class StreamPushServiceImpl implements IStreamPushService { 34 public class StreamPushServiceImpl implements IStreamPushService {
35 35
  36 + private final static Logger logger = LoggerFactory.getLogger(StreamPushServiceImpl.class);
  37 +
36 @Autowired 38 @Autowired
37 private GbStreamMapper gbStreamMapper; 39 private GbStreamMapper gbStreamMapper;
38 40
@@ -158,12 +160,17 @@ public class StreamPushServiceImpl implements IStreamPushService { @@ -158,12 +160,17 @@ public class StreamPushServiceImpl implements IStreamPushService {
158 public boolean removeFromGB(GbStream stream) { 160 public boolean removeFromGB(GbStream stream) {
159 // 判断是否需要发送事件 161 // 判断是否需要发送事件
160 gbStreamService.sendCatalogMsg(stream, CatalogEvent.DEL); 162 gbStreamService.sendCatalogMsg(stream, CatalogEvent.DEL);
161 - int del = gbStreamMapper.del(stream.getApp(), stream.getStream());  
162 platformGbStreamMapper.delByAppAndStream(stream.getApp(), stream.getStream()); 163 platformGbStreamMapper.delByAppAndStream(stream.getApp(), stream.getStream());
  164 + int del = gbStreamMapper.del(stream.getApp(), stream.getStream());
163 MediaServerItem mediaInfo = mediaServerService.getOne(stream.getMediaServerId()); 165 MediaServerItem mediaInfo = mediaServerService.getOne(stream.getMediaServerId());
164 JSONObject mediaList = zlmresTfulUtils.getMediaList(mediaInfo, stream.getApp(), stream.getStream()); 166 JSONObject mediaList = zlmresTfulUtils.getMediaList(mediaInfo, stream.getApp(), stream.getStream());
165 - if (mediaList == null) {  
166 - streamPushMapper.del(stream.getApp(), stream.getStream()); 167 + if (mediaList != null) {
  168 + if (mediaList.getInteger("code") == 0) {
  169 + JSONArray data = mediaList.getJSONArray("data");
  170 + if (data == null) {
  171 + streamPushMapper.del(stream.getApp(), stream.getStream());
  172 + }
  173 + }
167 } 174 }
168 return del > 0; 175 return del > 0;
169 } 176 }
@@ -180,9 +187,9 @@ public class StreamPushServiceImpl implements IStreamPushService { @@ -180,9 +187,9 @@ public class StreamPushServiceImpl implements IStreamPushService {
180 StreamPushItem streamPushItem = streamPushMapper.selectOne(app, streamId); 187 StreamPushItem streamPushItem = streamPushMapper.selectOne(app, streamId);
181 gbStreamService.sendCatalogMsg(streamPushItem, CatalogEvent.DEL); 188 gbStreamService.sendCatalogMsg(streamPushItem, CatalogEvent.DEL);
182 189
183 - int delStream = streamPushMapper.del(app, streamId);  
184 - gbStreamMapper.del(app, streamId);  
185 platformGbStreamMapper.delByAppAndStream(app, streamId); 190 platformGbStreamMapper.delByAppAndStream(app, streamId);
  191 + gbStreamMapper.del(app, streamId);
  192 + int delStream = streamPushMapper.del(app, streamId);
186 if (delStream > 0) { 193 if (delStream > 0) {
187 MediaServerItem mediaServerItem = mediaServerService.getOne(streamPushItem.getMediaServerId()); 194 MediaServerItem mediaServerItem = mediaServerService.getOne(streamPushItem.getMediaServerId());
188 zlmresTfulUtils.closeStreams(mediaServerItem,app, streamId); 195 zlmresTfulUtils.closeStreams(mediaServerItem,app, streamId);
@@ -376,6 +383,29 @@ public class StreamPushServiceImpl implements IStreamPushService { @@ -376,6 +383,29 @@ public class StreamPushServiceImpl implements IStreamPushService {
376 .collect(Collectors.toList()); 383 .collect(Collectors.toList());
377 384
378 if (streamPushItemsForPlatform.size() > 0) { 385 if (streamPushItemsForPlatform.size() > 0) {
  386 + // 获取所有平台,平台和目录信息一般不会特别大量。
  387 + List<ParentPlatform> parentPlatformList = parentPlatformMapper.getParentPlatformList();
  388 + Map<String, Map<String, PlatformCatalog>> platformInfoMap = new HashMap<>();
  389 + if (parentPlatformList.size() == 0) {
  390 + return;
  391 + }
  392 + for (ParentPlatform platform : parentPlatformList) {
  393 + Map<String, PlatformCatalog> catalogMap = new HashMap<>();
  394 +
  395 + // 创建根节点
  396 + PlatformCatalog platformCatalog = new PlatformCatalog();
  397 + platformCatalog.setId(platform.getServerGBId());
  398 + catalogMap.put(platform.getServerGBId(), platformCatalog);
  399 +
  400 + // 查询所有节点信息
  401 + List<PlatformCatalog> platformCatalogs = platformCatalogMapper.selectByPlatForm(platform.getServerGBId());
  402 + if (platformCatalogs.size() > 0) {
  403 + for (PlatformCatalog catalog : platformCatalogs) {
  404 + catalogMap.put(catalog.getId(), catalog);
  405 + }
  406 + }
  407 + platformInfoMap.put(platform.getServerGBId(), catalogMap);
  408 + }
379 List<StreamPushItem> streamPushItemListFroPlatform = new ArrayList<>(); 409 List<StreamPushItem> streamPushItemListFroPlatform = new ArrayList<>();
380 Map<String, List<GbStream>> platformForEvent = new HashMap<>(); 410 Map<String, List<GbStream>> platformForEvent = new HashMap<>();
381 // 遍历存储结果,查找app+Stream->platformId+catalogId的对应关系,然后执行批量写入 411 // 遍历存储结果,查找app+Stream->platformId+catalogId的对应关系,然后执行批量写入
@@ -388,6 +418,12 @@ public class StreamPushServiceImpl implements IStreamPushService { @@ -388,6 +418,12 @@ public class StreamPushServiceImpl implements IStreamPushService {
388 streamPushItemForPlatform.setGbStreamId(streamPushItem.getGbStreamId()); 418 streamPushItemForPlatform.setGbStreamId(streamPushItem.getGbStreamId());
389 if (platFormInfoArray.length > 0) { 419 if (platFormInfoArray.length > 0) {
390 // 数组 platFormInfoArray 0 为平台ID。 1为目录ID 420 // 数组 platFormInfoArray 0 为平台ID。 1为目录ID
  421 + // 不存在这个平台,则忽略导入此关联关系
  422 + if (platformInfoMap.get(platFormInfoArray[0]) == null
  423 + || platformInfoMap.get(platFormInfoArray[0]).get(platFormInfoArray[1]) == null) {
  424 + logger.info("导入数据时不存在平台或目录{}/{},已导入未分配", platFormInfoArray[0], platFormInfoArray[1] );
  425 + continue;
  426 + }
391 streamPushItemForPlatform.setPlatformId(platFormInfoArray[0]); 427 streamPushItemForPlatform.setPlatformId(platFormInfoArray[0]);
392 428
393 List<GbStream> gbStreamList = platformForEvent.get(streamPushItem.getPlatformId()); 429 List<GbStream> gbStreamList = platformForEvent.get(streamPushItem.getPlatformId());
@@ -406,8 +442,6 @@ public class StreamPushServiceImpl implements IStreamPushService { @@ -406,8 +442,6 @@ public class StreamPushServiceImpl implements IStreamPushService {
406 streamPushItemForPlatform.setCatalogId(platFormInfoArray[1]); 442 streamPushItemForPlatform.setCatalogId(platFormInfoArray[1]);
407 } 443 }
408 streamPushItemListFroPlatform.add(streamPushItemForPlatform); 444 streamPushItemListFroPlatform.add(streamPushItemForPlatform);
409 -  
410 -  
411 } 445 }
412 } 446 }
413 447
@@ -432,9 +466,9 @@ public class StreamPushServiceImpl implements IStreamPushService { @@ -432,9 +466,9 @@ public class StreamPushServiceImpl implements IStreamPushService {
432 } 466 }
433 gbStreamService.sendCatalogMsgs(gbStreams, CatalogEvent.DEL); 467 gbStreamService.sendCatalogMsgs(gbStreams, CatalogEvent.DEL);
434 468
435 - int delStream = streamPushMapper.delAllForGbStream(gbStreams);  
436 - gbStreamMapper.batchDelForGbStream(gbStreams);  
437 platformGbStreamMapper.delByGbStreams(gbStreams); 469 platformGbStreamMapper.delByGbStreams(gbStreams);
  470 + gbStreamMapper.batchDelForGbStream(gbStreams);
  471 + int delStream = streamPushMapper.delAllForGbStream(gbStreams);
438 if (delStream > 0) { 472 if (delStream > 0) {
439 for (GbStream gbStream : gbStreams) { 473 for (GbStream gbStream : gbStreams) {
440 MediaServerItem mediaServerItem = mediaServerService.getOne(gbStream.getMediaServerId()); 474 MediaServerItem mediaServerItem = mediaServerService.getOne(gbStream.getMediaServerId());