Commit f10b458fc919fbcadc4936bf3a7886088e20ac71

Authored by 648540858
1 parent f1c8ca60

优化订阅信息的发送与取消订阅

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 org.springframework.beans.factory.annotation.Autowired; 4 import org.springframework.beans.factory.annotation.Autowired;
4 import org.springframework.context.annotation.Bean; 5 import org.springframework.context.annotation.Bean;
5 import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; 6 import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
@@ -21,6 +22,7 @@ public class DynamicTask { @@ -21,6 +22,7 @@ public class DynamicTask {
21 private ThreadPoolTaskScheduler threadPoolTaskScheduler; 22 private ThreadPoolTaskScheduler threadPoolTaskScheduler;
22 23
23 private Map<String, ScheduledFuture<?>> futureMap = new ConcurrentHashMap<>(); 24 private Map<String, ScheduledFuture<?>> futureMap = new ConcurrentHashMap<>();
  25 + private Map<String, Runnable> runnableMap = new ConcurrentHashMap<>();
24 26
25 @Bean 27 @Bean
26 public ThreadPoolTaskScheduler threadPoolTaskScheduler() { 28 public ThreadPoolTaskScheduler threadPoolTaskScheduler() {
@@ -34,12 +36,12 @@ public class DynamicTask { @@ -34,12 +36,12 @@ public class DynamicTask {
34 * @param cycleForCatalog 间隔 36 * @param cycleForCatalog 间隔
35 * @return 37 * @return
36 */ 38 */
37 - public String startCron(String key, Runnable task, int cycleForCatalog) { 39 + public void startCron(String key, Runnable task, int cycleForCatalog) {
38 stop(key); 40 stop(key);
39 // scheduleWithFixedDelay 必须等待上一个任务结束才开始计时period, cycleForCatalog表示执行的间隔 41 // scheduleWithFixedDelay 必须等待上一个任务结束才开始计时period, cycleForCatalog表示执行的间隔
40 ScheduledFuture future = threadPoolTaskScheduler.scheduleWithFixedDelay(task, cycleForCatalog * 1000L); 42 ScheduledFuture future = threadPoolTaskScheduler.scheduleWithFixedDelay(task, cycleForCatalog * 1000L);
41 futureMap.put(key, future); 43 futureMap.put(key, future);
42 - return "startCron"; 44 + runnableMap.put(key, task);
43 } 45 }
44 46
45 /** 47 /**
@@ -49,18 +51,22 @@ public class DynamicTask { @@ -49,18 +51,22 @@ public class DynamicTask {
49 * @param delay 延时 /毫秒 51 * @param delay 延时 /毫秒
50 * @return 52 * @return
51 */ 53 */
52 - public String startDelay(String key, Runnable task, int delay) { 54 + public void startDelay(String key, Runnable task, int delay) {
53 stop(key); 55 stop(key);
54 Date starTime = new Date(System.currentTimeMillis() + delay); 56 Date starTime = new Date(System.currentTimeMillis() + delay);
55 // scheduleWithFixedDelay 必须等待上一个任务结束才开始计时period, cycleForCatalog表示执行的间隔 57 // scheduleWithFixedDelay 必须等待上一个任务结束才开始计时period, cycleForCatalog表示执行的间隔
56 ScheduledFuture future = threadPoolTaskScheduler.schedule(task, starTime); 58 ScheduledFuture future = threadPoolTaskScheduler.schedule(task, starTime);
57 futureMap.put(key, future); 59 futureMap.put(key, future);
58 - return "startCron";  
59 } 60 }
60 61
61 public void stop(String key) { 62 public void stop(String key) {
62 if (futureMap.get(key) != null && !futureMap.get(key).isCancelled()) { 63 if (futureMap.get(key) != null && !futureMap.get(key).isCancelled()) {
63 futureMap.get(key).cancel(true); 64 futureMap.get(key).cancel(true);
  65 + Runnable runnable = runnableMap.get(key);
  66 + if (runnable instanceof ISubscribeTask) {
  67 + ISubscribeTask subscribeTask = (ISubscribeTask) runnable;
  68 + subscribeTask.stop();
  69 + }
64 } 70 }
65 } 71 }
66 72
src/main/java/com/genersoft/iot/vmp/conf/runner/SipDeviceRunner.java
@@ -14,7 +14,7 @@ import java.util.List; @@ -14,7 +14,7 @@ import java.util.List;
14 14
15 15
16 /** 16 /**
17 - * 系统启动时控制设备离线 17 + * 系统启动时控制设备
18 */ 18 */
19 @Component 19 @Component
20 @Order(value=4) 20 @Order(value=4)
@@ -41,10 +41,14 @@ public class SipDeviceRunner implements CommandLineRunner { @@ -41,10 +41,14 @@ public class SipDeviceRunner implements CommandLineRunner {
41 for (String deviceId : onlineForAll) { 41 for (String deviceId : onlineForAll) {
42 storager.online(deviceId); 42 storager.online(deviceId);
43 Device device = redisCatchStorage.getDevice(deviceId); 43 Device device = redisCatchStorage.getDevice(deviceId);
44 - if (device != null && device.getSubscribeCycleForCatalog() > 0) {  
45 - // 查询在线设备那些开启了订阅,为设备开启定时的目录订阅  
46 - deviceService.addCatalogSubscribe(device);  
47 - deviceService.addMobilePositionSubscribe(device); 44 + if (device != null ) {
  45 + if (device.getSubscribeCycleForCatalog() > 0) {
  46 + // 查询在线设备那些开启了订阅,为设备开启定时的目录订阅
  47 + deviceService.addCatalogSubscribe(device);
  48 + }
  49 + if (device.getSubscribeCycleForMobilePosition() > 0) {
  50 + deviceService.addMobilePositionSubscribe(device);
  51 + }
48 } 52 }
49 } 53 }
50 // 重置cseq计数 54 // 重置cseq计数
src/main/java/com/genersoft/iot/vmp/gb28181/task/ISubscribeTask.java 0 → 100644
  1 +package com.genersoft.iot.vmp.gb28181.task;
  2 +
  3 +public interface ISubscribeTask extends Runnable{
  4 + void stop();
  5 +}
src/main/java/com/genersoft/iot/vmp/service/bean/CatalogSubscribeTask.java renamed to src/main/java/com/genersoft/iot/vmp/gb28181/task/impl/CatalogSubscribeTask.java
1 -package com.genersoft.iot.vmp.service.bean; 1 +package com.genersoft.iot.vmp.gb28181.task.impl;
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.task.ISubscribeTask;
4 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander; 5 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
5 -import com.genersoft.iot.vmp.gb28181.utils.XmlUtil;  
6 -import org.dom4j.DocumentException;  
7 -import org.dom4j.Element;  
8 import org.slf4j.Logger; 6 import org.slf4j.Logger;
9 import org.slf4j.LoggerFactory; 7 import org.slf4j.LoggerFactory;
10 8
  9 +import javax.sip.Dialog;
  10 +import javax.sip.DialogState;
11 import javax.sip.ResponseEvent; 11 import javax.sip.ResponseEvent;
12 12
13 /** 13 /**
14 * 目录订阅任务 14 * 目录订阅任务
15 */ 15 */
16 -public class CatalogSubscribeTask implements Runnable{ 16 +public class CatalogSubscribeTask implements ISubscribeTask {
17 private final Logger logger = LoggerFactory.getLogger(CatalogSubscribeTask.class); 17 private final Logger logger = LoggerFactory.getLogger(CatalogSubscribeTask.class);
18 - private Device device;  
19 - private ISIPCommander sipCommander; 18 + private Device device;
  19 + private final ISIPCommander sipCommander;
  20 + private Dialog dialog;
20 21
21 public CatalogSubscribeTask(Device device, ISIPCommander sipCommander) { 22 public CatalogSubscribeTask(Device device, ISIPCommander sipCommander) {
22 this.device = device; 23 this.device = device;
@@ -25,7 +26,10 @@ public class CatalogSubscribeTask implements Runnable{ @@ -25,7 +26,10 @@ public class CatalogSubscribeTask implements Runnable{
25 26
26 @Override 27 @Override
27 public void run() { 28 public void run() {
28 - sipCommander.catalogSubscribe(device, eventResult -> { 29 + sipCommander.catalogSubscribe(device, dialog, eventResult -> {
  30 + if (eventResult.dialog != null || eventResult.dialog.getState().equals(DialogState.CONFIRMED)) {
  31 + dialog = eventResult.dialog;
  32 + }
29 ResponseEvent event = (ResponseEvent) eventResult.event; 33 ResponseEvent event = (ResponseEvent) eventResult.event;
30 if (event.getResponse().getRawContent() != null) { 34 if (event.getResponse().getRawContent() != null) {
31 // 成功 35 // 成功
@@ -35,8 +39,37 @@ public class CatalogSubscribeTask implements Runnable{ @@ -35,8 +39,37 @@ public class CatalogSubscribeTask implements Runnable{
35 logger.info("[目录订阅]成功: {}", device.getDeviceId()); 39 logger.info("[目录订阅]成功: {}", device.getDeviceId());
36 } 40 }
37 },eventResult -> { 41 },eventResult -> {
  42 + dialog = null;
38 // 失败 43 // 失败
39 logger.warn("[目录订阅]失败,信令发送失败: {}-{} ", device.getDeviceId(), eventResult.msg); 44 logger.warn("[目录订阅]失败,信令发送失败: {}-{} ", device.getDeviceId(), eventResult.msg);
40 }); 45 });
41 } 46 }
  47 +
  48 + @Override
  49 + public void stop() {
  50 + /**
  51 + * dialog 的各个状态
  52 + * EARLY-> Early state状态-初始请求发送以后,收到了一个临时响应消息
  53 + * CONFIRMED-> Confirmed Dialog状态-已确认
  54 + * COMPLETED-> Completed Dialog状态-已完成
  55 + * TERMINATED-> Terminated Dialog状态-终止
  56 + */
  57 + logger.info("取消目录订阅时dialog状态为{}", DialogState.CONFIRMED);
  58 + if (dialog != null && dialog.getState().equals(DialogState.CONFIRMED)) {
  59 + device.setSubscribeCycleForCatalog(0);
  60 + sipCommander.mobilePositionSubscribe(device, dialog, eventResult -> {
  61 + ResponseEvent event = (ResponseEvent) eventResult.event;
  62 + if (event.getResponse().getRawContent() != null) {
  63 + // 成功
  64 + logger.info("[取消目录订阅订阅]成功: {}", device.getDeviceId());
  65 + }else {
  66 + // 成功
  67 + logger.info("[取消目录订阅订阅]成功: {}", device.getDeviceId());
  68 + }
  69 + },eventResult -> {
  70 + // 失败
  71 + logger.warn("[取消目录订阅订阅]失败,信令发送失败: {}-{} ", device.getDeviceId(), eventResult.msg);
  72 + });
  73 + }
  74 + }
42 } 75 }
src/main/java/com/genersoft/iot/vmp/gb28181/task/GPSSubscribeTask.java renamed to src/main/java/com/genersoft/iot/vmp/gb28181/task/impl/MobilePositionSubscribeHandlerTask.java
1 -package com.genersoft.iot.vmp.gb28181.task; 1 +package com.genersoft.iot.vmp.gb28181.task.impl;
2 2
3 -import com.alibaba.fastjson.JSON;  
4 import com.genersoft.iot.vmp.gb28181.bean.GbStream; 3 import com.genersoft.iot.vmp.gb28181.bean.GbStream;
5 import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; 4 import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
6 import com.genersoft.iot.vmp.gb28181.bean.SubscribeHolder; 5 import com.genersoft.iot.vmp.gb28181.bean.SubscribeHolder;
7 import com.genersoft.iot.vmp.gb28181.bean.SubscribeInfo; 6 import com.genersoft.iot.vmp.gb28181.bean.SubscribeInfo;
  7 +import com.genersoft.iot.vmp.gb28181.task.ISubscribeTask;
8 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform; 8 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
9 import com.genersoft.iot.vmp.service.bean.GPSMsgInfo; 9 import com.genersoft.iot.vmp.service.bean.GPSMsgInfo;
10 import com.genersoft.iot.vmp.storager.IRedisCatchStorage; 10 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
@@ -13,7 +13,10 @@ import com.genersoft.iot.vmp.storager.IVideoManagerStorage; @@ -13,7 +13,10 @@ import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
13 import java.text.SimpleDateFormat; 13 import java.text.SimpleDateFormat;
14 import java.util.List; 14 import java.util.List;
15 15
16 -public class GPSSubscribeTask implements Runnable{ 16 +/**
  17 + * 向已经订阅(移动位置)的上级发送MobilePosition消息
  18 + */
  19 +public class MobilePositionSubscribeHandlerTask implements ISubscribeTask {
17 20
18 private IRedisCatchStorage redisCatchStorage; 21 private IRedisCatchStorage redisCatchStorage;
19 private IVideoManagerStorage storager; 22 private IVideoManagerStorage storager;
@@ -25,7 +28,7 @@ public class GPSSubscribeTask implements Runnable{ @@ -25,7 +28,7 @@ public class GPSSubscribeTask implements Runnable{
25 28
26 private final SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 29 private final SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
27 30
28 - public GPSSubscribeTask(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) {
29 this.redisCatchStorage = redisCatchStorage; 32 this.redisCatchStorage = redisCatchStorage;
30 this.storager = storager; 33 this.storager = storager;
31 this.platformId = platformId; 34 this.platformId = platformId;
@@ -66,4 +69,9 @@ public class GPSSubscribeTask implements Runnable{ @@ -66,4 +69,9 @@ public class GPSSubscribeTask implements Runnable{
66 } 69 }
67 } 70 }
68 } 71 }
  72 +
  73 + @Override
  74 + public void stop() {
  75 +
  76 + }
69 } 77 }
src/main/java/com/genersoft/iot/vmp/service/bean/MobilePositionSubscribeTask.java renamed to src/main/java/com/genersoft/iot/vmp/gb28181/task/impl/MobilePositionSubscribeTask.java
1 -package com.genersoft.iot.vmp.service.bean; 1 +package com.genersoft.iot.vmp.gb28181.task.impl;
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.task.ISubscribeTask;
4 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander; 5 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
5 import org.dom4j.Element; 6 import org.dom4j.Element;
6 import org.slf4j.Logger; 7 import org.slf4j.Logger;
7 import org.slf4j.LoggerFactory; 8 import org.slf4j.LoggerFactory;
8 9
  10 +import javax.sip.Dialog;
  11 +import javax.sip.DialogState;
9 import javax.sip.ResponseEvent; 12 import javax.sip.ResponseEvent;
10 13
11 -public class MobilePositionSubscribeTask implements Runnable{ 14 +/**
  15 + * 移动位置订阅的定时更新
  16 + */
  17 +public class MobilePositionSubscribeTask implements ISubscribeTask {
12 private final Logger logger = LoggerFactory.getLogger(MobilePositionSubscribeTask.class); 18 private final Logger logger = LoggerFactory.getLogger(MobilePositionSubscribeTask.class);
13 private Device device; 19 private Device device;
14 private ISIPCommander sipCommander; 20 private ISIPCommander sipCommander;
  21 + private Dialog dialog;
15 22
16 public MobilePositionSubscribeTask(Device device, ISIPCommander sipCommander) { 23 public MobilePositionSubscribeTask(Device device, ISIPCommander sipCommander) {
17 this.device = device; 24 this.device = device;
@@ -20,9 +27,11 @@ public class MobilePositionSubscribeTask implements Runnable{ @@ -20,9 +27,11 @@ public class MobilePositionSubscribeTask implements Runnable{
20 27
21 @Override 28 @Override
22 public void run() { 29 public void run() {
23 - sipCommander.mobilePositionSubscribe(device, eventResult -> { 30 + sipCommander.mobilePositionSubscribe(device, dialog, eventResult -> {
  31 + if (eventResult.dialog != null || eventResult.dialog.getState().equals(DialogState.CONFIRMED)) {
  32 + dialog = eventResult.dialog;
  33 + }
24 ResponseEvent event = (ResponseEvent) eventResult.event; 34 ResponseEvent event = (ResponseEvent) eventResult.event;
25 - Element rootElement = null;  
26 if (event.getResponse().getRawContent() != null) { 35 if (event.getResponse().getRawContent() != null) {
27 // 成功 36 // 成功
28 logger.info("[移动位置订阅]成功: {}", device.getDeviceId()); 37 logger.info("[移动位置订阅]成功: {}", device.getDeviceId());
@@ -31,8 +40,38 @@ public class MobilePositionSubscribeTask implements Runnable{ @@ -31,8 +40,38 @@ public class MobilePositionSubscribeTask implements Runnable{
31 logger.info("[移动位置订阅]成功: {}", device.getDeviceId()); 40 logger.info("[移动位置订阅]成功: {}", device.getDeviceId());
32 } 41 }
33 },eventResult -> { 42 },eventResult -> {
  43 + dialog = null;
34 // 失败 44 // 失败
35 logger.warn("[移动位置订阅]失败,信令发送失败: {}-{} ", device.getDeviceId(), eventResult.msg); 45 logger.warn("[移动位置订阅]失败,信令发送失败: {}-{} ", device.getDeviceId(), eventResult.msg);
36 }); 46 });
  47 +
  48 + }
  49 +
  50 + @Override
  51 + public void stop() {
  52 + /**
  53 + * dialog 的各个状态
  54 + * EARLY-> Early state状态-初始请求发送以后,收到了一个临时响应消息
  55 + * CONFIRMED-> Confirmed Dialog状态-已确认
  56 + * COMPLETED-> Completed Dialog状态-已完成
  57 + * TERMINATED-> Terminated Dialog状态-终止
  58 + */
  59 + logger.info("取消移动订阅时dialog状态为{}", dialog.getState());
  60 + if (dialog != null && dialog.getState().equals(DialogState.CONFIRMED)) {
  61 + device.setSubscribeCycleForMobilePosition(0);
  62 + sipCommander.mobilePositionSubscribe(device, dialog, eventResult -> {
  63 + ResponseEvent event = (ResponseEvent) eventResult.event;
  64 + if (event.getResponse().getRawContent() != null) {
  65 + // 成功
  66 + logger.info("[取消移动位置订阅]成功: {}", device.getDeviceId());
  67 + }else {
  68 + // 成功
  69 + logger.info("[取消移动位置订阅]成功: {}", device.getDeviceId());
  70 + }
  71 + },eventResult -> {
  72 + // 失败
  73 + logger.warn("[取消移动位置订阅]失败,信令发送失败: {}-{} ", device.getDeviceId(), eventResult.msg);
  74 + });
  75 + }
37 } 76 }
38 } 77 }
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java
@@ -8,6 +8,8 @@ import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe; @@ -8,6 +8,8 @@ import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe;
8 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; 8 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
9 import com.genersoft.iot.vmp.service.bean.SSRCInfo; 9 import com.genersoft.iot.vmp.service.bean.SSRCInfo;
10 10
  11 +import javax.sip.Dialog;
  12 +
11 /** 13 /**
12 * @description:设备能力接口,用于定义设备的控制、查询能力 14 * @description:设备能力接口,用于定义设备的控制、查询能力
13 * @author: swwheihei 15 * @author: swwheihei
@@ -304,7 +306,7 @@ public interface ISIPCommander { @@ -304,7 +306,7 @@ public interface ISIPCommander {
304 * @param device 视频设备 306 * @param device 视频设备
305 * @return true = 命令发送成功 307 * @return true = 命令发送成功
306 */ 308 */
307 - boolean mobilePositionSubscribe(Device device, SipSubscribe.Event okEvent ,SipSubscribe.Event errorEvent); 309 + boolean mobilePositionSubscribe(Device device, Dialog dialog, SipSubscribe.Event okEvent , SipSubscribe.Event errorEvent);
308 310
309 /** 311 /**
310 * 订阅、取消订阅报警信息 312 * 订阅、取消订阅报警信息
@@ -324,7 +326,7 @@ public interface ISIPCommander { @@ -324,7 +326,7 @@ public interface ISIPCommander {
324 * @param device 视频设备 326 * @param device 视频设备
325 * @return true = 命令发送成功 327 * @return true = 命令发送成功
326 */ 328 */
327 - boolean catalogSubscribe(Device device, SipSubscribe.Event okEvent ,SipSubscribe.Event errorEvent); 329 + boolean catalogSubscribe(Device device, Dialog dialog, SipSubscribe.Event okEvent ,SipSubscribe.Event errorEvent);
328 330
329 /** 331 /**
330 * 拉框控制命令 332 * 拉框控制命令
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
@@ -36,6 +36,8 @@ import org.springframework.util.StringUtils; @@ -36,6 +36,8 @@ import org.springframework.util.StringUtils;
36 import javax.sip.*; 36 import javax.sip.*;
37 import javax.sip.address.SipURI; 37 import javax.sip.address.SipURI;
38 import javax.sip.header.CallIdHeader; 38 import javax.sip.header.CallIdHeader;
  39 +import javax.sip.header.ContentTypeHeader;
  40 +import javax.sip.header.ExpiresHeader;
39 import javax.sip.header.ViaHeader; 41 import javax.sip.header.ViaHeader;
40 import javax.sip.message.Request; 42 import javax.sip.message.Request;
41 import java.lang.reflect.Field; 43 import java.lang.reflect.Field;
@@ -57,6 +59,9 @@ public class SIPCommander implements ISIPCommander { @@ -57,6 +59,9 @@ public class SIPCommander implements ISIPCommander {
57 private SipConfig sipConfig; 59 private SipConfig sipConfig;
58 60
59 @Autowired 61 @Autowired
  62 + private SipFactory sipFactory;
  63 +
  64 + @Autowired
60 @Qualifier(value="tcpSipProvider") 65 @Qualifier(value="tcpSipProvider")
61 private SipProviderImpl tcpSipProvider; 66 private SipProviderImpl tcpSipProvider;
62 67
@@ -1453,7 +1458,7 @@ public class SIPCommander implements ISIPCommander { @@ -1453,7 +1458,7 @@ public class SIPCommander implements ISIPCommander {
1453 * @param device 视频设备 1458 * @param device 视频设备
1454 * @return true = 命令发送成功 1459 * @return true = 命令发送成功
1455 */ 1460 */
1456 - public boolean mobilePositionSubscribe(Device device, SipSubscribe.Event okEvent ,SipSubscribe.Event errorEvent) { 1461 + public boolean mobilePositionSubscribe(Device device, Dialog dialog, SipSubscribe.Event okEvent ,SipSubscribe.Event errorEvent) {
1457 try { 1462 try {
1458 StringBuffer subscribePostitionXml = new StringBuffer(200); 1463 StringBuffer subscribePostitionXml = new StringBuffer(200);
1459 String charset = device.getCharset(); 1464 String charset = device.getCharset();
@@ -1467,12 +1472,20 @@ public class SIPCommander implements ISIPCommander { @@ -1467,12 +1472,20 @@ public class SIPCommander implements ISIPCommander {
1467 } 1472 }
1468 subscribePostitionXml.append("</Query>\r\n"); 1473 subscribePostitionXml.append("</Query>\r\n");
1469 1474
1470 - String tm = Long.toString(System.currentTimeMillis());  
1471 -  
1472 - CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()  
1473 - : udpSipProvider.getNewCallId();  
1474 -  
1475 - Request request = headerProvider.createSubscribeRequest(device, subscribePostitionXml.toString(), "z9hG4bK-viaPos-" + tm, "fromTagPos" + tm, null, device.getSubscribeCycleForMobilePosition(), "presence" ,callIdHeader); //Position;id=" + tm.substring(tm.length() - 4)); 1475 + Request request;
  1476 + if (dialog != null) {
  1477 + logger.info("发送移动位置订阅消息时 dialog的状态为: {}", dialog.getState());
  1478 + request = dialog.createRequest(Request.SUBSCRIBE);
  1479 + ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml");
  1480 + request.setContent(subscribePostitionXml.toString(), contentTypeHeader);
  1481 + ExpiresHeader expireHeader = sipFactory.createHeaderFactory().createExpiresHeader(device.getSubscribeCycleForMobilePosition());
  1482 + request.addHeader(expireHeader);
  1483 + }else {
  1484 + String tm = Long.toString(System.currentTimeMillis());
  1485 + CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
  1486 + : udpSipProvider.getNewCallId();
  1487 + request = headerProvider.createSubscribeRequest(device, subscribePostitionXml.toString(), "z9hG4bK-viaPos-" + tm, "fromTagPos" + tm, null, device.getSubscribeCycleForMobilePosition(), "presence" ,callIdHeader); //Position;id=" + tm.substring(tm.length() - 4));
  1488 + }
1476 transmitRequest(device, request, errorEvent, okEvent); 1489 transmitRequest(device, request, errorEvent, okEvent);
1477 1490
1478 return true; 1491 return true;
@@ -1542,7 +1555,7 @@ public class SIPCommander implements ISIPCommander { @@ -1542,7 +1555,7 @@ public class SIPCommander implements ISIPCommander {
1542 } 1555 }
1543 1556
1544 @Override 1557 @Override
1545 - public boolean catalogSubscribe(Device device, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) { 1558 + public boolean catalogSubscribe(Device device, Dialog dialog, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) {
1546 try { 1559 try {
1547 StringBuffer cmdXml = new StringBuffer(200); 1560 StringBuffer cmdXml = new StringBuffer(200);
1548 String charset = device.getCharset(); 1561 String charset = device.getCharset();
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/SubscribeRequestProcessor.java
@@ -7,7 +7,7 @@ import com.genersoft.iot.vmp.gb28181.bean.CmdType; @@ -7,7 +7,7 @@ import com.genersoft.iot.vmp.gb28181.bean.CmdType;
7 import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; 7 import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
8 import com.genersoft.iot.vmp.gb28181.bean.SubscribeHolder; 8 import com.genersoft.iot.vmp.gb28181.bean.SubscribeHolder;
9 import com.genersoft.iot.vmp.gb28181.bean.SubscribeInfo; 9 import com.genersoft.iot.vmp.gb28181.bean.SubscribeInfo;
10 -import com.genersoft.iot.vmp.gb28181.task.GPSSubscribeTask; 10 +import com.genersoft.iot.vmp.gb28181.task.impl.MobilePositionSubscribeHandlerTask;
11 import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver; 11 import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver;
12 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform; 12 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
13 import com.genersoft.iot.vmp.gb28181.transmit.event.request.ISIPRequestProcessor; 13 import com.genersoft.iot.vmp.gb28181.transmit.event.request.ISIPRequestProcessor;
@@ -147,7 +147,7 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme @@ -147,7 +147,7 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme
147 } 147 }
148 String sn = XmlUtil.getText(rootElement, "SN"); 148 String sn = XmlUtil.getText(rootElement, "SN");
149 String key = VideoManagerConstants.SIP_SUBSCRIBE_PREFIX + userSetting.getServerId() + "_MobilePosition_" + platformId; 149 String key = VideoManagerConstants.SIP_SUBSCRIBE_PREFIX + userSetting.getServerId() + "_MobilePosition_" + platformId;
150 - logger.info("接收到{}的MobilePosition订阅", platformId); 150 + logger.info("[notify-MobilePosition]: {}", platformId);
151 StringBuilder resultXml = new StringBuilder(200); 151 StringBuilder resultXml = new StringBuilder(200);
152 resultXml.append("<?xml version=\"1.0\" ?>\r\n") 152 resultXml.append("<?xml version=\"1.0\" ?>\r\n")
153 .append("<Response>\r\n") 153 .append("<Response>\r\n")
@@ -162,7 +162,7 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme @@ -162,7 +162,7 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme
162 dynamicTask.stop(key); 162 dynamicTask.stop(key);
163 } 163 }
164 String interval = XmlUtil.getText(rootElement, "Interval"); // GPS上报时间间隔 164 String interval = XmlUtil.getText(rootElement, "Interval"); // GPS上报时间间隔
165 - dynamicTask.startCron(key, new GPSSubscribeTask(redisCatchStorage, sipCommanderForPlatform, storager, platformId, sn, key, subscribeHolder), Integer.parseInt(interval)); 165 + dynamicTask.startCron(key, new MobilePositionSubscribeHandlerTask(redisCatchStorage, sipCommanderForPlatform, storager, platformId, sn, key, subscribeHolder), Integer.parseInt(interval) -1 );
166 subscribeHolder.putMobilePositionSubscribe(platformId, subscribeInfo); 166 subscribeHolder.putMobilePositionSubscribe(platformId, subscribeInfo);
167 }else if (subscribeInfo.getExpires() == 0) { 167 }else if (subscribeInfo.getExpires() == 0) {
168 dynamicTask.stop(key); 168 dynamicTask.stop(key);
@@ -200,7 +200,7 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme @@ -200,7 +200,7 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme
200 } 200 }
201 String sn = XmlUtil.getText(rootElement, "SN"); 201 String sn = XmlUtil.getText(rootElement, "SN");
202 String key = VideoManagerConstants.SIP_SUBSCRIBE_PREFIX + userSetting.getServerId() + "_Catalog_" + platformId; 202 String key = VideoManagerConstants.SIP_SUBSCRIBE_PREFIX + userSetting.getServerId() + "_Catalog_" + platformId;
203 - logger.info("接收到{}的Catalog订阅", platformId); 203 + logger.info("[notify-Catalog]: {}", platformId);
204 StringBuilder resultXml = new StringBuilder(200); 204 StringBuilder resultXml = new StringBuilder(200);
205 resultXml.append("<?xml version=\"1.0\" ?>\r\n") 205 resultXml.append("<?xml version=\"1.0\" ?>\r\n")
206 .append("<Response>\r\n") 206 .append("<Response>\r\n")
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/response/impl/InviteResponseProcessor.java
@@ -81,7 +81,7 @@ public class InviteResponseProcessor extends SIPResponseProcessorAbstract { @@ -81,7 +81,7 @@ public class InviteResponseProcessor extends SIPResponseProcessorAbstract {
81 } 81 }
82 requestURI.setPort(event.getRemotePort()); 82 requestURI.setPort(event.getRemotePort());
83 reqAck.setRequestURI(requestURI); 83 reqAck.setRequestURI(requestURI);
84 - logger.info("向 " + event.getRemoteIpAddress() + ":" + event.getRemotePort() + "回复ack"); 84 + logger.info("[回复ack] {}-> {}:{} ",requestURI, event.getRemoteIpAddress(), event.getRemotePort());
85 85
86 dialog.sendAck(reqAck); 86 dialog.sendAck(reqAck);
87 87
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRTPServerFactory.java
@@ -82,9 +82,14 @@ public class ZLMRTPServerFactory { @@ -82,9 +82,14 @@ public class ZLMRTPServerFactory {
82 } 82 }
83 83
84 public int createRTPServer(MediaServerItem mediaServerItem, String streamId) { 84 public int createRTPServer(MediaServerItem mediaServerItem, String streamId) {
85 -  
86 - Map<String, Object> param = new HashMap<>();  
87 int result = -1; 85 int result = -1;
  86 + // 查询此rtp server 是否已经存在
  87 + JSONObject rtpInfo = zlmresTfulUtils.getRtpInfo(mediaServerItem, streamId);
  88 + if (rtpInfo.getInteger("code ") == 0 && rtpInfo.getBoolean("exist")) {
  89 + result = rtpInfo.getInteger("local_port");
  90 + return result;
  91 + }
  92 + Map<String, Object> param = new HashMap<>();
88 // 推流端口设置0则使用随机端口 93 // 推流端口设置0则使用随机端口
89 param.put("enable_tcp", 1); 94 param.put("enable_tcp", 1);
90 param.put("stream_id", streamId); 95 param.put("stream_id", streamId);
@@ -301,7 +306,7 @@ public class ZLMRTPServerFactory { @@ -301,7 +306,7 @@ public class ZLMRTPServerFactory {
301 result= true; 306 result= true;
302 logger.info("停止RTP推流成功"); 307 logger.info("停止RTP推流成功");
303 } else { 308 } else {
304 - logger.error("RTP推流失败: {}, 参数:{}",jsonObject.getString("msg"),JSONObject.toJSON(param)); 309 + logger.error("停止RTP推流失败: {}, 参数:{}",jsonObject.getString("msg"),JSONObject.toJSON(param));
305 } 310 }
306 return result; 311 return result;
307 } 312 }
src/main/java/com/genersoft/iot/vmp/service/impl/DeviceServiceImpl.java
@@ -4,8 +4,8 @@ import com.genersoft.iot.vmp.conf.DynamicTask; @@ -4,8 +4,8 @@ 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.service.IDeviceService; 6 import com.genersoft.iot.vmp.service.IDeviceService;
7 -import com.genersoft.iot.vmp.service.bean.CatalogSubscribeTask;  
8 -import com.genersoft.iot.vmp.service.bean.MobilePositionSubscribeTask; 7 +import com.genersoft.iot.vmp.gb28181.task.impl.CatalogSubscribeTask;
  8 +import com.genersoft.iot.vmp.gb28181.task.impl.MobilePositionSubscribeTask;
9 import org.slf4j.Logger; 9 import org.slf4j.Logger;
10 import org.slf4j.LoggerFactory; 10 import org.slf4j.LoggerFactory;
11 import org.springframework.beans.factory.annotation.Autowired; 11 import org.springframework.beans.factory.annotation.Autowired;
@@ -42,7 +42,7 @@ public class DeviceServiceImpl implements IDeviceService { @@ -42,7 +42,7 @@ public class DeviceServiceImpl implements IDeviceService {
42 int subscribeCycleForCatalog = device.getSubscribeCycleForCatalog(); 42 int subscribeCycleForCatalog = device.getSubscribeCycleForCatalog();
43 // 设置最小值为30 43 // 设置最小值为30
44 subscribeCycleForCatalog = Math.max(subscribeCycleForCatalog, 30); 44 subscribeCycleForCatalog = Math.max(subscribeCycleForCatalog, 30);
45 - dynamicTask.startCron(device.getDeviceId() + "catalog", catalogSubscribeTask, subscribeCycleForCatalog - 5); 45 + dynamicTask.startCron(device.getDeviceId() + "catalog", catalogSubscribeTask, subscribeCycleForCatalog);
46 return true; 46 return true;
47 } 47 }
48 48
@@ -53,8 +53,6 @@ public class DeviceServiceImpl implements IDeviceService { @@ -53,8 +53,6 @@ public class DeviceServiceImpl implements IDeviceService {
53 } 53 }
54 logger.info("移除目录订阅: {}", device.getDeviceId()); 54 logger.info("移除目录订阅: {}", device.getDeviceId());
55 dynamicTask.stop(device.getDeviceId() + "catalog"); 55 dynamicTask.stop(device.getDeviceId() + "catalog");
56 - device.setSubscribeCycleForCatalog(0);  
57 - sipCommander.catalogSubscribe(device, null, null);  
58 return true; 56 return true;
59 } 57 }
60 58
@@ -75,7 +73,7 @@ public class DeviceServiceImpl implements IDeviceService { @@ -75,7 +73,7 @@ public class DeviceServiceImpl implements IDeviceService {
75 int subscribeCycleForCatalog = device.getSubscribeCycleForCatalog(); 73 int subscribeCycleForCatalog = device.getSubscribeCycleForCatalog();
76 // 设置最小值为30 74 // 设置最小值为30
77 subscribeCycleForCatalog = Math.max(subscribeCycleForCatalog, 30); 75 subscribeCycleForCatalog = Math.max(subscribeCycleForCatalog, 30);
78 - dynamicTask.startCron(device.getDeviceId() + "mobile_position" , mobilePositionSubscribeTask, subscribeCycleForCatalog - 5); 76 + dynamicTask.startCron(device.getDeviceId() + "mobile_position" , mobilePositionSubscribeTask, subscribeCycleForCatalog -1 );
79 return true; 77 return true;
80 } 78 }
81 79
@@ -86,8 +84,6 @@ public class DeviceServiceImpl implements IDeviceService { @@ -86,8 +84,6 @@ public class DeviceServiceImpl implements IDeviceService {
86 } 84 }
87 logger.info("移除移动位置订阅: {}", device.getDeviceId()); 85 logger.info("移除移动位置订阅: {}", device.getDeviceId());
88 dynamicTask.stop(device.getDeviceId() + "mobile_position"); 86 dynamicTask.stop(device.getDeviceId() + "mobile_position");
89 - device.setSubscribeCycleForCatalog(0);  
90 - sipCommander.mobilePositionSubscribe(device, null, null);  
91 return true; 87 return true;
92 } 88 }
93 } 89 }
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/MobilePosition/MobilePositionController.java
@@ -8,6 +8,7 @@ import com.genersoft.iot.vmp.gb28181.bean.MobilePosition; @@ -8,6 +8,7 @@ import com.genersoft.iot.vmp.gb28181.bean.MobilePosition;
8 import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; 8 import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
9 import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; 9 import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
10 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; 10 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
  11 +import com.genersoft.iot.vmp.service.IDeviceService;
11 import com.genersoft.iot.vmp.storager.IVideoManagerStorage; 12 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
12 import com.github.pagehelper.util.StringUtil; 13 import com.github.pagehelper.util.StringUtil;
13 14
@@ -48,6 +49,9 @@ public class MobilePositionController { @@ -48,6 +49,9 @@ public class MobilePositionController {
48 @Autowired 49 @Autowired
49 private DeferredResultHolder resultHolder; 50 private DeferredResultHolder resultHolder;
50 51
  52 + @Autowired
  53 + private IDeviceService deviceService;
  54 +
51 /** 55 /**
52 * 查询历史轨迹 56 * 查询历史轨迹
53 * @param deviceId 设备ID 57 * @param deviceId 设备ID
@@ -163,7 +167,7 @@ public class MobilePositionController { @@ -163,7 +167,7 @@ public class MobilePositionController {
163 device.setMobilePositionSubmissionInterval(Integer.parseInt(interval)); 167 device.setMobilePositionSubmissionInterval(Integer.parseInt(interval));
164 storager.updateDevice(device); 168 storager.updateDevice(device);
165 String result = msg; 169 String result = msg;
166 - if (cmder.mobilePositionSubscribe(device, null, null)) { 170 + if (deviceService.removeMobilePositionSubscribe(device)) {
167 result += ",成功"; 171 result += ",成功";
168 } else { 172 } else {
169 result += ",失败"; 173 result += ",失败";
web_src/src/components/dialog/deviceEdit.vue
@@ -10,7 +10,7 @@ @@ -10,7 +10,7 @@
10 @close="close()" 10 @close="close()"
11 > 11 >
12 <div id="shared" style="margin-top: 1rem;margin-right: 100px;"> 12 <div id="shared" style="margin-top: 1rem;margin-right: 100px;">
13 - <el-form ref="form" :rules="rules" :model="form" label-width="240px" > 13 + <el-form ref="form" :rules="rules" :model="form" label-width="200px" >
14 <el-form-item label="设备编号" > 14 <el-form-item label="设备编号" >
15 <el-input v-model="form.deviceId" disabled></el-input> 15 <el-input v-model="form.deviceId" disabled></el-input>
16 </el-form-item> 16 </el-form-item>
@@ -36,13 +36,13 @@ @@ -36,13 +36,13 @@
36 <el-option key="UTF-8" label="UTF-8" value="utf-8"></el-option> 36 <el-option key="UTF-8" label="UTF-8" value="utf-8"></el-option>
37 </el-select> 37 </el-select>
38 </el-form-item> 38 </el-form-item>
39 - <el-form-item label="目录订阅周期(0为停用订阅)" prop="subscribeCycleForCatalog" > 39 + <el-form-item label="目录订阅" title="0为取消订阅" prop="subscribeCycleForCatalog" >
40 <el-input v-model="form.subscribeCycleForCatalog" clearable ></el-input> 40 <el-input v-model="form.subscribeCycleForCatalog" clearable ></el-input>
41 </el-form-item> 41 </el-form-item>
42 - <el-form-item label="移动位置订阅周期(0为停用订阅)" prop="subscribeCycleForCatalog" > 42 + <el-form-item label="移动位置订阅" title="0为取消订阅" prop="subscribeCycleForCatalog" >
43 <el-input v-model="form.subscribeCycleForMobilePosition" clearable ></el-input> 43 <el-input v-model="form.subscribeCycleForMobilePosition" clearable ></el-input>
44 </el-form-item> 44 </el-form-item>
45 - <el-form-item label="移动位置报送间隔" prop="subscribeCycleForCatalog" > 45 + <el-form-item v-if="form.subscribeCycleForMobilePosition > 0" label="移动位置报送间隔" prop="subscribeCycleForCatalog" >
46 <el-input v-model="form.mobilePositionSubmissionInterval" clearable ></el-input> 46 <el-input v-model="form.mobilePositionSubmissionInterval" clearable ></el-input>
47 </el-form-item> 47 </el-form-item>
48 <el-form-item> 48 <el-form-item>
@@ -98,6 +98,9 @@ export default { @@ -98,6 +98,9 @@ export default {
98 onSubmit: function () { 98 onSubmit: function () {
99 console.log("onSubmit"); 99 console.log("onSubmit");
100 console.log(this.form); 100 console.log(this.form);
  101 + this.form.subscribeCycleForCatalog = this.form.subscribeCycleForCatalog||0
  102 + this.form.subscribeCycleForMobilePosition = this.form.subscribeCycleForMobilePosition||0
  103 + this.form.mobilePositionSubmissionInterval = this.form.mobilePositionSubmissionInterval||0
101 this.$axios({ 104 this.$axios({
102 method: 'post', 105 method: 'post',
103 url:`/api/device/query/device/update/`, 106 url:`/api/device/query/device/update/`,