Commit f10b458fc919fbcadc4936bf3a7886088e20ac71

Authored by 648540858
1 parent f1c8ca60

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

src/main/java/com/genersoft/iot/vmp/conf/DynamicTask.java
1 1 package com.genersoft.iot.vmp.conf;
2 2  
  3 +import com.genersoft.iot.vmp.gb28181.task.ISubscribeTask;
3 4 import org.springframework.beans.factory.annotation.Autowired;
4 5 import org.springframework.context.annotation.Bean;
5 6 import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
... ... @@ -21,6 +22,7 @@ public class DynamicTask {
21 22 private ThreadPoolTaskScheduler threadPoolTaskScheduler;
22 23  
23 24 private Map<String, ScheduledFuture<?>> futureMap = new ConcurrentHashMap<>();
  25 + private Map<String, Runnable> runnableMap = new ConcurrentHashMap<>();
24 26  
25 27 @Bean
26 28 public ThreadPoolTaskScheduler threadPoolTaskScheduler() {
... ... @@ -34,12 +36,12 @@ public class DynamicTask {
34 36 * @param cycleForCatalog 间隔
35 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 40 stop(key);
39 41 // scheduleWithFixedDelay 必须等待上一个任务结束才开始计时period, cycleForCatalog表示执行的间隔
40 42 ScheduledFuture future = threadPoolTaskScheduler.scheduleWithFixedDelay(task, cycleForCatalog * 1000L);
41 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 51 * @param delay 延时 /毫秒
50 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 55 stop(key);
54 56 Date starTime = new Date(System.currentTimeMillis() + delay);
55 57 // scheduleWithFixedDelay 必须等待上一个任务结束才开始计时period, cycleForCatalog表示执行的间隔
56 58 ScheduledFuture future = threadPoolTaskScheduler.schedule(task, starTime);
57 59 futureMap.put(key, future);
58   - return "startCron";
59 60 }
60 61  
61 62 public void stop(String key) {
62 63 if (futureMap.get(key) != null && !futureMap.get(key).isCancelled()) {
63 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 14  
15 15  
16 16 /**
17   - * 系统启动时控制设备离线
  17 + * 系统启动时控制设备
18 18 */
19 19 @Component
20 20 @Order(value=4)
... ... @@ -41,10 +41,14 @@ public class SipDeviceRunner implements CommandLineRunner {
41 41 for (String deviceId : onlineForAll) {
42 42 storager.online(deviceId);
43 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 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 3 import com.genersoft.iot.vmp.gb28181.bean.Device;
  4 +import com.genersoft.iot.vmp.gb28181.task.ISubscribeTask;
4 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 6 import org.slf4j.Logger;
9 7 import org.slf4j.LoggerFactory;
10 8  
  9 +import javax.sip.Dialog;
  10 +import javax.sip.DialogState;
11 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 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 22 public CatalogSubscribeTask(Device device, ISIPCommander sipCommander) {
22 23 this.device = device;
... ... @@ -25,7 +26,10 @@ public class CatalogSubscribeTask implements Runnable{
25 26  
26 27 @Override
27 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 33 ResponseEvent event = (ResponseEvent) eventResult.event;
30 34 if (event.getResponse().getRawContent() != null) {
31 35 // 成功
... ... @@ -35,8 +39,37 @@ public class CatalogSubscribeTask implements Runnable{
35 39 logger.info("[目录订阅]成功: {}", device.getDeviceId());
36 40 }
37 41 },eventResult -> {
  42 + dialog = null;
38 43 // 失败
39 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 3 import com.genersoft.iot.vmp.gb28181.bean.GbStream;
5 4 import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
6 5 import com.genersoft.iot.vmp.gb28181.bean.SubscribeHolder;
7 6 import com.genersoft.iot.vmp.gb28181.bean.SubscribeInfo;
  7 +import com.genersoft.iot.vmp.gb28181.task.ISubscribeTask;
8 8 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
9 9 import com.genersoft.iot.vmp.service.bean.GPSMsgInfo;
10 10 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
... ... @@ -13,7 +13,10 @@ import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
13 13 import java.text.SimpleDateFormat;
14 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 21 private IRedisCatchStorage redisCatchStorage;
19 22 private IVideoManagerStorage storager;
... ... @@ -25,7 +28,7 @@ public class GPSSubscribeTask implements Runnable{
25 28  
26 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 32 this.redisCatchStorage = redisCatchStorage;
30 33 this.storager = storager;
31 34 this.platformId = platformId;
... ... @@ -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 3 import com.genersoft.iot.vmp.gb28181.bean.Device;
  4 +import com.genersoft.iot.vmp.gb28181.task.ISubscribeTask;
4 5 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
5 6 import org.dom4j.Element;
6 7 import org.slf4j.Logger;
7 8 import org.slf4j.LoggerFactory;
8 9  
  10 +import javax.sip.Dialog;
  11 +import javax.sip.DialogState;
9 12 import javax.sip.ResponseEvent;
10 13  
11   -public class MobilePositionSubscribeTask implements Runnable{
  14 +/**
  15 + * 移动位置订阅的定时更新
  16 + */
  17 +public class MobilePositionSubscribeTask implements ISubscribeTask {
12 18 private final Logger logger = LoggerFactory.getLogger(MobilePositionSubscribeTask.class);
13 19 private Device device;
14 20 private ISIPCommander sipCommander;
  21 + private Dialog dialog;
15 22  
16 23 public MobilePositionSubscribeTask(Device device, ISIPCommander sipCommander) {
17 24 this.device = device;
... ... @@ -20,9 +27,11 @@ public class MobilePositionSubscribeTask implements Runnable{
20 27  
21 28 @Override
22 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 34 ResponseEvent event = (ResponseEvent) eventResult.event;
25   - Element rootElement = null;
26 35 if (event.getResponse().getRawContent() != null) {
27 36 // 成功
28 37 logger.info("[移动位置订阅]成功: {}", device.getDeviceId());
... ... @@ -31,8 +40,38 @@ public class MobilePositionSubscribeTask implements Runnable{
31 40 logger.info("[移动位置订阅]成功: {}", device.getDeviceId());
32 41 }
33 42 },eventResult -> {
  43 + dialog = null;
34 44 // 失败
35 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 8 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
9 9 import com.genersoft.iot.vmp.service.bean.SSRCInfo;
10 10  
  11 +import javax.sip.Dialog;
  12 +
11 13 /**
12 14 * @description:设备能力接口,用于定义设备的控制、查询能力
13 15 * @author: swwheihei
... ... @@ -304,7 +306,7 @@ public interface ISIPCommander {
304 306 * @param device 视频设备
305 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 326 * @param device 视频设备
325 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 36 import javax.sip.*;
37 37 import javax.sip.address.SipURI;
38 38 import javax.sip.header.CallIdHeader;
  39 +import javax.sip.header.ContentTypeHeader;
  40 +import javax.sip.header.ExpiresHeader;
39 41 import javax.sip.header.ViaHeader;
40 42 import javax.sip.message.Request;
41 43 import java.lang.reflect.Field;
... ... @@ -57,6 +59,9 @@ public class SIPCommander implements ISIPCommander {
57 59 private SipConfig sipConfig;
58 60  
59 61 @Autowired
  62 + private SipFactory sipFactory;
  63 +
  64 + @Autowired
60 65 @Qualifier(value="tcpSipProvider")
61 66 private SipProviderImpl tcpSipProvider;
62 67  
... ... @@ -1453,7 +1458,7 @@ public class SIPCommander implements ISIPCommander {
1453 1458 * @param device 视频设备
1454 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 1462 try {
1458 1463 StringBuffer subscribePostitionXml = new StringBuffer(200);
1459 1464 String charset = device.getCharset();
... ... @@ -1467,12 +1472,20 @@ public class SIPCommander implements ISIPCommander {
1467 1472 }
1468 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 1489 transmitRequest(device, request, errorEvent, okEvent);
1477 1490  
1478 1491 return true;
... ... @@ -1542,7 +1555,7 @@ public class SIPCommander implements ISIPCommander {
1542 1555 }
1543 1556  
1544 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 1559 try {
1547 1560 StringBuffer cmdXml = new StringBuffer(200);
1548 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 import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
8 8 import com.genersoft.iot.vmp.gb28181.bean.SubscribeHolder;
9 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 11 import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver;
12 12 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
13 13 import com.genersoft.iot.vmp.gb28181.transmit.event.request.ISIPRequestProcessor;
... ... @@ -147,7 +147,7 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme
147 147 }
148 148 String sn = XmlUtil.getText(rootElement, "SN");
149 149 String key = VideoManagerConstants.SIP_SUBSCRIBE_PREFIX + userSetting.getServerId() + "_MobilePosition_" + platformId;
150   - logger.info("接收到{}的MobilePosition订阅", platformId);
  150 + logger.info("[notify-MobilePosition]: {}", platformId);
151 151 StringBuilder resultXml = new StringBuilder(200);
152 152 resultXml.append("<?xml version=\"1.0\" ?>\r\n")
153 153 .append("<Response>\r\n")
... ... @@ -162,7 +162,7 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme
162 162 dynamicTask.stop(key);
163 163 }
164 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 166 subscribeHolder.putMobilePositionSubscribe(platformId, subscribeInfo);
167 167 }else if (subscribeInfo.getExpires() == 0) {
168 168 dynamicTask.stop(key);
... ... @@ -200,7 +200,7 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme
200 200 }
201 201 String sn = XmlUtil.getText(rootElement, "SN");
202 202 String key = VideoManagerConstants.SIP_SUBSCRIBE_PREFIX + userSetting.getServerId() + "_Catalog_" + platformId;
203   - logger.info("接收到{}的Catalog订阅", platformId);
  203 + logger.info("[notify-Catalog]: {}", platformId);
204 204 StringBuilder resultXml = new StringBuilder(200);
205 205 resultXml.append("<?xml version=\"1.0\" ?>\r\n")
206 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 81 }
82 82 requestURI.setPort(event.getRemotePort());
83 83 reqAck.setRequestURI(requestURI);
84   - logger.info("向 " + event.getRemoteIpAddress() + ":" + event.getRemotePort() + "回复ack");
  84 + logger.info("[回复ack] {}-> {}:{} ",requestURI, event.getRemoteIpAddress(), event.getRemotePort());
85 85  
86 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 82 }
83 83  
84 84 public int createRTPServer(MediaServerItem mediaServerItem, String streamId) {
85   -
86   - Map<String, Object> param = new HashMap<>();
87 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 93 // 推流端口设置0则使用随机端口
89 94 param.put("enable_tcp", 1);
90 95 param.put("stream_id", streamId);
... ... @@ -301,7 +306,7 @@ public class ZLMRTPServerFactory {
301 306 result= true;
302 307 logger.info("停止RTP推流成功");
303 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 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 4 import com.genersoft.iot.vmp.gb28181.bean.Device;
5 5 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
6 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 9 import org.slf4j.Logger;
10 10 import org.slf4j.LoggerFactory;
11 11 import org.springframework.beans.factory.annotation.Autowired;
... ... @@ -42,7 +42,7 @@ public class DeviceServiceImpl implements IDeviceService {
42 42 int subscribeCycleForCatalog = device.getSubscribeCycleForCatalog();
43 43 // 设置最小值为30
44 44 subscribeCycleForCatalog = Math.max(subscribeCycleForCatalog, 30);
45   - dynamicTask.startCron(device.getDeviceId() + "catalog", catalogSubscribeTask, subscribeCycleForCatalog - 5);
  45 + dynamicTask.startCron(device.getDeviceId() + "catalog", catalogSubscribeTask, subscribeCycleForCatalog);
46 46 return true;
47 47 }
48 48  
... ... @@ -53,8 +53,6 @@ public class DeviceServiceImpl implements IDeviceService {
53 53 }
54 54 logger.info("移除目录订阅: {}", device.getDeviceId());
55 55 dynamicTask.stop(device.getDeviceId() + "catalog");
56   - device.setSubscribeCycleForCatalog(0);
57   - sipCommander.catalogSubscribe(device, null, null);
58 56 return true;
59 57 }
60 58  
... ... @@ -75,7 +73,7 @@ public class DeviceServiceImpl implements IDeviceService {
75 73 int subscribeCycleForCatalog = device.getSubscribeCycleForCatalog();
76 74 // 设置最小值为30
77 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 77 return true;
80 78 }
81 79  
... ... @@ -86,8 +84,6 @@ public class DeviceServiceImpl implements IDeviceService {
86 84 }
87 85 logger.info("移除移动位置订阅: {}", device.getDeviceId());
88 86 dynamicTask.stop(device.getDeviceId() + "mobile_position");
89   - device.setSubscribeCycleForCatalog(0);
90   - sipCommander.mobilePositionSubscribe(device, null, null);
91 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 8 import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
9 9 import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
10 10 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
  11 +import com.genersoft.iot.vmp.service.IDeviceService;
11 12 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
12 13 import com.github.pagehelper.util.StringUtil;
13 14  
... ... @@ -48,6 +49,9 @@ public class MobilePositionController {
48 49 @Autowired
49 50 private DeferredResultHolder resultHolder;
50 51  
  52 + @Autowired
  53 + private IDeviceService deviceService;
  54 +
51 55 /**
52 56 * 查询历史轨迹
53 57 * @param deviceId 设备ID
... ... @@ -163,7 +167,7 @@ public class MobilePositionController {
163 167 device.setMobilePositionSubmissionInterval(Integer.parseInt(interval));
164 168 storager.updateDevice(device);
165 169 String result = msg;
166   - if (cmder.mobilePositionSubscribe(device, null, null)) {
  170 + if (deviceService.removeMobilePositionSubscribe(device)) {
167 171 result += ",成功";
168 172 } else {
169 173 result += ",失败";
... ...
web_src/src/components/dialog/deviceEdit.vue
... ... @@ -10,7 +10,7 @@
10 10 @close="close()"
11 11 >
12 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 14 <el-form-item label="设备编号" >
15 15 <el-input v-model="form.deviceId" disabled></el-input>
16 16 </el-form-item>
... ... @@ -36,13 +36,13 @@
36 36 <el-option key="UTF-8" label="UTF-8" value="utf-8"></el-option>
37 37 </el-select>
38 38 </el-form-item>
39   - <el-form-item label="目录订阅周期(0为停用订阅)" prop="subscribeCycleForCatalog" >
  39 + <el-form-item label="目录订阅" title="0为取消订阅" prop="subscribeCycleForCatalog" >
40 40 <el-input v-model="form.subscribeCycleForCatalog" clearable ></el-input>
41 41 </el-form-item>
42   - <el-form-item label="移动位置订阅周期(0为停用订阅)" prop="subscribeCycleForCatalog" >
  42 + <el-form-item label="移动位置订阅" title="0为取消订阅" prop="subscribeCycleForCatalog" >
43 43 <el-input v-model="form.subscribeCycleForMobilePosition" clearable ></el-input>
44 44 </el-form-item>
45   - <el-form-item label="移动位置报送间隔" prop="subscribeCycleForCatalog" >
  45 + <el-form-item v-if="form.subscribeCycleForMobilePosition > 0" label="移动位置报送间隔" prop="subscribeCycleForCatalog" >
46 46 <el-input v-model="form.mobilePositionSubmissionInterval" clearable ></el-input>
47 47 </el-form-item>
48 48 <el-form-item>
... ... @@ -98,6 +98,9 @@ export default {
98 98 onSubmit: function () {
99 99 console.log("onSubmit");
100 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 104 this.$axios({
102 105 method: 'post',
103 106 url:`/api/device/query/device/update/`,
... ...