Commit e6ee7fe7477b485676ce506b4e971c9a50dfa588

Authored by 648540858
1 parent efc4a7bc

优化级联移动位置订阅位置更新

src/main/java/com/genersoft/iot/vmp/conf/DynamicTask.java
1 package com.genersoft.iot.vmp.conf; 1 package com.genersoft.iot.vmp.conf;
2 2
3 import com.genersoft.iot.vmp.gb28181.task.ISubscribeTask; 3 import com.genersoft.iot.vmp.gb28181.task.ISubscribeTask;
  4 +import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.cmd.CatalogResponseMessageHandler;
  5 +import org.slf4j.Logger;
  6 +import org.slf4j.LoggerFactory;
4 import org.springframework.beans.factory.annotation.Autowired; 7 import org.springframework.beans.factory.annotation.Autowired;
5 import org.springframework.context.annotation.Bean; 8 import org.springframework.context.annotation.Bean;
6 import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; 9 import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
@@ -18,6 +21,8 @@ import java.util.concurrent.ScheduledFuture; @@ -18,6 +21,8 @@ import java.util.concurrent.ScheduledFuture;
18 @Component 21 @Component
19 public class DynamicTask { 22 public class DynamicTask {
20 23
  24 + private Logger logger = LoggerFactory.getLogger(DynamicTask.class);
  25 +
21 @Autowired 26 @Autowired
22 private ThreadPoolTaskScheduler threadPoolTaskScheduler; 27 private ThreadPoolTaskScheduler threadPoolTaskScheduler;
23 28
@@ -26,7 +31,12 @@ public class DynamicTask { @@ -26,7 +31,12 @@ public class DynamicTask {
26 31
27 @Bean 32 @Bean
28 public ThreadPoolTaskScheduler threadPoolTaskScheduler() { 33 public ThreadPoolTaskScheduler threadPoolTaskScheduler() {
29 - return new ThreadPoolTaskScheduler(); 34 + ThreadPoolTaskScheduler schedulerPool = new ThreadPoolTaskScheduler();
  35 + schedulerPool.setPoolSize(300);
  36 + schedulerPool.setWaitForTasksToCompleteOnShutdown(true);
  37 + schedulerPool.setAwaitTerminationSeconds(10);
  38 + return schedulerPool;
  39 +
30 } 40 }
31 41
32 /** 42 /**
@@ -37,11 +47,24 @@ public class DynamicTask { @@ -37,11 +47,24 @@ public class DynamicTask {
37 * @return 47 * @return
38 */ 48 */
39 public void startCron(String key, Runnable task, int cycleForCatalog) { 49 public void startCron(String key, Runnable task, int cycleForCatalog) {
40 - stop(key); 50 + ScheduledFuture future = futureMap.get(key);
  51 + if (future != null) {
  52 + if (future.isCancelled()) {
  53 + logger.info("任务【{}】已存在但是关闭状态!!!", key);
  54 + } else {
  55 + logger.info("任务【{}】已存在且已启动!!!", key);
  56 + return;
  57 + }
  58 + }
41 // scheduleWithFixedDelay 必须等待上一个任务结束才开始计时period, cycleForCatalog表示执行的间隔 59 // scheduleWithFixedDelay 必须等待上一个任务结束才开始计时period, cycleForCatalog表示执行的间隔
42 - ScheduledFuture future = threadPoolTaskScheduler.scheduleAtFixedRate(task, cycleForCatalog * 1000L);  
43 - futureMap.put(key, future);  
44 - runnableMap.put(key, task); 60 + future = threadPoolTaskScheduler.scheduleAtFixedRate(task, cycleForCatalog * 1000L);
  61 + if (future != null){
  62 + futureMap.put(key, future);
  63 + runnableMap.put(key, task);
  64 + logger.info("任务【{}】启动成功!!!", key);
  65 + }else {
  66 + logger.info("任务【{}】启动失败!!!", key);
  67 + }
45 } 68 }
46 69
47 /** 70 /**
@@ -53,13 +76,31 @@ public class DynamicTask { @@ -53,13 +76,31 @@ public class DynamicTask {
53 */ 76 */
54 public void startDelay(String key, Runnable task, int delay) { 77 public void startDelay(String key, Runnable task, int delay) {
55 stop(key); 78 stop(key);
  79 + System.out.println("定时任务开始了");
56 Date starTime = new Date(System.currentTimeMillis() + delay); 80 Date starTime = new Date(System.currentTimeMillis() + delay);
  81 +
  82 + ScheduledFuture future = futureMap.get(key);
  83 + if (future != null) {
  84 + if (future.isCancelled()) {
  85 + logger.info("任务【{}】已存在但是关闭状态!!!", key);
  86 + } else {
  87 + logger.info("任务【{}】已存在且已启动!!!", key);
  88 + return;
  89 + }
  90 + }
57 // scheduleWithFixedDelay 必须等待上一个任务结束才开始计时period, cycleForCatalog表示执行的间隔 91 // scheduleWithFixedDelay 必须等待上一个任务结束才开始计时period, cycleForCatalog表示执行的间隔
58 - ScheduledFuture future = threadPoolTaskScheduler.schedule(task, starTime);  
59 - futureMap.put(key, future); 92 + future = threadPoolTaskScheduler.schedule(task, starTime);
  93 + if (future != null){
  94 + futureMap.put(key, future);
  95 + runnableMap.put(key, task);
  96 + logger.info("任务【{}】启动成功!!!", key);
  97 + }else {
  98 + logger.info("任务【{}】启动失败!!!", key);
  99 + }
60 } 100 }
61 101
62 public void stop(String key) { 102 public void stop(String key) {
  103 + System.out.println("定时任务结束了");
63 if (futureMap.get(key) != null && !futureMap.get(key).isCancelled()) { 104 if (futureMap.get(key) != null && !futureMap.get(key).isCancelled()) {
64 futureMap.get(key).cancel(true); 105 futureMap.get(key).cancel(true);
65 Runnable runnable = runnableMap.get(key); 106 Runnable runnable = runnableMap.get(key);
src/main/java/com/genersoft/iot/vmp/gb28181/bean/SubscribeHolder.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.common.VideoManagerConstants;
  4 +import com.genersoft.iot.vmp.conf.DynamicTask;
  5 +import com.genersoft.iot.vmp.gb28181.task.impl.MobilePositionSubscribeHandlerTask;
  6 +import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
  7 +import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
  8 +import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
  9 +import org.springframework.beans.factory.annotation.Autowired;
3 import org.springframework.stereotype.Component; 10 import org.springframework.stereotype.Component;
4 11
5 import java.util.ArrayList; 12 import java.util.ArrayList;
@@ -9,12 +16,32 @@ import java.util.concurrent.ConcurrentHashMap; @@ -9,12 +16,32 @@ import java.util.concurrent.ConcurrentHashMap;
9 @Component 16 @Component
10 public class SubscribeHolder { 17 public class SubscribeHolder {
11 18
  19 + @Autowired
  20 + private DynamicTask dynamicTask;
  21 +
  22 + @Autowired
  23 + private IRedisCatchStorage redisCatchStorage;
  24 +
  25 + @Autowired
  26 + private ISIPCommanderForPlatform sipCommanderForPlatform;
  27 +
  28 + @Autowired
  29 + private IVideoManagerStorage storager;
  30 +
  31 + private final String taskOverduePrefix = "subscribe_overdue_";
  32 +
12 private static ConcurrentHashMap<String, SubscribeInfo> catalogMap = new ConcurrentHashMap<>(); 33 private static ConcurrentHashMap<String, SubscribeInfo> catalogMap = new ConcurrentHashMap<>();
13 private static ConcurrentHashMap<String, SubscribeInfo> mobilePositionMap = new ConcurrentHashMap<>(); 34 private static ConcurrentHashMap<String, SubscribeInfo> mobilePositionMap = new ConcurrentHashMap<>();
14 35
15 36
16 public void putCatalogSubscribe(String platformId, SubscribeInfo subscribeInfo) { 37 public void putCatalogSubscribe(String platformId, SubscribeInfo subscribeInfo) {
17 catalogMap.put(platformId, subscribeInfo); 38 catalogMap.put(platformId, subscribeInfo);
  39 + // 添加订阅到期
  40 + String taskOverdueKey = taskOverduePrefix + "catalog_" + platformId;
  41 + dynamicTask.stop(taskOverdueKey);
  42 + // 添加任务处理订阅过期
  43 + dynamicTask.startDelay(taskOverdueKey, () -> removeCatalogSubscribe(subscribeInfo.getId()),
  44 + subscribeInfo.getExpires() * 1000);
18 } 45 }
19 46
20 public SubscribeInfo getCatalogSubscribe(String platformId) { 47 public SubscribeInfo getCatalogSubscribe(String platformId) {
@@ -23,10 +50,24 @@ public class SubscribeHolder { @@ -23,10 +50,24 @@ public class SubscribeHolder {
23 50
24 public void removeCatalogSubscribe(String platformId) { 51 public void removeCatalogSubscribe(String platformId) {
25 catalogMap.remove(platformId); 52 catalogMap.remove(platformId);
  53 + String taskOverdueKey = taskOverduePrefix + "catalog_" + platformId;
  54 + // 添加任务处理订阅过期
  55 + dynamicTask.stop(taskOverdueKey);
26 } 56 }
27 57
28 public void putMobilePositionSubscribe(String platformId, SubscribeInfo subscribeInfo) { 58 public void putMobilePositionSubscribe(String platformId, SubscribeInfo subscribeInfo) {
29 mobilePositionMap.put(platformId, subscribeInfo); 59 mobilePositionMap.put(platformId, subscribeInfo);
  60 + String key = VideoManagerConstants.SIP_SUBSCRIBE_PREFIX + "MobilePosition_" + platformId;
  61 + // 添加任务处理GPS定时推送
  62 + dynamicTask.startCron(key, new MobilePositionSubscribeHandlerTask(redisCatchStorage, sipCommanderForPlatform, storager, platformId, subscribeInfo.getSn(), key, this), subscribeInfo.getGpsInterval());
  63 + String taskOverdueKey = taskOverduePrefix + "MobilePosition_" + platformId;
  64 + dynamicTask.stop(taskOverdueKey);
  65 + // 添加任务处理订阅过期
  66 + dynamicTask.startDelay(taskOverdueKey, () -> {
  67 + System.out.println("订阅过期");
  68 + removeMobilePositionSubscribe(subscribeInfo.getId());
  69 + },
  70 + subscribeInfo.getExpires() * 1000);
30 } 71 }
31 72
32 public SubscribeInfo getMobilePositionSubscribe(String platformId) { 73 public SubscribeInfo getMobilePositionSubscribe(String platformId) {
@@ -35,6 +76,12 @@ public class SubscribeHolder { @@ -35,6 +76,12 @@ public class SubscribeHolder {
35 76
36 public void removeMobilePositionSubscribe(String platformId) { 77 public void removeMobilePositionSubscribe(String platformId) {
37 mobilePositionMap.remove(platformId); 78 mobilePositionMap.remove(platformId);
  79 + String key = VideoManagerConstants.SIP_SUBSCRIBE_PREFIX + "MobilePosition_" + platformId;
  80 + // 结束任务处理GPS定时推送
  81 + dynamicTask.stop(key);
  82 + String taskOverdueKey = taskOverduePrefix + "MobilePosition_" + platformId;
  83 + // 添加任务处理订阅过期
  84 + dynamicTask.stop(taskOverdueKey);
38 } 85 }
39 86
40 public List<String> getAllCatalogSubscribePlatform() { 87 public List<String> getAllCatalogSubscribePlatform() {
@@ -48,7 +95,7 @@ public class SubscribeHolder { @@ -48,7 +95,7 @@ public class SubscribeHolder {
48 } 95 }
49 96
50 public void removeAllSubscribe(String platformId) { 97 public void removeAllSubscribe(String platformId) {
51 - mobilePositionMap.remove(platformId);  
52 - catalogMap.remove(platformId); 98 + removeMobilePositionSubscribe(platformId);
  99 + removeCatalogSubscribe(platformId);
53 } 100 }
54 } 101 }
src/main/java/com/genersoft/iot/vmp/gb28181/bean/SubscribeInfo.java
@@ -33,6 +33,14 @@ public class SubscribeInfo { @@ -33,6 +33,14 @@ public class SubscribeInfo {
33 private ServerTransaction transaction; 33 private ServerTransaction transaction;
34 private Dialog dialog; 34 private Dialog dialog;
35 35
  36 + /**
  37 + * 以下为可选字段
  38 + * @return
  39 + */
  40 + private String sn;
  41 + private int gpsInterval;
  42 +
  43 +
36 public String getId() { 44 public String getId() {
37 return id; 45 return id;
38 } 46 }
@@ -88,4 +96,20 @@ public class SubscribeInfo { @@ -88,4 +96,20 @@ public class SubscribeInfo {
88 public void setDialog(Dialog dialog) { 96 public void setDialog(Dialog dialog) {
89 this.dialog = dialog; 97 this.dialog = dialog;
90 } 98 }
  99 +
  100 + public String getSn() {
  101 + return sn;
  102 + }
  103 +
  104 + public void setSn(String sn) {
  105 + this.sn = sn;
  106 + }
  107 +
  108 + public int getGpsInterval() {
  109 + return gpsInterval;
  110 + }
  111 +
  112 + public void setGpsInterval(int gpsInterval) {
  113 + this.gpsInterval = gpsInterval;
  114 + }
91 } 115 }
src/main/java/com/genersoft/iot/vmp/gb28181/event/subscribe/SubscribeListenerForPlatform.java deleted 100644 → 0
1 -package com.genersoft.iot.vmp.gb28181.event.subscribe;  
2 -  
3 -import com.genersoft.iot.vmp.common.VideoManagerConstants;  
4 -import com.genersoft.iot.vmp.conf.DynamicTask;  
5 -import com.genersoft.iot.vmp.conf.RedisKeyExpirationEventMessageListener;  
6 -import com.genersoft.iot.vmp.conf.UserSetting;  
7 -import org.slf4j.Logger;  
8 -import org.slf4j.LoggerFactory;  
9 -import org.springframework.beans.factory.annotation.Autowired;  
10 -import org.springframework.data.redis.connection.Message;  
11 -import org.springframework.data.redis.listener.RedisMessageListenerContainer;  
12 -import org.springframework.stereotype.Component;  
13 -  
14 -/**  
15 - * 平台订阅到期事件  
16 - */  
17 -@Component  
18 -public class SubscribeListenerForPlatform extends RedisKeyExpirationEventMessageListener {  
19 -  
20 - private Logger logger = LoggerFactory.getLogger(SubscribeListenerForPlatform.class);  
21 -  
22 - @Autowired  
23 - private UserSetting userSetting;  
24 -  
25 - @Autowired  
26 - private DynamicTask dynamicTask;  
27 -  
28 - public SubscribeListenerForPlatform(RedisMessageListenerContainer listenerContainer, UserSetting userSetting) {  
29 - super(listenerContainer, userSetting);  
30 - }  
31 -  
32 -  
33 - /**  
34 - * 监听失效的key  
35 - * @param message  
36 - * @param pattern  
37 - */  
38 - @Override  
39 - public void onMessage(Message message, byte[] pattern) {  
40 - // 获取失效的key  
41 - String expiredKey = message.toString();  
42 - logger.debug(expiredKey);  
43 - // 订阅到期  
44 - String PLATFORM_KEEPLIVEKEY_PREFIX = VideoManagerConstants.SIP_SUBSCRIBE_PREFIX + userSetting.getServerId() + "_";  
45 - if (expiredKey.startsWith(PLATFORM_KEEPLIVEKEY_PREFIX)) {  
46 - // 取消定时任务  
47 - dynamicTask.stop(expiredKey);  
48 - }  
49 - }  
50 -}  
src/main/java/com/genersoft/iot/vmp/gb28181/event/subscribe/catalog/CatalogEventLister.java
@@ -61,8 +61,6 @@ public class CatalogEventLister implements ApplicationListener&lt;CatalogEvent&gt; { @@ -61,8 +61,6 @@ public class CatalogEventLister implements ApplicationListener&lt;CatalogEvent&gt; {
61 if (event.getPlatformId() != null) { 61 if (event.getPlatformId() != null) {
62 parentPlatform = storager.queryParentPlatByServerGBId(event.getPlatformId()); 62 parentPlatform = storager.queryParentPlatByServerGBId(event.getPlatformId());
63 if (parentPlatform != null && !parentPlatform.isStatus())return; 63 if (parentPlatform != null && !parentPlatform.isStatus())return;
64 - String key = VideoManagerConstants.SIP_SUBSCRIBE_PREFIX + userSetting.getServerId() + "_Catalog_" + event.getPlatformId();  
65 -// subscribe = redisCatchStorage.getSubscribe(key);  
66 subscribe = subscribeHolder.getCatalogSubscribe(event.getPlatformId()); 64 subscribe = subscribeHolder.getCatalogSubscribe(event.getPlatformId());
67 65
68 if (subscribe == null) { 66 if (subscribe == null) {
src/main/java/com/genersoft/iot/vmp/gb28181/task/impl/CatalogSubscribeTask.java
@@ -46,7 +46,6 @@ public class CatalogSubscribeTask implements ISubscribeTask { @@ -46,7 +46,6 @@ public class CatalogSubscribeTask implements ISubscribeTask {
46 }); 46 });
47 } 47 }
48 48
49 - @Async  
50 @Override 49 @Override
51 public void stop() { 50 public void stop() {
52 /** 51 /**
src/main/java/com/genersoft/iot/vmp/gb28181/task/impl/MobilePositionSubscribeHandlerTask.java
@@ -24,52 +24,50 @@ public class MobilePositionSubscribeHandlerTask implements ISubscribeTask { @@ -24,52 +24,50 @@ public class MobilePositionSubscribeHandlerTask implements ISubscribeTask {
24 private IVideoManagerStorage storager; 24 private IVideoManagerStorage storager;
25 private ISIPCommanderForPlatform sipCommanderForPlatform; 25 private ISIPCommanderForPlatform sipCommanderForPlatform;
26 private SubscribeHolder subscribeHolder; 26 private SubscribeHolder subscribeHolder;
27 - private String platformId; 27 + private ParentPlatform platform;
28 private String sn; 28 private String sn;
29 private String key; 29 private String key;
30 30
31 public MobilePositionSubscribeHandlerTask(IRedisCatchStorage redisCatchStorage, ISIPCommanderForPlatform sipCommanderForPlatform, IVideoManagerStorage storager, String platformId, String sn, String key, SubscribeHolder subscribeInfo) { 31 public MobilePositionSubscribeHandlerTask(IRedisCatchStorage redisCatchStorage, ISIPCommanderForPlatform sipCommanderForPlatform, IVideoManagerStorage storager, String platformId, String sn, String key, SubscribeHolder subscribeInfo) {
  32 + System.out.println("MobilePositionSubscribeHandlerTask 初始化");
32 this.redisCatchStorage = redisCatchStorage; 33 this.redisCatchStorage = redisCatchStorage;
33 this.storager = storager; 34 this.storager = storager;
34 - this.platformId = platformId; 35 + this.platform = storager.queryParentPlatByServerGBId(platformId);
35 this.sn = sn; 36 this.sn = sn;
36 this.key = key; 37 this.key = key;
37 this.sipCommanderForPlatform = sipCommanderForPlatform; 38 this.sipCommanderForPlatform = sipCommanderForPlatform;
38 this.subscribeHolder = subscribeInfo; 39 this.subscribeHolder = subscribeInfo;
39 } 40 }
40 41
41 - @Async  
42 @Override 42 @Override
43 public void run() { 43 public void run() {
44 44
45 logger.info("执行MobilePositionSubscribeHandlerTask"); 45 logger.info("执行MobilePositionSubscribeHandlerTask");
46 - SubscribeInfo subscribe = subscribeHolder.getMobilePositionSubscribe(platformId); 46 + if (platform == null) return;
  47 + SubscribeInfo subscribe = subscribeHolder.getMobilePositionSubscribe(platform.getServerGBId());
47 if (subscribe != null) { 48 if (subscribe != null) {
48 - ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(platformId);  
49 - if (parentPlatform == null ) {  
50 - logger.info("发送订阅时未找到平台信息:{}", platformId);  
51 - return;  
52 - }  
53 - if (!parentPlatform.isStatus()) {  
54 - logger.info("发送订阅时发现平台已经离线:{}", platformId);  
55 - return;  
56 - } 49 +
  50 +// if (!parentPlatform.isStatus()) {
  51 +// logger.info("发送订阅时发现平台已经离线:{}", platformId);
  52 +// return;
  53 +// }
57 // TODO 暂时只处理视频流的回复,后续增加对国标设备的支持 54 // TODO 暂时只处理视频流的回复,后续增加对国标设备的支持
58 - List<GbStream> gbStreams = storager.queryGbStreamListInPlatform(platformId); 55 + List<GbStream> gbStreams = storager.queryGbStreamListInPlatform(platform.getServerGBId());
59 if (gbStreams.size() == 0) { 56 if (gbStreams.size() == 0) {
60 - logger.info("发送订阅时发现平台已经没有关联的直播流:{}", platformId); 57 + logger.info("发送订阅时发现平台已经没有关联的直播流:{}", platform.getServerGBId());
61 return; 58 return;
62 } 59 }
63 for (GbStream gbStream : gbStreams) { 60 for (GbStream gbStream : gbStreams) {
64 String gbId = gbStream.getGbId(); 61 String gbId = gbStream.getGbId();
65 GPSMsgInfo gpsMsgInfo = redisCatchStorage.getGpsMsgInfo(gbId); 62 GPSMsgInfo gpsMsgInfo = redisCatchStorage.getGpsMsgInfo(gbId);
66 if (gpsMsgInfo != null) { // 无最新位置不发送 63 if (gpsMsgInfo != null) { // 无最新位置不发送
  64 + logger.info("无最新位置不发送");
67 // 经纬度都为0不发送 65 // 经纬度都为0不发送
68 if (gpsMsgInfo.getLng() == 0 && gpsMsgInfo.getLat() == 0) { 66 if (gpsMsgInfo.getLng() == 0 && gpsMsgInfo.getLat() == 0) {
69 continue; 67 continue;
70 } 68 }
71 // 发送GPS消息 69 // 发送GPS消息
72 - sipCommanderForPlatform.sendNotifyMobilePosition(parentPlatform, gpsMsgInfo, subscribe); 70 + sipCommanderForPlatform.sendNotifyMobilePosition(platform, gpsMsgInfo, subscribe);
73 } 71 }
74 } 72 }
75 } 73 }
src/main/java/com/genersoft/iot/vmp/gb28181/task/impl/MobilePositionSubscribeTask.java
@@ -11,6 +11,8 @@ import org.springframework.scheduling.annotation.Async; @@ -11,6 +11,8 @@ import org.springframework.scheduling.annotation.Async;
11 import javax.sip.Dialog; 11 import javax.sip.Dialog;
12 import javax.sip.DialogState; 12 import javax.sip.DialogState;
13 import javax.sip.ResponseEvent; 13 import javax.sip.ResponseEvent;
  14 +import java.util.Timer;
  15 +import java.util.TimerTask;
14 16
15 /** 17 /**
16 * 移动位置订阅的定时更新 18 * 移动位置订阅的定时更新
@@ -21,18 +23,23 @@ public class MobilePositionSubscribeTask implements ISubscribeTask { @@ -21,18 +23,23 @@ public class MobilePositionSubscribeTask implements ISubscribeTask {
21 private ISIPCommander sipCommander; 23 private ISIPCommander sipCommander;
22 private Dialog dialog; 24 private Dialog dialog;
23 25
  26 + private Timer timer ;
  27 +
24 public MobilePositionSubscribeTask(Device device, ISIPCommander sipCommander) { 28 public MobilePositionSubscribeTask(Device device, ISIPCommander sipCommander) {
25 this.device = device; 29 this.device = device;
26 this.sipCommander = sipCommander; 30 this.sipCommander = sipCommander;
27 } 31 }
28 32
29 - @Async  
30 @Override 33 @Override
31 public void run() { 34 public void run() {
  35 + if (timer != null ) {
  36 + timer.cancel();
  37 + timer = null;
  38 + }
32 sipCommander.mobilePositionSubscribe(device, dialog, eventResult -> { 39 sipCommander.mobilePositionSubscribe(device, dialog, eventResult -> {
33 - if (eventResult.dialog != null || eventResult.dialog.getState().equals(DialogState.CONFIRMED)) {  
34 - dialog = eventResult.dialog;  
35 - } 40 +// if (eventResult.dialog != null || eventResult.dialog.getState().equals(DialogState.CONFIRMED)) {
  41 +// dialog = eventResult.dialog;
  42 +// }
36 ResponseEvent event = (ResponseEvent) eventResult.event; 43 ResponseEvent event = (ResponseEvent) eventResult.event;
37 if (event.getResponse().getRawContent() != null) { 44 if (event.getResponse().getRawContent() != null) {
38 // 成功 45 // 成功
@@ -45,6 +52,13 @@ public class MobilePositionSubscribeTask implements ISubscribeTask { @@ -45,6 +52,13 @@ public class MobilePositionSubscribeTask implements ISubscribeTask {
45 dialog = null; 52 dialog = null;
46 // 失败 53 // 失败
47 logger.warn("[移动位置订阅]失败,信令发送失败: {}-{} ", device.getDeviceId(), eventResult.msg); 54 logger.warn("[移动位置订阅]失败,信令发送失败: {}-{} ", device.getDeviceId(), eventResult.msg);
  55 + timer = new Timer();
  56 + timer.schedule(new TimerTask() {
  57 + @Override
  58 + public void run() {
  59 + MobilePositionSubscribeTask.this.run();
  60 + }
  61 + }, 2000);
48 }); 62 });
49 63
50 } 64 }
@@ -58,6 +72,10 @@ public class MobilePositionSubscribeTask implements ISubscribeTask { @@ -58,6 +72,10 @@ public class MobilePositionSubscribeTask implements ISubscribeTask {
58 * COMPLETED-> Completed Dialog状态-已完成 72 * COMPLETED-> Completed Dialog状态-已完成
59 * TERMINATED-> Terminated Dialog状态-终止 73 * TERMINATED-> Terminated Dialog状态-终止
60 */ 74 */
  75 + if (timer != null ) {
  76 + timer.cancel();
  77 + timer = null;
  78 + }
61 if (dialog != null && dialog.getState().equals(DialogState.CONFIRMED)) { 79 if (dialog != null && dialog.getState().equals(DialogState.CONFIRMED)) {
62 logger.info("取消移动订阅时dialog状态为{}", dialog.getState()); 80 logger.info("取消移动订阅时dialog状态为{}", dialog.getState());
63 device.setSubscribeCycleForMobilePosition(0); 81 device.setSubscribeCycleForMobilePosition(0);
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommanderFroPlatform.java
@@ -385,7 +385,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { @@ -385,7 +385,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
385 if (parentPlatform == null) { 385 if (parentPlatform == null) {
386 return false; 386 return false;
387 } 387 }
388 - 388 + logger.info("[发送 移动位置订阅] {}/{}->{},{}", parentPlatform.getServerGBId(), gpsMsgInfo.getId(), gpsMsgInfo.getLng(), gpsMsgInfo.getLat());
389 try { 389 try {
390 String characterSet = parentPlatform.getCharacterSet(); 390 String characterSet = parentPlatform.getCharacterSet();
391 StringBuffer deviceStatusXml = new StringBuffer(600); 391 StringBuffer deviceStatusXml = new StringBuffer(600);
@@ -405,7 +405,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { @@ -405,7 +405,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
405 CallIdHeader callIdHeader = parentPlatform.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId() 405 CallIdHeader callIdHeader = parentPlatform.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
406 : udpSipProvider.getNewCallId(); 406 : udpSipProvider.getNewCallId();
407 callIdHeader.setCallId(subscribeInfo.getCallId()); 407 callIdHeader.setCallId(subscribeInfo.getCallId());
408 - logger.info("[发送 移动位置订阅] {}/{}->{},{}", parentPlatform.getServerGBId(), gpsMsgInfo.getId(), gpsMsgInfo.getLng(), gpsMsgInfo.getLat()); 408 +
409 sendNotify(parentPlatform, deviceStatusXml.toString(), subscribeInfo, eventResult -> { 409 sendNotify(parentPlatform, deviceStatusXml.toString(), subscribeInfo, eventResult -> {
410 logger.error("发送NOTIFY通知消息失败。错误:{} {}", eventResult.statusCode, eventResult.msg); 410 logger.error("发送NOTIFY通知消息失败。错误:{} {}", eventResult.statusCode, eventResult.msg);
411 }, null); 411 }, null);
@@ -459,7 +459,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { @@ -459,7 +459,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
459 // 设置编码, 防止中文乱码 459 // 设置编码, 防止中文乱码
460 messageFactory.setDefaultContentEncodingCharset(characterSet); 460 messageFactory.setDefaultContentEncodingCharset(characterSet);
461 Dialog dialog = subscribeInfo.getDialog(); 461 Dialog dialog = subscribeInfo.getDialog();
462 - if (dialog == null) return; 462 + if (dialog == null || !dialog.getState().equals(DialogState.CONFIRMED)) return;
463 SIPRequest notifyRequest = (SIPRequest)dialog.createRequest(Request.NOTIFY); 463 SIPRequest notifyRequest = (SIPRequest)dialog.createRequest(Request.NOTIFY);
464 ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml"); 464 ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml");
465 notifyRequest.setContent(catalogXmlContent, contentTypeHeader); 465 notifyRequest.setContent(catalogXmlContent, contentTypeHeader);
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/SubscribeRequestProcessor.java
@@ -149,7 +149,6 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme @@ -149,7 +149,6 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme
149 subscribeInfo.setDialog(dialog); 149 subscribeInfo.setDialog(dialog);
150 } 150 }
151 String sn = XmlUtil.getText(rootElement, "SN"); 151 String sn = XmlUtil.getText(rootElement, "SN");
152 - String key = VideoManagerConstants.SIP_SUBSCRIBE_PREFIX + userSetting.getServerId() + "_MobilePosition_" + platformId;  
153 logger.info("[回复 移动位置订阅]: {}", platformId); 152 logger.info("[回复 移动位置订阅]: {}", platformId);
154 StringBuilder resultXml = new StringBuilder(200); 153 StringBuilder resultXml = new StringBuilder(200);
155 resultXml.append("<?xml version=\"1.0\" ?>\r\n") 154 resultXml.append("<?xml version=\"1.0\" ?>\r\n")
@@ -161,23 +160,25 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme @@ -161,23 +160,25 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme
161 .append("</Response>\r\n"); 160 .append("</Response>\r\n");
162 161
163 if (subscribeInfo.getExpires() > 0) { 162 if (subscribeInfo.getExpires() > 0) {
164 -  
165 - if (subscribeHolder.getMobilePositionSubscribe(platformId) == null ) {  
166 - String interval = XmlUtil.getText(rootElement, "Interval"); // GPS上报时间间隔  
167 - subscribeHolder.putMobilePositionSubscribe(platformId, subscribeInfo);  
168 - dynamicTask.startCron(key, new MobilePositionSubscribeHandlerTask(redisCatchStorage, sipCommanderForPlatform, storager, platformId, sn, key, subscribeHolder), Integer.parseInt(interval)); 163 + String interval = XmlUtil.getText(rootElement, "Interval"); // GPS上报时间间隔
  164 + if (interval == null) {
  165 + subscribeInfo.setGpsInterval(5);
169 }else { 166 }else {
170 - if (subscribeHolder.getMobilePositionSubscribe(platformId).getDialog() != null  
171 - && subscribeHolder.getMobilePositionSubscribe(platformId).getDialog().getState() != null  
172 - && !subscribeHolder.getMobilePositionSubscribe(platformId).getDialog().getState().equals(DialogState.CONFIRMED)) {  
173 - dynamicTask.stop(key);  
174 - String interval = XmlUtil.getText(rootElement, "Interval"); // GPS上报时间间隔  
175 - subscribeHolder.putMobilePositionSubscribe(platformId, subscribeInfo);  
176 - dynamicTask.startCron(key, new MobilePositionSubscribeHandlerTask(redisCatchStorage, sipCommanderForPlatform, storager, platformId, sn, key, subscribeHolder), Integer.parseInt(interval));  
177 - } 167 + subscribeInfo.setGpsInterval(Integer.parseInt(interval));
178 } 168 }
  169 +
  170 + subscribeInfo.setSn(sn);
  171 + subscribeHolder.putMobilePositionSubscribe(platformId, subscribeInfo);
  172 +// if (subscribeHolder.getMobilePositionSubscribe(platformId) == null ) {
  173 +// subscribeHolder.putMobilePositionSubscribe(platformId, subscribeInfo);
  174 +// }else {
  175 +// if (subscribeHolder.getMobilePositionSubscribe(platformId).getDialog() != null
  176 +// && subscribeHolder.getMobilePositionSubscribe(platformId).getDialog().getState() != null
  177 +// && !subscribeHolder.getMobilePositionSubscribe(platformId).getDialog().getState().equals(DialogState.CONFIRMED)) {
  178 +// subscribeHolder.putMobilePositionSubscribe(platformId, subscribeInfo);
  179 +// }
  180 +// }
179 }else if (subscribeInfo.getExpires() == 0) { 181 }else if (subscribeInfo.getExpires() == 0) {
180 - dynamicTask.stop(key);  
181 subscribeHolder.removeMobilePositionSubscribe(platformId); 182 subscribeHolder.removeMobilePositionSubscribe(platformId);
182 } 183 }
183 184
@@ -211,7 +212,6 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme @@ -211,7 +212,6 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme
211 subscribeInfo.setDialog(dialog); 212 subscribeInfo.setDialog(dialog);
212 } 213 }
213 String sn = XmlUtil.getText(rootElement, "SN"); 214 String sn = XmlUtil.getText(rootElement, "SN");
214 - String key = VideoManagerConstants.SIP_SUBSCRIBE_PREFIX + userSetting.getServerId() + "_Catalog_" + platformId;  
215 logger.info("[回复 目录订阅]: {}/{}", platformId, deviceID); 215 logger.info("[回复 目录订阅]: {}/{}", platformId, deviceID);
216 StringBuilder resultXml = new StringBuilder(200); 216 StringBuilder resultXml = new StringBuilder(200);
217 resultXml.append("<?xml version=\"1.0\" ?>\r\n") 217 resultXml.append("<?xml version=\"1.0\" ?>\r\n")
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/CatalogResponseMessageHandler.java
@@ -145,9 +145,6 @@ public class CatalogResponseMessageHandler extends SIPRequestProcessorParent imp @@ -145,9 +145,6 @@ public class CatalogResponseMessageHandler extends SIPRequestProcessorParent imp
145 } 145 }
146 // 回复200 OK 146 // 回复200 OK
147 responseAck(evt, Response.OK); 147 responseAck(evt, Response.OK);
148 - if (offLineDetector.isOnline(device.getDeviceId())) {  
149 - publisher.onlineEventPublish(device, VideoManagerConstants.EVENT_ONLINE_MESSAGE);  
150 - }  
151 } 148 }
152 } catch (DocumentException e) { 149 } catch (DocumentException e) {
153 e.printStackTrace(); 150 e.printStackTrace();
src/main/java/com/genersoft/iot/vmp/service/impl/DeviceServiceImpl.java
@@ -14,6 +14,8 @@ import org.slf4j.LoggerFactory; @@ -14,6 +14,8 @@ import org.slf4j.LoggerFactory;
14 import org.springframework.beans.factory.annotation.Autowired; 14 import org.springframework.beans.factory.annotation.Autowired;
15 import org.springframework.stereotype.Service; 15 import org.springframework.stereotype.Service;
16 16
  17 +import javax.sip.DialogState;
  18 +
17 /** 19 /**
18 * 设备业务(目录订阅) 20 * 设备业务(目录订阅)
19 */ 21 */
@@ -39,19 +41,17 @@ public class DeviceServiceImpl implements IDeviceService { @@ -39,19 +41,17 @@ public class DeviceServiceImpl implements IDeviceService {
39 if (device == null || device.getSubscribeCycleForCatalog() < 0) { 41 if (device == null || device.getSubscribeCycleForCatalog() < 0) {
40 return false; 42 return false;
41 } 43 }
42 - if (dynamicTask.contains(device.getDeviceId() + "catalog")) {  
43 - // 存在则停止现有的,开启新的  
44 - dynamicTask.stop(device.getDeviceId() + "catalog"); 44 + CatalogSubscribeTask task = (CatalogSubscribeTask)dynamicTask.get(device.getDeviceId() + "catalog");
  45 + if (task != null && task.getDialogState() != null && task.getDialogState().equals(DialogState.CONFIRMED)) { // 已存在不需要再次添加
  46 + return true;
45 } 47 }
46 logger.info("[添加目录订阅] 设备{}", device.getDeviceId()); 48 logger.info("[添加目录订阅] 设备{}", device.getDeviceId());
47 // 添加目录订阅 49 // 添加目录订阅
48 CatalogSubscribeTask catalogSubscribeTask = new CatalogSubscribeTask(device, sipCommander); 50 CatalogSubscribeTask catalogSubscribeTask = new CatalogSubscribeTask(device, sipCommander);
49 - catalogSubscribeTask.run();  
50 // 提前开始刷新订阅 51 // 提前开始刷新订阅
51 - int subscribeCycleForCatalog = device.getSubscribeCycleForCatalog(); 52 + int subscribeCycleForCatalog = Math.max(device.getSubscribeCycleForCatalog(),30);
52 // 设置最小值为30 53 // 设置最小值为30
53 - subscribeCycleForCatalog = Math.max(subscribeCycleForCatalog, 30);  
54 - dynamicTask.startCron(device.getDeviceId() + "catalog", catalogSubscribeTask, subscribeCycleForCatalog); 54 + dynamicTask.startCron(device.getDeviceId() + "catalog", catalogSubscribeTask, subscribeCycleForCatalog -1);
55 return true; 55 return true;
56 } 56 }
57 57
@@ -70,18 +70,16 @@ public class DeviceServiceImpl implements IDeviceService { @@ -70,18 +70,16 @@ public class DeviceServiceImpl implements IDeviceService {
70 if (device == null || device.getSubscribeCycleForMobilePosition() < 0) { 70 if (device == null || device.getSubscribeCycleForMobilePosition() < 0) {
71 return false; 71 return false;
72 } 72 }
73 - if (dynamicTask.contains(device.getDeviceId() + "mobile_position")) {  
74 - // 存在则停止现有的,开启新的  
75 - dynamicTask.stop(device.getDeviceId() + "mobile_position");  
76 - }  
77 logger.info("[添加移动位置订阅] 设备{}", device.getDeviceId()); 73 logger.info("[添加移动位置订阅] 设备{}", device.getDeviceId());
  74 + MobilePositionSubscribeTask task = (MobilePositionSubscribeTask)dynamicTask.get(device.getDeviceId() + "mobile_position");
  75 + if (task != null && task.getDialogState() != null && task.getDialogState().equals(DialogState.CONFIRMED)) { // 已存在不需要再次添加
  76 + return true;
  77 + }
78 // 添加目录订阅 78 // 添加目录订阅
79 MobilePositionSubscribeTask mobilePositionSubscribeTask = new MobilePositionSubscribeTask(device, sipCommander); 79 MobilePositionSubscribeTask mobilePositionSubscribeTask = new MobilePositionSubscribeTask(device, sipCommander);
80 - mobilePositionSubscribeTask.run();  
81 // 提前开始刷新订阅 80 // 提前开始刷新订阅
82 - int subscribeCycleForCatalog = device.getSubscribeCycleForCatalog();  
83 // 设置最小值为30 81 // 设置最小值为30
84 - subscribeCycleForCatalog = Math.max(subscribeCycleForCatalog, 30); 82 + int subscribeCycleForCatalog = Math.max(device.getSubscribeCycleForMobilePosition(),30);
85 dynamicTask.startCron(device.getDeviceId() + "mobile_position" , mobilePositionSubscribeTask, subscribeCycleForCatalog -1 ); 83 dynamicTask.startCron(device.getDeviceId() + "mobile_position" , mobilePositionSubscribeTask, subscribeCycleForCatalog -1 );
86 return true; 84 return true;
87 } 85 }
src/main/java/com/genersoft/iot/vmp/vmanager/server/ServerController.java
@@ -4,6 +4,7 @@ import com.alibaba.fastjson.JSON; @@ -4,6 +4,7 @@ import com.alibaba.fastjson.JSON;
4 import com.alibaba.fastjson.JSONObject; 4 import com.alibaba.fastjson.JSONObject;
5 import com.genersoft.iot.vmp.VManageBootstrap; 5 import com.genersoft.iot.vmp.VManageBootstrap;
6 import com.genersoft.iot.vmp.common.VersionPo; 6 import com.genersoft.iot.vmp.common.VersionPo;
  7 +import com.genersoft.iot.vmp.conf.DynamicTask;
7 import com.genersoft.iot.vmp.conf.SipConfig; 8 import com.genersoft.iot.vmp.conf.SipConfig;
8 import com.genersoft.iot.vmp.conf.UserSetting; 9 import com.genersoft.iot.vmp.conf.UserSetting;
9 import com.genersoft.iot.vmp.conf.VersionInfo; 10 import com.genersoft.iot.vmp.conf.VersionInfo;
@@ -27,6 +28,7 @@ import javax.sip.ObjectInUseException; @@ -27,6 +28,7 @@ import javax.sip.ObjectInUseException;
27 import javax.sip.SipProvider; 28 import javax.sip.SipProvider;
28 import java.util.Iterator; 29 import java.util.Iterator;
29 import java.util.List; 30 import java.util.List;
  31 +import java.util.Set;
30 32
31 @SuppressWarnings("rawtypes") 33 @SuppressWarnings("rawtypes")
32 @Api(tags = "服务控制") 34 @Api(tags = "服务控制")
@@ -42,13 +44,16 @@ public class ServerController { @@ -42,13 +44,16 @@ public class ServerController {
42 private IMediaServerService mediaServerService; 44 private IMediaServerService mediaServerService;
43 45
44 @Autowired 46 @Autowired
45 - VersionInfo versionInfo; 47 + private VersionInfo versionInfo;
46 48
47 @Autowired 49 @Autowired
48 - SipConfig sipConfig; 50 + private SipConfig sipConfig;
49 51
50 @Autowired 52 @Autowired
51 - UserSetting userSetting; 53 + private UserSetting userSetting;
  54 +
  55 + @Autowired
  56 + private DynamicTask dynamicTask;
52 57
53 @Value("${server.port}") 58 @Value("${server.port}")
54 private int serverPort; 59 private int serverPort;
@@ -248,4 +253,35 @@ public class ServerController { @@ -248,4 +253,35 @@ public class ServerController {
248 result.setData(jsonObject); 253 result.setData(jsonObject);
249 return result; 254 return result;
250 } 255 }
  256 +
  257 +// @ApiOperation("当前进行中的动态任务")
  258 +// @GetMapping(value = "/dynamicTask")
  259 +// @ResponseBody
  260 +// public WVPResult<JSONObject> getDynamicTask(){
  261 +// WVPResult<JSONObject> result = new WVPResult<>();
  262 +// result.setCode(0);
  263 +// result.setMsg("success");
  264 +//
  265 +// JSONObject jsonObject = new JSONObject();
  266 +//
  267 +// Set<String> allKeys = dynamicTask.getAllKeys();
  268 +// jsonObject.put("server.port", serverPort);
  269 +// if (StringUtils.isEmpty(type)) {
  270 +// jsonObject.put("sip", JSON.toJSON(sipConfig));
  271 +// jsonObject.put("base", JSON.toJSON(userSetting));
  272 +// }else {
  273 +// switch (type){
  274 +// case "sip":
  275 +// jsonObject.put("sip", sipConfig);
  276 +// break;
  277 +// case "base":
  278 +// jsonObject.put("base", userSetting);
  279 +// break;
  280 +// default:
  281 +// break;
  282 +// }
  283 +// }
  284 +// result.setData(jsonObject);
  285 +// return result;
  286 +// }
251 } 287 }