Commit 40a806329ce08d5f50795cf965ef773aa48fdd3e

Authored by 648540858
2 parents ba8633e9 e6ee7fe7

Merge remote-tracking branch 'origin/wvp-28181-2.0' into map

# Conflicts:
#	src/main/java/com/genersoft/iot/vmp/gb28181/event/subscribe/SubscribeListenerForPlatform.java
Showing 39 changed files with 1024 additions and 340 deletions
README.md
@@ -130,5 +130,14 @@ QQ私信一般不回, 精力有限.欢迎大家在群里讨论.觉得项目对 @@ -130,5 +130,14 @@ QQ私信一般不回, 精力有限.欢迎大家在群里讨论.觉得项目对
130 130
131 131
132 # 致谢 132 # 致谢
133 -感谢作者[夏楚](https://github.com/xia-chu) 提供这么棒的开源流媒体服务框架 133 +感谢作者[夏楚](https://github.com/xia-chu) 提供这么棒的开源流媒体服务框架,并在开发过程中给予支持与帮助。
  134 +感谢作者[dexter langhuihui](https://github.com/langhuihui) 开源这么好用的WEB播放器。
  135 +感谢作者[Kyle](https://gitee.com/kkkkk5G) 开源了好用的前端页面
  136 +感谢各位大佬的赞助以及对项目的指正与帮助。包括但不限于代码贡献、问题反馈、资金捐赠等各种方式的支持!以下排名不分先后:
  137 +[lawrencehj](https://github.com/lawrencehj) @陆丰-创奇科技 [swwhaha](https://github.com/swwheihei)
  138 +[hotcoffie](https://github.com/hotcoffie) [xiaomu](https://github.com/nikmu) [TristingChen](https://github.com/TristingChen)
  139 +[chenparty](https://github.com/chenparty) [Hotleave](https://github.com/hotleave) [ydwxb](https://github.com/ydwxb)
  140 +[ydpd](https://github.com/ydpd) [szy833](https://github.com/szy833) [ydwxb](https://github.com/ydwxb)
  141 +
  142 +ps: 刚增加了这个名单,肯定遗漏了一些大佬,欢迎大佬联系我添加。
134 143
src/main/java/com/genersoft/iot/vmp/common/VideoManagerConstants.java
@@ -22,6 +22,9 @@ public class VideoManagerConstants { @@ -22,6 +22,9 @@ public class VideoManagerConstants {
22 22
23 public static final String DEVICE_PREFIX = "VMP_DEVICE_"; 23 public static final String DEVICE_PREFIX = "VMP_DEVICE_";
24 24
  25 + // 设备同步完成
  26 + public static final String DEVICE_SYNC_PREFIX = "VMP_DEVICE_SYNC_";
  27 +
25 public static final String CACHEKEY_PREFIX = "VMP_CHANNEL_"; 28 public static final String CACHEKEY_PREFIX = "VMP_CHANNEL_";
26 29
27 public static final String KEEPLIVEKEY_PREFIX = "VMP_KEEPALIVE_"; 30 public static final String KEEPLIVEKEY_PREFIX = "VMP_KEEPALIVE_";
@@ -69,6 +72,7 @@ public class VideoManagerConstants { @@ -69,6 +72,7 @@ public class VideoManagerConstants {
69 72
70 public static final String SYSTEM_INFO_NET_PREFIX = "VMP_SYSTEM_INFO_NET_"; 73 public static final String SYSTEM_INFO_NET_PREFIX = "VMP_SYSTEM_INFO_NET_";
71 74
  75 +
72 //************************** redis 消息********************************* 76 //************************** redis 消息*********************************
73 77
74 // 流变化的通知 78 // 流变化的通知
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 /**
@@ -53,13 +76,31 @@ public class DynamicTask { @@ -53,13 +76,31 @@ public class DynamicTask {
53 */ 76 */
54 public void startDelay(String key, Runnable task, int delay) { 77 public void startDelay(String key, Runnable task, int delay) {
55 stop(key); 78 stop(key);
  79 + System.out.println("定时任务开始了");
56 Date starTime = new Date(System.currentTimeMillis() + delay); 80 Date starTime = new Date(System.currentTimeMillis() + delay);
  81 +
  82 + ScheduledFuture future = futureMap.get(key);
  83 + if (future != null) {
  84 + if (future.isCancelled()) {
  85 + logger.info("任务【{}】已存在但是关闭状态!!!", key);
  86 + } else {
  87 + logger.info("任务【{}】已存在且已启动!!!", key);
  88 + return;
  89 + }
  90 + }
57 // scheduleWithFixedDelay 必须等待上一个任务结束才开始计时period, cycleForCatalog表示执行的间隔 91 // scheduleWithFixedDelay 必须等待上一个任务结束才开始计时period, cycleForCatalog表示执行的间隔
58 - ScheduledFuture future = threadPoolTaskScheduler.schedule(task, starTime);  
59 - futureMap.put(key, future); 92 + future = threadPoolTaskScheduler.schedule(task, starTime);
  93 + if (future != null){
  94 + futureMap.put(key, future);
  95 + runnableMap.put(key, task);
  96 + logger.info("任务【{}】启动成功!!!", key);
  97 + }else {
  98 + logger.info("任务【{}】启动失败!!!", key);
  99 + }
60 } 100 }
61 101
62 public void stop(String key) { 102 public void stop(String key) {
  103 + System.out.println("定时任务结束了");
63 if (futureMap.get(key) != null && !futureMap.get(key).isCancelled()) { 104 if (futureMap.get(key) != null && !futureMap.get(key).isCancelled()) {
64 futureMap.get(key).cancel(true); 105 futureMap.get(key).cancel(true);
65 Runnable runnable = runnableMap.get(key); 106 Runnable runnable = runnableMap.get(key);
@@ -78,4 +119,7 @@ public class DynamicTask { @@ -78,4 +119,7 @@ public class DynamicTask {
78 return futureMap.keySet(); 119 return futureMap.keySet();
79 } 120 }
80 121
  122 + public Runnable get(String key) {
  123 + return runnableMap.get(key);
  124 + }
81 } 125 }
src/main/java/com/genersoft/iot/vmp/gb28181/bean/CatalogData.java
@@ -8,6 +8,12 @@ public class CatalogData { @@ -8,6 +8,12 @@ public class CatalogData {
8 private List<DeviceChannel> channelList; 8 private List<DeviceChannel> channelList;
9 private Date lastTime; 9 private Date lastTime;
10 private Device device; 10 private Device device;
  11 + private String errorMsg;
  12 +
  13 + public enum CatalogDataStatus{
  14 + ready, runIng, end
  15 + }
  16 + private CatalogDataStatus status;
11 17
12 public int getTotal() { 18 public int getTotal() {
13 return total; 19 return total;
@@ -40,4 +46,20 @@ public class CatalogData { @@ -40,4 +46,20 @@ public class CatalogData {
40 public void setDevice(Device device) { 46 public void setDevice(Device device) {
41 this.device = device; 47 this.device = device;
42 } 48 }
  49 +
  50 + public String getErrorMsg() {
  51 + return errorMsg;
  52 + }
  53 +
  54 + public void setErrorMsg(String errorMsg) {
  55 + this.errorMsg = errorMsg;
  56 + }
  57 +
  58 + public CatalogDataStatus getStatus() {
  59 + return status;
  60 + }
  61 +
  62 + public void setStatus(CatalogDataStatus status) {
  63 + this.status = status;
  64 + }
43 } 65 }
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/bean/SyncStatus.java 0 → 100644
  1 +package com.genersoft.iot.vmp.gb28181.bean;
  2 +
  3 +/**
  4 + * 摄像机同步状态
  5 + */
  6 +public class SyncStatus {
  7 + private int total;
  8 + private int current;
  9 + private String errorMsg;
  10 +
  11 + public int getTotal() {
  12 + return total;
  13 + }
  14 +
  15 + public void setTotal(int total) {
  16 + this.total = total;
  17 + }
  18 +
  19 + public int getCurrent() {
  20 + return current;
  21 + }
  22 +
  23 + public void setCurrent(int current) {
  24 + this.current = current;
  25 + }
  26 +
  27 + public String getErrorMsg() {
  28 + return errorMsg;
  29 + }
  30 +
  31 + public void setErrorMsg(String errorMsg) {
  32 + this.errorMsg = errorMsg;
  33 + }
  34 +}
src/main/java/com/genersoft/iot/vmp/gb28181/event/online/OnlineEventListener.java
@@ -95,11 +95,12 @@ public class OnlineEventListener implements ApplicationListener&lt;OnlineEvent&gt; { @@ -95,11 +95,12 @@ public class OnlineEventListener implements ApplicationListener&lt;OnlineEvent&gt; {
95 } 95 }
96 // 处理上线监听 96 // 处理上线监听
97 storager.updateDevice(device); 97 storager.updateDevice(device);
98 - List<DeviceChannel> deviceChannelList = storager.queryOnlineChannelsByDeviceId(device.getDeviceId());  
99 - eventPublisher.catalogEventPublish(null, deviceChannelList, CatalogEvent.ON);  
100 // 上线添加订阅 98 // 上线添加订阅
101 if (device.getSubscribeCycleForCatalog() > 0) { 99 if (device.getSubscribeCycleForCatalog() > 0) {
  100 + // 查询在线设备那些开启了订阅,为设备开启定时的目录订阅
102 deviceService.addCatalogSubscribe(device); 101 deviceService.addCatalogSubscribe(device);
  102 + }
  103 + if (device.getSubscribeCycleForMobilePosition() > 0) {
103 deviceService.addMobilePositionSubscribe(device); 104 deviceService.addMobilePositionSubscribe(device);
104 } 105 }
105 } 106 }
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 - // 订阅到期  
43 - String PLATFORM_KEEPLIVEKEY_PREFIX = VideoManagerConstants.SIP_SUBSCRIBE_PREFIX + userSetting.getServerId() + "_";  
44 - if (expiredKey.startsWith(PLATFORM_KEEPLIVEKEY_PREFIX)) {  
45 - // 取消定时任务  
46 - dynamicTask.stop(expiredKey);  
47 - }  
48 - }  
49 -}  
src/main/java/com/genersoft/iot/vmp/gb28181/event/subscribe/catalog/CatalogEventLister.java
@@ -61,8 +61,6 @@ public class CatalogEventLister implements ApplicationListener&lt;CatalogEvent&gt; { @@ -61,8 +61,6 @@ public class CatalogEventLister implements ApplicationListener&lt;CatalogEvent&gt; {
61 if (event.getPlatformId() != null) { 61 if (event.getPlatformId() != null) {
62 parentPlatform = storager.queryParentPlatByServerGBId(event.getPlatformId()); 62 parentPlatform = storager.queryParentPlatByServerGBId(event.getPlatformId());
63 if (parentPlatform != null && !parentPlatform.isStatus())return; 63 if (parentPlatform != null && !parentPlatform.isStatus())return;
64 - String key = VideoManagerConstants.SIP_SUBSCRIBE_PREFIX + userSetting.getServerId() + "_Catalog_" + event.getPlatformId();  
65 -// subscribe = redisCatchStorage.getSubscribe(key);  
66 subscribe = subscribeHolder.getCatalogSubscribe(event.getPlatformId()); 64 subscribe = subscribeHolder.getCatalogSubscribe(event.getPlatformId());
67 65
68 if (subscribe == null) { 66 if (subscribe == null) {
src/main/java/com/genersoft/iot/vmp/gb28181/session/CatalogDataCatch.java
@@ -3,6 +3,7 @@ package com.genersoft.iot.vmp.gb28181.session; @@ -3,6 +3,7 @@ package com.genersoft.iot.vmp.gb28181.session;
3 import com.genersoft.iot.vmp.gb28181.bean.CatalogData; 3 import com.genersoft.iot.vmp.gb28181.bean.CatalogData;
4 import com.genersoft.iot.vmp.gb28181.bean.Device; 4 import com.genersoft.iot.vmp.gb28181.bean.Device;
5 import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; 5 import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
  6 +import com.genersoft.iot.vmp.gb28181.bean.SyncStatus;
6 import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; 7 import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
7 import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; 8 import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
8 import com.genersoft.iot.vmp.storager.IVideoManagerStorage; 9 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
@@ -25,6 +26,17 @@ public class CatalogDataCatch { @@ -25,6 +26,17 @@ public class CatalogDataCatch {
25 @Autowired 26 @Autowired
26 private IVideoManagerStorage storager; 27 private IVideoManagerStorage storager;
27 28
  29 + public void addReady(String key) {
  30 + CatalogData catalogData = data.get(key);
  31 + if (catalogData == null || catalogData.getStatus().equals(CatalogData.CatalogDataStatus.end)) {
  32 + catalogData = new CatalogData();
  33 + catalogData.setChannelList(new ArrayList<>());
  34 + catalogData.setStatus(CatalogData.CatalogDataStatus.ready);
  35 + catalogData.setLastTime(new Date(System.currentTimeMillis()));
  36 + data.put(key, catalogData);
  37 + }
  38 + }
  39 +
28 public void put(String key, int total, Device device, List<DeviceChannel> deviceChannelList) { 40 public void put(String key, int total, Device device, List<DeviceChannel> deviceChannelList) {
29 CatalogData catalogData = data.get(key); 41 CatalogData catalogData = data.get(key);
30 if (catalogData == null) { 42 if (catalogData == null) {
@@ -32,10 +44,16 @@ public class CatalogDataCatch { @@ -32,10 +44,16 @@ public class CatalogDataCatch {
32 catalogData.setTotal(total); 44 catalogData.setTotal(total);
33 catalogData.setDevice(device); 45 catalogData.setDevice(device);
34 catalogData.setChannelList(new ArrayList<>()); 46 catalogData.setChannelList(new ArrayList<>());
  47 + catalogData.setStatus(CatalogData.CatalogDataStatus.runIng);
  48 + catalogData.setLastTime(new Date(System.currentTimeMillis()));
35 data.put(key, catalogData); 49 data.put(key, catalogData);
  50 + }else {
  51 + catalogData.setTotal(total);
  52 + catalogData.setDevice(device);
  53 + catalogData.setStatus(CatalogData.CatalogDataStatus.runIng);
  54 + catalogData.getChannelList().addAll(deviceChannelList);
  55 + catalogData.setLastTime(new Date(System.currentTimeMillis()));
36 } 56 }
37 - catalogData.getChannelList().addAll(deviceChannelList);  
38 - catalogData.setLastTime(new Date(System.currentTimeMillis()));  
39 } 57 }
40 58
41 public List<DeviceChannel> get(String key) { 59 public List<DeviceChannel> get(String key) {
@@ -44,6 +62,22 @@ public class CatalogDataCatch { @@ -44,6 +62,22 @@ public class CatalogDataCatch {
44 return catalogData.getChannelList(); 62 return catalogData.getChannelList();
45 } 63 }
46 64
  65 + public int getTotal(String key) {
  66 + CatalogData catalogData = data.get(key);
  67 + if (catalogData == null) return 0;
  68 + return catalogData.getTotal();
  69 + }
  70 +
  71 + public SyncStatus getSyncStatus(String key) {
  72 + CatalogData catalogData = data.get(key);
  73 + if (catalogData == null) return null;
  74 + SyncStatus syncStatus = new SyncStatus();
  75 + syncStatus.setCurrent(catalogData.getChannelList().size());
  76 + syncStatus.setTotal(catalogData.getTotal());
  77 + syncStatus.setErrorMsg(catalogData.getErrorMsg());
  78 + return syncStatus;
  79 + }
  80 +
47 public void del(String key) { 81 public void del(String key) {
48 data.remove(key); 82 data.remove(key);
49 } 83 }
@@ -51,24 +85,32 @@ public class CatalogDataCatch { @@ -51,24 +85,32 @@ public class CatalogDataCatch {
51 @Scheduled(fixedRate = 5 * 1000) //每5秒执行一次, 发现数据5秒未更新则移除数据并认为数据接收超时 85 @Scheduled(fixedRate = 5 * 1000) //每5秒执行一次, 发现数据5秒未更新则移除数据并认为数据接收超时
52 private void timerTask(){ 86 private void timerTask(){
53 Set<String> keys = data.keySet(); 87 Set<String> keys = data.keySet();
54 - Calendar calendar = Calendar.getInstance();  
55 - calendar.setTime(new Date());  
56 - calendar.set(Calendar.SECOND, calendar.get(Calendar.SECOND) - 5); 88 + Calendar calendarBefore5S = Calendar.getInstance();
  89 + calendarBefore5S.setTime(new Date());
  90 + calendarBefore5S.set(Calendar.SECOND, calendarBefore5S.get(Calendar.SECOND) - 5);
  91 +
  92 + Calendar calendarBefore30S = Calendar.getInstance();
  93 + calendarBefore30S.setTime(new Date());
  94 + calendarBefore30S.set(Calendar.SECOND, calendarBefore30S.get(Calendar.SECOND) - 30);
57 for (String key : keys) { 95 for (String key : keys) {
58 CatalogData catalogData = data.get(key); 96 CatalogData catalogData = data.get(key);
59 - if (catalogData.getLastTime().before(calendar.getTime())) {  
60 - 97 + if (catalogData.getLastTime().before(calendarBefore5S.getTime())) { // 超过五秒收不到消息任务超时, 只更新这一部分数据
61 storager.resetChannels(catalogData.getDevice().getDeviceId(), catalogData.getChannelList()); 98 storager.resetChannels(catalogData.getDevice().getDeviceId(), catalogData.getChannelList());
62 - RequestMessage msg = new RequestMessage();  
63 - msg.setKey(key);  
64 - WVPResult<Object> result = new WVPResult<>();  
65 - result.setCode(0);  
66 - result.setMsg("更新成功,共" + catalogData.getTotal() + "条,已更新" + catalogData.getChannelList().size() + "条");  
67 - result.setData(catalogData.getDevice());  
68 - msg.setData(result);  
69 - deferredResultHolder.invokeAllResult(msg); 99 + String errorMsg = "更新成功,共" + catalogData.getTotal() + "条,已更新" + catalogData.getChannelList().size() + "条";
  100 + catalogData.setStatus(CatalogData.CatalogDataStatus.end);
  101 + catalogData.setErrorMsg(errorMsg);
  102 + }
  103 + if (catalogData.getLastTime().before(calendarBefore30S.getTime())) { // 超过三十秒,如果标记为end则删除
70 data.remove(key); 104 data.remove(key);
71 } 105 }
72 } 106 }
73 } 107 }
  108 +
  109 +
  110 + public void setChannelSyncEnd(String key, String errorMsg) {
  111 + CatalogData catalogData = data.get(key);
  112 + if (catalogData == null)return;
  113 + catalogData.setStatus(CatalogData.CatalogDataStatus.end);
  114 + catalogData.setErrorMsg(errorMsg);
  115 + }
74 } 116 }
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,37 +42,45 @@ public class MobilePositionSubscribeHandlerTask implements ISubscribeTask { @@ -41,37 +42,45 @@ 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 + logger.info("执行MobilePositionSubscribeHandlerTask");
  46 + if (platform == null) return;
  47 + SubscribeInfo subscribe = subscribeHolder.getMobilePositionSubscribe(platform.getServerGBId());
46 if (subscribe != null) { 48 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 - } 49 +
  50 +// if (!parentPlatform.isStatus()) {
  51 +// logger.info("发送订阅时发现平台已经离线:{}", platformId);
  52 +// return;
  53 +// }
  54 + // TODO 暂时只处理视频流的回复,后续增加对国标设备的支持
  55 + List<GbStream> gbStreams = storager.queryGbStreamListInPlatform(platform.getServerGBId());
  56 + if (gbStreams.size() == 0) {
  57 + logger.info("发送订阅时发现平台已经没有关联的直播流:{}", platform.getServerGBId());
  58 + return;
  59 + }
  60 + for (GbStream gbStream : gbStreams) {
  61 + String gbId = gbStream.getGbId();
  62 + GPSMsgInfo gpsMsgInfo = redisCatchStorage.getGpsMsgInfo(gbId);
  63 + if (gpsMsgInfo != null) { // 无最新位置不发送
  64 + logger.info("无最新位置不发送");
  65 + // 经纬度都为0不发送
  66 + if (gpsMsgInfo.getLng() == 0 && gpsMsgInfo.getLat() == 0) {
  67 + continue;
67 } 68 }
  69 + // 发送GPS消息
  70 + sipCommanderForPlatform.sendNotifyMobilePosition(platform, gpsMsgInfo, subscribe);
68 } 71 }
69 } 72 }
70 } 73 }
  74 + logger.info("结束执行MobilePositionSubscribeHandlerTask");
71 } 75 }
72 76
73 @Override 77 @Override
74 public void stop() { 78 public void stop() {
75 79
76 } 80 }
  81 +
  82 + @Override
  83 + public DialogState getDialogState() {
  84 + return null;
  85 + }
77 } 86 }
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,8 +72,12 @@ public class MobilePositionSubscribeTask implements ISubscribeTask { @@ -56,8 +72,12 @@ public class MobilePositionSubscribeTask implements ISubscribeTask {
56 * COMPLETED-> Completed Dialog状态-已完成 72 * COMPLETED-> Completed Dialog状态-已完成
57 * TERMINATED-> Terminated Dialog状态-终止 73 * TERMINATED-> Terminated Dialog状态-终止
58 */ 74 */
59 - logger.info("取消移动订阅时dialog状态为{}", dialog.getState()); 75 + if (timer != null ) {
  76 + timer.cancel();
  77 + timer = null;
  78 + }
60 if (dialog != null && dialog.getState().equals(DialogState.CONFIRMED)) { 79 if (dialog != null && dialog.getState().equals(DialogState.CONFIRMED)) {
  80 + logger.info("取消移动订阅时dialog状态为{}", dialog.getState());
61 device.setSubscribeCycleForMobilePosition(0); 81 device.setSubscribeCycleForMobilePosition(0);
62 sipCommander.mobilePositionSubscribe(device, dialog, eventResult -> { 82 sipCommander.mobilePositionSubscribe(device, dialog, eventResult -> {
63 ResponseEvent event = (ResponseEvent) eventResult.event; 83 ResponseEvent event = (ResponseEvent) eventResult.event;
@@ -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/ISIPCommanderForPlatform.java
@@ -46,6 +46,7 @@ public interface ISIPCommanderForPlatform { @@ -46,6 +46,7 @@ public interface ISIPCommanderForPlatform {
46 * @return 46 * @return
47 */ 47 */
48 boolean catalogQuery(DeviceChannel channel, ParentPlatform parentPlatform, String sn, String fromTag, int size); 48 boolean catalogQuery(DeviceChannel channel, ParentPlatform parentPlatform, String sn, String fromTag, int size);
  49 + boolean catalogQuery(List<DeviceChannel> channels, ParentPlatform parentPlatform, String sn, String fromTag);
49 50
50 /** 51 /**
51 * 向上级回复DeviceInfo查询信息 52 * 向上级回复DeviceInfo查询信息
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
@@ -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
@@ -215,44 +215,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { @@ -215,44 +215,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
215 return false; 215 return false;
216 } 216 }
217 try { 217 try {
218 - String characterSet = parentPlatform.getCharacterSet();  
219 - StringBuffer catalogXml = new StringBuffer(600);  
220 - catalogXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet +"\"?>\r\n");  
221 - catalogXml.append("<Response>\r\n");  
222 - catalogXml.append("<CmdType>Catalog</CmdType>\r\n");  
223 - catalogXml.append("<SN>" +sn + "</SN>\r\n");  
224 - catalogXml.append("<DeviceID>" + parentPlatform.getDeviceGBId() + "</DeviceID>\r\n");  
225 - catalogXml.append("<SumNum>" + size + "</SumNum>\r\n");  
226 - catalogXml.append("<DeviceList Num=\"1\">\r\n");  
227 - catalogXml.append("<Item>\r\n");  
228 - if (channel != null) {  
229 - catalogXml.append("<DeviceID>" + channel.getChannelId() + "</DeviceID>\r\n");  
230 - catalogXml.append("<Name>" + channel.getName() + "</Name>\r\n");  
231 - catalogXml.append("<Manufacturer>" + channel.getManufacture() + "</Manufacturer>\r\n");  
232 - catalogXml.append("<Model>" + channel.getModel() + "</Model>\r\n");  
233 - catalogXml.append("<Owner>" + channel.getOwner() + "</Owner>\r\n");  
234 - catalogXml.append("<CivilCode>" + channel.getCivilCode() + "</CivilCode>\r\n");  
235 - catalogXml.append("<Address>" + channel.getAddress() + "</Address>\r\n");  
236 - catalogXml.append("<Parental>" + channel.getParental() + "</Parental>\r\n");  
237 - if (channel.getParentId() != null) {  
238 - catalogXml.append("<ParentID>" + channel.getParentId() + "</ParentID>\r\n");  
239 - }  
240 - catalogXml.append("<Secrecy>" + channel.getSecrecy() + "</Secrecy>\r\n");  
241 - catalogXml.append("<RegisterWay>" + channel.getRegisterWay() + "</RegisterWay>\r\n");  
242 - catalogXml.append("<Status>" + (channel.getStatus() == 0?"OFF":"ON") + "</Status>\r\n");  
243 - catalogXml.append("<Longitude>" + channel.getLongitude() + "</Longitude>\r\n");  
244 - catalogXml.append("<Latitude>" + channel.getLatitude() + "</Latitude>\r\n");  
245 - catalogXml.append("<IPAddress>" + channel.getIpAddress() + "</IPAddress>\r\n");  
246 - catalogXml.append("<Port>" + channel.getPort() + "</Port>\r\n");  
247 - catalogXml.append("<Info>\r\n");  
248 - catalogXml.append("<PTZType>" + channel.getPTZType() + "</PTZType>\r\n");  
249 - catalogXml.append("</Info>\r\n");  
250 - }  
251 -  
252 -  
253 - catalogXml.append("</Item>\r\n");  
254 - catalogXml.append("</DeviceList>\r\n");  
255 - catalogXml.append("</Response>\r\n"); 218 + String catalogXml = getCatalogXml(channel, sn, parentPlatform, size);
256 219
257 // callid 220 // callid
258 CallIdHeader callIdHeader = parentPlatform.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId() 221 CallIdHeader callIdHeader = parentPlatform.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
@@ -268,6 +231,77 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { @@ -268,6 +231,77 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
268 return true; 231 return true;
269 } 232 }
270 233
  234 + @Override
  235 + public boolean catalogQuery(List<DeviceChannel> channels, ParentPlatform parentPlatform, String sn, String fromTag) {
  236 + if ( parentPlatform ==null) {
  237 + return false;
  238 + }
  239 + sendCatalogResponse(channels, parentPlatform, sn, fromTag, 0);
  240 + return true;
  241 + }
  242 + private String getCatalogXml(DeviceChannel channel, String sn, ParentPlatform parentPlatform, int size) {
  243 + String characterSet = parentPlatform.getCharacterSet();
  244 + StringBuffer catalogXml = new StringBuffer(600);
  245 + catalogXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet +"\"?>\r\n");
  246 + catalogXml.append("<Response>\r\n");
  247 + catalogXml.append("<CmdType>Catalog</CmdType>\r\n");
  248 + catalogXml.append("<SN>" +sn + "</SN>\r\n");
  249 + catalogXml.append("<DeviceID>" + parentPlatform.getDeviceGBId() + "</DeviceID>\r\n");
  250 + catalogXml.append("<SumNum>" + size + "</SumNum>\r\n");
  251 + catalogXml.append("<DeviceList Num=\"1\">\r\n");
  252 + catalogXml.append("<Item>\r\n");
  253 + if (channel != null) {
  254 + catalogXml.append("<DeviceID>" + channel.getChannelId() + "</DeviceID>\r\n");
  255 + catalogXml.append("<Name>" + channel.getName() + "</Name>\r\n");
  256 + catalogXml.append("<Manufacturer>" + channel.getManufacture() + "</Manufacturer>\r\n");
  257 + catalogXml.append("<Model>" + channel.getModel() + "</Model>\r\n");
  258 + catalogXml.append("<Owner>" + channel.getOwner() + "</Owner>\r\n");
  259 + catalogXml.append("<CivilCode>" + channel.getCivilCode() + "</CivilCode>\r\n");
  260 + catalogXml.append("<Address>" + channel.getAddress() + "</Address>\r\n");
  261 + catalogXml.append("<Parental>" + channel.getParental() + "</Parental>\r\n");
  262 + if (channel.getParentId() != null) {
  263 + catalogXml.append("<ParentID>" + channel.getParentId() + "</ParentID>\r\n");
  264 + }
  265 + catalogXml.append("<Secrecy>" + channel.getSecrecy() + "</Secrecy>\r\n");
  266 + catalogXml.append("<RegisterWay>" + channel.getRegisterWay() + "</RegisterWay>\r\n");
  267 + catalogXml.append("<Status>" + (channel.getStatus() == 0?"OFF":"ON") + "</Status>\r\n");
  268 + catalogXml.append("<Longitude>" + channel.getLongitude() + "</Longitude>\r\n");
  269 + catalogXml.append("<Latitude>" + channel.getLatitude() + "</Latitude>\r\n");
  270 + catalogXml.append("<IPAddress>" + channel.getIpAddress() + "</IPAddress>\r\n");
  271 + catalogXml.append("<Port>" + channel.getPort() + "</Port>\r\n");
  272 + catalogXml.append("<Info>\r\n");
  273 + catalogXml.append("<PTZType>" + channel.getPTZType() + "</PTZType>\r\n");
  274 + catalogXml.append("</Info>\r\n");
  275 + }
  276 +
  277 +
  278 + catalogXml.append("</Item>\r\n");
  279 + catalogXml.append("</DeviceList>\r\n");
  280 + catalogXml.append("</Response>\r\n");
  281 + return catalogXml.toString();
  282 + }
  283 +
  284 + private void sendCatalogResponse(List<DeviceChannel> channels, ParentPlatform parentPlatform, String sn, String fromTag, int index) {
  285 + if (index >= channels.size()) {
  286 + return;
  287 + }
  288 + try {
  289 + DeviceChannel deviceChannel = channels.get(index);
  290 + String catalogXml = getCatalogXml(deviceChannel, sn, parentPlatform, channels.size());
  291 + // callid
  292 + CallIdHeader callIdHeader = parentPlatform.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
  293 + : udpSipProvider.getNewCallId();
  294 +
  295 + Request request = headerProviderPlarformProvider.createMessageRequest(parentPlatform, catalogXml, fromTag, callIdHeader);
  296 + transmitRequest(parentPlatform, request, null, eventResult -> {
  297 + int indexNext = index + 1;
  298 + sendCatalogResponse(channels, parentPlatform, sn, fromTag, indexNext);
  299 + });
  300 + } catch (SipException | ParseException | InvalidArgumentException e) {
  301 + e.printStackTrace();
  302 + }
  303 + }
  304 +
271 /** 305 /**
272 * 向上级回复DeviceInfo查询信息 306 * 向上级回复DeviceInfo查询信息
273 * @param parentPlatform 平台信息 307 * @param parentPlatform 平台信息
@@ -351,7 +385,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { @@ -351,7 +385,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
351 if (parentPlatform == null) { 385 if (parentPlatform == null) {
352 return false; 386 return false;
353 } 387 }
354 - 388 + logger.info("[发送 移动位置订阅] {}/{}->{},{}", parentPlatform.getServerGBId(), gpsMsgInfo.getId(), gpsMsgInfo.getLng(), gpsMsgInfo.getLat());
355 try { 389 try {
356 String characterSet = parentPlatform.getCharacterSet(); 390 String characterSet = parentPlatform.getCharacterSet();
357 StringBuffer deviceStatusXml = new StringBuffer(600); 391 StringBuffer deviceStatusXml = new StringBuffer(600);
@@ -371,7 +405,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { @@ -371,7 +405,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
371 CallIdHeader callIdHeader = parentPlatform.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId() 405 CallIdHeader callIdHeader = parentPlatform.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
372 : udpSipProvider.getNewCallId(); 406 : udpSipProvider.getNewCallId();
373 callIdHeader.setCallId(subscribeInfo.getCallId()); 407 callIdHeader.setCallId(subscribeInfo.getCallId());
374 - logger.info("[发送Notify-MobilePosition] {}/{}->{},{}", parentPlatform.getServerGBId(), gpsMsgInfo.getId(), gpsMsgInfo.getLng(), gpsMsgInfo.getLat()); 408 +
375 sendNotify(parentPlatform, deviceStatusXml.toString(), subscribeInfo, eventResult -> { 409 sendNotify(parentPlatform, deviceStatusXml.toString(), subscribeInfo, eventResult -> {
376 logger.error("发送NOTIFY通知消息失败。错误:{} {}", eventResult.statusCode, eventResult.msg); 410 logger.error("发送NOTIFY通知消息失败。错误:{} {}", eventResult.statusCode, eventResult.msg);
377 }, null); 411 }, null);
@@ -425,7 +459,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { @@ -425,7 +459,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
425 // 设置编码, 防止中文乱码 459 // 设置编码, 防止中文乱码
426 messageFactory.setDefaultContentEncodingCharset(characterSet); 460 messageFactory.setDefaultContentEncodingCharset(characterSet);
427 Dialog dialog = subscribeInfo.getDialog(); 461 Dialog dialog = subscribeInfo.getDialog();
428 - if (dialog == null) return; 462 + if (dialog == null || !dialog.getState().equals(DialogState.CONFIRMED)) return;
429 SIPRequest notifyRequest = (SIPRequest)dialog.createRequest(Request.NOTIFY); 463 SIPRequest notifyRequest = (SIPRequest)dialog.createRequest(Request.NOTIFY);
430 ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml"); 464 ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml");
431 notifyRequest.setContent(catalogXmlContent, contentTypeHeader); 465 notifyRequest.setContent(catalogXmlContent, contentTypeHeader);
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/NotifyRequestProcessor.java
@@ -147,7 +147,7 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements @@ -147,7 +147,7 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements
147 } else { 147 } else {
148 mobilePosition.setAltitude(0.0); 148 mobilePosition.setAltitude(0.0);
149 } 149 }
150 - logger.info("[收到Notify-MobilePosition]:{}/{}->{}.{}", mobilePosition.getDeviceId(), mobilePosition.getChannelId(), 150 + logger.info("[收到 移动位置订阅]:{}/{}->{}.{}", mobilePosition.getDeviceId(), mobilePosition.getChannelId(),
151 mobilePosition.getLongitude(), mobilePosition.getLatitude()); 151 mobilePosition.getLongitude(), mobilePosition.getLatitude());
152 mobilePosition.setReportSource("Mobile Position"); 152 mobilePosition.setReportSource("Mobile Position");
153 // 默认来源坐标系为WGS-84处理 153 // 默认来源坐标系为WGS-84处理
@@ -283,7 +283,7 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements @@ -283,7 +283,7 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements
283 Element eventElement = itemDevice.element("Event"); 283 Element eventElement = itemDevice.element("Event");
284 DeviceChannel channel = XmlUtil.channelContentHander(itemDevice); 284 DeviceChannel channel = XmlUtil.channelContentHander(itemDevice);
285 channel.setDeviceId(device.getDeviceId()); 285 channel.setDeviceId(device.getDeviceId());
286 - logger.info("[收到Notify-Catalog]:{}/{}", device.getDeviceId(), channel.getChannelId()); 286 + logger.info("[收到 目录订阅]:{}/{}", device.getDeviceId(), channel.getChannelId());
287 switch (eventElement.getText().toUpperCase()) { 287 switch (eventElement.getText().toUpperCase()) {
288 case CatalogEvent.ON: // 上线 288 case CatalogEvent.ON: // 上线
289 logger.info("收到来自设备【{}】的通道【{}】上线通知", device.getDeviceId(), channel.getChannelId()); 289 logger.info("收到来自设备【{}】的通道【{}】上线通知", device.getDeviceId(), channel.getChannelId());
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/SubscribeRequestProcessor.java
@@ -137,6 +137,9 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme @@ -137,6 +137,9 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme
137 String deviceID = XmlUtil.getText(rootElement, "DeviceID"); 137 String deviceID = XmlUtil.getText(rootElement, "DeviceID");
138 ParentPlatform platform = storager.queryParentPlatByServerGBId(platformId); 138 ParentPlatform platform = storager.queryParentPlatByServerGBId(platformId);
139 SubscribeInfo subscribeInfo = new SubscribeInfo(evt, platformId); 139 SubscribeInfo subscribeInfo = new SubscribeInfo(evt, platformId);
  140 + if (platform == null) {
  141 + return;
  142 + }
140 if (evt.getServerTransaction() == null) { 143 if (evt.getServerTransaction() == null) {
141 ServerTransaction serverTransaction = platform.getTransport().equals("TCP") ? tcpSipProvider.getNewServerTransaction(evt.getRequest()) 144 ServerTransaction serverTransaction = platform.getTransport().equals("TCP") ? tcpSipProvider.getNewServerTransaction(evt.getRequest())
142 : udpSipProvider.getNewServerTransaction(evt.getRequest()); 145 : udpSipProvider.getNewServerTransaction(evt.getRequest());
@@ -146,8 +149,7 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme @@ -146,8 +149,7 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme
146 subscribeInfo.setDialog(dialog); 149 subscribeInfo.setDialog(dialog);
147 } 150 }
148 String sn = XmlUtil.getText(rootElement, "SN"); 151 String sn = XmlUtil.getText(rootElement, "SN");
149 - String key = VideoManagerConstants.SIP_SUBSCRIBE_PREFIX + userSetting.getServerId() + "_MobilePosition_" + platformId;  
150 - logger.info("[notify-MobilePosition]: {}", platformId); 152 + logger.info("[回复 移动位置订阅]: {}", platformId);
151 StringBuilder resultXml = new StringBuilder(200); 153 StringBuilder resultXml = new StringBuilder(200);
152 resultXml.append("<?xml version=\"1.0\" ?>\r\n") 154 resultXml.append("<?xml version=\"1.0\" ?>\r\n")
153 .append("<Response>\r\n") 155 .append("<Response>\r\n")
@@ -158,14 +160,25 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme @@ -158,14 +160,25 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme
158 .append("</Response>\r\n"); 160 .append("</Response>\r\n");
159 161
160 if (subscribeInfo.getExpires() > 0) { 162 if (subscribeInfo.getExpires() > 0) {
161 - if (subscribeHolder.getMobilePositionSubscribe(platformId) != null) {  
162 - dynamicTask.stop(key);  
163 - }  
164 String interval = XmlUtil.getText(rootElement, "Interval"); // GPS上报时间间隔 163 String interval = XmlUtil.getText(rootElement, "Interval"); // GPS上报时间间隔
165 - 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);
166 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 +// }
167 }else if (subscribeInfo.getExpires() == 0) { 181 }else if (subscribeInfo.getExpires() == 0) {
168 - dynamicTask.stop(key);  
169 subscribeHolder.removeMobilePositionSubscribe(platformId); 182 subscribeHolder.removeMobilePositionSubscribe(platformId);
170 } 183 }
171 184
@@ -199,8 +212,7 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme @@ -199,8 +212,7 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme
199 subscribeInfo.setDialog(dialog); 212 subscribeInfo.setDialog(dialog);
200 } 213 }
201 String sn = XmlUtil.getText(rootElement, "SN"); 214 String sn = XmlUtil.getText(rootElement, "SN");
202 - String key = VideoManagerConstants.SIP_SUBSCRIBE_PREFIX + userSetting.getServerId() + "_Catalog_" + platformId;  
203 - logger.info("[notify-Catalog]: {}", platformId); 215 + logger.info("[回复 目录订阅]: {}/{}", platformId, deviceID);
204 StringBuilder resultXml = new StringBuilder(200); 216 StringBuilder resultXml = new StringBuilder(200);
205 resultXml.append("<?xml version=\"1.0\" ?>\r\n") 217 resultXml.append("<?xml version=\"1.0\" ?>\r\n")
206 .append("<Response>\r\n") 218 .append("<Response>\r\n")
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/MessageRequestProcessor.java
@@ -12,6 +12,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorP @@ -12,6 +12,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorP
12 import com.genersoft.iot.vmp.gb28181.utils.SipUtils; 12 import com.genersoft.iot.vmp.gb28181.utils.SipUtils;
13 import com.genersoft.iot.vmp.storager.IRedisCatchStorage; 13 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
14 import com.genersoft.iot.vmp.storager.IVideoManagerStorage; 14 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
  15 +import gov.nist.javax.sip.message.SIPRequest;
15 import org.dom4j.DocumentException; 16 import org.dom4j.DocumentException;
16 import org.dom4j.Element; 17 import org.dom4j.Element;
17 import org.slf4j.Logger; 18 import org.slf4j.Logger;
@@ -23,6 +24,7 @@ import org.springframework.stereotype.Component; @@ -23,6 +24,7 @@ import org.springframework.stereotype.Component;
23 import javax.sip.InvalidArgumentException; 24 import javax.sip.InvalidArgumentException;
24 import javax.sip.RequestEvent; 25 import javax.sip.RequestEvent;
25 import javax.sip.SipException; 26 import javax.sip.SipException;
  27 +import javax.sip.address.SipURI;
26 import javax.sip.header.CSeqHeader; 28 import javax.sip.header.CSeqHeader;
27 import javax.sip.header.CallIdHeader; 29 import javax.sip.header.CallIdHeader;
28 import javax.sip.message.Response; 30 import javax.sip.message.Response;
@@ -81,6 +83,17 @@ public class MessageRequestProcessor extends SIPRequestProcessorParent implement @@ -81,6 +83,17 @@ public class MessageRequestProcessor extends SIPRequestProcessorParent implement
81 // 查询上级平台是否存在 83 // 查询上级平台是否存在
82 ParentPlatform parentPlatform = storage.queryParentPlatByServerGBId(deviceId); 84 ParentPlatform parentPlatform = storage.queryParentPlatByServerGBId(deviceId);
83 try { 85 try {
  86 + if (device != null && parentPlatform != null) {
  87 + logger.warn("[重复]平台与设备编号重复:{}", deviceId);
  88 + SIPRequest request = (SIPRequest) evt.getRequest();
  89 + String hostAddress = request.getRemoteAddress().getHostAddress();
  90 + int remotePort = request.getRemotePort();
  91 + if (device.getHostAddress().equals(hostAddress + ":" + remotePort)) {
  92 + parentPlatform = null;
  93 + }else {
  94 + device = null;
  95 + }
  96 + }
84 if (device == null && parentPlatform == null) { 97 if (device == null && parentPlatform == null) {
85 // 不存在则回复404 98 // 不存在则回复404
86 responseAck(evt, Response.NOT_FOUND, "device "+ deviceId +" not found"); 99 responseAck(evt, Response.NOT_FOUND, "device "+ deviceId +" not found");
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/control/cmd/DeviceControlQueryMessageHandler.java
@@ -23,6 +23,7 @@ import javax.sip.*; @@ -23,6 +23,7 @@ import javax.sip.*;
23 import javax.sip.address.SipURI; 23 import javax.sip.address.SipURI;
24 import javax.sip.header.HeaderAddress; 24 import javax.sip.header.HeaderAddress;
25 import javax.sip.header.ToHeader; 25 import javax.sip.header.ToHeader;
  26 +import javax.sip.message.Response;
26 import java.text.ParseException; 27 import java.text.ParseException;
27 import java.util.Iterator; 28 import java.util.Iterator;
28 29
@@ -103,6 +104,18 @@ public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent @@ -103,6 +104,18 @@ public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent
103 if (!StringUtils.isEmpty(getText(rootElement,"PTZCmd")) && !parentPlatform.getServerGBId().equals(targetGBId)) { 104 if (!StringUtils.isEmpty(getText(rootElement,"PTZCmd")) && !parentPlatform.getServerGBId().equals(targetGBId)) {
104 String cmdString = getText(rootElement,"PTZCmd"); 105 String cmdString = getText(rootElement,"PTZCmd");
105 Device deviceForPlatform = storager.queryVideoDeviceByPlatformIdAndChannelId(parentPlatform.getServerGBId(), channelId); 106 Device deviceForPlatform = storager.queryVideoDeviceByPlatformIdAndChannelId(parentPlatform.getServerGBId(), channelId);
  107 + if (deviceForPlatform == null) {
  108 + try {
  109 + responseAck(evt, Response.NOT_FOUND);
  110 + return;
  111 + } catch (SipException e) {
  112 + e.printStackTrace();
  113 + } catch (InvalidArgumentException e) {
  114 + e.printStackTrace();
  115 + } catch (ParseException e) {
  116 + e.printStackTrace();
  117 + }
  118 + }
106 cmder.fronEndCmd(deviceForPlatform, channelId, cmdString, eventResult -> { 119 cmder.fronEndCmd(deviceForPlatform, channelId, cmdString, eventResult -> {
107 // 失败的回复 120 // 失败的回复
108 try { 121 try {
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/CatalogNotifyMessageHandler.java
@@ -18,6 +18,7 @@ import javax.sip.SipException; @@ -18,6 +18,7 @@ import javax.sip.SipException;
18 import javax.sip.header.FromHeader; 18 import javax.sip.header.FromHeader;
19 import javax.sip.message.Response; 19 import javax.sip.message.Response;
20 import java.text.ParseException; 20 import java.text.ParseException;
  21 +import java.util.ArrayList;
21 import java.util.List; 22 import java.util.List;
22 23
23 @Component 24 @Component
@@ -58,7 +59,8 @@ public class CatalogNotifyMessageHandler extends SIPRequestProcessorParent imple @@ -58,7 +59,8 @@ public class CatalogNotifyMessageHandler extends SIPRequestProcessorParent imple
58 List<DeviceChannelInPlatform> deviceChannels = storage.queryChannelListInParentPlatform(parentPlatform.getServerGBId()); 59 List<DeviceChannelInPlatform> deviceChannels = storage.queryChannelListInParentPlatform(parentPlatform.getServerGBId());
59 // 查询关联的直播通道 60 // 查询关联的直播通道
60 List<GbStream> gbStreams = storage.queryGbStreamListInPlatform(parentPlatform.getServerGBId()); 61 List<GbStream> gbStreams = storage.queryGbStreamListInPlatform(parentPlatform.getServerGBId());
61 - int size = deviceChannels.size() + gbStreams.size(); 62 +
  63 + List<DeviceChannel> allChannels = new ArrayList<>();
62 // 回复目录信息 64 // 回复目录信息
63 List<PlatformCatalog> catalogs = storage.queryCatalogInPlatform(parentPlatform.getServerGBId()); 65 List<PlatformCatalog> catalogs = storage.queryCatalogInPlatform(parentPlatform.getServerGBId());
64 if (catalogs.size() > 0) { 66 if (catalogs.size() > 0) {
@@ -81,9 +83,7 @@ public class CatalogNotifyMessageHandler extends SIPRequestProcessorParent imple @@ -81,9 +83,7 @@ public class CatalogNotifyMessageHandler extends SIPRequestProcessorParent imple
81 deviceChannel.setModel("live"); 83 deviceChannel.setModel("live");
82 deviceChannel.setOwner("wvp-pro"); 84 deviceChannel.setOwner("wvp-pro");
83 deviceChannel.setSecrecy("0"); 85 deviceChannel.setSecrecy("0");
84 - cmderFroPlatform.catalogQuery(deviceChannel, parentPlatform, sn, fromHeader.getTag(), size);  
85 - // 防止发送过快  
86 - Thread.sleep(100); 86 + allChannels.add(deviceChannel);
87 } 87 }
88 } 88 }
89 // 回复级联的通道 89 // 回复级联的通道
@@ -96,9 +96,7 @@ public class CatalogNotifyMessageHandler extends SIPRequestProcessorParent imple @@ -96,9 +96,7 @@ public class CatalogNotifyMessageHandler extends SIPRequestProcessorParent imple
96 deviceChannel.setParental(0); 96 deviceChannel.setParental(0);
97 deviceChannel.setParentId(channel.getCatalogId()); 97 deviceChannel.setParentId(channel.getCatalogId());
98 deviceChannel.setCivilCode(parentPlatform.getDeviceGBId().substring(0, 6)); 98 deviceChannel.setCivilCode(parentPlatform.getDeviceGBId().substring(0, 6));
99 - cmderFroPlatform.catalogQuery(deviceChannel, parentPlatform, sn, fromHeader.getTag(), size);  
100 - // 防止发送过快  
101 - Thread.sleep(100); 99 + allChannels.add(deviceChannel);
102 } 100 }
103 } 101 }
104 // 回复直播的通道 102 // 回复直播的通道
@@ -114,7 +112,8 @@ public class CatalogNotifyMessageHandler extends SIPRequestProcessorParent imple @@ -114,7 +112,8 @@ public class CatalogNotifyMessageHandler extends SIPRequestProcessorParent imple
114 deviceChannel.setLatitude(gbStream.getLatitude()); 112 deviceChannel.setLatitude(gbStream.getLatitude());
115 deviceChannel.setDeviceId(parentPlatform.getDeviceGBId()); 113 deviceChannel.setDeviceId(parentPlatform.getDeviceGBId());
116 deviceChannel.setManufacture("wvp-pro"); 114 deviceChannel.setManufacture("wvp-pro");
117 - deviceChannel.setStatus(gbStream.isStatus()?1:0); 115 +// deviceChannel.setStatus(gbStream.isStatus()?1:0);
  116 + deviceChannel.setStatus(1);
118 deviceChannel.setParentId(gbStream.getCatalogId()); 117 deviceChannel.setParentId(gbStream.getCatalogId());
119 deviceChannel.setRegisterWay(1); 118 deviceChannel.setRegisterWay(1);
120 deviceChannel.setCivilCode(parentPlatform.getDeviceGBId().substring(0,6)); 119 deviceChannel.setCivilCode(parentPlatform.getDeviceGBId().substring(0,6));
@@ -122,16 +121,16 @@ public class CatalogNotifyMessageHandler extends SIPRequestProcessorParent imple @@ -122,16 +121,16 @@ public class CatalogNotifyMessageHandler extends SIPRequestProcessorParent imple
122 deviceChannel.setOwner("wvp-pro"); 121 deviceChannel.setOwner("wvp-pro");
123 deviceChannel.setParental(0); 122 deviceChannel.setParental(0);
124 deviceChannel.setSecrecy("0"); 123 deviceChannel.setSecrecy("0");
125 - cmderFroPlatform.catalogQuery(deviceChannel, parentPlatform, sn, fromHeader.getTag(), size);  
126 - // 防止发送过快  
127 - Thread.sleep(100); 124 + allChannels.add(deviceChannel);
128 } 125 }
129 } 126 }
130 - if (size == 0) { 127 + if (allChannels.size() > 0) {
  128 + cmderFroPlatform.catalogQuery(allChannels, parentPlatform, sn, fromHeader.getTag());
  129 + }else {
131 // 回复无通道 130 // 回复无通道
132 - cmderFroPlatform.catalogQuery(null, parentPlatform, sn, fromHeader.getTag(), size); 131 + cmderFroPlatform.catalogQuery(null, parentPlatform, sn, fromHeader.getTag(), 0);
133 } 132 }
134 - } catch (SipException | InvalidArgumentException | ParseException | InterruptedException e) { 133 + } catch (SipException | InvalidArgumentException | ParseException e) {
135 e.printStackTrace(); 134 e.printStackTrace();
136 } 135 }
137 136
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/query/cmd/CatalogQueryMessageHandler.java
@@ -22,6 +22,7 @@ import javax.sip.SipException; @@ -22,6 +22,7 @@ import javax.sip.SipException;
22 import javax.sip.header.FromHeader; 22 import javax.sip.header.FromHeader;
23 import javax.sip.message.Response; 23 import javax.sip.message.Response;
24 import java.text.ParseException; 24 import java.text.ParseException;
  25 +import java.util.ArrayList;
25 import java.util.List; 26 import java.util.List;
26 27
27 @Component 28 @Component
@@ -45,6 +46,9 @@ public class CatalogQueryMessageHandler extends SIPRequestProcessorParent implem @@ -45,6 +46,9 @@ public class CatalogQueryMessageHandler extends SIPRequestProcessorParent implem
45 @Autowired 46 @Autowired
46 private EventPublisher publisher; 47 private EventPublisher publisher;
47 48
  49 + @Autowired
  50 + private IVideoManagerStorage storage;
  51 +
48 @Override 52 @Override
49 public void afterPropertiesSet() throws Exception { 53 public void afterPropertiesSet() throws Exception {
50 queryMessageHandler.addHandler(cmdType, this); 54 queryMessageHandler.addHandler(cmdType, this);
@@ -71,10 +75,11 @@ public class CatalogQueryMessageHandler extends SIPRequestProcessorParent implem @@ -71,10 +75,11 @@ public class CatalogQueryMessageHandler extends SIPRequestProcessorParent implem
71 List<GbStream> gbStreams = storager.queryGbStreamListInPlatform(parentPlatform.getServerGBId()); 75 List<GbStream> gbStreams = storager.queryGbStreamListInPlatform(parentPlatform.getServerGBId());
72 // 回复目录信息 76 // 回复目录信息
73 List<PlatformCatalog> catalogs = storager.queryCatalogInPlatform(parentPlatform.getServerGBId()); 77 List<PlatformCatalog> catalogs = storager.queryCatalogInPlatform(parentPlatform.getServerGBId());
74 - int size = catalogs.size() + deviceChannelInPlatforms.size() + gbStreams.size(); 78 +
  79 + List<DeviceChannel> allChannels = new ArrayList<>();
75 if (catalogs.size() > 0) { 80 if (catalogs.size() > 0) {
76 for (PlatformCatalog catalog : catalogs) { 81 for (PlatformCatalog catalog : catalogs) {
77 - if (catalog.getParentId().equals(parentPlatform.getServerGBId())) { 82 + if (catalog.getParentId().equals(catalog.getPlatformId())) {
78 catalog.setParentId(parentPlatform.getDeviceGBId()); 83 catalog.setParentId(parentPlatform.getDeviceGBId());
79 } 84 }
80 DeviceChannel deviceChannel = new DeviceChannel(); 85 DeviceChannel deviceChannel = new DeviceChannel();
@@ -92,9 +97,7 @@ public class CatalogQueryMessageHandler extends SIPRequestProcessorParent implem @@ -92,9 +97,7 @@ public class CatalogQueryMessageHandler extends SIPRequestProcessorParent implem
92 deviceChannel.setModel("live"); 97 deviceChannel.setModel("live");
93 deviceChannel.setOwner("wvp-pro"); 98 deviceChannel.setOwner("wvp-pro");
94 deviceChannel.setSecrecy("0"); 99 deviceChannel.setSecrecy("0");
95 - cmderFroPlatform.catalogQuery(deviceChannel, parentPlatform, sn, fromHeader.getTag(), size);  
96 - // 防止发送过快  
97 - Thread.sleep(100); 100 + allChannels.add(deviceChannel);
98 } 101 }
99 } 102 }
100 // 回复级联的通道 103 // 回复级联的通道
@@ -103,20 +106,18 @@ public class CatalogQueryMessageHandler extends SIPRequestProcessorParent implem @@ -103,20 +106,18 @@ public class CatalogQueryMessageHandler extends SIPRequestProcessorParent implem
103 if (channel.getCatalogId().equals(parentPlatform.getServerGBId())) { 106 if (channel.getCatalogId().equals(parentPlatform.getServerGBId())) {
104 channel.setCatalogId(parentPlatform.getDeviceGBId()); 107 channel.setCatalogId(parentPlatform.getDeviceGBId());
105 } 108 }
106 - DeviceChannel deviceChannel = storager.queryChannel(channel.getDeviceId(), channel.getChannelId()); 109 + DeviceChannel deviceChannel = storage.queryChannel(channel.getDeviceId(), channel.getChannelId());
107 deviceChannel.setParental(0); 110 deviceChannel.setParental(0);
108 deviceChannel.setParentId(channel.getCatalogId()); 111 deviceChannel.setParentId(channel.getCatalogId());
109 deviceChannel.setCivilCode(parentPlatform.getDeviceGBId().substring(0, 6)); 112 deviceChannel.setCivilCode(parentPlatform.getDeviceGBId().substring(0, 6));
110 - cmderFroPlatform.catalogQuery(deviceChannel, parentPlatform, sn, fromHeader.getTag(), size);  
111 - // 防止发送过快  
112 - Thread.sleep(100); 113 + allChannels.add(deviceChannel);
113 } 114 }
114 } 115 }
115 // 回复直播的通道 116 // 回复直播的通道
116 if (gbStreams.size() > 0) { 117 if (gbStreams.size() > 0) {
117 for (GbStream gbStream : gbStreams) { 118 for (GbStream gbStream : gbStreams) {
118 if (gbStream.getCatalogId().equals(parentPlatform.getServerGBId())) { 119 if (gbStream.getCatalogId().equals(parentPlatform.getServerGBId())) {
119 - gbStream.setCatalogId(parentPlatform.getDeviceGBId()); 120 + gbStream.setCatalogId(null);
120 } 121 }
121 DeviceChannel deviceChannel = new DeviceChannel(); 122 DeviceChannel deviceChannel = new DeviceChannel();
122 deviceChannel.setChannelId(gbStream.getGbId()); 123 deviceChannel.setChannelId(gbStream.getGbId());
@@ -125,7 +126,8 @@ public class CatalogQueryMessageHandler extends SIPRequestProcessorParent implem @@ -125,7 +126,8 @@ public class CatalogQueryMessageHandler extends SIPRequestProcessorParent implem
125 deviceChannel.setLatitude(gbStream.getLatitude()); 126 deviceChannel.setLatitude(gbStream.getLatitude());
126 deviceChannel.setDeviceId(parentPlatform.getDeviceGBId()); 127 deviceChannel.setDeviceId(parentPlatform.getDeviceGBId());
127 deviceChannel.setManufacture("wvp-pro"); 128 deviceChannel.setManufacture("wvp-pro");
128 - deviceChannel.setStatus(gbStream.isStatus()?1:0); 129 +// deviceChannel.setStatus(gbStream.isStatus()?1:0);
  130 + deviceChannel.setStatus(1);
129 deviceChannel.setParentId(gbStream.getCatalogId()); 131 deviceChannel.setParentId(gbStream.getCatalogId());
130 deviceChannel.setRegisterWay(1); 132 deviceChannel.setRegisterWay(1);
131 deviceChannel.setCivilCode(parentPlatform.getDeviceGBId().substring(0,6)); 133 deviceChannel.setCivilCode(parentPlatform.getDeviceGBId().substring(0,6));
@@ -133,15 +135,14 @@ public class CatalogQueryMessageHandler extends SIPRequestProcessorParent implem @@ -133,15 +135,14 @@ public class CatalogQueryMessageHandler extends SIPRequestProcessorParent implem
133 deviceChannel.setOwner("wvp-pro"); 135 deviceChannel.setOwner("wvp-pro");
134 deviceChannel.setParental(0); 136 deviceChannel.setParental(0);
135 deviceChannel.setSecrecy("0"); 137 deviceChannel.setSecrecy("0");
136 -  
137 - cmderFroPlatform.catalogQuery(deviceChannel, parentPlatform, sn, fromHeader.getTag(), size);  
138 - // 防止发送过快  
139 - Thread.sleep(100); 138 + allChannels.add(deviceChannel);
140 } 139 }
141 } 140 }
142 - if (size == 0) { 141 + if (allChannels.size() > 0) {
  142 + cmderFroPlatform.catalogQuery(allChannels, parentPlatform, sn, fromHeader.getTag());
  143 + }else {
143 // 回复无通道 144 // 回复无通道
144 - cmderFroPlatform.catalogQuery(null, parentPlatform, sn, fromHeader.getTag(), size); 145 + cmderFroPlatform.catalogQuery(null, parentPlatform, sn, fromHeader.getTag(), 0);
145 } 146 }
146 } catch (SipException e) { 147 } catch (SipException e) {
147 e.printStackTrace(); 148 e.printStackTrace();
@@ -149,8 +150,6 @@ public class CatalogQueryMessageHandler extends SIPRequestProcessorParent implem @@ -149,8 +150,6 @@ public class CatalogQueryMessageHandler extends SIPRequestProcessorParent implem
149 e.printStackTrace(); 150 e.printStackTrace();
150 } catch (ParseException e) { 151 } catch (ParseException e) {
151 e.printStackTrace(); 152 e.printStackTrace();
152 - } catch (InterruptedException e) {  
153 - e.printStackTrace();  
154 } 153 }
155 154
156 } 155 }
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/CatalogResponseMessageHandler.java
@@ -116,16 +116,15 @@ public class CatalogResponseMessageHandler extends SIPRequestProcessorParent imp @@ -116,16 +116,15 @@ public class CatalogResponseMessageHandler extends SIPRequestProcessorParent imp
116 continue; 116 continue;
117 } 117 }
118 //by brewswang 118 //by brewswang
119 - if (NumericUtil.isDouble(XmlUtil.getText(itemDevice, "Longitude"))) {//如果包含位置信息,就更新一下位置  
120 - processNotifyMobilePosition(evt, itemDevice);  
121 - }  
122 - 119 +// if (NumericUtil.isDouble(XmlUtil.getText(itemDevice, "Longitude"))) {//如果包含位置信息,就更新一下位置
  120 +// processNotifyMobilePosition(evt, itemDevice);
  121 +// }
123 DeviceChannel deviceChannel = XmlUtil.channelContentHander(itemDevice); 122 DeviceChannel deviceChannel = XmlUtil.channelContentHander(itemDevice);
124 deviceChannel.setDeviceId(device.getDeviceId()); 123 deviceChannel.setDeviceId(device.getDeviceId());
125 - logger.debug("收到来自设备【{}】的通道: {}【{}】", device.getDeviceId(), deviceChannel.getName(), deviceChannel.getChannelId()); 124 +
126 channelList.add(deviceChannel); 125 channelList.add(deviceChannel);
127 } 126 }
128 - 127 + logger.info("收到来自设备【{}】的通道: {}个,{}/{}", device.getDeviceId(), channelList.size(), catalogDataCatch.get(key) == null ? 0 :catalogDataCatch.get(key).size(), sumNum);
129 catalogDataCatch.put(key, sumNum, device, channelList); 128 catalogDataCatch.put(key, sumNum, device, channelList);
130 if (catalogDataCatch.get(key).size() == sumNum) { 129 if (catalogDataCatch.get(key).size() == sumNum) {
131 // 数据已经完整接收 130 // 数据已经完整接收
@@ -147,9 +146,6 @@ public class CatalogResponseMessageHandler extends SIPRequestProcessorParent imp @@ -147,9 +146,6 @@ public class CatalogResponseMessageHandler extends SIPRequestProcessorParent imp
147 } 146 }
148 // 回复200 OK 147 // 回复200 OK
149 responseAck(evt, Response.OK); 148 responseAck(evt, Response.OK);
150 - if (offLineDetector.isOnline(device.getDeviceId())) {  
151 - publisher.onlineEventPublish(device, VideoManagerConstants.EVENT_ONLINE_MESSAGE);  
152 - }  
153 } 149 }
154 } catch (DocumentException e) { 150 } catch (DocumentException e) {
155 e.printStackTrace(); 151 e.printStackTrace();
@@ -231,4 +227,23 @@ public class CatalogResponseMessageHandler extends SIPRequestProcessorParent imp @@ -231,4 +227,23 @@ public class CatalogResponseMessageHandler extends SIPRequestProcessorParent imp
231 e.printStackTrace(); 227 e.printStackTrace();
232 } 228 }
233 } 229 }
  230 +
  231 + public SyncStatus getChannelSyncProgress(String deviceId) {
  232 + String key = DeferredResultHolder.CALLBACK_CMD_CATALOG + deviceId;
  233 + if (catalogDataCatch.get(key) == null) {
  234 + return null;
  235 + }else {
  236 + return catalogDataCatch.getSyncStatus(key);
  237 + }
  238 + }
  239 +
  240 + public void setChannelSyncReady(String deviceId) {
  241 + String key = DeferredResultHolder.CALLBACK_CMD_CATALOG + deviceId;
  242 + catalogDataCatch.addReady(key);
  243 + }
  244 +
  245 + public void setChannelSyncEnd(String deviceId, String errorMsg) {
  246 + String key = DeferredResultHolder.CALLBACK_CMD_CATALOG + deviceId;
  247 + catalogDataCatch.setChannelSyncEnd(key, errorMsg);
  248 + }
234 } 249 }
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java
@@ -396,7 +396,7 @@ public class ZLMHttpHookListener { @@ -396,7 +396,7 @@ public class ZLMHttpHookListener {
396 } 396 }
397 } 397 }
398 if (gbStreams.size() > 0) { 398 if (gbStreams.size() > 0) {
399 - eventPublisher.catalogEventPublishForStream(null, gbStreams, CatalogEvent.ON); 399 +// eventPublisher.catalogEventPublishForStream(null, gbStreams, CatalogEvent.ON);
400 } 400 }
401 401
402 }else { 402 }else {
@@ -408,7 +408,7 @@ public class ZLMHttpHookListener { @@ -408,7 +408,7 @@ public class ZLMHttpHookListener {
408 } 408 }
409 GbStream gbStream = storager.getGbStream(app, streamId); 409 GbStream gbStream = storager.getGbStream(app, streamId);
410 if (gbStream != null) { 410 if (gbStream != null) {
411 - eventPublisher.catalogEventPublishForStream(null, gbStream, CatalogEvent.OFF); 411 +// eventPublisher.catalogEventPublishForStream(null, gbStream, CatalogEvent.OFF);
412 } 412 }
413 zlmMediaListManager.removeMedia(app, streamId); 413 zlmMediaListManager.removeMedia(app, streamId);
414 } 414 }
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMMediaListManager.java
@@ -204,6 +204,7 @@ public class ZLMMediaListManager { @@ -204,6 +204,7 @@ public class ZLMMediaListManager {
204 if (streamProxyItem == null) { 204 if (streamProxyItem == null) {
205 result = storager.removeMedia(app, streamId); 205 result = storager.removeMedia(app, streamId);
206 }else { 206 }else {
  207 + // TODO 暂不设置为离线
207 result =storager.mediaOutline(app, streamId); 208 result =storager.mediaOutline(app, streamId);
208 } 209 }
209 return result; 210 return result;
src/main/java/com/genersoft/iot/vmp/service/IDeviceService.java
1 package com.genersoft.iot.vmp.service; 1 package com.genersoft.iot.vmp.service;
2 2
3 import com.genersoft.iot.vmp.gb28181.bean.Device; 3 import com.genersoft.iot.vmp.gb28181.bean.Device;
  4 +import com.genersoft.iot.vmp.gb28181.bean.SyncStatus;
4 5
5 /** 6 /**
6 * 设备相关业务处理 7 * 设备相关业务处理
@@ -34,4 +35,24 @@ public interface IDeviceService { @@ -34,4 +35,24 @@ public interface IDeviceService {
34 * @return 35 * @return
35 */ 36 */
36 boolean removeMobilePositionSubscribe(Device device); 37 boolean removeMobilePositionSubscribe(Device device);
  38 +
  39 + /**
  40 + * 移除移动位置订阅
  41 + * @param deviceId 设备ID
  42 + * @return
  43 + */
  44 + SyncStatus getChannelSyncStatus(String deviceId);
  45 +
  46 + /**
  47 + * 设置通道同步状态
  48 + * @param deviceId 设备ID
  49 + */
  50 + void setChannelSyncReady(String deviceId);
  51 +
  52 + /**
  53 + * 设置同步结束
  54 + * @param deviceId 设备ID
  55 + * @param errorMsg 错误信息
  56 + */
  57 + void setChannelSyncEnd(String deviceId, String errorMsg);
37 } 58 }
src/main/java/com/genersoft/iot/vmp/service/impl/DeviceServiceImpl.java
@@ -3,14 +3,19 @@ package com.genersoft.iot.vmp.service.impl; @@ -3,14 +3,19 @@ package com.genersoft.iot.vmp.service.impl;
3 import com.genersoft.iot.vmp.conf.DynamicTask; 3 import com.genersoft.iot.vmp.conf.DynamicTask;
4 import com.genersoft.iot.vmp.gb28181.bean.Device; 4 import com.genersoft.iot.vmp.gb28181.bean.Device;
5 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander; 5 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
  6 +import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.cmd.CatalogResponseMessageHandler;
6 import com.genersoft.iot.vmp.service.IDeviceService; 7 import com.genersoft.iot.vmp.service.IDeviceService;
7 import com.genersoft.iot.vmp.gb28181.task.impl.CatalogSubscribeTask; 8 import com.genersoft.iot.vmp.gb28181.task.impl.CatalogSubscribeTask;
8 import com.genersoft.iot.vmp.gb28181.task.impl.MobilePositionSubscribeTask; 9 import com.genersoft.iot.vmp.gb28181.task.impl.MobilePositionSubscribeTask;
  10 +import com.genersoft.iot.vmp.gb28181.bean.SyncStatus;
  11 +import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
9 import org.slf4j.Logger; 12 import org.slf4j.Logger;
10 import org.slf4j.LoggerFactory; 13 import org.slf4j.LoggerFactory;
11 import org.springframework.beans.factory.annotation.Autowired; 14 import org.springframework.beans.factory.annotation.Autowired;
12 import org.springframework.stereotype.Service; 15 import org.springframework.stereotype.Service;
13 16
  17 +import javax.sip.DialogState;
  18 +
14 /** 19 /**
15 * 设备业务(目录订阅) 20 * 设备业务(目录订阅)
16 */ 21 */
@@ -25,24 +30,28 @@ public class DeviceServiceImpl implements IDeviceService { @@ -25,24 +30,28 @@ public class DeviceServiceImpl implements IDeviceService {
25 @Autowired 30 @Autowired
26 private ISIPCommander sipCommander; 31 private ISIPCommander sipCommander;
27 32
  33 + @Autowired
  34 + private CatalogResponseMessageHandler catalogResponseMessageHandler;
  35 +
  36 + @Autowired
  37 + private IRedisCatchStorage redisCatchStorage;
  38 +
28 @Override 39 @Override
29 public boolean addCatalogSubscribe(Device device) { 40 public boolean addCatalogSubscribe(Device device) {
30 if (device == null || device.getSubscribeCycleForCatalog() < 0) { 41 if (device == null || device.getSubscribeCycleForCatalog() < 0) {
31 return false; 42 return false;
32 } 43 }
33 - if (dynamicTask.contains(device.getDeviceId() + "catalog")) {  
34 - // 存在则停止现有的,开启新的  
35 - 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;
36 } 47 }
37 logger.info("[添加目录订阅] 设备{}", device.getDeviceId()); 48 logger.info("[添加目录订阅] 设备{}", device.getDeviceId());
38 // 添加目录订阅 49 // 添加目录订阅
39 CatalogSubscribeTask catalogSubscribeTask = new CatalogSubscribeTask(device, sipCommander); 50 CatalogSubscribeTask catalogSubscribeTask = new CatalogSubscribeTask(device, sipCommander);
40 - catalogSubscribeTask.run();  
41 // 提前开始刷新订阅 51 // 提前开始刷新订阅
42 - int subscribeCycleForCatalog = device.getSubscribeCycleForCatalog(); 52 + int subscribeCycleForCatalog = Math.max(device.getSubscribeCycleForCatalog(),30);
43 // 设置最小值为30 53 // 设置最小值为30
44 - subscribeCycleForCatalog = Math.max(subscribeCycleForCatalog, 30);  
45 - dynamicTask.startCron(device.getDeviceId() + "catalog", catalogSubscribeTask, subscribeCycleForCatalog); 54 + dynamicTask.startCron(device.getDeviceId() + "catalog", catalogSubscribeTask, subscribeCycleForCatalog -1);
46 return true; 55 return true;
47 } 56 }
48 57
@@ -61,18 +70,16 @@ public class DeviceServiceImpl implements IDeviceService { @@ -61,18 +70,16 @@ public class DeviceServiceImpl implements IDeviceService {
61 if (device == null || device.getSubscribeCycleForMobilePosition() < 0) { 70 if (device == null || device.getSubscribeCycleForMobilePosition() < 0) {
62 return false; 71 return false;
63 } 72 }
64 - if (dynamicTask.contains(device.getDeviceId() + "mobile_position")) {  
65 - // 存在则停止现有的,开启新的  
66 - dynamicTask.stop(device.getDeviceId() + "mobile_position");  
67 - }  
68 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 + }
69 // 添加目录订阅 78 // 添加目录订阅
70 MobilePositionSubscribeTask mobilePositionSubscribeTask = new MobilePositionSubscribeTask(device, sipCommander); 79 MobilePositionSubscribeTask mobilePositionSubscribeTask = new MobilePositionSubscribeTask(device, sipCommander);
71 - mobilePositionSubscribeTask.run();  
72 // 提前开始刷新订阅 80 // 提前开始刷新订阅
73 - int subscribeCycleForCatalog = device.getSubscribeCycleForCatalog();  
74 // 设置最小值为30 81 // 设置最小值为30
75 - subscribeCycleForCatalog = Math.max(subscribeCycleForCatalog, 30); 82 + int subscribeCycleForCatalog = Math.max(device.getSubscribeCycleForMobilePosition(),30);
76 dynamicTask.startCron(device.getDeviceId() + "mobile_position" , mobilePositionSubscribeTask, subscribeCycleForCatalog -1 ); 83 dynamicTask.startCron(device.getDeviceId() + "mobile_position" , mobilePositionSubscribeTask, subscribeCycleForCatalog -1 );
77 return true; 84 return true;
78 } 85 }
@@ -86,4 +93,19 @@ public class DeviceServiceImpl implements IDeviceService { @@ -86,4 +93,19 @@ public class DeviceServiceImpl implements IDeviceService {
86 dynamicTask.stop(device.getDeviceId() + "mobile_position"); 93 dynamicTask.stop(device.getDeviceId() + "mobile_position");
87 return true; 94 return true;
88 } 95 }
  96 +
  97 + @Override
  98 + public SyncStatus getChannelSyncStatus(String deviceId) {
  99 + return catalogResponseMessageHandler.getChannelSyncProgress(deviceId);
  100 + }
  101 +
  102 + @Override
  103 + public void setChannelSyncReady(String deviceId) {
  104 + catalogResponseMessageHandler.setChannelSyncReady(deviceId);
  105 + }
  106 +
  107 + @Override
  108 + public void setChannelSyncEnd(String deviceId, String errorMsg) {
  109 + catalogResponseMessageHandler.setChannelSyncEnd(deviceId, errorMsg);
  110 + }
89 } 111 }
src/main/java/com/genersoft/iot/vmp/service/impl/GbStreamServiceImpl.java
@@ -100,7 +100,8 @@ public class GbStreamServiceImpl implements IGbStreamService { @@ -100,7 +100,8 @@ public class GbStreamServiceImpl implements IGbStreamService {
100 deviceChannel.setLatitude(gbStream.getLatitude()); 100 deviceChannel.setLatitude(gbStream.getLatitude());
101 deviceChannel.setDeviceId(deviceGBId); 101 deviceChannel.setDeviceId(deviceGBId);
102 deviceChannel.setManufacture("wvp-pro"); 102 deviceChannel.setManufacture("wvp-pro");
103 - deviceChannel.setStatus(gbStream.isStatus()?1:0); 103 +// deviceChannel.setStatus(gbStream.isStatus()?1:0);
  104 + deviceChannel.setStatus(1);
104 deviceChannel.setParentId(catalogId ==null?gbStream.getCatalogId():catalogId); 105 deviceChannel.setParentId(catalogId ==null?gbStream.getCatalogId():catalogId);
105 deviceChannel.setRegisterWay(1); 106 deviceChannel.setRegisterWay(1);
106 deviceChannel.setCivilCode(deviceGBId.substring(0, 6)); 107 deviceChannel.setCivilCode(deviceGBId.substring(0, 6));
src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java
@@ -216,4 +216,5 @@ public interface IRedisCatchStorage { @@ -216,4 +216,5 @@ public interface IRedisCatchStorage {
216 void sendMobilePositionMsg(JSONObject jsonObject); 216 void sendMobilePositionMsg(JSONObject jsonObject);
217 217
218 void sendStreamPushRequestedMsg(MessageForPushChannel messageForPushChannel); 218 void sendStreamPushRequestedMsg(MessageForPushChannel messageForPushChannel);
  219 +
219 } 220 }
src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java
@@ -638,4 +638,5 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { @@ -638,4 +638,5 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
638 logger.info("[redis 推流被请求通知] {}: {}-{}", key, msg.getApp(), msg.getStream()); 638 logger.info("[redis 推流被请求通知] {}: {}-{}", key, msg.getApp(), msg.getStream());
639 redis.convertAndSend(key, (JSONObject)JSON.toJSON(msg)); 639 redis.convertAndSend(key, (JSONObject)JSON.toJSON(msg));
640 } 640 }
  641 +
641 } 642 }
src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStorageImpl.java
@@ -445,8 +445,6 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage { @@ -445,8 +445,6 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage {
445 device.setOnline(1); 445 device.setOnline(1);
446 logger.info("更新设备在线: " + deviceId); 446 logger.info("更新设备在线: " + deviceId);
447 redisCatchStorage.updateDevice(device); 447 redisCatchStorage.updateDevice(device);
448 - List<DeviceChannel> deviceChannelList = deviceChannelMapper.queryOnlineChannelsByDeviceId(deviceId);  
449 - eventPublisher.catalogEventPublish(null, deviceChannelList, CatalogEvent.ON);  
450 return deviceMapper.update(device) > 0; 448 return deviceMapper.update(device) > 0;
451 } 449 }
452 450
src/main/java/com/genersoft/iot/vmp/utils/Coordtransform.java 0 → 100644
  1 +package com.genersoft.iot.vmp.utils;
  2 +
  3 +/**
  4 + * 坐标转换
  5 + * 一个提供了百度坐标(BD09)、国测局坐标(火星坐标,GCJ02)、和WGS84坐标系之间的转换的工具类
  6 + * 参考https://github.com/wandergis/coordtransform 写的Java版本
  7 + * @author Xinconan
  8 + * @date 2016-03-18
  9 + * @url https://github.com/xinconan/coordtransform
  10 + */
  11 +public class Coordtransform {
  12 +
  13 + private static double x_PI = 3.14159265358979324 * 3000.0 / 180.0;
  14 + private static double PI = 3.1415926535897932384626;
  15 + private static double a = 6378245.0;
  16 + private static double ee = 0.00669342162296594323;
  17 +
  18 + /**
  19 + * 百度坐标系 (BD-09) 与 火星坐标系 (GCJ-02)的转换
  20 + * 即 百度 转 谷歌、高德
  21 + * @param bd_lon
  22 + * @param bd_lat
  23 + * @return Double[lon,lat]
  24 + */
  25 + public static Double[] BD09ToGCJ02(Double bd_lon,Double bd_lat){
  26 + double x = bd_lon - 0.0065;
  27 + double y = bd_lat - 0.006;
  28 + double z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * x_PI);
  29 + double theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * x_PI);
  30 + Double[] arr = new Double[2];
  31 + arr[0] = z * Math.cos(theta);
  32 + arr[1] = z * Math.sin(theta);
  33 + return arr;
  34 + }
  35 +
  36 + /**
  37 + * 火星坐标系 (GCJ-02) 与百度坐标系 (BD-09) 的转换
  38 + * 即谷歌、高德 转 百度
  39 + * @param gcj_lon
  40 + * @param gcj_lat
  41 + * @return Double[lon,lat]
  42 + */
  43 + public static Double[] GCJ02ToBD09(Double gcj_lon,Double gcj_lat){
  44 + double z = Math.sqrt(gcj_lon * gcj_lon + gcj_lat * gcj_lat) + 0.00002 * Math.sin(gcj_lat * x_PI);
  45 + double theta = Math.atan2(gcj_lat, gcj_lon) + 0.000003 * Math.cos(gcj_lon * x_PI);
  46 + Double[] arr = new Double[2];
  47 + arr[0] = z * Math.cos(theta) + 0.0065;
  48 + arr[1] = z * Math.sin(theta) + 0.006;
  49 + return arr;
  50 + }
  51 +
  52 + /**
  53 + * WGS84转GCJ02
  54 + * @param wgs_lon
  55 + * @param wgs_lat
  56 + * @return Double[lon,lat]
  57 + */
  58 + public static Double[] WGS84ToGCJ02(Double wgs_lon,Double wgs_lat){
  59 + if(outOfChina(wgs_lon, wgs_lat)){
  60 + return new Double[]{wgs_lon,wgs_lat};
  61 + }
  62 + double dlat = transformlat(wgs_lon - 105.0, wgs_lat - 35.0);
  63 + double dlng = transformlng(wgs_lon - 105.0, wgs_lat - 35.0);
  64 + double radlat = wgs_lat / 180.0 * PI;
  65 + double magic = Math.sin(radlat);
  66 + magic = 1 - ee * magic * magic;
  67 + double sqrtmagic = Math.sqrt(magic);
  68 + dlat = (dlat * 180.0) / ((a * (1 - ee)) / (magic * sqrtmagic) * PI);
  69 + dlng = (dlng * 180.0) / (a / sqrtmagic * Math.cos(radlat) * PI);
  70 + Double[] arr = new Double[2];
  71 + arr[0] = wgs_lon + dlng;
  72 + arr[1] = wgs_lat + dlat;
  73 + return arr;
  74 + }
  75 +
  76 + /**
  77 + * GCJ02转WGS84
  78 + * @param gcj_lon
  79 + * @param gcj_lat
  80 + * @return Double[lon,lat]
  81 + */
  82 + public static Double[] GCJ02ToWGS84(Double gcj_lon,Double gcj_lat){
  83 + if(outOfChina(gcj_lon, gcj_lat)){
  84 + return new Double[]{gcj_lon,gcj_lat};
  85 + }
  86 + double dlat = transformlat(gcj_lon - 105.0, gcj_lat - 35.0);
  87 + double dlng = transformlng(gcj_lon - 105.0, gcj_lat - 35.0);
  88 + double radlat = gcj_lat / 180.0 * PI;
  89 + double magic = Math.sin(radlat);
  90 + magic = 1 - ee * magic * magic;
  91 + double sqrtmagic = Math.sqrt(magic);
  92 + dlat = (dlat * 180.0) / ((a * (1 - ee)) / (magic * sqrtmagic) * PI);
  93 + dlng = (dlng * 180.0) / (a / sqrtmagic * Math.cos(radlat) * PI);
  94 + double mglat = gcj_lat + dlat;
  95 + double mglng = gcj_lon + dlng;
  96 + return new Double[]{gcj_lon * 2 - mglng, gcj_lat * 2 - mglat};
  97 + }
  98 +
  99 + private static Double transformlat(double lng, double lat) {
  100 + double ret = -100.0 + 2.0 * lng + 3.0 * lat + 0.2 * lat * lat + 0.1 * lng * lat + 0.2 * Math.sqrt(Math.abs(lng));
  101 + ret += (20.0 * Math.sin(6.0 * lng * PI) + 20.0 * Math.sin(2.0 * lng * PI)) * 2.0 / 3.0;
  102 + ret += (20.0 * Math.sin(lat * PI) + 40.0 * Math.sin(lat / 3.0 * PI)) * 2.0 / 3.0;
  103 + ret += (160.0 * Math.sin(lat / 12.0 * PI) + 320 * Math.sin(lat * PI / 30.0)) * 2.0 / 3.0;
  104 + return ret;
  105 + }
  106 +
  107 + private static Double transformlng(double lng,double lat) {
  108 + double ret = 300.0 + lng + 2.0 * lat + 0.1 * lng * lng + 0.1 * lng * lat + 0.1 * Math.sqrt(Math.abs(lng));
  109 + ret += (20.0 * Math.sin(6.0 * lng * PI) + 20.0 * Math.sin(2.0 * lng * PI)) * 2.0 / 3.0;
  110 + ret += (20.0 * Math.sin(lng * PI) + 40.0 * Math.sin(lng / 3.0 * PI)) * 2.0 / 3.0;
  111 + ret += (150.0 * Math.sin(lng / 12.0 * PI) + 300.0 * Math.sin(lng / 30.0 * PI)) * 2.0 / 3.0;
  112 + return ret;
  113 + }
  114 +
  115 + /**
  116 + * outOfChina
  117 + * @描述: 判断是否在国内,不在国内则不做偏移
  118 + * @param lng
  119 + * @param lat
  120 + * @return {boolean}
  121 + */
  122 + private static boolean outOfChina(Double lng,Double lat) {
  123 + return (lng < 72.004 || lng > 137.8347) || ((lat < 0.8293 || lat > 55.8271) || false);
  124 + };
  125 +
  126 +}
src/main/java/com/genersoft/iot/vmp/utils/GpsUtil.java
@@ -17,48 +17,57 @@ public class GpsUtil { @@ -17,48 +17,57 @@ public class GpsUtil {
17 public static BaiduPoint Wgs84ToBd09(String xx, String yy) { 17 public static BaiduPoint Wgs84ToBd09(String xx, String yy) {
18 18
19 19
20 - try {  
21 - Socket s = new Socket("api.map.baidu.com", 80);  
22 - BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream(), "UTF-8"));  
23 - OutputStream out = s.getOutputStream();  
24 - StringBuffer sb = new StringBuffer("GET /ag/coord/convert?from=0&to=4");  
25 - sb.append("&x=" + xx + "&y=" + yy);  
26 - sb.append("&callback=BMap.Convertor.cbk_3976 HTTP/1.1\r\n");  
27 - sb.append("User-Agent: Java/1.6.0_20\r\n");  
28 - sb.append("Host: api.map.baidu.com:80\r\n");  
29 - sb.append("Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2\r\n");  
30 - sb.append("Connection: Close\r\n");  
31 - sb.append("\r\n");  
32 - out.write(sb.toString().getBytes());  
33 - String json = "";  
34 - String tmp = "";  
35 - while ((tmp = br.readLine()) != null) {  
36 - // logger.info(tmp);  
37 - json += tmp;  
38 - } 20 +// try {
  21 +// Socket s = new Socket("api.map.baidu.com", 80);
  22 +// BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream(), "UTF-8"));
  23 +// OutputStream out = s.getOutputStream();
  24 +// StringBuffer sb = new StringBuffer("GET /ag/coord/convert?from=0&to=4");
  25 +// sb.append("&x=" + xx + "&y=" + yy);
  26 +// sb.append("&callback=BMap.Convertor.cbk_3976 HTTP/1.1\r\n");
  27 +// sb.append("User-Agent: Java/1.6.0_20\r\n");
  28 +// sb.append("Host: api.map.baidu.com:80\r\n");
  29 +// sb.append("Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2\r\n");
  30 +// sb.append("Connection: Close\r\n");
  31 +// sb.append("\r\n");
  32 +// out.write(sb.toString().getBytes());
  33 +// String json = "";
  34 +// String tmp = "";
  35 +// while ((tmp = br.readLine()) != null) {
  36 +// // logger.info(tmp);
  37 +// json += tmp;
  38 +// }
  39 +//
  40 +// s.close();
  41 +// int start = json.indexOf("cbk_3976");
  42 +// int end = json.lastIndexOf("}");
  43 +// if (start != -1 && end != -1 && json.contains("\"x\":\"")) {
  44 +// json = json.substring(start, end);
  45 +// String[] point = json.split(",");
  46 +// String x = point[1].split(":")[1].replace("\"", "");
  47 +// String y = point[2].split(":")[1].replace("\"", "");
  48 +// BaiduPoint bdPoint= new BaiduPoint();
  49 +// bdPoint.setBdLng(new String(decode(x)));
  50 +// bdPoint.setBdLat(new String(decode(y)));
  51 +// return bdPoint;
  52 +// //return (new String(decode(x)) + "," + new String(decode(y)));
  53 +// } else {
  54 +// logger.info("gps坐标无效!!");
  55 +// }
  56 +// out.close();
  57 +// br.close();
  58 +// } catch (Exception e) {
  59 +// e.printStackTrace();
  60 +// }
39 61
40 - s.close();  
41 - int start = json.indexOf("cbk_3976");  
42 - int end = json.lastIndexOf("}");  
43 - if (start != -1 && end != -1 && json.contains("\"x\":\"")) {  
44 - json = json.substring(start, end);  
45 - String[] point = json.split(",");  
46 - String x = point[1].split(":")[1].replace("\"", "");  
47 - String y = point[2].split(":")[1].replace("\"", "");  
48 - BaiduPoint bdPoint= new BaiduPoint();  
49 - bdPoint.setBdLng(new String(decode(x)));  
50 - bdPoint.setBdLat(new String(decode(y)));  
51 - return bdPoint;  
52 - //return (new String(decode(x)) + "," + new String(decode(y)));  
53 - } else {  
54 - logger.info("gps坐标无效!!");  
55 - }  
56 - out.close();  
57 - br.close();  
58 - } catch (Exception e) {  
59 - e.printStackTrace();  
60 - }  
61 - return null; 62 +
  63 + double lng = Double.parseDouble(xx);
  64 + double lat = Double.parseDouble(yy);
  65 + Double[] gcj02 = Coordtransform.WGS84ToGCJ02(lng, lat);
  66 + Double[] doubles = Coordtransform.GCJ02ToBD09(gcj02[0], gcj02[1]);
  67 + BaiduPoint bdPoint= new BaiduPoint();
  68 + bdPoint.setBdLng(doubles[0] + "");
  69 + bdPoint.setBdLat(doubles[1] + "");
  70 + return bdPoint;
62 } 71 }
63 72
64 /** 73 /**
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceQuery.java
@@ -4,7 +4,13 @@ import com.alibaba.fastjson.JSONObject; @@ -4,7 +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;
  8 +import com.genersoft.iot.vmp.gb28181.bean.SyncStatus;
7 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;
8 import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; 14 import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
9 import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; 15 import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
10 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; 16 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
@@ -18,6 +24,7 @@ import io.swagger.annotations.Api; @@ -18,6 +24,7 @@ import io.swagger.annotations.Api;
18 import io.swagger.annotations.ApiImplicitParam; 24 import io.swagger.annotations.ApiImplicitParam;
19 import io.swagger.annotations.ApiImplicitParams; 25 import io.swagger.annotations.ApiImplicitParams;
20 import io.swagger.annotations.ApiOperation; 26 import io.swagger.annotations.ApiOperation;
  27 +import org.kxml2.wap.wv.WV;
21 import org.slf4j.Logger; 28 import org.slf4j.Logger;
22 import org.slf4j.LoggerFactory; 29 import org.slf4j.LoggerFactory;
23 import org.springframework.beans.factory.annotation.Autowired; 30 import org.springframework.beans.factory.annotation.Autowired;
@@ -27,9 +34,8 @@ import org.springframework.util.StringUtils; @@ -27,9 +34,8 @@ import org.springframework.util.StringUtils;
27 import org.springframework.web.bind.annotation.*; 34 import org.springframework.web.bind.annotation.*;
28 import org.springframework.web.context.request.async.DeferredResult; 35 import org.springframework.web.context.request.async.DeferredResult;
29 36
30 -import java.util.List;  
31 -import java.util.Set;  
32 -import java.util.UUID; 37 +import javax.sip.DialogState;
  38 +import java.util.*;
33 39
34 @Api(tags = "国标设备查询", value = "国标设备查询") 40 @Api(tags = "国标设备查询", value = "国标设备查询")
35 @SuppressWarnings("rawtypes") 41 @SuppressWarnings("rawtypes")
@@ -61,6 +67,9 @@ public class DeviceQuery { @@ -61,6 +67,9 @@ public class DeviceQuery {
61 @Autowired 67 @Autowired
62 private DynamicTask dynamicTask; 68 private DynamicTask dynamicTask;
63 69
  70 + @Autowired
  71 + private SubscribeHolder subscribeHolder;
  72 +
64 /** 73 /**
65 * 使用ID查询国标设备 74 * 使用ID查询国标设备
66 * @param deviceId 国标ID 75 * @param deviceId 国标ID
@@ -149,48 +158,30 @@ public class DeviceQuery { @@ -149,48 +158,30 @@ public class DeviceQuery {
149 @ApiImplicitParam(name="deviceId", value = "设备id", required = true, dataTypeClass = String.class), 158 @ApiImplicitParam(name="deviceId", value = "设备id", required = true, dataTypeClass = String.class),
150 }) 159 })
151 @PostMapping("/devices/{deviceId}/sync") 160 @PostMapping("/devices/{deviceId}/sync")
152 - public DeferredResult<ResponseEntity<Device>> devicesSync(@PathVariable String deviceId){ 161 + public WVPResult<SyncStatus> devicesSync(@PathVariable String deviceId){
153 162
154 if (logger.isDebugEnabled()) { 163 if (logger.isDebugEnabled()) {
155 logger.debug("设备通道信息同步API调用,deviceId:" + deviceId); 164 logger.debug("设备通道信息同步API调用,deviceId:" + deviceId);
156 } 165 }
157 Device device = storager.queryVideoDevice(deviceId); 166 Device device = storager.queryVideoDevice(deviceId);
158 - String key = DeferredResultHolder.CALLBACK_CMD_CATALOG + deviceId;  
159 - String uuid = UUID.randomUUID().toString();  
160 - // 默认超时时间为30分钟  
161 - DeferredResult<ResponseEntity<Device>> result = new DeferredResult<ResponseEntity<Device>>(30*60*1000L);  
162 - result.onTimeout(()->{  
163 - logger.warn("设备[{}]通道信息同步超时", deviceId);  
164 - // 释放rtpserver  
165 - RequestMessage msg = new RequestMessage();  
166 - msg.setKey(key);  
167 - msg.setId(uuid);  
168 - WVPResult<Object> wvpResult = new WVPResult<>();  
169 - wvpResult.setCode(-1);  
170 - wvpResult.setData(device);  
171 - wvpResult.setMsg("更新超时");  
172 - msg.setData(wvpResult);  
173 - resultHolder.invokeAllResult(msg);  
174 -  
175 - });  
176 - // 等待其他相同请求返回时一起返回  
177 - if (resultHolder.exist(key, null)) {  
178 - return result; 167 + SyncStatus syncStatus = deviceService.getChannelSyncStatus(deviceId);
  168 + // 已存在则返回进度
  169 + if (syncStatus != null && syncStatus.getErrorMsg() == null) {
  170 + WVPResult<SyncStatus> wvpResult = new WVPResult<>();
  171 + wvpResult.setCode(0);
  172 + wvpResult.setData(syncStatus);
  173 + return wvpResult;
179 } 174 }
180 - cmder.catalogQuery(device, event -> {  
181 - RequestMessage msg = new RequestMessage();  
182 - msg.setKey(key);  
183 - msg.setId(uuid);  
184 - WVPResult<Object> wvpResult = new WVPResult<>();  
185 - wvpResult.setCode(-1);  
186 - wvpResult.setData(device);  
187 - wvpResult.setMsg(String.format("同步通道失败,错误码: %s, %s", event.statusCode, event.msg));  
188 - msg.setData(wvpResult);  
189 - resultHolder.invokeAllResult(msg); 175 + SyncStatus syncStatusReady = new SyncStatus();
  176 + deviceService.setChannelSyncReady(deviceId);
  177 + cmder.catalogQuery(device, event -> {
  178 + String errorMsg = String.format("同步通道失败,错误码: %s, %s", event.statusCode, event.msg);
  179 + deviceService.setChannelSyncEnd(deviceId, errorMsg);
190 }); 180 });
191 -  
192 - resultHolder.put(key, uuid, result);  
193 - return result; 181 + WVPResult<SyncStatus> wvpResult = new WVPResult<>();
  182 + wvpResult.setCode(0);
  183 + wvpResult.setMsg("开始同步");
  184 + return wvpResult;
194 } 185 }
195 186
196 /** 187 /**
@@ -467,4 +458,47 @@ public class DeviceQuery { @@ -467,4 +458,47 @@ public class DeviceQuery {
467 public WVPResult<List<DeviceChannelTree>> tree(@PathVariable String deviceId) { 458 public WVPResult<List<DeviceChannelTree>> tree(@PathVariable String deviceId) {
468 return WVPResult.Data(storager.tree(deviceId)); 459 return WVPResult.Data(storager.tree(deviceId));
469 } 460 }
  461 +
  462 + @GetMapping("/{deviceId}/sync_status")
  463 + @ApiOperation(value = "获取通道同步进度", notes = "获取通道同步进度")
  464 + public WVPResult<SyncStatus> getSyncStatus(@PathVariable String deviceId) {
  465 + SyncStatus channelSyncStatus = deviceService.getChannelSyncStatus(deviceId);
  466 + WVPResult<SyncStatus> wvpResult = new WVPResult<>();
  467 + if (channelSyncStatus == null) {
  468 + wvpResult.setCode(-1);
  469 + wvpResult.setMsg("同步尚未开始");
  470 + }else {
  471 + wvpResult.setCode(0);
  472 + wvpResult.setData(channelSyncStatus);
  473 + if (channelSyncStatus.getErrorMsg() != null) {
  474 + wvpResult.setMsg(channelSyncStatus.getErrorMsg());
  475 + }
  476 + }
  477 + return wvpResult;
  478 + }
  479 +
  480 + @GetMapping("/{deviceId}/subscribe_info")
  481 + @ApiOperation(value = "获取设备的订阅状态", notes = "获取设备的订阅状态")
  482 + public WVPResult<Map<String, String>> getSubscribeInfo(@PathVariable String deviceId) {
  483 + Set<String> allKeys = dynamicTask.getAllKeys();
  484 + Map<String, String> dialogStateMap = new HashMap<>();
  485 + for (String key : allKeys) {
  486 + if (key.startsWith(deviceId)) {
  487 + ISubscribeTask subscribeTask = (ISubscribeTask)dynamicTask.get(key);
  488 + DialogState dialogState = subscribeTask.getDialogState();
  489 + if (dialogState == null) {
  490 + continue;
  491 + }
  492 + if (subscribeTask instanceof CatalogSubscribeTask) {
  493 + dialogStateMap.put("catalog", dialogState.toString());
  494 + }else if (subscribeTask instanceof MobilePositionSubscribeTask) {
  495 + dialogStateMap.put("mobilePosition", dialogState.toString());
  496 + }
  497 + }
  498 + }
  499 + WVPResult<Map<String, String>> wvpResult = new WVPResult<>();
  500 + wvpResult.setCode(0);
  501 + wvpResult.setData(dialogStateMap);
  502 + return wvpResult;
  503 + }
470 } 504 }
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/DeviceList.vue
@@ -57,7 +57,7 @@ @@ -57,7 +57,7 @@
57 57
58 <el-table-column label="操作" width="450" align="center" fixed="right"> 58 <el-table-column label="操作" width="450" align="center" fixed="right">
59 <template slot-scope="scope"> 59 <template slot-scope="scope">
60 - <el-button size="mini" :loading="scope.row.loading" v-if="scope.row.online!=0" icon="el-icon-refresh" @click="refDevice(scope.row)">刷新</el-button> 60 + <el-button size="mini" v-if="scope.row.online!=0" icon="el-icon-refresh" @click="refDevice(scope.row)" @mouseover="getTooltipContent(scope.row.deviceId)">刷新</el-button>
61 <el-button-group> 61 <el-button-group>
62 <el-button size="mini" icon="el-icon-video-camera-solid" v-bind:disabled="scope.row.online==0" type="primary" @click="showChannelList(scope.row)">通道</el-button> 62 <el-button size="mini" icon="el-icon-video-camera-solid" v-bind:disabled="scope.row.online==0" type="primary" @click="showChannelList(scope.row)">通道</el-button>
63 <el-button size="mini" icon="el-icon-location" v-bind:disabled="scope.row.online==0" type="primary" @click="showDevicePosition(scope.row)">定位</el-button> 63 <el-button size="mini" icon="el-icon-location" v-bind:disabled="scope.row.online==0" type="primary" @click="showDevicePosition(scope.row)">定位</el-button>
@@ -78,6 +78,7 @@ @@ -78,6 +78,7 @@
78 :total="total"> 78 :total="total">
79 </el-pagination> 79 </el-pagination>
80 <deviceEdit ref="deviceEdit" ></deviceEdit> 80 <deviceEdit ref="deviceEdit" ></deviceEdit>
  81 + <syncChannelProgress ref="syncChannelProgress" ></syncChannelProgress>
81 </el-main> 82 </el-main>
82 </el-container> 83 </el-container>
83 </div> 84 </div>
@@ -86,11 +87,13 @@ @@ -86,11 +87,13 @@
86 <script> 87 <script>
87 import uiHeader from './UiHeader.vue' 88 import uiHeader from './UiHeader.vue'
88 import deviceEdit from './dialog/deviceEdit.vue' 89 import deviceEdit from './dialog/deviceEdit.vue'
  90 + import syncChannelProgress from './dialog/SyncChannelProgress.vue'
89 export default { 91 export default {
90 name: 'app', 92 name: 'app',
91 components: { 93 components: {
92 uiHeader, 94 uiHeader,
93 - deviceEdit 95 + deviceEdit,
  96 + syncChannelProgress,
94 }, 97 },
95 data() { 98 data() {
96 return { 99 return {
@@ -104,7 +107,7 @@ @@ -104,7 +107,7 @@
104 currentPage:1, 107 currentPage:1,
105 count:15, 108 count:15,
106 total:0, 109 total:0,
107 - getDeviceListLoading: false 110 + getDeviceListLoading: false,
108 }; 111 };
109 }, 112 },
110 computed: { 113 computed: {
@@ -117,8 +120,6 @@ @@ -117,8 +120,6 @@
117 }); 120 });
118 this.currentDeviceChannelsLenth = channels.length; 121 this.currentDeviceChannelsLenth = channels.length;
119 } 122 }
120 -  
121 - console.log("数据:" + JSON.stringify(channels));  
122 return channels; 123 return channels;
123 } 124 }
124 }, 125 },
@@ -153,13 +154,11 @@ @@ -153,13 +154,11 @@
153 count: that.count 154 count: that.count
154 } 155 }
155 }).then(function (res) { 156 }).then(function (res) {
156 - console.log(res);  
157 - console.log(res.data.list);  
158 that.total = res.data.total; 157 that.total = res.data.total;
159 that.deviceList = res.data.list; 158 that.deviceList = res.data.list;
160 that.getDeviceListLoading = false; 159 that.getDeviceListLoading = false;
161 }).catch(function (error) { 160 }).catch(function (error) {
162 - console.log(error); 161 + console.error(error);
163 that.getDeviceListLoading = false; 162 that.getDeviceListLoading = false;
164 }); 163 });
165 164
@@ -182,7 +181,7 @@ @@ -182,7 +181,7 @@
182 }).then((res)=>{ 181 }).then((res)=>{
183 this.getDeviceList(); 182 this.getDeviceList();
184 }).catch((error) =>{ 183 }).catch((error) =>{
185 - console.log(error); 184 + console.error(error);
186 }); 185 });
187 }).catch(() => { 186 }).catch(() => {
188 187
@@ -191,11 +190,9 @@ @@ -191,11 +190,9 @@
191 190
192 }, 191 },
193 showChannelList: function(row) { 192 showChannelList: function(row) {
194 - console.log(JSON.stringify(row))  
195 this.$router.push(`/channelList/${row.deviceId}/0/15/1`); 193 this.$router.push(`/channelList/${row.deviceId}/0/15/1`);
196 }, 194 },
197 showDevicePosition: function(row) { 195 showDevicePosition: function(row) {
198 - console.log(JSON.stringify(row))  
199 this.$router.push(`/devicePosition/${row.deviceId}/0/15/1`); 196 this.$router.push(`/devicePosition/${row.deviceId}/0/15/1`);
200 }, 197 },
201 198
@@ -203,12 +200,11 @@ @@ -203,12 +200,11 @@
203 //刷新设备信息 200 //刷新设备信息
204 refDevice: function(itemData) { 201 refDevice: function(itemData) {
205 console.log("刷新对应设备:" + itemData.deviceId); 202 console.log("刷新对应设备:" + itemData.deviceId);
206 - var that = this;  
207 - that.$set(itemData,"loading", true); 203 + let that = this;
208 this.$axios({ 204 this.$axios({
209 method: 'post', 205 method: 'post',
210 url: '/api/device/query/devices/' + itemData.deviceId + '/sync' 206 url: '/api/device/query/devices/' + itemData.deviceId + '/sync'
211 - }).then(function(res) { 207 + }).then((res) => {
212 console.log("刷新设备结果:"+JSON.stringify(res)); 208 console.log("刷新设备结果:"+JSON.stringify(res));
213 if (res.data.code !==0) { 209 if (res.data.code !==0) {
214 that.$message({ 210 that.$message({
@@ -217,24 +213,44 @@ @@ -217,24 +213,44 @@
217 type: 'error' 213 type: 'error'
218 }); 214 });
219 }else{ 215 }else{
220 - that.$message({  
221 - showClose: true,  
222 - message: res.data.msg,  
223 - type: 'success'  
224 - }); 216 + // that.$message({
  217 + // showClose: true,
  218 + // message: res.data.msg,
  219 + // type: 'success'
  220 + // });
  221 + this.$refs.syncChannelProgress.openDialog(itemData.deviceId)
225 } 222 }
226 that.initData() 223 that.initData()
227 - that.$set(itemData,"loading", true);  
228 - }).catch(function(e) { 224 + }).catch((e) => {
229 console.error(e) 225 console.error(e)
230 that.$message({ 226 that.$message({
231 showClose: true, 227 showClose: true,
232 message: e, 228 message: e,
233 type: 'error' 229 type: 'error'
234 }); 230 });
235 - that.$set(itemData,"loading", true);  
236 }); 231 });
  232 +
237 }, 233 },
  234 +
  235 + getTooltipContent: async function (deviceId){
  236 + let result = "";
  237 + await this.$axios({
  238 + method: 'get',
  239 + async: false,
  240 + url:`/api/device/query/${deviceId}/sync_status/`,
  241 + }).then((res) => {
  242 + if (res.data.code == 0) {
  243 + if (res.data.data.errorMsg !== null) {
  244 + result = res.data.data.errorMsg
  245 + } else if (res.data.msg !== null) {
  246 + result = res.data.msg
  247 + } else {
  248 + result = `同步中...[${res.data.data.current}/${res.data.data.total}]`;
  249 + }
  250 + }
  251 + })
  252 + return result;
  253 + },
238 //通知设备上传媒体流 254 //通知设备上传媒体流
239 sendDevicePush: function(itemData) { 255 sendDevicePush: function(itemData) {
240 // let deviceId = this.currentDevice.deviceId; 256 // let deviceId = this.currentDevice.deviceId;
@@ -251,7 +267,6 @@ @@ -251,7 +267,6 @@
251 // }); 267 // });
252 }, 268 },
253 transportChange: function (row) { 269 transportChange: function (row) {
254 - console.log(row);  
255 console.log(`修改传输方式为 ${row.streamMode}:${row.deviceId} `); 270 console.log(`修改传输方式为 ${row.streamMode}:${row.deviceId} `);
256 let that = this; 271 let that = this;
257 this.$axios({ 272 this.$axios({
@@ -263,7 +278,6 @@ @@ -263,7 +278,6 @@
263 }); 278 });
264 }, 279 },
265 edit: function (row) { 280 edit: function (row) {
266 - console.log(row);  
267 this.$refs.deviceEdit.openDialog(row, ()=>{ 281 this.$refs.deviceEdit.openDialog(row, ()=>{
268 this.$refs.deviceEdit.close(); 282 this.$refs.deviceEdit.close();
269 this.$message({ 283 this.$message({
web_src/src/components/dialog/SyncChannelProgress.vue 0 → 100644
  1 +<template>
  2 + <div id="SyncChannelProgress" v-loading="isLoging">
  3 + <el-dialog
  4 + width="240px"
  5 + top="13%"
  6 + :append-to-body="true"
  7 + :close-on-click-modal="false"
  8 + :visible.sync="showDialog"
  9 + :destroy-on-close="true"
  10 + :show-close="true"
  11 + @close="close()"
  12 + style="text-align: center">
  13 + <el-progress type="circle" :percentage="percentage" :status="syncStatus"></el-progress>
  14 + <div style="text-align: center">
  15 + {{msg}}
  16 + </div>
  17 + </el-dialog>
  18 + </div>
  19 +</template>
  20 +
  21 +<script>
  22 +
  23 +export default {
  24 + name: "SyncChannelProgress",
  25 + computed: {},
  26 + props: ['platformId'],
  27 + created() {},
  28 + data() {
  29 + return {
  30 + syncStatus: null,
  31 + percentage: 0,
  32 + total: 0,
  33 + current: 0,
  34 + showDialog: false,
  35 + isLoging: false,
  36 + syncFlag: false,
  37 + deviceId: null,
  38 + timmer: null,
  39 + msg: "正在同步",
  40 + };
  41 + },
  42 + methods: {
  43 + openDialog: function (deviceId) {
  44 + console.log("deviceId: " + deviceId)
  45 + this.deviceId = deviceId;
  46 + this.showDialog = true;
  47 + this.msg = "";
  48 + this.percentage= 0;
  49 + this.total= 0;
  50 + this.current= 0;
  51 + this.syncFlag= false;
  52 + this.syncStatus = null;
  53 + this.getProgress()
  54 + },
  55 + getProgress(){
  56 + this.$axios({
  57 + method: 'get',
  58 + url:`/api/device/query/${this.deviceId}/sync_status/`,
  59 + }).then((res) => {
  60 + if (res.data.code == 0) {
  61 + if (!this.syncFlag) {
  62 + this.syncFlag = true;
  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)
  80 + }
  81 + }else {
  82 + if (this.syncFlag) {
  83 + this.syncStatus = "success"
  84 + this.percentage = 100;
  85 + this.msg = '同步成功';
  86 + }else {
  87 + this.syncStatus = "error"
  88 + this.msg = res.data.msg;
  89 + }
  90 + }
  91 + }).catch((error) =>{
  92 + console.log(error);
  93 + this.syncStatus = "error"
  94 + this.msg = error.response.data.msg;
  95 + });
  96 + },
  97 + close: function (){
  98 + window.clearTimeout(this.timmer)
  99 + }
  100 + },
  101 +};
  102 +</script>