Commit e6ee7fe7477b485676ce506b4e971c9a50dfa588
1 parent
efc4a7bc
优化级联移动位置订阅位置更新
Showing
13 changed files
with
227 additions
and
121 deletions
src/main/java/com/genersoft/iot/vmp/conf/DynamicTask.java
| 1 | 1 | package com.genersoft.iot.vmp.conf; |
| 2 | 2 | |
| 3 | 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 | 7 | import org.springframework.beans.factory.annotation.Autowired; |
| 5 | 8 | import org.springframework.context.annotation.Bean; |
| 6 | 9 | import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; |
| ... | ... | @@ -18,6 +21,8 @@ import java.util.concurrent.ScheduledFuture; |
| 18 | 21 | @Component |
| 19 | 22 | public class DynamicTask { |
| 20 | 23 | |
| 24 | + private Logger logger = LoggerFactory.getLogger(DynamicTask.class); | |
| 25 | + | |
| 21 | 26 | @Autowired |
| 22 | 27 | private ThreadPoolTaskScheduler threadPoolTaskScheduler; |
| 23 | 28 | |
| ... | ... | @@ -26,7 +31,12 @@ public class DynamicTask { |
| 26 | 31 | |
| 27 | 32 | @Bean |
| 28 | 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 | 47 | * @return |
| 38 | 48 | */ |
| 39 | 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 | 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 | 76 | */ |
| 54 | 77 | public void startDelay(String key, Runnable task, int delay) { |
| 55 | 78 | stop(key); |
| 79 | + System.out.println("定时任务开始了"); | |
| 56 | 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 | 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 | 102 | public void stop(String key) { |
| 103 | + System.out.println("定时任务结束了"); | |
| 63 | 104 | if (futureMap.get(key) != null && !futureMap.get(key).isCancelled()) { |
| 64 | 105 | futureMap.get(key).cancel(true); |
| 65 | 106 | Runnable runnable = runnableMap.get(key); | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/bean/SubscribeHolder.java
| 1 | 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 | 10 | import org.springframework.stereotype.Component; |
| 4 | 11 | |
| 5 | 12 | import java.util.ArrayList; |
| ... | ... | @@ -9,12 +16,32 @@ import java.util.concurrent.ConcurrentHashMap; |
| 9 | 16 | @Component |
| 10 | 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 | 33 | private static ConcurrentHashMap<String, SubscribeInfo> catalogMap = new ConcurrentHashMap<>(); |
| 13 | 34 | private static ConcurrentHashMap<String, SubscribeInfo> mobilePositionMap = new ConcurrentHashMap<>(); |
| 14 | 35 | |
| 15 | 36 | |
| 16 | 37 | public void putCatalogSubscribe(String platformId, SubscribeInfo subscribeInfo) { |
| 17 | 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 | 47 | public SubscribeInfo getCatalogSubscribe(String platformId) { |
| ... | ... | @@ -23,10 +50,24 @@ public class SubscribeHolder { |
| 23 | 50 | |
| 24 | 51 | public void removeCatalogSubscribe(String platformId) { |
| 25 | 52 | catalogMap.remove(platformId); |
| 53 | + String taskOverdueKey = taskOverduePrefix + "catalog_" + platformId; | |
| 54 | + // 添加任务处理订阅过期 | |
| 55 | + dynamicTask.stop(taskOverdueKey); | |
| 26 | 56 | } |
| 27 | 57 | |
| 28 | 58 | public void putMobilePositionSubscribe(String platformId, SubscribeInfo subscribeInfo) { |
| 29 | 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 | 73 | public SubscribeInfo getMobilePositionSubscribe(String platformId) { |
| ... | ... | @@ -35,6 +76,12 @@ public class SubscribeHolder { |
| 35 | 76 | |
| 36 | 77 | public void removeMobilePositionSubscribe(String platformId) { |
| 37 | 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 | 87 | public List<String> getAllCatalogSubscribePlatform() { |
| ... | ... | @@ -48,7 +95,7 @@ public class SubscribeHolder { |
| 48 | 95 | } |
| 49 | 96 | |
| 50 | 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 | 33 | private ServerTransaction transaction; |
| 34 | 34 | private Dialog dialog; |
| 35 | 35 | |
| 36 | + /** | |
| 37 | + * 以下为可选字段 | |
| 38 | + * @return | |
| 39 | + */ | |
| 40 | + private String sn; | |
| 41 | + private int gpsInterval; | |
| 42 | + | |
| 43 | + | |
| 36 | 44 | public String getId() { |
| 37 | 45 | return id; |
| 38 | 46 | } |
| ... | ... | @@ -88,4 +96,20 @@ public class SubscribeInfo { |
| 88 | 96 | public void setDialog(Dialog dialog) { |
| 89 | 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<CatalogEvent> { |
| 61 | 61 | if (event.getPlatformId() != null) { |
| 62 | 62 | parentPlatform = storager.queryParentPlatByServerGBId(event.getPlatformId()); |
| 63 | 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 | 64 | subscribe = subscribeHolder.getCatalogSubscribe(event.getPlatformId()); |
| 67 | 65 | |
| 68 | 66 | if (subscribe == null) { | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/task/impl/CatalogSubscribeTask.java
src/main/java/com/genersoft/iot/vmp/gb28181/task/impl/MobilePositionSubscribeHandlerTask.java
| ... | ... | @@ -24,52 +24,50 @@ public class MobilePositionSubscribeHandlerTask implements ISubscribeTask { |
| 24 | 24 | private IVideoManagerStorage storager; |
| 25 | 25 | private ISIPCommanderForPlatform sipCommanderForPlatform; |
| 26 | 26 | private SubscribeHolder subscribeHolder; |
| 27 | - private String platformId; | |
| 27 | + private ParentPlatform platform; | |
| 28 | 28 | private String sn; |
| 29 | 29 | private String key; |
| 30 | 30 | |
| 31 | 31 | public MobilePositionSubscribeHandlerTask(IRedisCatchStorage redisCatchStorage, ISIPCommanderForPlatform sipCommanderForPlatform, IVideoManagerStorage storager, String platformId, String sn, String key, SubscribeHolder subscribeInfo) { |
| 32 | + System.out.println("MobilePositionSubscribeHandlerTask 初始化"); | |
| 32 | 33 | this.redisCatchStorage = redisCatchStorage; |
| 33 | 34 | this.storager = storager; |
| 34 | - this.platformId = platformId; | |
| 35 | + this.platform = storager.queryParentPlatByServerGBId(platformId); | |
| 35 | 36 | this.sn = sn; |
| 36 | 37 | this.key = key; |
| 37 | 38 | this.sipCommanderForPlatform = sipCommanderForPlatform; |
| 38 | 39 | this.subscribeHolder = subscribeInfo; |
| 39 | 40 | } |
| 40 | 41 | |
| 41 | - @Async | |
| 42 | 42 | @Override |
| 43 | 43 | public void run() { |
| 44 | 44 | |
| 45 | 45 | logger.info("执行MobilePositionSubscribeHandlerTask"); |
| 46 | - SubscribeInfo subscribe = subscribeHolder.getMobilePositionSubscribe(platformId); | |
| 46 | + if (platform == null) return; | |
| 47 | + SubscribeInfo subscribe = subscribeHolder.getMobilePositionSubscribe(platform.getServerGBId()); | |
| 47 | 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 | 54 | // TODO 暂时只处理视频流的回复,后续增加对国标设备的支持 |
| 58 | - List<GbStream> gbStreams = storager.queryGbStreamListInPlatform(platformId); | |
| 55 | + List<GbStream> gbStreams = storager.queryGbStreamListInPlatform(platform.getServerGBId()); | |
| 59 | 56 | if (gbStreams.size() == 0) { |
| 60 | - logger.info("发送订阅时发现平台已经没有关联的直播流:{}", platformId); | |
| 57 | + logger.info("发送订阅时发现平台已经没有关联的直播流:{}", platform.getServerGBId()); | |
| 61 | 58 | return; |
| 62 | 59 | } |
| 63 | 60 | for (GbStream gbStream : gbStreams) { |
| 64 | 61 | String gbId = gbStream.getGbId(); |
| 65 | 62 | GPSMsgInfo gpsMsgInfo = redisCatchStorage.getGpsMsgInfo(gbId); |
| 66 | 63 | if (gpsMsgInfo != null) { // 无最新位置不发送 |
| 64 | + logger.info("无最新位置不发送"); | |
| 67 | 65 | // 经纬度都为0不发送 |
| 68 | 66 | if (gpsMsgInfo.getLng() == 0 && gpsMsgInfo.getLat() == 0) { |
| 69 | 67 | continue; |
| 70 | 68 | } |
| 71 | 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 | 11 | import javax.sip.Dialog; |
| 12 | 12 | import javax.sip.DialogState; |
| 13 | 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 | 23 | private ISIPCommander sipCommander; |
| 22 | 24 | private Dialog dialog; |
| 23 | 25 | |
| 26 | + private Timer timer ; | |
| 27 | + | |
| 24 | 28 | public MobilePositionSubscribeTask(Device device, ISIPCommander sipCommander) { |
| 25 | 29 | this.device = device; |
| 26 | 30 | this.sipCommander = sipCommander; |
| 27 | 31 | } |
| 28 | 32 | |
| 29 | - @Async | |
| 30 | 33 | @Override |
| 31 | 34 | public void run() { |
| 35 | + if (timer != null ) { | |
| 36 | + timer.cancel(); | |
| 37 | + timer = null; | |
| 38 | + } | |
| 32 | 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 | 43 | ResponseEvent event = (ResponseEvent) eventResult.event; |
| 37 | 44 | if (event.getResponse().getRawContent() != null) { |
| 38 | 45 | // 成功 |
| ... | ... | @@ -45,6 +52,13 @@ public class MobilePositionSubscribeTask implements ISubscribeTask { |
| 45 | 52 | dialog = null; |
| 46 | 53 | // 失败 |
| 47 | 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 | 72 | * COMPLETED-> Completed Dialog状态-已完成 |
| 59 | 73 | * TERMINATED-> Terminated Dialog状态-终止 |
| 60 | 74 | */ |
| 75 | + if (timer != null ) { | |
| 76 | + timer.cancel(); | |
| 77 | + timer = null; | |
| 78 | + } | |
| 61 | 79 | if (dialog != null && dialog.getState().equals(DialogState.CONFIRMED)) { |
| 62 | 80 | logger.info("取消移动订阅时dialog状态为{}", dialog.getState()); |
| 63 | 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 | 385 | if (parentPlatform == null) { |
| 386 | 386 | return false; |
| 387 | 387 | } |
| 388 | - | |
| 388 | + logger.info("[发送 移动位置订阅] {}/{}->{},{}", parentPlatform.getServerGBId(), gpsMsgInfo.getId(), gpsMsgInfo.getLng(), gpsMsgInfo.getLat()); | |
| 389 | 389 | try { |
| 390 | 390 | String characterSet = parentPlatform.getCharacterSet(); |
| 391 | 391 | StringBuffer deviceStatusXml = new StringBuffer(600); |
| ... | ... | @@ -405,7 +405,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { |
| 405 | 405 | CallIdHeader callIdHeader = parentPlatform.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId() |
| 406 | 406 | : udpSipProvider.getNewCallId(); |
| 407 | 407 | callIdHeader.setCallId(subscribeInfo.getCallId()); |
| 408 | - logger.info("[发送 移动位置订阅] {}/{}->{},{}", parentPlatform.getServerGBId(), gpsMsgInfo.getId(), gpsMsgInfo.getLng(), gpsMsgInfo.getLat()); | |
| 408 | + | |
| 409 | 409 | sendNotify(parentPlatform, deviceStatusXml.toString(), subscribeInfo, eventResult -> { |
| 410 | 410 | logger.error("发送NOTIFY通知消息失败。错误:{} {}", eventResult.statusCode, eventResult.msg); |
| 411 | 411 | }, null); |
| ... | ... | @@ -459,7 +459,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { |
| 459 | 459 | // 设置编码, 防止中文乱码 |
| 460 | 460 | messageFactory.setDefaultContentEncodingCharset(characterSet); |
| 461 | 461 | Dialog dialog = subscribeInfo.getDialog(); |
| 462 | - if (dialog == null) return; | |
| 462 | + if (dialog == null || !dialog.getState().equals(DialogState.CONFIRMED)) return; | |
| 463 | 463 | SIPRequest notifyRequest = (SIPRequest)dialog.createRequest(Request.NOTIFY); |
| 464 | 464 | ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml"); |
| 465 | 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 | 149 | subscribeInfo.setDialog(dialog); |
| 150 | 150 | } |
| 151 | 151 | String sn = XmlUtil.getText(rootElement, "SN"); |
| 152 | - String key = VideoManagerConstants.SIP_SUBSCRIBE_PREFIX + userSetting.getServerId() + "_MobilePosition_" + platformId; | |
| 153 | 152 | logger.info("[回复 移动位置订阅]: {}", platformId); |
| 154 | 153 | StringBuilder resultXml = new StringBuilder(200); |
| 155 | 154 | resultXml.append("<?xml version=\"1.0\" ?>\r\n") |
| ... | ... | @@ -161,23 +160,25 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme |
| 161 | 160 | .append("</Response>\r\n"); |
| 162 | 161 | |
| 163 | 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 | 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 | 181 | }else if (subscribeInfo.getExpires() == 0) { |
| 180 | - dynamicTask.stop(key); | |
| 181 | 182 | subscribeHolder.removeMobilePositionSubscribe(platformId); |
| 182 | 183 | } |
| 183 | 184 | |
| ... | ... | @@ -211,7 +212,6 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme |
| 211 | 212 | subscribeInfo.setDialog(dialog); |
| 212 | 213 | } |
| 213 | 214 | String sn = XmlUtil.getText(rootElement, "SN"); |
| 214 | - String key = VideoManagerConstants.SIP_SUBSCRIBE_PREFIX + userSetting.getServerId() + "_Catalog_" + platformId; | |
| 215 | 215 | logger.info("[回复 目录订阅]: {}/{}", platformId, deviceID); |
| 216 | 216 | StringBuilder resultXml = new StringBuilder(200); |
| 217 | 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 | 145 | } |
| 146 | 146 | // 回复200 OK |
| 147 | 147 | responseAck(evt, Response.OK); |
| 148 | - if (offLineDetector.isOnline(device.getDeviceId())) { | |
| 149 | - publisher.onlineEventPublish(device, VideoManagerConstants.EVENT_ONLINE_MESSAGE); | |
| 150 | - } | |
| 151 | 148 | } |
| 152 | 149 | } catch (DocumentException e) { |
| 153 | 150 | e.printStackTrace(); | ... | ... |
src/main/java/com/genersoft/iot/vmp/service/impl/DeviceServiceImpl.java
| ... | ... | @@ -14,6 +14,8 @@ import org.slf4j.LoggerFactory; |
| 14 | 14 | import org.springframework.beans.factory.annotation.Autowired; |
| 15 | 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 | 41 | if (device == null || device.getSubscribeCycleForCatalog() < 0) { |
| 40 | 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 | 48 | logger.info("[添加目录订阅] 设备{}", device.getDeviceId()); |
| 47 | 49 | // 添加目录订阅 |
| 48 | 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 | 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 | 55 | return true; |
| 56 | 56 | } |
| 57 | 57 | |
| ... | ... | @@ -70,18 +70,16 @@ public class DeviceServiceImpl implements IDeviceService { |
| 70 | 70 | if (device == null || device.getSubscribeCycleForMobilePosition() < 0) { |
| 71 | 71 | return false; |
| 72 | 72 | } |
| 73 | - if (dynamicTask.contains(device.getDeviceId() + "mobile_position")) { | |
| 74 | - // 存在则停止现有的,开启新的 | |
| 75 | - dynamicTask.stop(device.getDeviceId() + "mobile_position"); | |
| 76 | - } | |
| 77 | 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 | 79 | MobilePositionSubscribeTask mobilePositionSubscribeTask = new MobilePositionSubscribeTask(device, sipCommander); |
| 80 | - mobilePositionSubscribeTask.run(); | |
| 81 | 80 | // 提前开始刷新订阅 |
| 82 | - int subscribeCycleForCatalog = device.getSubscribeCycleForCatalog(); | |
| 83 | 81 | // 设置最小值为30 |
| 84 | - subscribeCycleForCatalog = Math.max(subscribeCycleForCatalog, 30); | |
| 82 | + int subscribeCycleForCatalog = Math.max(device.getSubscribeCycleForMobilePosition(),30); | |
| 85 | 83 | dynamicTask.startCron(device.getDeviceId() + "mobile_position" , mobilePositionSubscribeTask, subscribeCycleForCatalog -1 ); |
| 86 | 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 | 4 | import com.alibaba.fastjson.JSONObject; |
| 5 | 5 | import com.genersoft.iot.vmp.VManageBootstrap; |
| 6 | 6 | import com.genersoft.iot.vmp.common.VersionPo; |
| 7 | +import com.genersoft.iot.vmp.conf.DynamicTask; | |
| 7 | 8 | import com.genersoft.iot.vmp.conf.SipConfig; |
| 8 | 9 | import com.genersoft.iot.vmp.conf.UserSetting; |
| 9 | 10 | import com.genersoft.iot.vmp.conf.VersionInfo; |
| ... | ... | @@ -27,6 +28,7 @@ import javax.sip.ObjectInUseException; |
| 27 | 28 | import javax.sip.SipProvider; |
| 28 | 29 | import java.util.Iterator; |
| 29 | 30 | import java.util.List; |
| 31 | +import java.util.Set; | |
| 30 | 32 | |
| 31 | 33 | @SuppressWarnings("rawtypes") |
| 32 | 34 | @Api(tags = "服务控制") |
| ... | ... | @@ -42,13 +44,16 @@ public class ServerController { |
| 42 | 44 | private IMediaServerService mediaServerService; |
| 43 | 45 | |
| 44 | 46 | @Autowired |
| 45 | - VersionInfo versionInfo; | |
| 47 | + private VersionInfo versionInfo; | |
| 46 | 48 | |
| 47 | 49 | @Autowired |
| 48 | - SipConfig sipConfig; | |
| 50 | + private SipConfig sipConfig; | |
| 49 | 51 | |
| 50 | 52 | @Autowired |
| 51 | - UserSetting userSetting; | |
| 53 | + private UserSetting userSetting; | |
| 54 | + | |
| 55 | + @Autowired | |
| 56 | + private DynamicTask dynamicTask; | |
| 52 | 57 | |
| 53 | 58 | @Value("${server.port}") |
| 54 | 59 | private int serverPort; |
| ... | ... | @@ -248,4 +253,35 @@ public class ServerController { |
| 248 | 253 | result.setData(jsonObject); |
| 249 | 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 | } | ... | ... |