Commit 22e1d92a9d8ae6aa257889f882722b8e48648abc
Committed by
GitHub
Merge branch '648540858:wvp-28181-2.0' into wvp-28181-2.0
Showing
26 changed files
with
543 additions
and
246 deletions
bootstrap.sh
0 → 100755
| 1 | +#!/bin/bash | ||
| 2 | + | ||
| 3 | +###################################################### | ||
| 4 | +# Copyright 2019 Pham Ngoc Hoai | ||
| 5 | +# | ||
| 6 | +# Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 7 | +# you may not use this file except in compliance with the License. | ||
| 8 | +# You may obtain a copy of the License at | ||
| 9 | +# | ||
| 10 | +# http://www.apache.org/licenses/LICENSE-2.0 | ||
| 11 | +# | ||
| 12 | +# Unless required by applicable law or agreed to in writing, software | ||
| 13 | +# distributed under the License is distributed on an "AS IS" BASIS, | ||
| 14 | +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 15 | +# See the License for the specific language governing permissions and | ||
| 16 | +# limitations under the License. | ||
| 17 | +# | ||
| 18 | +# Repo: https://github.com/tyrion9/spring-boot-startup-script | ||
| 19 | +# | ||
| 20 | +######### PARAM ###################################### | ||
| 21 | + | ||
| 22 | +JAVA_OPT=-Xmx1024m | ||
| 23 | +JARFILE=`ls -1r *.jar 2>/dev/null | head -n 1` | ||
| 24 | +PID_FILE=pid.file | ||
| 25 | +RUNNING=N | ||
| 26 | +PWD=`pwd` | ||
| 27 | + | ||
| 28 | +######### DO NOT MODIFY ######## | ||
| 29 | + | ||
| 30 | +if [ -f $PID_FILE ]; then | ||
| 31 | + PID=`cat $PID_FILE` | ||
| 32 | + if [ ! -z "$PID" ] && kill -0 $PID 2>/dev/null; then | ||
| 33 | + RUNNING=Y | ||
| 34 | + fi | ||
| 35 | +fi | ||
| 36 | + | ||
| 37 | +start() | ||
| 38 | +{ | ||
| 39 | + if [ $RUNNING == "Y" ]; then | ||
| 40 | + echo "Application already started" | ||
| 41 | + else | ||
| 42 | + if [ -z "$JARFILE" ] | ||
| 43 | + then | ||
| 44 | + echo "ERROR: jar file not found" | ||
| 45 | + else | ||
| 46 | + nohup java $JAVA_OPT -Djava.security.egd=file:/dev/./urandom -jar $PWD/$JARFILE > nohup.out 2>&1 & | ||
| 47 | + echo $! > $PID_FILE | ||
| 48 | + echo "Application $JARFILE starting..." | ||
| 49 | + tail -f nohup.out | ||
| 50 | + fi | ||
| 51 | + fi | ||
| 52 | +} | ||
| 53 | + | ||
| 54 | +stop() | ||
| 55 | +{ | ||
| 56 | + if [ $RUNNING == "Y" ]; then | ||
| 57 | + kill -9 $PID | ||
| 58 | + rm -f $PID_FILE | ||
| 59 | + echo "Application stopped" | ||
| 60 | + else | ||
| 61 | + echo "Application not running" | ||
| 62 | + fi | ||
| 63 | +} | ||
| 64 | + | ||
| 65 | +restart() | ||
| 66 | +{ | ||
| 67 | + stop | ||
| 68 | + start | ||
| 69 | +} | ||
| 70 | + | ||
| 71 | +case "$1" in | ||
| 72 | + | ||
| 73 | + 'start') | ||
| 74 | + start | ||
| 75 | + ;; | ||
| 76 | + | ||
| 77 | + 'stop') | ||
| 78 | + stop | ||
| 79 | + ;; | ||
| 80 | + | ||
| 81 | + 'restart') | ||
| 82 | + restart | ||
| 83 | + ;; | ||
| 84 | + | ||
| 85 | + *) | ||
| 86 | + echo "Usage: $0 { start | stop | restart }" | ||
| 87 | + exit 1 | ||
| 88 | + ;; | ||
| 89 | +esac | ||
| 90 | +exit 0 | ||
| 91 | + |
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.scheduleWithFixedDelay(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 | /** |
| @@ -54,9 +77,25 @@ public class DynamicTask { | @@ -54,9 +77,25 @@ public class DynamicTask { | ||
| 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); |
| 56 | Date starTime = new Date(System.currentTimeMillis() + delay); | 79 | Date starTime = new Date(System.currentTimeMillis() + delay); |
| 80 | + | ||
| 81 | + ScheduledFuture future = futureMap.get(key); | ||
| 82 | + if (future != null) { | ||
| 83 | + if (future.isCancelled()) { | ||
| 84 | + logger.info("任务【{}】已存在但是关闭状态!!!", key); | ||
| 85 | + } else { | ||
| 86 | + logger.info("任务【{}】已存在且已启动!!!", key); | ||
| 87 | + return; | ||
| 88 | + } | ||
| 89 | + } | ||
| 57 | // scheduleWithFixedDelay 必须等待上一个任务结束才开始计时period, cycleForCatalog表示执行的间隔 | 90 | // scheduleWithFixedDelay 必须等待上一个任务结束才开始计时period, cycleForCatalog表示执行的间隔 |
| 58 | - ScheduledFuture future = threadPoolTaskScheduler.schedule(task, starTime); | ||
| 59 | - futureMap.put(key, future); | 91 | + future = threadPoolTaskScheduler.schedule(task, starTime); |
| 92 | + if (future != null){ | ||
| 93 | + futureMap.put(key, future); | ||
| 94 | + runnableMap.put(key, task); | ||
| 95 | + logger.info("任务【{}】启动成功!!!", key); | ||
| 96 | + }else { | ||
| 97 | + logger.info("任务【{}】启动失败!!!", key); | ||
| 98 | + } | ||
| 60 | } | 99 | } |
| 61 | 100 | ||
| 62 | public void stop(String key) { | 101 | public void stop(String key) { |
| @@ -78,4 +117,7 @@ public class DynamicTask { | @@ -78,4 +117,7 @@ public class DynamicTask { | ||
| 78 | return futureMap.keySet(); | 117 | return futureMap.keySet(); |
| 79 | } | 118 | } |
| 80 | 119 | ||
| 120 | + public Runnable get(String key) { | ||
| 121 | + return runnableMap.get(key); | ||
| 122 | + } | ||
| 81 | } | 123 | } |
src/main/java/com/genersoft/iot/vmp/gb28181/SipLayer.java
| @@ -48,6 +48,7 @@ public class SipLayer{ | @@ -48,6 +48,7 @@ public class SipLayer{ | ||
| 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", "true"); | 50 | properties.setProperty("gov.nist.javax.sip.LOG_MESSAGE_CONTENT", "true"); |
| 51 | + properties.setProperty("gov.nist.javax.sip.DELIVER_UNSOLICITED_NOTIFY", "true"); // 接收所有notify请求,即使没有订阅 | ||
| 51 | /** | 52 | /** |
| 52 | * sip_server_log.log 和 sip_debug_log.log public static final int TRACE_NONE = | 53 | * 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 | 54 | * 0; public static final int TRACE_MESSAGES = 16; public static final int |
src/main/java/com/genersoft/iot/vmp/gb28181/bean/CatalogData.java
| @@ -4,6 +4,7 @@ import java.util.Date; | @@ -4,6 +4,7 @@ import java.util.Date; | ||
| 4 | import java.util.List; | 4 | import java.util.List; |
| 5 | 5 | ||
| 6 | public class CatalogData { | 6 | public class CatalogData { |
| 7 | + private int sn; // 命令序列号 | ||
| 7 | private int total; | 8 | private int total; |
| 8 | private List<DeviceChannel> channelList; | 9 | private List<DeviceChannel> channelList; |
| 9 | private Date lastTime; | 10 | private Date lastTime; |
| @@ -15,6 +16,15 @@ public class CatalogData { | @@ -15,6 +16,15 @@ public class CatalogData { | ||
| 15 | } | 16 | } |
| 16 | private CatalogDataStatus status; | 17 | private CatalogDataStatus status; |
| 17 | 18 | ||
| 19 | + | ||
| 20 | + public int getSn() { | ||
| 21 | + return sn; | ||
| 22 | + } | ||
| 23 | + | ||
| 24 | + public void setSn(int sn) { | ||
| 25 | + this.sn = sn; | ||
| 26 | + } | ||
| 27 | + | ||
| 18 | public int getTotal() { | 28 | public int getTotal() { |
| 19 | return total; | 29 | return total; |
| 20 | } | 30 | } |
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/online/OnlineEventListener.java
| @@ -54,6 +54,7 @@ public class OnlineEventListener implements ApplicationListener<OnlineEvent> { | @@ -54,6 +54,7 @@ public class OnlineEventListener implements ApplicationListener<OnlineEvent> { | ||
| 54 | @Autowired | 54 | @Autowired |
| 55 | private SIPCommander cmder; | 55 | private SIPCommander cmder; |
| 56 | 56 | ||
| 57 | + | ||
| 57 | private SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); | 58 | private SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); |
| 58 | 59 | ||
| 59 | @Override | 60 | @Override |
| @@ -76,7 +77,7 @@ public class OnlineEventListener implements ApplicationListener<OnlineEvent> { | @@ -76,7 +77,7 @@ public class OnlineEventListener implements ApplicationListener<OnlineEvent> { | ||
| 76 | if (deviceInStore == null) { //第一次上线 | 77 | if (deviceInStore == null) { //第一次上线 |
| 77 | logger.info("[{}] 首次注册,查询设备信息以及通道信息", device.getDeviceId()); | 78 | logger.info("[{}] 首次注册,查询设备信息以及通道信息", device.getDeviceId()); |
| 78 | cmder.deviceInfoQuery(device); | 79 | cmder.deviceInfoQuery(device); |
| 79 | - cmder.catalogQuery(device, null); | 80 | + deviceService.sync(device); |
| 80 | } | 81 | } |
| 81 | break; | 82 | break; |
| 82 | // 设备主动发送心跳触发的在线事件 | 83 | // 设备主动发送心跳触发的在线事件 |
| @@ -99,7 +100,10 @@ public class OnlineEventListener implements ApplicationListener<OnlineEvent> { | @@ -99,7 +100,10 @@ public class OnlineEventListener implements ApplicationListener<OnlineEvent> { | ||
| 99 | storager.updateDevice(device); | 100 | storager.updateDevice(device); |
| 100 | // 上线添加订阅 | 101 | // 上线添加订阅 |
| 101 | if (device.getSubscribeCycleForCatalog() > 0) { | 102 | if (device.getSubscribeCycleForCatalog() > 0) { |
| 103 | + // 查询在线设备那些开启了订阅,为设备开启定时的目录订阅 | ||
| 102 | deviceService.addCatalogSubscribe(device); | 104 | deviceService.addCatalogSubscribe(device); |
| 105 | + } | ||
| 106 | + if (device.getSubscribeCycleForMobilePosition() > 0) { | ||
| 103 | deviceService.addMobilePositionSubscribe(device); | 107 | deviceService.addMobilePositionSubscribe(device); |
| 104 | } | 108 | } |
| 105 | } | 109 | } |
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,8 +61,6 @@ public class CatalogEventLister implements ApplicationListener<CatalogEvent> { | ||
| 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/session/CatalogDataCatch.java
| @@ -26,28 +26,35 @@ public class CatalogDataCatch { | @@ -26,28 +26,35 @@ public class CatalogDataCatch { | ||
| 26 | @Autowired | 26 | @Autowired |
| 27 | private IVideoManagerStorage storager; | 27 | private IVideoManagerStorage storager; |
| 28 | 28 | ||
| 29 | - public void addReady(String key) { | ||
| 30 | - CatalogData catalogData = data.get(key); | 29 | + public void addReady(Device device, int sn ) { |
| 30 | + CatalogData catalogData = data.get(device.getDeviceId()); | ||
| 31 | if (catalogData == null || catalogData.getStatus().equals(CatalogData.CatalogDataStatus.end)) { | 31 | if (catalogData == null || catalogData.getStatus().equals(CatalogData.CatalogDataStatus.end)) { |
| 32 | catalogData = new CatalogData(); | 32 | catalogData = new CatalogData(); |
| 33 | catalogData.setChannelList(new ArrayList<>()); | 33 | catalogData.setChannelList(new ArrayList<>()); |
| 34 | + catalogData.setDevice(device); | ||
| 35 | + catalogData.setSn(sn); | ||
| 34 | catalogData.setStatus(CatalogData.CatalogDataStatus.ready); | 36 | catalogData.setStatus(CatalogData.CatalogDataStatus.ready); |
| 35 | catalogData.setLastTime(new Date(System.currentTimeMillis())); | 37 | catalogData.setLastTime(new Date(System.currentTimeMillis())); |
| 36 | - data.put(key, catalogData); | 38 | + data.put(device.getDeviceId(), catalogData); |
| 37 | } | 39 | } |
| 38 | } | 40 | } |
| 39 | 41 | ||
| 40 | - public void put(String key, int total, Device device, List<DeviceChannel> deviceChannelList) { | ||
| 41 | - CatalogData catalogData = data.get(key); | 42 | + public void put(String deviceId, int sn, int total, Device device, List<DeviceChannel> deviceChannelList) { |
| 43 | + CatalogData catalogData = data.get(deviceId); | ||
| 42 | if (catalogData == null) { | 44 | if (catalogData == null) { |
| 43 | catalogData = new CatalogData(); | 45 | catalogData = new CatalogData(); |
| 46 | + catalogData.setSn(sn); | ||
| 44 | catalogData.setTotal(total); | 47 | catalogData.setTotal(total); |
| 45 | catalogData.setDevice(device); | 48 | catalogData.setDevice(device); |
| 46 | catalogData.setChannelList(new ArrayList<>()); | 49 | catalogData.setChannelList(new ArrayList<>()); |
| 47 | catalogData.setStatus(CatalogData.CatalogDataStatus.runIng); | 50 | catalogData.setStatus(CatalogData.CatalogDataStatus.runIng); |
| 48 | catalogData.setLastTime(new Date(System.currentTimeMillis())); | 51 | catalogData.setLastTime(new Date(System.currentTimeMillis())); |
| 49 | - data.put(key, catalogData); | 52 | + data.put(deviceId, catalogData); |
| 50 | }else { | 53 | }else { |
| 54 | + // 同一个设备的通道同步请求只考虑一个,其他的直接忽略 | ||
| 55 | + if (catalogData.getSn() != sn) { | ||
| 56 | + return; | ||
| 57 | + } | ||
| 51 | catalogData.setTotal(total); | 58 | catalogData.setTotal(total); |
| 52 | catalogData.setDevice(device); | 59 | catalogData.setDevice(device); |
| 53 | catalogData.setStatus(CatalogData.CatalogDataStatus.runIng); | 60 | catalogData.setStatus(CatalogData.CatalogDataStatus.runIng); |
| @@ -56,20 +63,20 @@ public class CatalogDataCatch { | @@ -56,20 +63,20 @@ public class CatalogDataCatch { | ||
| 56 | } | 63 | } |
| 57 | } | 64 | } |
| 58 | 65 | ||
| 59 | - public List<DeviceChannel> get(String key) { | ||
| 60 | - CatalogData catalogData = data.get(key); | 66 | + public List<DeviceChannel> get(String deviceId) { |
| 67 | + CatalogData catalogData = data.get(deviceId); | ||
| 61 | if (catalogData == null) return null; | 68 | if (catalogData == null) return null; |
| 62 | return catalogData.getChannelList(); | 69 | return catalogData.getChannelList(); |
| 63 | } | 70 | } |
| 64 | 71 | ||
| 65 | - public int getTotal(String key) { | ||
| 66 | - CatalogData catalogData = data.get(key); | 72 | + public int getTotal(String deviceId) { |
| 73 | + CatalogData catalogData = data.get(deviceId); | ||
| 67 | if (catalogData == null) return 0; | 74 | if (catalogData == null) return 0; |
| 68 | return catalogData.getTotal(); | 75 | return catalogData.getTotal(); |
| 69 | } | 76 | } |
| 70 | 77 | ||
| 71 | - public SyncStatus getSyncStatus(String key) { | ||
| 72 | - CatalogData catalogData = data.get(key); | 78 | + public SyncStatus getSyncStatus(String deviceId) { |
| 79 | + CatalogData catalogData = data.get(deviceId); | ||
| 73 | if (catalogData == null) return null; | 80 | if (catalogData == null) return null; |
| 74 | SyncStatus syncStatus = new SyncStatus(); | 81 | SyncStatus syncStatus = new SyncStatus(); |
| 75 | syncStatus.setCurrent(catalogData.getChannelList().size()); | 82 | syncStatus.setCurrent(catalogData.getChannelList().size()); |
| @@ -78,10 +85,6 @@ public class CatalogDataCatch { | @@ -78,10 +85,6 @@ public class CatalogDataCatch { | ||
| 78 | return syncStatus; | 85 | return syncStatus; |
| 79 | } | 86 | } |
| 80 | 87 | ||
| 81 | - public void del(String key) { | ||
| 82 | - data.remove(key); | ||
| 83 | - } | ||
| 84 | - | ||
| 85 | @Scheduled(fixedRate = 5 * 1000) //每5秒执行一次, 发现数据5秒未更新则移除数据并认为数据接收超时 | 88 | @Scheduled(fixedRate = 5 * 1000) //每5秒执行一次, 发现数据5秒未更新则移除数据并认为数据接收超时 |
| 86 | private void timerTask(){ | 89 | private void timerTask(){ |
| 87 | Set<String> keys = data.keySet(); | 90 | Set<String> keys = data.keySet(); |
| @@ -92,23 +95,30 @@ public class CatalogDataCatch { | @@ -92,23 +95,30 @@ public class CatalogDataCatch { | ||
| 92 | Calendar calendarBefore30S = Calendar.getInstance(); | 95 | Calendar calendarBefore30S = Calendar.getInstance(); |
| 93 | calendarBefore30S.setTime(new Date()); | 96 | calendarBefore30S.setTime(new Date()); |
| 94 | calendarBefore30S.set(Calendar.SECOND, calendarBefore30S.get(Calendar.SECOND) - 30); | 97 | calendarBefore30S.set(Calendar.SECOND, calendarBefore30S.get(Calendar.SECOND) - 30); |
| 95 | - for (String key : keys) { | ||
| 96 | - CatalogData catalogData = data.get(key); | ||
| 97 | - if (catalogData.getLastTime().before(calendarBefore5S.getTime())) { // 超过五秒收不到消息任务超时, 只更新这一部分数据 | ||
| 98 | - storager.resetChannels(catalogData.getDevice().getDeviceId(), catalogData.getChannelList()); | ||
| 99 | - String errorMsg = "更新成功,共" + catalogData.getTotal() + "条,已更新" + catalogData.getChannelList().size() + "条"; | 98 | + for (String deviceId : keys) { |
| 99 | + CatalogData catalogData = data.get(deviceId); | ||
| 100 | + if ( catalogData.getLastTime().before(calendarBefore5S.getTime())) { // 超过五秒收不到消息任务超时, 只更新这一部分数据 | ||
| 101 | + if (catalogData.getStatus().equals(CatalogData.CatalogDataStatus.runIng)) { | ||
| 102 | + storager.resetChannels(catalogData.getDevice().getDeviceId(), catalogData.getChannelList()); | ||
| 103 | + if (catalogData.getTotal() != catalogData.getChannelList().size()) { | ||
| 104 | + String errorMsg = "更新成功,共" + catalogData.getTotal() + "条,已更新" + catalogData.getChannelList().size() + "条"; | ||
| 105 | + catalogData.setErrorMsg(errorMsg); | ||
| 106 | + } | ||
| 107 | + }else if (catalogData.getStatus().equals(CatalogData.CatalogDataStatus.ready)) { | ||
| 108 | + String errorMsg = "同步失败,等待回复超时"; | ||
| 109 | + catalogData.setErrorMsg(errorMsg); | ||
| 110 | + } | ||
| 100 | catalogData.setStatus(CatalogData.CatalogDataStatus.end); | 111 | catalogData.setStatus(CatalogData.CatalogDataStatus.end); |
| 101 | - catalogData.setErrorMsg(errorMsg); | ||
| 102 | } | 112 | } |
| 103 | - if (catalogData.getLastTime().before(calendarBefore30S.getTime())) { // 超过三十秒,如果标记为end则删除 | ||
| 104 | - data.remove(key); | 113 | + if (catalogData.getStatus().equals(CatalogData.CatalogDataStatus.end) && catalogData.getLastTime().before(calendarBefore30S.getTime())) { // 超过三十秒,如果标记为end则删除 |
| 114 | + data.remove(deviceId); | ||
| 105 | } | 115 | } |
| 106 | } | 116 | } |
| 107 | } | 117 | } |
| 108 | 118 | ||
| 109 | 119 | ||
| 110 | - public void setChannelSyncEnd(String key, String errorMsg) { | ||
| 111 | - CatalogData catalogData = data.get(key); | 120 | + public void setChannelSyncEnd(String deviceId, String errorMsg) { |
| 121 | + CatalogData catalogData = data.get(deviceId); | ||
| 112 | if (catalogData == null)return; | 122 | if (catalogData == null)return; |
| 113 | catalogData.setStatus(CatalogData.CatalogDataStatus.end); | 123 | catalogData.setStatus(CatalogData.CatalogDataStatus.end); |
| 114 | catalogData.setErrorMsg(errorMsg); | 124 | catalogData.setErrorMsg(errorMsg); |
src/main/java/com/genersoft/iot/vmp/gb28181/task/ISubscribeTask.java
| 1 | package com.genersoft.iot.vmp.gb28181.task; | 1 | package com.genersoft.iot.vmp.gb28181.task; |
| 2 | 2 | ||
| 3 | +import javax.sip.DialogState; | ||
| 4 | + | ||
| 3 | public interface ISubscribeTask extends Runnable{ | 5 | public interface ISubscribeTask extends Runnable{ |
| 4 | void stop(); | 6 | void stop(); |
| 7 | + | ||
| 8 | + DialogState getDialogState(); | ||
| 5 | } | 9 | } |
src/main/java/com/genersoft/iot/vmp/gb28181/task/impl/CatalogSubscribeTask.java
| @@ -5,6 +5,7 @@ import com.genersoft.iot.vmp.gb28181.task.ISubscribeTask; | @@ -5,6 +5,7 @@ import com.genersoft.iot.vmp.gb28181.task.ISubscribeTask; | ||
| 5 | import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander; | 5 | import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander; |
| 6 | import org.slf4j.Logger; | 6 | import org.slf4j.Logger; |
| 7 | import org.slf4j.LoggerFactory; | 7 | import org.slf4j.LoggerFactory; |
| 8 | +import org.springframework.scheduling.annotation.Async; | ||
| 8 | 9 | ||
| 9 | import javax.sip.Dialog; | 10 | import javax.sip.Dialog; |
| 10 | import javax.sip.DialogState; | 11 | import javax.sip.DialogState; |
| @@ -72,4 +73,10 @@ public class CatalogSubscribeTask implements ISubscribeTask { | @@ -72,4 +73,10 @@ public class CatalogSubscribeTask implements ISubscribeTask { | ||
| 72 | }); | 73 | }); |
| 73 | } | 74 | } |
| 74 | } | 75 | } |
| 76 | + | ||
| 77 | + @Override | ||
| 78 | + public DialogState getDialogState() { | ||
| 79 | + if (dialog == null) return null; | ||
| 80 | + return dialog.getState(); | ||
| 81 | + } | ||
| 75 | } | 82 | } |
src/main/java/com/genersoft/iot/vmp/gb28181/task/impl/MobilePositionSubscribeHandlerTask.java
| 1 | package com.genersoft.iot.vmp.gb28181.task.impl; | 1 | package com.genersoft.iot.vmp.gb28181.task.impl; |
| 2 | 2 | ||
| 3 | -import com.genersoft.iot.vmp.gb28181.bean.GbStream; | ||
| 4 | -import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; | ||
| 5 | -import com.genersoft.iot.vmp.gb28181.bean.SubscribeHolder; | ||
| 6 | -import com.genersoft.iot.vmp.gb28181.bean.SubscribeInfo; | 3 | +import com.genersoft.iot.vmp.gb28181.bean.*; |
| 7 | import com.genersoft.iot.vmp.gb28181.task.ISubscribeTask; | 4 | import com.genersoft.iot.vmp.gb28181.task.ISubscribeTask; |
| 8 | import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform; | 5 | import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform; |
| 9 | import com.genersoft.iot.vmp.service.bean.GPSMsgInfo; | 6 | import com.genersoft.iot.vmp.service.bean.GPSMsgInfo; |
| 10 | import com.genersoft.iot.vmp.storager.IRedisCatchStorage; | 7 | import com.genersoft.iot.vmp.storager.IRedisCatchStorage; |
| 11 | import com.genersoft.iot.vmp.storager.IVideoManagerStorage; | 8 | import com.genersoft.iot.vmp.storager.IVideoManagerStorage; |
| 9 | +import org.slf4j.Logger; | ||
| 10 | +import org.slf4j.LoggerFactory; | ||
| 11 | +import org.springframework.scheduling.annotation.Async; | ||
| 12 | 12 | ||
| 13 | -import java.text.SimpleDateFormat; | 13 | +import javax.sip.DialogState; |
| 14 | import java.util.List; | 14 | import java.util.List; |
| 15 | 15 | ||
| 16 | /** | 16 | /** |
| @@ -18,20 +18,21 @@ import java.util.List; | @@ -18,20 +18,21 @@ import java.util.List; | ||
| 18 | */ | 18 | */ |
| 19 | public class MobilePositionSubscribeHandlerTask implements ISubscribeTask { | 19 | public class MobilePositionSubscribeHandlerTask implements ISubscribeTask { |
| 20 | 20 | ||
| 21 | + private Logger logger = LoggerFactory.getLogger(MobilePositionSubscribeHandlerTask.class); | ||
| 22 | + | ||
| 21 | private IRedisCatchStorage redisCatchStorage; | 23 | private IRedisCatchStorage redisCatchStorage; |
| 22 | private IVideoManagerStorage storager; | 24 | private IVideoManagerStorage storager; |
| 23 | private ISIPCommanderForPlatform sipCommanderForPlatform; | 25 | private ISIPCommanderForPlatform sipCommanderForPlatform; |
| 24 | private SubscribeHolder subscribeHolder; | 26 | private SubscribeHolder subscribeHolder; |
| 25 | - private String platformId; | 27 | + private ParentPlatform platform; |
| 26 | private String sn; | 28 | private String sn; |
| 27 | private String key; | 29 | private String key; |
| 28 | 30 | ||
| 29 | - private final SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); | ||
| 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; |
| @@ -41,30 +42,31 @@ public class MobilePositionSubscribeHandlerTask implements ISubscribeTask { | @@ -41,30 +42,31 @@ public class MobilePositionSubscribeHandlerTask implements ISubscribeTask { | ||
| 41 | @Override | 42 | @Override |
| 42 | public void run() { | 43 | public void run() { |
| 43 | 44 | ||
| 44 | - SubscribeInfo subscribe = subscribeHolder.getMobilePositionSubscribe(platformId); | ||
| 45 | - | 45 | + if (platform == null) return; |
| 46 | + SubscribeInfo subscribe = subscribeHolder.getMobilePositionSubscribe(platform.getServerGBId()); | ||
| 46 | if (subscribe != null) { | 47 | if (subscribe != null) { |
| 47 | - ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(platformId); | ||
| 48 | - if (parentPlatform == null || parentPlatform.isStatus()) { | ||
| 49 | - // TODO 暂时只处理视频流的回复,后续增加对国标设备的支持 | ||
| 50 | - List<GbStream> gbStreams = storager.queryGbStreamListInPlatform(platformId); | ||
| 51 | - if (gbStreams.size() > 0) { | ||
| 52 | - for (GbStream gbStream : gbStreams) { | ||
| 53 | - String gbId = gbStream.getGbId(); | ||
| 54 | - GPSMsgInfo gpsMsgInfo = redisCatchStorage.getGpsMsgInfo(gbId); | ||
| 55 | - if (gpsMsgInfo != null) { | ||
| 56 | - // 发送GPS消息 | ||
| 57 | - sipCommanderForPlatform.sendNotifyMobilePosition(parentPlatform, gpsMsgInfo, subscribe); | ||
| 58 | - }else { | ||
| 59 | - // 没有在redis找到新的消息就使用数据库的消息 | ||
| 60 | - gpsMsgInfo = new GPSMsgInfo(); | ||
| 61 | - gpsMsgInfo.setId(gbId); | ||
| 62 | - gpsMsgInfo.setLat(gbStream.getLongitude()); | ||
| 63 | - gpsMsgInfo.setLng(gbStream.getLongitude()); | ||
| 64 | - // 发送GPS消息 | ||
| 65 | - sipCommanderForPlatform.sendNotifyMobilePosition(parentPlatform, gpsMsgInfo, subscribe); | ||
| 66 | - } | 48 | + |
| 49 | +// if (!parentPlatform.isStatus()) { | ||
| 50 | +// logger.info("发送订阅时发现平台已经离线:{}", platformId); | ||
| 51 | +// return; | ||
| 52 | +// } | ||
| 53 | + // TODO 暂时只处理视频流的回复,后续增加对国标设备的支持 | ||
| 54 | + List<GbStream> gbStreams = storager.queryGbStreamListInPlatform(platform.getServerGBId()); | ||
| 55 | + if (gbStreams.size() == 0) { | ||
| 56 | + logger.info("发送订阅时发现平台已经没有关联的直播流:{}", platform.getServerGBId()); | ||
| 57 | + return; | ||
| 58 | + } | ||
| 59 | + for (GbStream gbStream : gbStreams) { | ||
| 60 | + String gbId = gbStream.getGbId(); | ||
| 61 | + GPSMsgInfo gpsMsgInfo = redisCatchStorage.getGpsMsgInfo(gbId); | ||
| 62 | + if (gpsMsgInfo != null) { // 无最新位置不发送 | ||
| 63 | + logger.info("无最新位置不发送"); | ||
| 64 | + // 经纬度都为0不发送 | ||
| 65 | + if (gpsMsgInfo.getLng() == 0 && gpsMsgInfo.getLat() == 0) { | ||
| 66 | + continue; | ||
| 67 | } | 67 | } |
| 68 | + // 发送GPS消息 | ||
| 69 | + sipCommanderForPlatform.sendNotifyMobilePosition(platform, gpsMsgInfo, subscribe); | ||
| 68 | } | 70 | } |
| 69 | } | 71 | } |
| 70 | } | 72 | } |
| @@ -74,4 +76,9 @@ public class MobilePositionSubscribeHandlerTask implements ISubscribeTask { | @@ -74,4 +76,9 @@ public class MobilePositionSubscribeHandlerTask implements ISubscribeTask { | ||
| 74 | public void stop() { | 76 | public void stop() { |
| 75 | 77 | ||
| 76 | } | 78 | } |
| 79 | + | ||
| 80 | + @Override | ||
| 81 | + public DialogState getDialogState() { | ||
| 82 | + return null; | ||
| 83 | + } | ||
| 77 | } | 84 | } |
src/main/java/com/genersoft/iot/vmp/gb28181/task/impl/MobilePositionSubscribeTask.java
| @@ -6,10 +6,13 @@ import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander; | @@ -6,10 +6,13 @@ import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander; | ||
| 6 | import org.dom4j.Element; | 6 | import org.dom4j.Element; |
| 7 | import org.slf4j.Logger; | 7 | import org.slf4j.Logger; |
| 8 | import org.slf4j.LoggerFactory; | 8 | import org.slf4j.LoggerFactory; |
| 9 | +import org.springframework.scheduling.annotation.Async; | ||
| 9 | 10 | ||
| 10 | import javax.sip.Dialog; | 11 | import javax.sip.Dialog; |
| 11 | import javax.sip.DialogState; | 12 | import javax.sip.DialogState; |
| 12 | import javax.sip.ResponseEvent; | 13 | import javax.sip.ResponseEvent; |
| 14 | +import java.util.Timer; | ||
| 15 | +import java.util.TimerTask; | ||
| 13 | 16 | ||
| 14 | /** | 17 | /** |
| 15 | * 移动位置订阅的定时更新 | 18 | * 移动位置订阅的定时更新 |
| @@ -20,6 +23,8 @@ public class MobilePositionSubscribeTask implements ISubscribeTask { | @@ -20,6 +23,8 @@ public class MobilePositionSubscribeTask implements ISubscribeTask { | ||
| 20 | private ISIPCommander sipCommander; | 23 | private ISIPCommander sipCommander; |
| 21 | private Dialog dialog; | 24 | private Dialog dialog; |
| 22 | 25 | ||
| 26 | + private Timer timer ; | ||
| 27 | + | ||
| 23 | public MobilePositionSubscribeTask(Device device, ISIPCommander sipCommander) { | 28 | public MobilePositionSubscribeTask(Device device, ISIPCommander sipCommander) { |
| 24 | this.device = device; | 29 | this.device = device; |
| 25 | this.sipCommander = sipCommander; | 30 | this.sipCommander = sipCommander; |
| @@ -27,10 +32,14 @@ public class MobilePositionSubscribeTask implements ISubscribeTask { | @@ -27,10 +32,14 @@ public class MobilePositionSubscribeTask implements ISubscribeTask { | ||
| 27 | 32 | ||
| 28 | @Override | 33 | @Override |
| 29 | public void run() { | 34 | public void run() { |
| 35 | + if (timer != null ) { | ||
| 36 | + timer.cancel(); | ||
| 37 | + timer = null; | ||
| 38 | + } | ||
| 30 | sipCommander.mobilePositionSubscribe(device, dialog, eventResult -> { | 39 | sipCommander.mobilePositionSubscribe(device, dialog, eventResult -> { |
| 31 | - if (eventResult.dialog != null || eventResult.dialog.getState().equals(DialogState.CONFIRMED)) { | ||
| 32 | - dialog = eventResult.dialog; | ||
| 33 | - } | 40 | +// if (eventResult.dialog != null || eventResult.dialog.getState().equals(DialogState.CONFIRMED)) { |
| 41 | +// dialog = eventResult.dialog; | ||
| 42 | +// } | ||
| 34 | ResponseEvent event = (ResponseEvent) eventResult.event; | 43 | ResponseEvent event = (ResponseEvent) eventResult.event; |
| 35 | if (event.getResponse().getRawContent() != null) { | 44 | if (event.getResponse().getRawContent() != null) { |
| 36 | // 成功 | 45 | // 成功 |
| @@ -43,6 +52,13 @@ public class MobilePositionSubscribeTask implements ISubscribeTask { | @@ -43,6 +52,13 @@ public class MobilePositionSubscribeTask implements ISubscribeTask { | ||
| 43 | dialog = null; | 52 | dialog = null; |
| 44 | // 失败 | 53 | // 失败 |
| 45 | 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); | ||
| 46 | }); | 62 | }); |
| 47 | 63 | ||
| 48 | } | 64 | } |
| @@ -56,6 +72,10 @@ public class MobilePositionSubscribeTask implements ISubscribeTask { | @@ -56,6 +72,10 @@ public class MobilePositionSubscribeTask implements ISubscribeTask { | ||
| 56 | * COMPLETED-> Completed Dialog状态-已完成 | 72 | * COMPLETED-> Completed Dialog状态-已完成 |
| 57 | * TERMINATED-> Terminated Dialog状态-终止 | 73 | * TERMINATED-> Terminated Dialog状态-终止 |
| 58 | */ | 74 | */ |
| 75 | + if (timer != null ) { | ||
| 76 | + timer.cancel(); | ||
| 77 | + timer = null; | ||
| 78 | + } | ||
| 59 | if (dialog != null && dialog.getState().equals(DialogState.CONFIRMED)) { | 79 | if (dialog != null && dialog.getState().equals(DialogState.CONFIRMED)) { |
| 60 | logger.info("取消移动订阅时dialog状态为{}", dialog.getState()); | 80 | logger.info("取消移动订阅时dialog状态为{}", dialog.getState()); |
| 61 | device.setSubscribeCycleForMobilePosition(0); | 81 | device.setSubscribeCycleForMobilePosition(0); |
| @@ -74,4 +94,9 @@ public class MobilePositionSubscribeTask implements ISubscribeTask { | @@ -74,4 +94,9 @@ public class MobilePositionSubscribeTask implements ISubscribeTask { | ||
| 74 | }); | 94 | }); |
| 75 | } | 95 | } |
| 76 | } | 96 | } |
| 97 | + @Override | ||
| 98 | + public DialogState getDialogState() { | ||
| 99 | + if (dialog == null) return null; | ||
| 100 | + return dialog.getState(); | ||
| 101 | + } | ||
| 77 | } | 102 | } |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java
| @@ -250,7 +250,7 @@ public interface ISIPCommander { | @@ -250,7 +250,7 @@ public interface ISIPCommander { | ||
| 250 | * | 250 | * |
| 251 | * @param device 视频设备 | 251 | * @param device 视频设备 |
| 252 | */ | 252 | */ |
| 253 | - boolean catalogQuery(Device device, SipSubscribe.Event errorEvent); | 253 | + boolean catalogQuery(Device device, int sn, SipSubscribe.Event errorEvent); |
| 254 | 254 | ||
| 255 | /** | 255 | /** |
| 256 | * 查询录像信息 | 256 | * 查询录像信息 |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
| @@ -1208,14 +1208,14 @@ public class SIPCommander implements ISIPCommander { | @@ -1208,14 +1208,14 @@ public class SIPCommander implements ISIPCommander { | ||
| 1208 | * @param device 视频设备 | 1208 | * @param device 视频设备 |
| 1209 | */ | 1209 | */ |
| 1210 | @Override | 1210 | @Override |
| 1211 | - public boolean catalogQuery(Device device, SipSubscribe.Event errorEvent) { | 1211 | + public boolean catalogQuery(Device device, int sn, SipSubscribe.Event errorEvent) { |
| 1212 | try { | 1212 | try { |
| 1213 | StringBuffer catalogXml = new StringBuffer(200); | 1213 | StringBuffer catalogXml = new StringBuffer(200); |
| 1214 | String charset = device.getCharset(); | 1214 | String charset = device.getCharset(); |
| 1215 | catalogXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n"); | 1215 | catalogXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n"); |
| 1216 | catalogXml.append("<Query>\r\n"); | 1216 | catalogXml.append("<Query>\r\n"); |
| 1217 | catalogXml.append("<CmdType>Catalog</CmdType>\r\n"); | 1217 | catalogXml.append("<CmdType>Catalog</CmdType>\r\n"); |
| 1218 | - catalogXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n"); | 1218 | + catalogXml.append("<SN>" + sn + "</SN>\r\n"); |
| 1219 | catalogXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n"); | 1219 | catalogXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n"); |
| 1220 | catalogXml.append("</Query>\r\n"); | 1220 | catalogXml.append("</Query>\r\n"); |
| 1221 | 1221 | ||
| @@ -1566,17 +1566,28 @@ public class SIPCommander implements ISIPCommander { | @@ -1566,17 +1566,28 @@ public class SIPCommander implements ISIPCommander { | ||
| 1566 | cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n"); | 1566 | cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n"); |
| 1567 | cmdXml.append("</Query>\r\n"); | 1567 | cmdXml.append("</Query>\r\n"); |
| 1568 | 1568 | ||
| 1569 | - String tm = Long.toString(System.currentTimeMillis()); | ||
| 1570 | 1569 | ||
| 1571 | - CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId() | ||
| 1572 | - : udpSipProvider.getNewCallId(); | 1570 | + Request request; |
| 1571 | + if (dialog != null) { | ||
| 1572 | + logger.info("发送目录订阅消息时 dialog的状态为: {}", dialog.getState()); | ||
| 1573 | + request = dialog.createRequest(Request.SUBSCRIBE); | ||
| 1574 | + ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml"); | ||
| 1575 | + request.setContent(cmdXml.toString(), contentTypeHeader); | ||
| 1576 | + ExpiresHeader expireHeader = sipFactory.createHeaderFactory().createExpiresHeader(device.getSubscribeCycleForMobilePosition()); | ||
| 1577 | + request.addHeader(expireHeader); | ||
| 1578 | + }else { | ||
| 1579 | + String tm = Long.toString(System.currentTimeMillis()); | ||
| 1573 | 1580 | ||
| 1574 | - // 有效时间默认为60秒以上 | ||
| 1575 | - Request request = headerProvider.createSubscribeRequest(device, cmdXml.toString(), "z9hG4bK-viaPos-" + tm, | ||
| 1576 | - "fromTagPos" + tm, null, device.getSubscribeCycleForCatalog(), "Catalog" , | ||
| 1577 | - callIdHeader); | ||
| 1578 | - transmitRequest(device, request, errorEvent, okEvent); | 1581 | + CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId() |
| 1582 | + : udpSipProvider.getNewCallId(); | ||
| 1583 | + | ||
| 1584 | + // 有效时间默认为60秒以上 | ||
| 1585 | + request = headerProvider.createSubscribeRequest(device, cmdXml.toString(), "z9hG4bK-viaPos-" + tm, | ||
| 1586 | + "fromTagPos" + tm, null, device.getSubscribeCycleForCatalog(), "Catalog" , | ||
| 1587 | + callIdHeader); | ||
| 1579 | 1588 | ||
| 1589 | + } | ||
| 1590 | + transmitRequest(device, request, errorEvent, okEvent); | ||
| 1580 | return true; | 1591 | return true; |
| 1581 | 1592 | ||
| 1582 | } catch ( NumberFormatException | ParseException | InvalidArgumentException | SipException e) { | 1593 | } catch ( NumberFormatException | ParseException | InvalidArgumentException | SipException e) { |
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("[发送Notify-MobilePosition] {}/{}->{},{}", 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/NotifyRequestProcessor.java
| @@ -146,7 +146,7 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements | @@ -146,7 +146,7 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements | ||
| 146 | } else { | 146 | } else { |
| 147 | mobilePosition.setAltitude(0.0); | 147 | mobilePosition.setAltitude(0.0); |
| 148 | } | 148 | } |
| 149 | - logger.info("[收到Notify-MobilePosition]:{}/{}->{}.{}", mobilePosition.getDeviceId(), mobilePosition.getChannelId(), | 149 | + logger.info("[收到 移动位置订阅]:{}/{}->{}.{}", mobilePosition.getDeviceId(), mobilePosition.getChannelId(), |
| 150 | mobilePosition.getLongitude(), mobilePosition.getLatitude()); | 150 | mobilePosition.getLongitude(), mobilePosition.getLatitude()); |
| 151 | mobilePosition.setReportSource("Mobile Position"); | 151 | mobilePosition.setReportSource("Mobile Position"); |
| 152 | BaiduPoint bp = GpsUtil.Wgs84ToBd09(String.valueOf(mobilePosition.getLongitude()), String.valueOf(mobilePosition.getLatitude())); | 152 | BaiduPoint bp = GpsUtil.Wgs84ToBd09(String.valueOf(mobilePosition.getLongitude()), String.valueOf(mobilePosition.getLatitude())); |
| @@ -281,7 +281,7 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements | @@ -281,7 +281,7 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements | ||
| 281 | Element eventElement = itemDevice.element("Event"); | 281 | Element eventElement = itemDevice.element("Event"); |
| 282 | DeviceChannel channel = XmlUtil.channelContentHander(itemDevice); | 282 | DeviceChannel channel = XmlUtil.channelContentHander(itemDevice); |
| 283 | channel.setDeviceId(device.getDeviceId()); | 283 | channel.setDeviceId(device.getDeviceId()); |
| 284 | - logger.info("[收到Notify-Catalog]:{}/{}", device.getDeviceId(), channel.getChannelId()); | 284 | + logger.info("[收到 目录订阅]:{}/{}", device.getDeviceId(), channel.getChannelId()); |
| 285 | switch (eventElement.getText().toUpperCase()) { | 285 | switch (eventElement.getText().toUpperCase()) { |
| 286 | case CatalogEvent.ON: // 上线 | 286 | case CatalogEvent.ON: // 上线 |
| 287 | logger.info("收到来自设备【{}】的通道【{}】上线通知", device.getDeviceId(), channel.getChannelId()); | 287 | logger.info("收到来自设备【{}】的通道【{}】上线通知", device.getDeviceId(), channel.getChannelId()); |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/SubscribeRequestProcessor.java
| @@ -149,8 +149,7 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme | @@ -149,8 +149,7 @@ 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("[notify-MobilePosition]: {}", 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") |
| 156 | .append("<Response>\r\n") | 155 | .append("<Response>\r\n") |
| @@ -161,14 +160,25 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme | @@ -161,14 +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 | - if (subscribeHolder.getMobilePositionSubscribe(platformId) != null) { | ||
| 165 | - dynamicTask.stop(key); | ||
| 166 | - } | ||
| 167 | String interval = XmlUtil.getText(rootElement, "Interval"); // GPS上报时间间隔 | 163 | String interval = XmlUtil.getText(rootElement, "Interval"); // GPS上报时间间隔 |
| 168 | - dynamicTask.startCron(key, new MobilePositionSubscribeHandlerTask(redisCatchStorage, sipCommanderForPlatform, storager, platformId, sn, key, subscribeHolder), Integer.parseInt(interval) -1 ); | 164 | + if (interval == null) { |
| 165 | + subscribeInfo.setGpsInterval(5); | ||
| 166 | + }else { | ||
| 167 | + subscribeInfo.setGpsInterval(Integer.parseInt(interval)); | ||
| 168 | + } | ||
| 169 | + | ||
| 170 | + subscribeInfo.setSn(sn); | ||
| 169 | subscribeHolder.putMobilePositionSubscribe(platformId, subscribeInfo); | 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 | +// } | ||
| 170 | }else if (subscribeInfo.getExpires() == 0) { | 181 | }else if (subscribeInfo.getExpires() == 0) { |
| 171 | - dynamicTask.stop(key); | ||
| 172 | subscribeHolder.removeMobilePositionSubscribe(platformId); | 182 | subscribeHolder.removeMobilePositionSubscribe(platformId); |
| 173 | } | 183 | } |
| 174 | 184 | ||
| @@ -202,8 +212,7 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme | @@ -202,8 +212,7 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme | ||
| 202 | subscribeInfo.setDialog(dialog); | 212 | subscribeInfo.setDialog(dialog); |
| 203 | } | 213 | } |
| 204 | String sn = XmlUtil.getText(rootElement, "SN"); | 214 | String sn = XmlUtil.getText(rootElement, "SN"); |
| 205 | - String key = VideoManagerConstants.SIP_SUBSCRIBE_PREFIX + userSetting.getServerId() + "_Catalog_" + platformId; | ||
| 206 | - logger.info("[notify-Catalog]: {}", platformId); | 215 | + logger.info("[回复 目录订阅]: {}/{}", platformId, deviceID); |
| 207 | StringBuilder resultXml = new StringBuilder(200); | 216 | StringBuilder resultXml = new StringBuilder(200); |
| 208 | resultXml.append("<?xml version=\"1.0\" ?>\r\n") | 217 | resultXml.append("<?xml version=\"1.0\" ?>\r\n") |
| 209 | .append("<Response>\r\n") | 218 | .append("<Response>\r\n") |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/CatalogResponseMessageHandler.java
| @@ -86,23 +86,17 @@ public class CatalogResponseMessageHandler extends SIPRequestProcessorParent imp | @@ -86,23 +86,17 @@ public class CatalogResponseMessageHandler extends SIPRequestProcessorParent imp | ||
| 86 | rootElement = getRootElement(evt, device.getCharset()); | 86 | rootElement = getRootElement(evt, device.getCharset()); |
| 87 | Element deviceListElement = rootElement.element("DeviceList"); | 87 | Element deviceListElement = rootElement.element("DeviceList"); |
| 88 | Element sumNumElement = rootElement.element("SumNum"); | 88 | Element sumNumElement = rootElement.element("SumNum"); |
| 89 | - if (sumNumElement == null || deviceListElement == null) { | 89 | + Element snElement = rootElement.element("SN"); |
| 90 | + if (snElement == null || sumNumElement == null || deviceListElement == null) { | ||
| 90 | responseAck(evt, Response.BAD_REQUEST, "xml error"); | 91 | responseAck(evt, Response.BAD_REQUEST, "xml error"); |
| 91 | return; | 92 | return; |
| 92 | } | 93 | } |
| 93 | int sumNum = Integer.parseInt(sumNumElement.getText()); | 94 | int sumNum = Integer.parseInt(sumNumElement.getText()); |
| 95 | + | ||
| 94 | if (sumNum == 0) { | 96 | if (sumNum == 0) { |
| 95 | // 数据已经完整接收 | 97 | // 数据已经完整接收 |
| 96 | storager.cleanChannelsForDevice(device.getDeviceId()); | 98 | storager.cleanChannelsForDevice(device.getDeviceId()); |
| 97 | - RequestMessage msg = new RequestMessage(); | ||
| 98 | - msg.setKey(key); | ||
| 99 | - WVPResult<Object> result = new WVPResult<>(); | ||
| 100 | - result.setCode(0); | ||
| 101 | - result.setData(device); | ||
| 102 | - msg.setData(result); | ||
| 103 | - result.setMsg("更新成功,共0条"); | ||
| 104 | - deferredResultHolder.invokeAllResult(msg); | ||
| 105 | - catalogDataCatch.del(key); | 99 | + catalogDataCatch.setChannelSyncEnd(device.getDeviceId(), null); |
| 106 | }else { | 100 | }else { |
| 107 | Iterator<Element> deviceListIterator = deviceListElement.elementIterator(); | 101 | Iterator<Element> deviceListIterator = deviceListElement.elementIterator(); |
| 108 | if (deviceListIterator != null) { | 102 | if (deviceListIterator != null) { |
| @@ -123,31 +117,22 @@ public class CatalogResponseMessageHandler extends SIPRequestProcessorParent imp | @@ -123,31 +117,22 @@ public class CatalogResponseMessageHandler extends SIPRequestProcessorParent imp | ||
| 123 | 117 | ||
| 124 | channelList.add(deviceChannel); | 118 | channelList.add(deviceChannel); |
| 125 | } | 119 | } |
| 120 | + int sn = Integer.parseInt(snElement.getText()); | ||
| 126 | logger.info("收到来自设备【{}】的通道: {}个,{}/{}", device.getDeviceId(), channelList.size(), catalogDataCatch.get(key) == null ? 0 :catalogDataCatch.get(key).size(), sumNum); | 121 | logger.info("收到来自设备【{}】的通道: {}个,{}/{}", device.getDeviceId(), channelList.size(), catalogDataCatch.get(key) == null ? 0 :catalogDataCatch.get(key).size(), sumNum); |
| 127 | - catalogDataCatch.put(key, sumNum, device, channelList); | ||
| 128 | - if (catalogDataCatch.get(key).size() == sumNum) { | 122 | + catalogDataCatch.put(device.getDeviceId(), sn, sumNum, device, channelList); |
| 123 | + if (catalogDataCatch.get(device.getDeviceId()).size() == sumNum) { | ||
| 129 | // 数据已经完整接收 | 124 | // 数据已经完整接收 |
| 130 | - boolean resetChannelsResult = storager.resetChannels(device.getDeviceId(), catalogDataCatch.get(key)); | ||
| 131 | - RequestMessage msg = new RequestMessage(); | ||
| 132 | - msg.setKey(key); | ||
| 133 | - WVPResult<Object> result = new WVPResult<>(); | ||
| 134 | - result.setCode(0); | ||
| 135 | - result.setData(device); | ||
| 136 | - if (resetChannelsResult || sumNum ==0) { | ||
| 137 | - result.setMsg("更新成功,共" + sumNum + "条,已更新" + catalogDataCatch.get(key).size() + "条"); | 125 | + boolean resetChannelsResult = storager.resetChannels(device.getDeviceId(), catalogDataCatch.get(device.getDeviceId())); |
| 126 | + if (!resetChannelsResult) { | ||
| 127 | + String errorMsg = "接收成功,写入失败,共" + sumNum + "条,已接收" + catalogDataCatch.get(device.getDeviceId()).size() + "条"; | ||
| 128 | + catalogDataCatch.setChannelSyncEnd(device.getDeviceId(), errorMsg); | ||
| 138 | }else { | 129 | }else { |
| 139 | - result.setMsg("接收成功,写入失败,共" + sumNum + "条,已接收" + catalogDataCatch.get(key).size() + "条"); | 130 | + catalogDataCatch.setChannelSyncEnd(device.getDeviceId(), null); |
| 140 | } | 131 | } |
| 141 | - msg.setData(result); | ||
| 142 | - deferredResultHolder.invokeAllResult(msg); | ||
| 143 | - catalogDataCatch.del(key); | ||
| 144 | } | 132 | } |
| 145 | } | 133 | } |
| 146 | // 回复200 OK | 134 | // 回复200 OK |
| 147 | responseAck(evt, Response.OK); | 135 | responseAck(evt, Response.OK); |
| 148 | - if (offLineDetector.isOnline(device.getDeviceId())) { | ||
| 149 | - publisher.onlineEventPublish(device, VideoManagerConstants.EVENT_ONLINE_MESSAGE); | ||
| 150 | - } | ||
| 151 | } | 136 | } |
| 152 | } catch (DocumentException e) { | 137 | } catch (DocumentException e) { |
| 153 | e.printStackTrace(); | 138 | e.printStackTrace(); |
| @@ -231,21 +216,18 @@ public class CatalogResponseMessageHandler extends SIPRequestProcessorParent imp | @@ -231,21 +216,18 @@ public class CatalogResponseMessageHandler extends SIPRequestProcessorParent imp | ||
| 231 | } | 216 | } |
| 232 | 217 | ||
| 233 | public SyncStatus getChannelSyncProgress(String deviceId) { | 218 | public SyncStatus getChannelSyncProgress(String deviceId) { |
| 234 | - String key = DeferredResultHolder.CALLBACK_CMD_CATALOG + deviceId; | ||
| 235 | - if (catalogDataCatch.get(key) == null) { | 219 | + if (catalogDataCatch.get(deviceId) == null) { |
| 236 | return null; | 220 | return null; |
| 237 | }else { | 221 | }else { |
| 238 | - return catalogDataCatch.getSyncStatus(key); | 222 | + return catalogDataCatch.getSyncStatus(deviceId); |
| 239 | } | 223 | } |
| 240 | } | 224 | } |
| 241 | 225 | ||
| 242 | - public void setChannelSyncReady(String deviceId) { | ||
| 243 | - String key = DeferredResultHolder.CALLBACK_CMD_CATALOG + deviceId; | ||
| 244 | - catalogDataCatch.addReady(key); | 226 | + public void setChannelSyncReady(Device device, int sn) { |
| 227 | + catalogDataCatch.addReady(device, sn); | ||
| 245 | } | 228 | } |
| 246 | 229 | ||
| 247 | public void setChannelSyncEnd(String deviceId, String errorMsg) { | 230 | public void setChannelSyncEnd(String deviceId, String errorMsg) { |
| 248 | - String key = DeferredResultHolder.CALLBACK_CMD_CATALOG + deviceId; | ||
| 249 | - catalogDataCatch.setChannelSyncEnd(key, errorMsg); | 231 | + catalogDataCatch.setChannelSyncEnd(deviceId, errorMsg); |
| 250 | } | 232 | } |
| 251 | } | 233 | } |
src/main/java/com/genersoft/iot/vmp/service/IDeviceService.java
| @@ -44,15 +44,8 @@ public interface IDeviceService { | @@ -44,15 +44,8 @@ public interface IDeviceService { | ||
| 44 | SyncStatus getChannelSyncStatus(String deviceId); | 44 | SyncStatus getChannelSyncStatus(String deviceId); |
| 45 | 45 | ||
| 46 | /** | 46 | /** |
| 47 | - * 设置通道同步状态 | ||
| 48 | - * @param deviceId 设备ID | ||
| 49 | - */ | ||
| 50 | - void setChannelSyncReady(String deviceId); | ||
| 51 | - | ||
| 52 | - /** | ||
| 53 | - * 设置同步结束 | ||
| 54 | - * @param deviceId 设备ID | ||
| 55 | - * @param errorMsg 错误信息 | 47 | + * 通道同步 |
| 48 | + * @param device | ||
| 56 | */ | 49 | */ |
| 57 | - void setChannelSyncEnd(String deviceId, String errorMsg); | 50 | + void sync(Device device); |
| 58 | } | 51 | } |
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 | } |
| @@ -102,12 +100,16 @@ public class DeviceServiceImpl implements IDeviceService { | @@ -102,12 +100,16 @@ public class DeviceServiceImpl implements IDeviceService { | ||
| 102 | } | 100 | } |
| 103 | 101 | ||
| 104 | @Override | 102 | @Override |
| 105 | - public void setChannelSyncReady(String deviceId) { | ||
| 106 | - catalogResponseMessageHandler.setChannelSyncReady(deviceId); | ||
| 107 | - } | ||
| 108 | - | ||
| 109 | - @Override | ||
| 110 | - public void setChannelSyncEnd(String deviceId, String errorMsg) { | ||
| 111 | - catalogResponseMessageHandler.setChannelSyncEnd(deviceId, errorMsg); | 103 | + public void sync(Device device) { |
| 104 | + if (catalogResponseMessageHandler.getChannelSyncProgress(device.getDeviceId()) != null) { | ||
| 105 | + logger.info("开启同步时发现同步已经存在"); | ||
| 106 | + return; | ||
| 107 | + } | ||
| 108 | + int sn = (int)((Math.random()*9+1)*100000); | ||
| 109 | + catalogResponseMessageHandler.setChannelSyncReady(device, sn); | ||
| 110 | + sipCommander.catalogQuery(device, sn, event -> { | ||
| 111 | + String errorMsg = String.format("同步通道失败,错误码: %s, %s", event.statusCode, event.msg); | ||
| 112 | + catalogResponseMessageHandler.setChannelSyncEnd(device.getDeviceId(), errorMsg); | ||
| 113 | + }); | ||
| 112 | } | 114 | } |
| 113 | } | 115 | } |
src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStorageImpl.java
| @@ -238,12 +238,15 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage { | @@ -238,12 +238,15 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage { | ||
| 238 | 238 | ||
| 239 | @Override | 239 | @Override |
| 240 | public boolean resetChannels(String deviceId, List<DeviceChannel> deviceChannelList) { | 240 | public boolean resetChannels(String deviceId, List<DeviceChannel> deviceChannelList) { |
| 241 | + if (deviceChannelList == null) { | ||
| 242 | + return false; | ||
| 243 | + } | ||
| 241 | TransactionStatus transactionStatus = dataSourceTransactionManager.getTransaction(transactionDefinition); | 244 | TransactionStatus transactionStatus = dataSourceTransactionManager.getTransaction(transactionDefinition); |
| 242 | // 数据去重 | 245 | // 数据去重 |
| 243 | List<DeviceChannel> channels = new ArrayList<>(); | 246 | List<DeviceChannel> channels = new ArrayList<>(); |
| 244 | StringBuilder stringBuilder = new StringBuilder(); | 247 | StringBuilder stringBuilder = new StringBuilder(); |
| 245 | Map<String, Integer> subContMap = new HashMap<>(); | 248 | Map<String, Integer> subContMap = new HashMap<>(); |
| 246 | - if (deviceChannelList.size() > 1) { | 249 | + if (deviceChannelList != null && deviceChannelList.size() > 1) { |
| 247 | // 数据去重 | 250 | // 数据去重 |
| 248 | Set<String> gbIdSet = new HashSet<>(); | 251 | Set<String> gbIdSet = new HashSet<>(); |
| 249 | for (DeviceChannel deviceChannel : deviceChannelList) { | 252 | for (DeviceChannel deviceChannel : deviceChannelList) { |
| @@ -300,6 +303,7 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage { | @@ -300,6 +303,7 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage { | ||
| 300 | dataSourceTransactionManager.commit(transactionStatus); //手动提交 | 303 | dataSourceTransactionManager.commit(transactionStatus); //手动提交 |
| 301 | return true; | 304 | return true; |
| 302 | }catch (Exception e) { | 305 | }catch (Exception e) { |
| 306 | + e.printStackTrace(); | ||
| 303 | dataSourceTransactionManager.rollback(transactionStatus); | 307 | dataSourceTransactionManager.rollback(transactionStatus); |
| 304 | return false; | 308 | return false; |
| 305 | } | 309 | } |
| @@ -415,10 +419,9 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage { | @@ -415,10 +419,9 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage { | ||
| 415 | TransactionStatus transactionStatus = dataSourceTransactionManager.getTransaction(transactionDefinition); | 419 | TransactionStatus transactionStatus = dataSourceTransactionManager.getTransaction(transactionDefinition); |
| 416 | boolean result = false; | 420 | boolean result = false; |
| 417 | try { | 421 | try { |
| 418 | - if (platformChannelMapper.delChannelForDeviceId(deviceId) <0 // 删除与国标平台的关联 | ||
| 419 | - || deviceChannelMapper.cleanChannelsByDeviceId(deviceId) < 0 // 删除他的通道 | ||
| 420 | - || deviceMapper.del(deviceId) < 0 // 移除设备信息 | ||
| 421 | - ) { | 422 | + platformChannelMapper.delChannelForDeviceId(deviceId); |
| 423 | + deviceChannelMapper.cleanChannelsByDeviceId(deviceId); | ||
| 424 | + if ( deviceMapper.del(deviceId) < 0 ) { | ||
| 422 | //事务回滚 | 425 | //事务回滚 |
| 423 | dataSourceTransactionManager.rollback(transactionStatus); | 426 | dataSourceTransactionManager.rollback(transactionStatus); |
| 424 | } | 427 | } |
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceQuery.java
| @@ -4,8 +4,13 @@ import com.alibaba.fastjson.JSONObject; | @@ -4,8 +4,13 @@ import com.alibaba.fastjson.JSONObject; | ||
| 4 | import com.genersoft.iot.vmp.conf.DynamicTask; | 4 | import com.genersoft.iot.vmp.conf.DynamicTask; |
| 5 | import com.genersoft.iot.vmp.gb28181.bean.Device; | 5 | 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.bean.SubscribeHolder; | ||
| 7 | import com.genersoft.iot.vmp.gb28181.bean.SyncStatus; | 8 | import com.genersoft.iot.vmp.gb28181.bean.SyncStatus; |
| 8 | import com.genersoft.iot.vmp.gb28181.event.DeviceOffLineDetector; | 9 | import com.genersoft.iot.vmp.gb28181.event.DeviceOffLineDetector; |
| 10 | +import com.genersoft.iot.vmp.gb28181.task.ISubscribeTask; | ||
| 11 | +import com.genersoft.iot.vmp.gb28181.task.impl.CatalogSubscribeTask; | ||
| 12 | +import com.genersoft.iot.vmp.gb28181.task.impl.MobilePositionSubscribeHandlerTask; | ||
| 13 | +import com.genersoft.iot.vmp.gb28181.task.impl.MobilePositionSubscribeTask; | ||
| 9 | import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; | 14 | import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; |
| 10 | import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; | 15 | import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; |
| 11 | import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; | 16 | import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; |
| @@ -29,9 +34,8 @@ import org.springframework.util.StringUtils; | @@ -29,9 +34,8 @@ import org.springframework.util.StringUtils; | ||
| 29 | import org.springframework.web.bind.annotation.*; | 34 | import org.springframework.web.bind.annotation.*; |
| 30 | import org.springframework.web.context.request.async.DeferredResult; | 35 | import org.springframework.web.context.request.async.DeferredResult; |
| 31 | 36 | ||
| 32 | -import java.util.List; | ||
| 33 | -import java.util.Set; | ||
| 34 | -import java.util.UUID; | 37 | +import javax.sip.DialogState; |
| 38 | +import java.util.*; | ||
| 35 | 39 | ||
| 36 | @Api(tags = "国标设备查询", value = "国标设备查询") | 40 | @Api(tags = "国标设备查询", value = "国标设备查询") |
| 37 | @SuppressWarnings("rawtypes") | 41 | @SuppressWarnings("rawtypes") |
| @@ -63,6 +67,9 @@ public class DeviceQuery { | @@ -63,6 +67,9 @@ public class DeviceQuery { | ||
| 63 | @Autowired | 67 | @Autowired |
| 64 | private DynamicTask dynamicTask; | 68 | private DynamicTask dynamicTask; |
| 65 | 69 | ||
| 70 | + @Autowired | ||
| 71 | + private SubscribeHolder subscribeHolder; | ||
| 72 | + | ||
| 66 | /** | 73 | /** |
| 67 | * 使用ID查询国标设备 | 74 | * 使用ID查询国标设备 |
| 68 | * @param deviceId 国标ID | 75 | * @param deviceId 国标ID |
| @@ -165,12 +172,8 @@ public class DeviceQuery { | @@ -165,12 +172,8 @@ public class DeviceQuery { | ||
| 165 | wvpResult.setData(syncStatus); | 172 | wvpResult.setData(syncStatus); |
| 166 | return wvpResult; | 173 | return wvpResult; |
| 167 | } | 174 | } |
| 168 | - SyncStatus syncStatusReady = new SyncStatus(); | ||
| 169 | - deviceService.setChannelSyncReady(deviceId); | ||
| 170 | - cmder.catalogQuery(device, event -> { | ||
| 171 | - String errorMsg = String.format("同步通道失败,错误码: %s, %s", event.statusCode, event.msg); | ||
| 172 | - deviceService.setChannelSyncEnd(deviceId, errorMsg); | ||
| 173 | - }); | 175 | + deviceService.sync(device); |
| 176 | + | ||
| 174 | WVPResult<SyncStatus> wvpResult = new WVPResult<>(); | 177 | WVPResult<SyncStatus> wvpResult = new WVPResult<>(); |
| 175 | wvpResult.setCode(0); | 178 | wvpResult.setCode(0); |
| 176 | wvpResult.setMsg("开始同步"); | 179 | wvpResult.setMsg("开始同步"); |
| @@ -469,4 +472,29 @@ public class DeviceQuery { | @@ -469,4 +472,29 @@ public class DeviceQuery { | ||
| 469 | } | 472 | } |
| 470 | return wvpResult; | 473 | return wvpResult; |
| 471 | } | 474 | } |
| 475 | + | ||
| 476 | + @GetMapping("/{deviceId}/subscribe_info") | ||
| 477 | + @ApiOperation(value = "获取设备的订阅状态", notes = "获取设备的订阅状态") | ||
| 478 | + public WVPResult<Map<String, String>> getSubscribeInfo(@PathVariable String deviceId) { | ||
| 479 | + Set<String> allKeys = dynamicTask.getAllKeys(); | ||
| 480 | + Map<String, String> dialogStateMap = new HashMap<>(); | ||
| 481 | + for (String key : allKeys) { | ||
| 482 | + if (key.startsWith(deviceId)) { | ||
| 483 | + ISubscribeTask subscribeTask = (ISubscribeTask)dynamicTask.get(key); | ||
| 484 | + DialogState dialogState = subscribeTask.getDialogState(); | ||
| 485 | + if (dialogState == null) { | ||
| 486 | + continue; | ||
| 487 | + } | ||
| 488 | + if (subscribeTask instanceof CatalogSubscribeTask) { | ||
| 489 | + dialogStateMap.put("catalog", dialogState.toString()); | ||
| 490 | + }else if (subscribeTask instanceof MobilePositionSubscribeTask) { | ||
| 491 | + dialogStateMap.put("mobilePosition", dialogState.toString()); | ||
| 492 | + } | ||
| 493 | + } | ||
| 494 | + } | ||
| 495 | + WVPResult<Map<String, String>> wvpResult = new WVPResult<>(); | ||
| 496 | + wvpResult.setCode(0); | ||
| 497 | + wvpResult.setData(dialogStateMap); | ||
| 498 | + return wvpResult; | ||
| 499 | + } | ||
| 472 | } | 500 | } |
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 | } |
web_src/src/components/dialog/SyncChannelProgress.vue
| @@ -61,23 +61,36 @@ export default { | @@ -61,23 +61,36 @@ export default { | ||
| 61 | if (!this.syncFlag) { | 61 | if (!this.syncFlag) { |
| 62 | this.syncFlag = true; | 62 | this.syncFlag = true; |
| 63 | } | 63 | } |
| 64 | - if (res.data.data == null) { | ||
| 65 | - this.syncStatus = "success" | ||
| 66 | - this.percentage = 100; | ||
| 67 | - this.msg = '同步成功'; | ||
| 68 | - }else if (res.data.data.total == 0){ | ||
| 69 | - this.msg = `等待同步中`; | ||
| 70 | - this.timmer = setTimeout(this.getProgress, 300) | ||
| 71 | - }else if (res.data.data.errorMsg !== null ){ | ||
| 72 | - this.msg = res.data.data.errorMsg; | ||
| 73 | - this.syncStatus = "exception" | ||
| 74 | - }else { | ||
| 75 | - this.total = res.data.data.total; | ||
| 76 | - this.current = res.data.data.current; | ||
| 77 | - this.percentage = Math.floor(Number(res.data.data.current)/Number(res.data.data.total)* 10000)/100; | ||
| 78 | - this.msg = `同步中...[${res.data.data.current}/${res.data.data.total}]`; | ||
| 79 | - this.timmer = setTimeout(this.getProgress, 300) | 64 | + |
| 65 | + if (res.data.data != null) { | ||
| 66 | + if (res.data.data.total == 0) { | ||
| 67 | + if (res.data.data.errorMsg !== null ){ | ||
| 68 | + this.msg = res.data.data.errorMsg; | ||
| 69 | + this.syncStatus = "exception" | ||
| 70 | + }else { | ||
| 71 | + this.msg = `等待同步中`; | ||
| 72 | + this.timmer = setTimeout(this.getProgress, 300) | ||
| 73 | + } | ||
| 74 | + }else { | ||
| 75 | + if (res.data.data.total == res.data.data.current) { | ||
| 76 | + this.syncStatus = "success" | ||
| 77 | + this.percentage = 100; | ||
| 78 | + this.msg = '同步成功'; | ||
| 79 | + }else { | ||
| 80 | + if (res.data.data.errorMsg !== null ){ | ||
| 81 | + this.msg = res.data.data.errorMsg; | ||
| 82 | + this.syncStatus = "exception" | ||
| 83 | + }else { | ||
| 84 | + this.total = res.data.data.total; | ||
| 85 | + this.current = res.data.data.current; | ||
| 86 | + this.percentage = Math.floor(Number(res.data.data.current)/Number(res.data.data.total)* 10000)/100; | ||
| 87 | + this.msg = `同步中...[${res.data.data.current}/${res.data.data.total}]`; | ||
| 88 | + this.timmer = setTimeout(this.getProgress, 300) | ||
| 89 | + } | ||
| 90 | + } | ||
| 91 | + } | ||
| 80 | } | 92 | } |
| 93 | + | ||
| 81 | }else { | 94 | }else { |
| 82 | if (this.syncFlag) { | 95 | if (this.syncFlag) { |
| 83 | this.syncStatus = "success" | 96 | this.syncStatus = "success" |