Просмотр исходного кода

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

648540858 3 лет назад
Родитель
Сommit
f10b458fc9
16 измененных файлов с 242 добавлено и 124 удалено
  1. 10 4
      src/main/java/com/genersoft/iot/vmp/conf/DynamicTask.java
  2. 9 5
      src/main/java/com/genersoft/iot/vmp/conf/runner/SipDeviceRunner.java
  3. 5 0
      src/main/java/com/genersoft/iot/vmp/gb28181/task/ISubscribeTask.java
  4. 75 0
      src/main/java/com/genersoft/iot/vmp/gb28181/task/impl/CatalogSubscribeTask.java
  5. 12 4
      src/main/java/com/genersoft/iot/vmp/gb28181/task/GPSSubscribeTask.java
  6. 77 0
      src/main/java/com/genersoft/iot/vmp/gb28181/task/impl/MobilePositionSubscribeTask.java
  7. 4 2
      src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java
  8. 21 8
      src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
  9. 4 4
      src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/SubscribeRequestProcessor.java
  10. 1 1
      src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/response/impl/InviteResponseProcessor.java
  11. 8 3
      src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRTPServerFactory.java
  12. 0 42
      src/main/java/com/genersoft/iot/vmp/service/bean/CatalogSubscribeTask.java
  13. 0 38
      src/main/java/com/genersoft/iot/vmp/service/bean/MobilePositionSubscribeTask.java
  14. 4 8
      src/main/java/com/genersoft/iot/vmp/service/impl/DeviceServiceImpl.java
  15. 5 1
      src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/MobilePosition/MobilePositionController.java
  16. 7 4
      web_src/src/components/dialog/deviceEdit.vue

+ 10 - 4
src/main/java/com/genersoft/iot/vmp/conf/DynamicTask.java

@@ -1,5 +1,6 @@
 package com.genersoft.iot.vmp.conf;
 
+import com.genersoft.iot.vmp.gb28181.task.ISubscribeTask;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.annotation.Bean;
 import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
@@ -21,6 +22,7 @@ public class DynamicTask {
     private ThreadPoolTaskScheduler threadPoolTaskScheduler;
 
     private Map<String, ScheduledFuture<?>> futureMap = new ConcurrentHashMap<>();
+    private Map<String, Runnable> runnableMap = new ConcurrentHashMap<>();
 
     @Bean
     public ThreadPoolTaskScheduler threadPoolTaskScheduler() {
@@ -34,12 +36,12 @@ public class DynamicTask {
      * @param cycleForCatalog 间隔
      * @return
      */
-    public String startCron(String key, Runnable task, int cycleForCatalog) {
+    public void startCron(String key, Runnable task, int cycleForCatalog) {
         stop(key);
         // scheduleWithFixedDelay 必须等待上一个任务结束才开始计时period, cycleForCatalog表示执行的间隔
         ScheduledFuture future = threadPoolTaskScheduler.scheduleWithFixedDelay(task, cycleForCatalog * 1000L);
         futureMap.put(key, future);
-        return "startCron";
+        runnableMap.put(key, task);
     }
 
     /**
@@ -49,18 +51,22 @@ public class DynamicTask {
      * @param delay 延时 /毫秒
      * @return
      */
-    public String startDelay(String key, Runnable task, int delay) {
+    public void startDelay(String key, Runnable task, int delay) {
         stop(key);
         Date starTime = new Date(System.currentTimeMillis() + delay);
         // scheduleWithFixedDelay 必须等待上一个任务结束才开始计时period, cycleForCatalog表示执行的间隔
         ScheduledFuture future = threadPoolTaskScheduler.schedule(task, starTime);
         futureMap.put(key, future);
-        return "startCron";
     }
 
     public void stop(String key) {
         if (futureMap.get(key) != null && !futureMap.get(key).isCancelled()) {
             futureMap.get(key).cancel(true);
+            Runnable runnable = runnableMap.get(key);
+            if (runnable instanceof ISubscribeTask) {
+                ISubscribeTask subscribeTask = (ISubscribeTask) runnable;
+                subscribeTask.stop();
+            }
         }
     }
 

+ 9 - 5
src/main/java/com/genersoft/iot/vmp/conf/runner/SipDeviceRunner.java

@@ -14,7 +14,7 @@ import java.util.List;
 
 
 /**
- * 系统启动时控制设备离线
+ * 系统启动时控制设备
  */
 @Component
 @Order(value=4)
@@ -41,10 +41,14 @@ public class SipDeviceRunner implements CommandLineRunner {
         for (String deviceId : onlineForAll) {
             storager.online(deviceId);
             Device device = redisCatchStorage.getDevice(deviceId);
-            if (device != null && device.getSubscribeCycleForCatalog() > 0) {
-                // 查询在线设备那些开启了订阅,为设备开启定时的目录订阅
-                deviceService.addCatalogSubscribe(device);
-                deviceService.addMobilePositionSubscribe(device);
+            if (device != null ) {
+                if (device.getSubscribeCycleForCatalog() > 0) {
+                    // 查询在线设备那些开启了订阅,为设备开启定时的目录订阅
+                    deviceService.addCatalogSubscribe(device);
+                }
+                if (device.getSubscribeCycleForMobilePosition() > 0) {
+                    deviceService.addMobilePositionSubscribe(device);
+                }
             }
         }
         // 重置cseq计数

+ 5 - 0
src/main/java/com/genersoft/iot/vmp/gb28181/task/ISubscribeTask.java

@@ -0,0 +1,5 @@
+package com.genersoft.iot.vmp.gb28181.task;
+
+public interface ISubscribeTask extends Runnable{
+    void stop();
+}

+ 75 - 0
src/main/java/com/genersoft/iot/vmp/gb28181/task/impl/CatalogSubscribeTask.java

@@ -0,0 +1,75 @@
+package com.genersoft.iot.vmp.gb28181.task.impl;
+
+import com.genersoft.iot.vmp.gb28181.bean.Device;
+import com.genersoft.iot.vmp.gb28181.task.ISubscribeTask;
+import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.sip.Dialog;
+import javax.sip.DialogState;
+import javax.sip.ResponseEvent;
+
+/**
+ * 目录订阅任务
+ */
+public class CatalogSubscribeTask implements ISubscribeTask {
+    private final Logger logger = LoggerFactory.getLogger(CatalogSubscribeTask.class);
+    private Device device;
+    private final ISIPCommander sipCommander;
+    private Dialog dialog;
+
+    public CatalogSubscribeTask(Device device, ISIPCommander sipCommander) {
+        this.device = device;
+        this.sipCommander = sipCommander;
+    }
+
+    @Override
+    public void run() {
+        sipCommander.catalogSubscribe(device, dialog, eventResult -> {
+            if (eventResult.dialog != null || eventResult.dialog.getState().equals(DialogState.CONFIRMED)) {
+                dialog = eventResult.dialog;
+            }
+            ResponseEvent event = (ResponseEvent) eventResult.event;
+            if (event.getResponse().getRawContent() != null) {
+                // 成功
+                logger.info("[目录订阅]成功: {}", device.getDeviceId());
+            }else {
+                // 成功
+                logger.info("[目录订阅]成功: {}", device.getDeviceId());
+            }
+        },eventResult -> {
+            dialog = null;
+            // 失败
+            logger.warn("[目录订阅]失败,信令发送失败: {}-{} ", device.getDeviceId(), eventResult.msg);
+        });
+    }
+
+    @Override
+    public void stop() {
+        /**
+         * dialog 的各个状态
+         * EARLY-> Early state状态-初始请求发送以后,收到了一个临时响应消息
+         * CONFIRMED-> Confirmed Dialog状态-已确认
+         * COMPLETED-> Completed Dialog状态-已完成
+         * TERMINATED-> Terminated Dialog状态-终止
+         */
+        logger.info("取消目录订阅时dialog状态为{}", DialogState.CONFIRMED);
+        if (dialog != null && dialog.getState().equals(DialogState.CONFIRMED)) {
+            device.setSubscribeCycleForCatalog(0);
+            sipCommander.mobilePositionSubscribe(device, dialog, eventResult -> {
+                ResponseEvent event = (ResponseEvent) eventResult.event;
+                if (event.getResponse().getRawContent() != null) {
+                    // 成功
+                    logger.info("[取消目录订阅订阅]成功: {}", device.getDeviceId());
+                }else {
+                    // 成功
+                    logger.info("[取消目录订阅订阅]成功: {}", device.getDeviceId());
+                }
+            },eventResult -> {
+                // 失败
+                logger.warn("[取消目录订阅订阅]失败,信令发送失败: {}-{} ", device.getDeviceId(), eventResult.msg);
+            });
+        }
+    }
+}

+ 12 - 4
src/main/java/com/genersoft/iot/vmp/gb28181/task/GPSSubscribeTask.java

@@ -1,10 +1,10 @@
-package com.genersoft.iot.vmp.gb28181.task;
+package com.genersoft.iot.vmp.gb28181.task.impl;
 
-import com.alibaba.fastjson.JSON;
 import com.genersoft.iot.vmp.gb28181.bean.GbStream;
 import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
 import com.genersoft.iot.vmp.gb28181.bean.SubscribeHolder;
 import com.genersoft.iot.vmp.gb28181.bean.SubscribeInfo;
+import com.genersoft.iot.vmp.gb28181.task.ISubscribeTask;
 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
 import com.genersoft.iot.vmp.service.bean.GPSMsgInfo;
 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
@@ -13,7 +13,10 @@ import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
 import java.text.SimpleDateFormat;
 import java.util.List;
 
-public class GPSSubscribeTask implements Runnable{
+/**
+ * 向已经订阅(移动位置)的上级发送MobilePosition消息
+ */
+public class MobilePositionSubscribeHandlerTask implements ISubscribeTask {
 
     private IRedisCatchStorage redisCatchStorage;
     private IVideoManagerStorage storager;
@@ -25,7 +28,7 @@ public class GPSSubscribeTask implements Runnable{
 
     private final SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
 
-    public GPSSubscribeTask(IRedisCatchStorage redisCatchStorage, ISIPCommanderForPlatform sipCommanderForPlatform, IVideoManagerStorage storager, String platformId, String sn, String key, SubscribeHolder subscribeInfo) {
+    public MobilePositionSubscribeHandlerTask(IRedisCatchStorage redisCatchStorage, ISIPCommanderForPlatform sipCommanderForPlatform, IVideoManagerStorage storager, String platformId, String sn, String key, SubscribeHolder subscribeInfo) {
         this.redisCatchStorage = redisCatchStorage;
         this.storager = storager;
         this.platformId = platformId;
@@ -66,4 +69,9 @@ public class GPSSubscribeTask implements Runnable{
             }
         }
     }
+
+    @Override
+    public void stop() {
+
+    }
 }

+ 77 - 0
src/main/java/com/genersoft/iot/vmp/gb28181/task/impl/MobilePositionSubscribeTask.java

@@ -0,0 +1,77 @@
+package com.genersoft.iot.vmp.gb28181.task.impl;
+
+import com.genersoft.iot.vmp.gb28181.bean.Device;
+import com.genersoft.iot.vmp.gb28181.task.ISubscribeTask;
+import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
+import org.dom4j.Element;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.sip.Dialog;
+import javax.sip.DialogState;
+import javax.sip.ResponseEvent;
+
+/**
+ * 移动位置订阅的定时更新
+ */
+public class MobilePositionSubscribeTask implements ISubscribeTask {
+    private final Logger logger = LoggerFactory.getLogger(MobilePositionSubscribeTask.class);
+    private  Device device;
+    private  ISIPCommander sipCommander;
+    private Dialog dialog;
+
+    public MobilePositionSubscribeTask(Device device, ISIPCommander sipCommander) {
+        this.device = device;
+        this.sipCommander = sipCommander;
+    }
+
+    @Override
+    public void run() {
+        sipCommander.mobilePositionSubscribe(device, dialog, eventResult -> {
+            if (eventResult.dialog != null || eventResult.dialog.getState().equals(DialogState.CONFIRMED)) {
+                dialog = eventResult.dialog;
+            }
+            ResponseEvent event = (ResponseEvent) eventResult.event;
+            if (event.getResponse().getRawContent() != null) {
+                // 成功
+                logger.info("[移动位置订阅]成功: {}", device.getDeviceId());
+            }else {
+                // 成功
+                logger.info("[移动位置订阅]成功: {}", device.getDeviceId());
+            }
+        },eventResult -> {
+            dialog = null;
+            // 失败
+            logger.warn("[移动位置订阅]失败,信令发送失败: {}-{} ", device.getDeviceId(), eventResult.msg);
+        });
+
+    }
+
+    @Override
+    public void stop() {
+        /**
+         * dialog 的各个状态
+         * EARLY-> Early state状态-初始请求发送以后,收到了一个临时响应消息
+         * CONFIRMED-> Confirmed Dialog状态-已确认
+         * COMPLETED-> Completed Dialog状态-已完成
+         * TERMINATED-> Terminated Dialog状态-终止
+         */
+        logger.info("取消移动订阅时dialog状态为{}", dialog.getState());
+        if (dialog != null && dialog.getState().equals(DialogState.CONFIRMED)) {
+            device.setSubscribeCycleForMobilePosition(0);
+            sipCommander.mobilePositionSubscribe(device, dialog, eventResult -> {
+                ResponseEvent event = (ResponseEvent) eventResult.event;
+                if (event.getResponse().getRawContent() != null) {
+                    // 成功
+                    logger.info("[取消移动位置订阅]成功: {}", device.getDeviceId());
+                }else {
+                    // 成功
+                    logger.info("[取消移动位置订阅]成功: {}", device.getDeviceId());
+                }
+            },eventResult -> {
+                // 失败
+                logger.warn("[取消移动位置订阅]失败,信令发送失败: {}-{} ", device.getDeviceId(), eventResult.msg);
+            });
+        }
+    }
+}

+ 4 - 2
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java

@@ -8,6 +8,8 @@ import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe;
 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
 import com.genersoft.iot.vmp.service.bean.SSRCInfo;
 
+import javax.sip.Dialog;
+
 /**    
  * @description:设备能力接口,用于定义设备的控制、查询能力   
  * @author: swwheihei
@@ -304,7 +306,7 @@ public interface ISIPCommander {
 	 * @param device	视频设备
 	 * @return			true = 命令发送成功
 	 */
-	boolean mobilePositionSubscribe(Device device, SipSubscribe.Event okEvent ,SipSubscribe.Event errorEvent);
+	boolean mobilePositionSubscribe(Device device, Dialog dialog, SipSubscribe.Event okEvent , SipSubscribe.Event errorEvent);
 
 	/**
 	 * 订阅、取消订阅报警信息
@@ -324,7 +326,7 @@ public interface ISIPCommander {
 	 * @param device		视频设备
 	 * @return				true = 命令发送成功
 	 */
-	boolean catalogSubscribe(Device device, SipSubscribe.Event okEvent ,SipSubscribe.Event errorEvent);
+	boolean catalogSubscribe(Device device, Dialog dialog, SipSubscribe.Event okEvent ,SipSubscribe.Event errorEvent);
 
 	/**
 	 * 拉框控制命令

+ 21 - 8
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java

@@ -36,6 +36,8 @@ import org.springframework.util.StringUtils;
 import javax.sip.*;
 import javax.sip.address.SipURI;
 import javax.sip.header.CallIdHeader;
+import javax.sip.header.ContentTypeHeader;
+import javax.sip.header.ExpiresHeader;
 import javax.sip.header.ViaHeader;
 import javax.sip.message.Request;
 import java.lang.reflect.Field;
@@ -56,6 +58,9 @@ public class SIPCommander implements ISIPCommander {
 	@Autowired
 	private SipConfig sipConfig;
 
+	@Autowired
+	private SipFactory sipFactory;
+
 	@Autowired
 	@Qualifier(value="tcpSipProvider")
 	private SipProviderImpl tcpSipProvider;
@@ -1453,7 +1458,7 @@ public class SIPCommander implements ISIPCommander {
 	 * @param device	视频设备
 	 * @return			true = 命令发送成功
 	 */
-	public boolean mobilePositionSubscribe(Device device, SipSubscribe.Event okEvent ,SipSubscribe.Event errorEvent) {
+	public boolean mobilePositionSubscribe(Device device, Dialog dialog, SipSubscribe.Event okEvent ,SipSubscribe.Event errorEvent) {
 		try {
 			StringBuffer subscribePostitionXml = new StringBuffer(200);
 			String charset = device.getCharset();
@@ -1467,12 +1472,20 @@ public class SIPCommander implements ISIPCommander {
 			}
 			subscribePostitionXml.append("</Query>\r\n");
 
-			String tm = Long.toString(System.currentTimeMillis());
-
-			CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
-					: udpSipProvider.getNewCallId();
-
-			Request request = headerProvider.createSubscribeRequest(device, subscribePostitionXml.toString(), "z9hG4bK-viaPos-" + tm, "fromTagPos" + tm, null, device.getSubscribeCycleForMobilePosition(), "presence" ,callIdHeader); //Position;id=" + tm.substring(tm.length() - 4));
+			Request request;
+			if (dialog != null) {
+				logger.info("发送移动位置订阅消息时 dialog的状态为: {}", dialog.getState());
+				request = dialog.createRequest(Request.SUBSCRIBE);
+				ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml");
+				request.setContent(subscribePostitionXml.toString(), contentTypeHeader);
+				ExpiresHeader expireHeader = sipFactory.createHeaderFactory().createExpiresHeader(device.getSubscribeCycleForMobilePosition());
+				request.addHeader(expireHeader);
+			}else {
+				String tm = Long.toString(System.currentTimeMillis());
+				CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
+						: udpSipProvider.getNewCallId();
+				request = headerProvider.createSubscribeRequest(device, subscribePostitionXml.toString(), "z9hG4bK-viaPos-" + tm, "fromTagPos" + tm, null, device.getSubscribeCycleForMobilePosition(), "presence" ,callIdHeader); //Position;id=" + tm.substring(tm.length() - 4));
+			}
 			transmitRequest(device, request, errorEvent, okEvent);
 
 			return true;
@@ -1542,7 +1555,7 @@ public class SIPCommander implements ISIPCommander {
 	}
 
 	@Override
-	public boolean catalogSubscribe(Device device, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) {
+	public boolean catalogSubscribe(Device device, Dialog dialog, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) {
 		try {
 			StringBuffer cmdXml = new StringBuffer(200);
 			String charset = device.getCharset();

+ 4 - 4
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;
 import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
 import com.genersoft.iot.vmp.gb28181.bean.SubscribeHolder;
 import com.genersoft.iot.vmp.gb28181.bean.SubscribeInfo;
-import com.genersoft.iot.vmp.gb28181.task.GPSSubscribeTask;
+import com.genersoft.iot.vmp.gb28181.task.impl.MobilePositionSubscribeHandlerTask;
 import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver;
 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
 import com.genersoft.iot.vmp.gb28181.transmit.event.request.ISIPRequestProcessor;
@@ -147,7 +147,7 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme
 		}
 		String sn = XmlUtil.getText(rootElement, "SN");
 		String key = VideoManagerConstants.SIP_SUBSCRIBE_PREFIX + userSetting.getServerId() +  "_MobilePosition_" + platformId;
-		logger.info("接收到{}的MobilePosition订阅", platformId);
+		logger.info("[notify-MobilePosition]: {}", platformId);
 		StringBuilder resultXml = new StringBuilder(200);
 		resultXml.append("<?xml version=\"1.0\" ?>\r\n")
 				.append("<Response>\r\n")
@@ -162,7 +162,7 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme
 				dynamicTask.stop(key);
 			}
 			String interval = XmlUtil.getText(rootElement, "Interval"); // GPS上报时间间隔
-			dynamicTask.startCron(key, new GPSSubscribeTask(redisCatchStorage, sipCommanderForPlatform, storager,  platformId, sn, key, subscribeHolder), Integer.parseInt(interval));
+			dynamicTask.startCron(key, new MobilePositionSubscribeHandlerTask(redisCatchStorage, sipCommanderForPlatform, storager,  platformId, sn, key, subscribeHolder), Integer.parseInt(interval) -1 );
 			subscribeHolder.putMobilePositionSubscribe(platformId, subscribeInfo);
 		}else if (subscribeInfo.getExpires() == 0) {
 			dynamicTask.stop(key);
@@ -200,7 +200,7 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme
 		}
 		String sn = XmlUtil.getText(rootElement, "SN");
 		String key = VideoManagerConstants.SIP_SUBSCRIBE_PREFIX + userSetting.getServerId() +  "_Catalog_" + platformId;
-		logger.info("接收到{}的Catalog订阅", platformId);
+		logger.info("[notify-Catalog]: {}", platformId);
 		StringBuilder resultXml = new StringBuilder(200);
 		resultXml.append("<?xml version=\"1.0\" ?>\r\n")
 				.append("<Response>\r\n")

+ 1 - 1
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/response/impl/InviteResponseProcessor.java

@@ -81,7 +81,7 @@ public class InviteResponseProcessor extends SIPResponseProcessorAbstract {
 				}
 				requestURI.setPort(event.getRemotePort());
 				reqAck.setRequestURI(requestURI);
-				logger.info("向 " + event.getRemoteIpAddress() + ":" + event.getRemotePort() + "回复ack");
+				logger.info("[回复ack] {}-> {}:{} ",requestURI, event.getRemoteIpAddress(), event.getRemotePort());
 
 				dialog.sendAck(reqAck);
 

+ 8 - 3
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRTPServerFactory.java

@@ -82,9 +82,14 @@ public class ZLMRTPServerFactory {
     }
 
     public int createRTPServer(MediaServerItem mediaServerItem, String streamId) {
-
-        Map<String, Object> param = new HashMap<>();
         int result = -1;
+        // 查询此rtp server 是否已经存在
+        JSONObject rtpInfo = zlmresTfulUtils.getRtpInfo(mediaServerItem, streamId);
+        if (rtpInfo.getInteger("code ") == 0 && rtpInfo.getBoolean("exist")) {
+            result = rtpInfo.getInteger("local_port");
+            return result;
+        }
+        Map<String, Object> param = new HashMap<>();
         // 推流端口设置0则使用随机端口
         param.put("enable_tcp", 1);
         param.put("stream_id", streamId);
@@ -301,7 +306,7 @@ public class ZLMRTPServerFactory {
             result= true;
             logger.info("停止RTP推流成功");
         } else {
-            logger.error("RTP推流失败: {}, 参数:{}",jsonObject.getString("msg"),JSONObject.toJSON(param));
+            logger.error("停止RTP推流失败: {}, 参数:{}",jsonObject.getString("msg"),JSONObject.toJSON(param));
         }
         return result;
     }

+ 0 - 42
src/main/java/com/genersoft/iot/vmp/service/bean/CatalogSubscribeTask.java

@@ -1,42 +0,0 @@
-package com.genersoft.iot.vmp.service.bean;
-
-import com.genersoft.iot.vmp.gb28181.bean.Device;
-import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
-import com.genersoft.iot.vmp.gb28181.utils.XmlUtil;
-import org.dom4j.DocumentException;
-import org.dom4j.Element;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import javax.sip.ResponseEvent;
-
-/**
- * 目录订阅任务
- */
-public class CatalogSubscribeTask implements Runnable{
-    private final Logger logger = LoggerFactory.getLogger(CatalogSubscribeTask.class);
-    private  Device device;
-    private  ISIPCommander sipCommander;
-
-    public CatalogSubscribeTask(Device device, ISIPCommander sipCommander) {
-        this.device = device;
-        this.sipCommander = sipCommander;
-    }
-
-    @Override
-    public void run() {
-        sipCommander.catalogSubscribe(device, eventResult -> {
-            ResponseEvent event = (ResponseEvent) eventResult.event;
-            if (event.getResponse().getRawContent() != null) {
-                // 成功
-                logger.info("[目录订阅]成功: {}", device.getDeviceId());
-            }else {
-                // 成功
-                logger.info("[目录订阅]成功: {}", device.getDeviceId());
-            }
-        },eventResult -> {
-            // 失败
-            logger.warn("[目录订阅]失败,信令发送失败: {}-{} ", device.getDeviceId(), eventResult.msg);
-        });
-    }
-}

+ 0 - 38
src/main/java/com/genersoft/iot/vmp/service/bean/MobilePositionSubscribeTask.java

@@ -1,38 +0,0 @@
-package com.genersoft.iot.vmp.service.bean;
-
-import com.genersoft.iot.vmp.gb28181.bean.Device;
-import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
-import org.dom4j.Element;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import javax.sip.ResponseEvent;
-
-public class MobilePositionSubscribeTask implements Runnable{
-    private final Logger logger = LoggerFactory.getLogger(MobilePositionSubscribeTask.class);
-    private  Device device;
-    private  ISIPCommander sipCommander;
-
-    public MobilePositionSubscribeTask(Device device, ISIPCommander sipCommander) {
-        this.device = device;
-        this.sipCommander = sipCommander;
-    }
-
-    @Override
-    public void run() {
-        sipCommander.mobilePositionSubscribe(device, eventResult -> {
-            ResponseEvent event = (ResponseEvent) eventResult.event;
-            Element rootElement = null;
-            if (event.getResponse().getRawContent() != null) {
-                // 成功
-                logger.info("[移动位置订阅]成功: {}", device.getDeviceId());
-            }else {
-                // 成功
-                logger.info("[移动位置订阅]成功: {}", device.getDeviceId());
-            }
-        },eventResult -> {
-            // 失败
-            logger.warn("[移动位置订阅]失败,信令发送失败: {}-{} ", device.getDeviceId(), eventResult.msg);
-        });
-    }
-}

+ 4 - 8
src/main/java/com/genersoft/iot/vmp/service/impl/DeviceServiceImpl.java

@@ -4,8 +4,8 @@ import com.genersoft.iot.vmp.conf.DynamicTask;
 import com.genersoft.iot.vmp.gb28181.bean.Device;
 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
 import com.genersoft.iot.vmp.service.IDeviceService;
-import com.genersoft.iot.vmp.service.bean.CatalogSubscribeTask;
-import com.genersoft.iot.vmp.service.bean.MobilePositionSubscribeTask;
+import com.genersoft.iot.vmp.gb28181.task.impl.CatalogSubscribeTask;
+import com.genersoft.iot.vmp.gb28181.task.impl.MobilePositionSubscribeTask;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -42,7 +42,7 @@ public class DeviceServiceImpl implements IDeviceService {
         int subscribeCycleForCatalog = device.getSubscribeCycleForCatalog();
         // 设置最小值为30
         subscribeCycleForCatalog = Math.max(subscribeCycleForCatalog, 30);
-        dynamicTask.startCron(device.getDeviceId() + "catalog", catalogSubscribeTask, subscribeCycleForCatalog - 5);
+        dynamicTask.startCron(device.getDeviceId() + "catalog", catalogSubscribeTask, subscribeCycleForCatalog);
         return true;
     }
 
@@ -53,8 +53,6 @@ public class DeviceServiceImpl implements IDeviceService {
         }
         logger.info("移除目录订阅: {}", device.getDeviceId());
         dynamicTask.stop(device.getDeviceId() + "catalog");
-        device.setSubscribeCycleForCatalog(0);
-        sipCommander.catalogSubscribe(device, null, null);
         return true;
     }
 
@@ -75,7 +73,7 @@ public class DeviceServiceImpl implements IDeviceService {
         int subscribeCycleForCatalog = device.getSubscribeCycleForCatalog();
         // 设置最小值为30
         subscribeCycleForCatalog = Math.max(subscribeCycleForCatalog, 30);
-        dynamicTask.startCron(device.getDeviceId() + "mobile_position" , mobilePositionSubscribeTask, subscribeCycleForCatalog - 5);
+        dynamicTask.startCron(device.getDeviceId() + "mobile_position" , mobilePositionSubscribeTask, subscribeCycleForCatalog -1 );
         return true;
     }
 
@@ -86,8 +84,6 @@ public class DeviceServiceImpl implements IDeviceService {
         }
         logger.info("移除移动位置订阅: {}", device.getDeviceId());
         dynamicTask.stop(device.getDeviceId() + "mobile_position");
-        device.setSubscribeCycleForCatalog(0);
-        sipCommander.mobilePositionSubscribe(device, null, null);
         return true;
     }
 }

+ 5 - 1
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/MobilePosition/MobilePositionController.java

@@ -8,6 +8,7 @@ import com.genersoft.iot.vmp.gb28181.bean.MobilePosition;
 import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
 import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
+import com.genersoft.iot.vmp.service.IDeviceService;
 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
 import com.github.pagehelper.util.StringUtil;
 
@@ -48,6 +49,9 @@ public class MobilePositionController {
 	@Autowired
 	private DeferredResultHolder resultHolder;
 
+	@Autowired
+	private IDeviceService deviceService;
+
     /**
      *  查询历史轨迹
      * @param deviceId 设备ID
@@ -163,7 +167,7 @@ public class MobilePositionController {
         device.setMobilePositionSubmissionInterval(Integer.parseInt(interval));
         storager.updateDevice(device);
         String result = msg;
-        if (cmder.mobilePositionSubscribe(device, null, null)) {
+        if (deviceService.removeMobilePositionSubscribe(device)) {
             result += ",成功";
         } else {
             result += ",失败";

+ 7 - 4
web_src/src/components/dialog/deviceEdit.vue

@@ -10,7 +10,7 @@
       @close="close()"
     >
       <div id="shared" style="margin-top: 1rem;margin-right: 100px;">
-        <el-form ref="form" :rules="rules" :model="form" label-width="240px" >
+        <el-form ref="form" :rules="rules" :model="form" label-width="200px" >
           <el-form-item label="设备编号" >
             <el-input v-model="form.deviceId" disabled></el-input>
           </el-form-item>
@@ -36,13 +36,13 @@
               <el-option key="UTF-8" label="UTF-8" value="utf-8"></el-option>
             </el-select>
           </el-form-item>
-          <el-form-item label="目录订阅周期(0为停用订阅)" prop="subscribeCycleForCatalog" >
+          <el-form-item label="目录订阅" title="0为取消订阅" prop="subscribeCycleForCatalog" >
             <el-input v-model="form.subscribeCycleForCatalog" clearable ></el-input>
           </el-form-item>
-          <el-form-item label="移动位置订阅周期(0为停用订阅)" prop="subscribeCycleForCatalog" >
+          <el-form-item label="移动位置订阅" title="0为取消订阅" prop="subscribeCycleForCatalog" >
             <el-input v-model="form.subscribeCycleForMobilePosition" clearable ></el-input>
           </el-form-item>
-          <el-form-item label="移动位置报送间隔" prop="subscribeCycleForCatalog" >
+          <el-form-item v-if="form.subscribeCycleForMobilePosition > 0" label="移动位置报送间隔" prop="subscribeCycleForCatalog" >
             <el-input v-model="form.mobilePositionSubmissionInterval" clearable ></el-input>
           </el-form-item>
           <el-form-item>
@@ -98,6 +98,9 @@ export default {
     onSubmit: function () {
       console.log("onSubmit");
       console.log(this.form);
+      this.form.subscribeCycleForCatalog = this.form.subscribeCycleForCatalog||0
+      this.form.subscribeCycleForMobilePosition = this.form.subscribeCycleForMobilePosition||0
+      this.form.mobilePositionSubmissionInterval = this.form.mobilePositionSubmissionInterval||0
       this.$axios({
         method: 'post',
         url:`/api/device/query/device/update/`,