Commit 47abdde3392f2c5fd88d382ae63c4756b97ed4b0

Authored by 648540858
1 parent d88c95f4

解决设备上线停止线程导致的报错,优化录像的获取以及通道的更新

src/main/java/com/genersoft/iot/vmp/conf/DynamicTask.java
@@ -103,12 +103,12 @@ public class DynamicTask { @@ -103,12 +103,12 @@ public class DynamicTask {
103 103
104 public void stop(String key) { 104 public void stop(String key) {
105 if (futureMap.get(key) != null && !futureMap.get(key).isCancelled()) { 105 if (futureMap.get(key) != null && !futureMap.get(key).isCancelled()) {
106 - futureMap.get(key).cancel(true);  
107 - Runnable runnable = runnableMap.get(key);  
108 - if (runnable instanceof ISubscribeTask) {  
109 - ISubscribeTask subscribeTask = (ISubscribeTask) runnable;  
110 - subscribeTask.stop();  
111 - } 106 +// Runnable runnable = runnableMap.get(key);
  107 +// if (runnable instanceof ISubscribeTask) {
  108 +// ISubscribeTask subscribeTask = (ISubscribeTask) runnable;
  109 +// subscribeTask.stop();
  110 +// }
  111 + futureMap.get(key).cancel(false);
112 } 112 }
113 } 113 }
114 114
src/main/java/com/genersoft/iot/vmp/gb28181/bean/HandlerCatchData.java 0 → 100644
  1 +package com.genersoft.iot.vmp.gb28181.bean;
  2 +
  3 +import org.dom4j.Element;
  4 +
  5 +import javax.sip.RequestEvent;
  6 +
  7 +/**
  8 + * @author lin
  9 + */
  10 +public class HandlerCatchData {
  11 + private RequestEvent evt;
  12 + private Device device;
  13 + private Element rootElement;
  14 +
  15 + public HandlerCatchData(RequestEvent evt, Device device, Element rootElement) {
  16 + this.evt = evt;
  17 + this.device = device;
  18 + this.rootElement = rootElement;
  19 + }
  20 +
  21 + public RequestEvent getEvt() {
  22 + return evt;
  23 + }
  24 +
  25 + public void setEvt(RequestEvent evt) {
  26 + this.evt = evt;
  27 + }
  28 +
  29 + public Device getDevice() {
  30 + return device;
  31 + }
  32 +
  33 + public void setDevice(Device device) {
  34 + this.device = device;
  35 + }
  36 +
  37 + public Element getRootElement() {
  38 + return rootElement;
  39 + }
  40 +
  41 + public void setRootElement(Element rootElement) {
  42 + this.rootElement = rootElement;
  43 + }
  44 +}
src/main/java/com/genersoft/iot/vmp/gb28181/bean/SubscribeHolder.java
@@ -2,6 +2,7 @@ package com.genersoft.iot.vmp.gb28181.bean; @@ -2,6 +2,7 @@ package com.genersoft.iot.vmp.gb28181.bean;
2 2
3 import com.genersoft.iot.vmp.common.VideoManagerConstants; 3 import com.genersoft.iot.vmp.common.VideoManagerConstants;
4 import com.genersoft.iot.vmp.conf.DynamicTask; 4 import com.genersoft.iot.vmp.conf.DynamicTask;
  5 +import com.genersoft.iot.vmp.gb28181.task.ISubscribeTask;
5 import com.genersoft.iot.vmp.gb28181.task.impl.MobilePositionSubscribeHandlerTask; 6 import com.genersoft.iot.vmp.gb28181.task.impl.MobilePositionSubscribeHandlerTask;
6 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform; 7 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
7 import com.genersoft.iot.vmp.storager.IRedisCatchStorage; 8 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
@@ -38,7 +39,6 @@ public class SubscribeHolder { @@ -38,7 +39,6 @@ public class SubscribeHolder {
38 catalogMap.put(platformId, subscribeInfo); 39 catalogMap.put(platformId, subscribeInfo);
39 // 添加订阅到期 40 // 添加订阅到期
40 String taskOverdueKey = taskOverduePrefix + "catalog_" + platformId; 41 String taskOverdueKey = taskOverduePrefix + "catalog_" + platformId;
41 - dynamicTask.stop(taskOverdueKey);  
42 // 添加任务处理订阅过期 42 // 添加任务处理订阅过期
43 dynamicTask.startDelay(taskOverdueKey, () -> removeCatalogSubscribe(subscribeInfo.getId()), 43 dynamicTask.startDelay(taskOverdueKey, () -> removeCatalogSubscribe(subscribeInfo.getId()),
44 subscribeInfo.getExpires() * 1000); 44 subscribeInfo.getExpires() * 1000);
@@ -49,10 +49,17 @@ public class SubscribeHolder { @@ -49,10 +49,17 @@ public class SubscribeHolder {
49 } 49 }
50 50
51 public void removeCatalogSubscribe(String platformId) { 51 public void removeCatalogSubscribe(String platformId) {
  52 +
52 catalogMap.remove(platformId); 53 catalogMap.remove(platformId);
53 String taskOverdueKey = taskOverduePrefix + "catalog_" + platformId; 54 String taskOverdueKey = taskOverduePrefix + "catalog_" + platformId;
  55 + Runnable runnable = dynamicTask.get(taskOverdueKey);
  56 + if (runnable instanceof ISubscribeTask) {
  57 + ISubscribeTask subscribeTask = (ISubscribeTask) runnable;
  58 + subscribeTask.stop();
  59 + }
54 // 添加任务处理订阅过期 60 // 添加任务处理订阅过期
55 dynamicTask.stop(taskOverdueKey); 61 dynamicTask.stop(taskOverdueKey);
  62 +
56 } 63 }
57 64
58 public void putMobilePositionSubscribe(String platformId, SubscribeInfo subscribeInfo) { 65 public void putMobilePositionSubscribe(String platformId, SubscribeInfo subscribeInfo) {
@@ -63,7 +70,6 @@ public class SubscribeHolder { @@ -63,7 +70,6 @@ public class SubscribeHolder {
63 storager, platformId, subscribeInfo.getSn(), key, this, dynamicTask), 70 storager, platformId, subscribeInfo.getSn(), key, this, dynamicTask),
64 subscribeInfo.getGpsInterval() * 1000); 71 subscribeInfo.getGpsInterval() * 1000);
65 String taskOverdueKey = taskOverduePrefix + "MobilePosition_" + platformId; 72 String taskOverdueKey = taskOverduePrefix + "MobilePosition_" + platformId;
66 - dynamicTask.stop(taskOverdueKey);  
67 // 添加任务处理订阅过期 73 // 添加任务处理订阅过期
68 dynamicTask.startDelay(taskOverdueKey, () -> { 74 dynamicTask.startDelay(taskOverdueKey, () -> {
69 removeMobilePositionSubscribe(subscribeInfo.getId()); 75 removeMobilePositionSubscribe(subscribeInfo.getId());
@@ -81,6 +87,11 @@ public class SubscribeHolder { @@ -81,6 +87,11 @@ public class SubscribeHolder {
81 // 结束任务处理GPS定时推送 87 // 结束任务处理GPS定时推送
82 dynamicTask.stop(key); 88 dynamicTask.stop(key);
83 String taskOverdueKey = taskOverduePrefix + "MobilePosition_" + platformId; 89 String taskOverdueKey = taskOverduePrefix + "MobilePosition_" + platformId;
  90 + Runnable runnable = dynamicTask.get(taskOverdueKey);
  91 + if (runnable instanceof ISubscribeTask) {
  92 + ISubscribeTask subscribeTask = (ISubscribeTask) runnable;
  93 + subscribeTask.stop();
  94 + }
84 // 添加任务处理订阅过期 95 // 添加任务处理订阅过期
85 dynamicTask.stop(taskOverdueKey); 96 dynamicTask.stop(taskOverdueKey);
86 } 97 }
src/main/java/com/genersoft/iot/vmp/gb28181/event/subscribe/catalog/CatalogEventLister.java
@@ -66,7 +66,7 @@ public class CatalogEventLister implements ApplicationListener<CatalogEvent> { @@ -66,7 +66,7 @@ public class CatalogEventLister implements ApplicationListener<CatalogEvent> {
66 subscribe = subscribeHolder.getCatalogSubscribe(event.getPlatformId()); 66 subscribe = subscribeHolder.getCatalogSubscribe(event.getPlatformId());
67 67
68 if (subscribe == null) { 68 if (subscribe == null) {
69 - logger.info("发送订阅消息时发现订阅信息已经不存在"); 69 + logger.info("发送订阅消息时发现订阅信息已经不存在: {}", event.getPlatformId());
70 return; 70 return;
71 } 71 }
72 }else { 72 }else {
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorObserver.java
@@ -150,30 +150,24 @@ public class SIPProcessorObserver implements ISIPProcessorObserver { @@ -150,30 +150,24 @@ public class SIPProcessorObserver implements ISIPProcessorObserver {
150 public void processTimeout(TimeoutEvent timeoutEvent) { 150 public void processTimeout(TimeoutEvent timeoutEvent) {
151 logger.info("[消息发送超时]"); 151 logger.info("[消息发送超时]");
152 ClientTransaction clientTransaction = timeoutEvent.getClientTransaction(); 152 ClientTransaction clientTransaction = timeoutEvent.getClientTransaction();
153 - eventPublisher.requestTimeOut(timeoutEvent); 153 +
154 if (clientTransaction != null) { 154 if (clientTransaction != null) {
  155 + logger.info("[发送错误订阅] clientTransaction != null");
155 Request request = clientTransaction.getRequest(); 156 Request request = clientTransaction.getRequest();
156 if (request != null) { 157 if (request != null) {
  158 + logger.info("[发送错误订阅] request != null");
157 CallIdHeader callIdHeader = (CallIdHeader) request.getHeader(CallIdHeader.NAME); 159 CallIdHeader callIdHeader = (CallIdHeader) request.getHeader(CallIdHeader.NAME);
158 if (callIdHeader != null) { 160 if (callIdHeader != null) {
  161 + logger.info("[发送错误订阅]");
159 SipSubscribe.Event subscribe = sipSubscribe.getErrorSubscribe(callIdHeader.getCallId()); 162 SipSubscribe.Event subscribe = sipSubscribe.getErrorSubscribe(callIdHeader.getCallId());
160 SipSubscribe.EventResult eventResult = new SipSubscribe.EventResult(timeoutEvent); 163 SipSubscribe.EventResult eventResult = new SipSubscribe.EventResult(timeoutEvent);
161 subscribe.response(eventResult); 164 subscribe.response(eventResult);
  165 + sipSubscribe.removeOkSubscribe(callIdHeader.getCallId());
162 sipSubscribe.removeErrorSubscribe(callIdHeader.getCallId()); 166 sipSubscribe.removeErrorSubscribe(callIdHeader.getCallId());
163 } 167 }
164 } 168 }
165 } 169 }
166 -  
167 -// Timeout timeout = timeoutEvent.getTimeout();  
168 -// ServerTransaction serverTransaction = timeoutEvent.getServerTransaction();  
169 -// if (serverTransaction != null) {  
170 -// Request request = serverTransaction.getRequest();  
171 -// URI requestURI = request.getRequestURI();  
172 -// Header header = request.getHeader(FromHeader.NAME);  
173 -// }  
174 -// if(timeoutProcessor != null) {  
175 -// timeoutProcessor.process(timeoutEvent);  
176 -// } 170 + eventPublisher.requestTimeOut(timeoutEvent);
177 } 171 }
178 172
179 @Override 173 @Override
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
@@ -1487,7 +1487,6 @@ public class SIPCommander implements ISIPCommander { @@ -1487,7 +1487,6 @@ public class SIPCommander implements ISIPCommander {
1487 1487
1488 Request request; 1488 Request request;
1489 if (dialog != null) { 1489 if (dialog != null) {
1490 - logger.info("发送移动位置订阅消息时 dialog的状态为: {}", dialog.getState());  
1491 request = dialog.createRequest(Request.SUBSCRIBE); 1490 request = dialog.createRequest(Request.SUBSCRIBE);
1492 ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml"); 1491 ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml");
1493 request.setContent(subscribePostitionXml.toString(), contentTypeHeader); 1492 request.setContent(subscribePostitionXml.toString(), contentTypeHeader);
@@ -1583,12 +1582,12 @@ public class SIPCommander implements ISIPCommander { @@ -1583,12 +1582,12 @@ public class SIPCommander implements ISIPCommander {
1583 1582
1584 Request request; 1583 Request request;
1585 if (dialog != null) { 1584 if (dialog != null) {
1586 - logger.info("发送目录订阅消息时 dialog的状态为: {}", dialog.getState());  
1587 request = dialog.createRequest(Request.SUBSCRIBE); 1585 request = dialog.createRequest(Request.SUBSCRIBE);
  1586 + ExpiresHeader expiresHeader = sipFactory.createHeaderFactory().createExpiresHeader(device.getSubscribeCycleForCatalog());
  1587 + request.setExpires(expiresHeader);
  1588 +
1588 ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml"); 1589 ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml");
1589 request.setContent(cmdXml.toString(), contentTypeHeader); 1590 request.setContent(cmdXml.toString(), contentTypeHeader);
1590 - ExpiresHeader expireHeader = sipFactory.createHeaderFactory().createExpiresHeader(device.getSubscribeCycleForMobilePosition());  
1591 - request.addHeader(expireHeader);  
1592 }else { 1591 }else {
1593 String tm = Long.toString(System.currentTimeMillis()); 1592 String tm = Long.toString(System.currentTimeMillis());
1594 1593
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/NotifyRequestProcessor.java
1 package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl; 1 package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl;
2 2
3 import com.alibaba.fastjson.JSONObject; 3 import com.alibaba.fastjson.JSONObject;
4 -import com.genersoft.iot.vmp.common.VideoManagerConstants;  
5 import com.genersoft.iot.vmp.conf.SipConfig; 4 import com.genersoft.iot.vmp.conf.SipConfig;
6 import com.genersoft.iot.vmp.conf.UserSetting; 5 import com.genersoft.iot.vmp.conf.UserSetting;
7 import com.genersoft.iot.vmp.gb28181.bean.*; 6 import com.genersoft.iot.vmp.gb28181.bean.*;
@@ -26,6 +25,8 @@ import org.slf4j.Logger; @@ -26,6 +25,8 @@ import org.slf4j.Logger;
26 import org.slf4j.LoggerFactory; 25 import org.slf4j.LoggerFactory;
27 import org.springframework.beans.factory.InitializingBean; 26 import org.springframework.beans.factory.InitializingBean;
28 import org.springframework.beans.factory.annotation.Autowired; 27 import org.springframework.beans.factory.annotation.Autowired;
  28 +import org.springframework.beans.factory.annotation.Qualifier;
  29 +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
29 import org.springframework.stereotype.Component; 30 import org.springframework.stereotype.Component;
30 import org.springframework.util.StringUtils; 31 import org.springframework.util.StringUtils;
31 32
@@ -36,6 +37,7 @@ import javax.sip.header.FromHeader; @@ -36,6 +37,7 @@ import javax.sip.header.FromHeader;
36 import javax.sip.message.Response; 37 import javax.sip.message.Response;
37 import java.text.ParseException; 38 import java.text.ParseException;
38 import java.util.Iterator; 39 import java.util.Iterator;
  40 +import java.util.concurrent.ConcurrentLinkedQueue;
39 41
40 /** 42 /**
41 * SIP命令类型: NOTIFY请求 43 * SIP命令类型: NOTIFY请求
@@ -64,11 +66,19 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements @@ -64,11 +66,19 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements
64 @Autowired 66 @Autowired
65 private EventPublisher publisher; 67 private EventPublisher publisher;
66 68
67 - private String method = "NOTIFY"; 69 + private final String method = "NOTIFY";
68 70
69 @Autowired 71 @Autowired
70 private SIPProcessorObserver sipProcessorObserver; 72 private SIPProcessorObserver sipProcessorObserver;
71 73
  74 + private boolean taskQueueHandlerRun = false;
  75 +
  76 + private final ConcurrentLinkedQueue<HandlerCatchData> taskQueue = new ConcurrentLinkedQueue<>();
  77 +
  78 + @Qualifier("taskExecutor")
  79 + @Autowired
  80 + private ThreadPoolTaskExecutor taskExecutor;
  81 +
72 @Override 82 @Override
73 public void afterPropertiesSet() throws Exception { 83 public void afterPropertiesSet() throws Exception {
74 // 添加消息处理的订阅 84 // 添加消息处理的订阅
@@ -78,23 +88,40 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements @@ -78,23 +88,40 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements
78 @Override 88 @Override
79 public void process(RequestEvent evt) { 89 public void process(RequestEvent evt) {
80 try { 90 try {
81 - Element rootElement = getRootElement(evt);  
82 - String cmd = XmlUtil.getText(rootElement, "CmdType");  
83 -  
84 - if (CmdType.CATALOG.equals(cmd)) {  
85 - logger.info("接收到Catalog通知");  
86 - processNotifyCatalogList(evt);  
87 - } else if (CmdType.ALARM.equals(cmd)) {  
88 - logger.info("接收到Alarm通知");  
89 - processNotifyAlarm(evt);  
90 - } else if (CmdType.MOBILE_POSITION.equals(cmd)) {  
91 - logger.info("接收到MobilePosition通知");  
92 - processNotifyMobilePosition(evt);  
93 - } else {  
94 - logger.info("接收到消息:" + cmd);  
95 - responseAck(evt, Response.OK); 91 +
  92 + taskQueue.offer(new HandlerCatchData(evt, null, null));
  93 + responseAck(evt, Response.OK);
  94 + if (!taskQueueHandlerRun) {
  95 + taskQueueHandlerRun = true;
  96 + taskExecutor.execute(()-> {
  97 + while (!taskQueue.isEmpty()) {
  98 + try {
  99 + HandlerCatchData take = taskQueue.poll();
  100 + Element rootElement = getRootElement(take.getEvt());
  101 + String cmd = XmlUtil.getText(rootElement, "CmdType");
  102 +
  103 + if (CmdType.CATALOG.equals(cmd)) {
  104 + logger.info("接收到Catalog通知");
  105 + processNotifyCatalogList(take.getEvt());
  106 + } else if (CmdType.ALARM.equals(cmd)) {
  107 + logger.info("接收到Alarm通知");
  108 + processNotifyAlarm(take.getEvt());
  109 + } else if (CmdType.MOBILE_POSITION.equals(cmd)) {
  110 + logger.info("接收到MobilePosition通知");
  111 + processNotifyMobilePosition(take.getEvt());
  112 + } else {
  113 + logger.info("接收到消息:" + cmd);
  114 + }
  115 + } catch (DocumentException e) {
  116 + throw new RuntimeException(e);
  117 + }
  118 + }
  119 + taskQueueHandlerRun = false;
  120 + });
96 } 121 }
97 - } catch (DocumentException | SipException | InvalidArgumentException | ParseException e) { 122 +
  123 +
  124 + } catch (SipException | InvalidArgumentException | ParseException e) {
98 e.printStackTrace(); 125 e.printStackTrace();
99 } 126 }
100 } 127 }
@@ -167,8 +194,7 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements @@ -167,8 +194,7 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements
167 jsonObject.put("direction", mobilePosition.getDirection()); 194 jsonObject.put("direction", mobilePosition.getDirection());
168 jsonObject.put("speed", mobilePosition.getSpeed()); 195 jsonObject.put("speed", mobilePosition.getSpeed());
169 redisCatchStorage.sendMobilePositionMsg(jsonObject); 196 redisCatchStorage.sendMobilePositionMsg(jsonObject);
170 - responseAck(evt, Response.OK);  
171 - } catch (DocumentException | SipException | InvalidArgumentException | ParseException e) { 197 + } catch (DocumentException e) {
172 e.printStackTrace(); 198 e.printStackTrace();
173 } 199 }
174 } 200 }
@@ -189,7 +215,7 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements @@ -189,7 +215,7 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements
189 215
190 Device device = redisCatchStorage.getDevice(deviceId); 216 Device device = redisCatchStorage.getDevice(deviceId);
191 if (device == null) { 217 if (device == null) {
192 - responseAck(evt, Response.NOT_FOUND, "device is not found"); 218 + logger.warn("[ NotifyAlarm ] 未找到设备:{}", deviceId);
193 return; 219 return;
194 } 220 }
195 rootElement = getRootElement(evt, device.getCharset()); 221 rootElement = getRootElement(evt, device.getCharset());
@@ -199,7 +225,7 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements @@ -199,7 +225,7 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements
199 deviceAlarm.setAlarmMethod(XmlUtil.getText(rootElement, "AlarmMethod")); 225 deviceAlarm.setAlarmMethod(XmlUtil.getText(rootElement, "AlarmMethod"));
200 String alarmTime = XmlUtil.getText(rootElement, "AlarmTime"); 226 String alarmTime = XmlUtil.getText(rootElement, "AlarmTime");
201 if (alarmTime == null) { 227 if (alarmTime == null) {
202 - responseAck(evt, Response.BAD_REQUEST, "AlarmTime cannot be null"); 228 + logger.warn("[ NotifyAlarm ] AlarmTime cannot be null");
203 return; 229 return;
204 } 230 }
205 deviceAlarm.setAlarmTime(DateUtil.ISO8601Toyyyy_MM_dd_HH_mm_ss(alarmTime)); 231 deviceAlarm.setAlarmTime(DateUtil.ISO8601Toyyyy_MM_dd_HH_mm_ss(alarmTime));
@@ -219,7 +245,7 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements @@ -219,7 +245,7 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements
219 deviceAlarm.setLatitude(0.00); 245 deviceAlarm.setLatitude(0.00);
220 } 246 }
221 logger.info("[收到Notify-Alarm]:{}/{}", device.getDeviceId(), deviceAlarm.getChannelId()); 247 logger.info("[收到Notify-Alarm]:{}/{}", device.getDeviceId(), deviceAlarm.getChannelId());
222 - if (deviceAlarm.getAlarmMethod().equals("4")) { 248 + if ("4".equals(deviceAlarm.getAlarmMethod())) {
223 MobilePosition mobilePosition = new MobilePosition(); 249 MobilePosition mobilePosition = new MobilePosition();
224 mobilePosition.setDeviceId(deviceAlarm.getDeviceId()); 250 mobilePosition.setDeviceId(deviceAlarm.getDeviceId());
225 mobilePosition.setTime(deviceAlarm.getAlarmTime()); 251 mobilePosition.setTime(deviceAlarm.getAlarmTime());
@@ -240,11 +266,10 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements @@ -240,11 +266,10 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements
240 // TODO: 需要实现存储报警信息、报警分类 266 // TODO: 需要实现存储报警信息、报警分类
241 267
242 // 回复200 OK 268 // 回复200 OK
243 - responseAck(evt, Response.OK);  
244 if (redisCatchStorage.deviceIsOnline(deviceId)) { 269 if (redisCatchStorage.deviceIsOnline(deviceId)) {
245 publisher.deviceAlarmEventPublish(deviceAlarm); 270 publisher.deviceAlarmEventPublish(deviceAlarm);
246 } 271 }
247 - } catch (DocumentException | SipException | InvalidArgumentException | ParseException e) { 272 + } catch (DocumentException e) {
248 e.printStackTrace(); 273 e.printStackTrace();
249 } 274 }
250 } 275 }
@@ -280,64 +305,60 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements @@ -280,64 +305,60 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements
280 continue; 305 continue;
281 } 306 }
282 Element eventElement = itemDevice.element("Event"); 307 Element eventElement = itemDevice.element("Event");
  308 + String event;
  309 + if (eventElement == null) {
  310 + logger.warn("[收到 目录订阅]:{}, 但是Event为空, 设为默认值 ADD", (device != null ? device.getDeviceId():"" ));
  311 + event = CatalogEvent.ADD;
  312 + }else {
  313 + event = eventElement.getText().toUpperCase();
  314 + }
283 DeviceChannel channel = XmlUtil.channelContentHander(itemDevice); 315 DeviceChannel channel = XmlUtil.channelContentHander(itemDevice);
284 channel.setDeviceId(device.getDeviceId()); 316 channel.setDeviceId(device.getDeviceId());
285 logger.info("[收到 目录订阅]:{}/{}", device.getDeviceId(), channel.getChannelId()); 317 logger.info("[收到 目录订阅]:{}/{}", device.getDeviceId(), channel.getChannelId());
286 - switch (eventElement.getText().toUpperCase()) { 318 + switch (event) {
287 case CatalogEvent.ON: 319 case CatalogEvent.ON:
288 // 上线 320 // 上线
289 logger.info("收到来自设备【{}】的通道【{}】上线通知", device.getDeviceId(), channel.getChannelId()); 321 logger.info("收到来自设备【{}】的通道【{}】上线通知", device.getDeviceId(), channel.getChannelId());
290 storager.deviceChannelOnline(deviceId, channel.getChannelId()); 322 storager.deviceChannelOnline(deviceId, channel.getChannelId());
291 - // 回复200 OK  
292 - responseAck(evt, Response.OK);  
293 break; 323 break;
294 case CatalogEvent.OFF : 324 case CatalogEvent.OFF :
295 // 离线 325 // 离线
296 logger.info("收到来自设备【{}】的通道【{}】离线通知", device.getDeviceId(), channel.getChannelId()); 326 logger.info("收到来自设备【{}】的通道【{}】离线通知", device.getDeviceId(), channel.getChannelId());
297 storager.deviceChannelOffline(deviceId, channel.getChannelId()); 327 storager.deviceChannelOffline(deviceId, channel.getChannelId());
298 - // 回复200 OK  
299 - responseAck(evt, Response.OK);  
300 break; 328 break;
301 case CatalogEvent.VLOST: 329 case CatalogEvent.VLOST:
302 // 视频丢失 330 // 视频丢失
303 logger.info("收到来自设备【{}】的通道【{}】视频丢失通知", device.getDeviceId(), channel.getChannelId()); 331 logger.info("收到来自设备【{}】的通道【{}】视频丢失通知", device.getDeviceId(), channel.getChannelId());
304 storager.deviceChannelOffline(deviceId, channel.getChannelId()); 332 storager.deviceChannelOffline(deviceId, channel.getChannelId());
305 - // 回复200 OK  
306 - responseAck(evt, Response.OK);  
307 break; 333 break;
308 case CatalogEvent.DEFECT: 334 case CatalogEvent.DEFECT:
309 // 故障 335 // 故障
310 - // 回复200 OK  
311 - responseAck(evt, Response.OK);  
312 break; 336 break;
313 case CatalogEvent.ADD: 337 case CatalogEvent.ADD:
314 // 增加 338 // 增加
315 logger.info("收到来自设备【{}】的增加通道【{}】通知", device.getDeviceId(), channel.getChannelId()); 339 logger.info("收到来自设备【{}】的增加通道【{}】通知", device.getDeviceId(), channel.getChannelId());
316 storager.updateChannel(deviceId, channel); 340 storager.updateChannel(deviceId, channel);
317 - responseAck(evt, Response.OK);  
318 break; 341 break;
319 case CatalogEvent.DEL: 342 case CatalogEvent.DEL:
320 // 删除 343 // 删除
321 logger.info("收到来自设备【{}】的删除通道【{}】通知", device.getDeviceId(), channel.getChannelId()); 344 logger.info("收到来自设备【{}】的删除通道【{}】通知", device.getDeviceId(), channel.getChannelId());
322 storager.delChannel(deviceId, channel.getChannelId()); 345 storager.delChannel(deviceId, channel.getChannelId());
323 - responseAck(evt, Response.OK);  
324 break; 346 break;
325 case CatalogEvent.UPDATE: 347 case CatalogEvent.UPDATE:
326 // 更新 348 // 更新
327 logger.info("收到来自设备【{}】的更新通道【{}】通知", device.getDeviceId(), channel.getChannelId()); 349 logger.info("收到来自设备【{}】的更新通道【{}】通知", device.getDeviceId(), channel.getChannelId());
328 storager.updateChannel(deviceId, channel); 350 storager.updateChannel(deviceId, channel);
329 - responseAck(evt, Response.OK);  
330 break; 351 break;
331 default: 352 default:
332 - responseAck(evt, Response.BAD_REQUEST, "event not found"); 353 + logger.warn("[ NotifyCatalog ] event not found : {}", event );
333 354
334 } 355 }
335 // 转发变化信息 356 // 转发变化信息
336 - eventPublisher.catalogEventPublish(null, channel, eventElement.getText().toUpperCase()); 357 + eventPublisher.catalogEventPublish(null, channel, event);
337 358
338 } 359 }
339 } 360 }
340 - } catch (DocumentException | SipException | InvalidArgumentException | ParseException e) { 361 + } catch (DocumentException e) {
341 e.printStackTrace(); 362 e.printStackTrace();
342 } 363 }
343 } 364 }
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/CatalogResponseMessageHandler.java
@@ -20,6 +20,8 @@ import org.slf4j.Logger; @@ -20,6 +20,8 @@ import org.slf4j.Logger;
20 import org.slf4j.LoggerFactory; 20 import org.slf4j.LoggerFactory;
21 import org.springframework.beans.factory.InitializingBean; 21 import org.springframework.beans.factory.InitializingBean;
22 import org.springframework.beans.factory.annotation.Autowired; 22 import org.springframework.beans.factory.annotation.Autowired;
  23 +import org.springframework.beans.factory.annotation.Qualifier;
  24 +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
23 import org.springframework.stereotype.Component; 25 import org.springframework.stereotype.Component;
24 import org.springframework.util.StringUtils; 26 import org.springframework.util.StringUtils;
25 27
@@ -31,6 +33,7 @@ import java.text.ParseException; @@ -31,6 +33,7 @@ import java.text.ParseException;
31 import java.util.ArrayList; 33 import java.util.ArrayList;
32 import java.util.Iterator; 34 import java.util.Iterator;
33 import java.util.List; 35 import java.util.List;
  36 +import java.util.concurrent.ConcurrentLinkedQueue;
34 37
35 @Component 38 @Component
36 public class CatalogResponseMessageHandler extends SIPRequestProcessorParent implements InitializingBean, IMessageHandler { 39 public class CatalogResponseMessageHandler extends SIPRequestProcessorParent implements InitializingBean, IMessageHandler {
@@ -38,9 +41,13 @@ public class CatalogResponseMessageHandler extends SIPRequestProcessorParent imp @@ -38,9 +41,13 @@ public class CatalogResponseMessageHandler extends SIPRequestProcessorParent imp
38 private Logger logger = LoggerFactory.getLogger(CatalogResponseMessageHandler.class); 41 private Logger logger = LoggerFactory.getLogger(CatalogResponseMessageHandler.class);
39 private final String cmdType = "Catalog"; 42 private final String cmdType = "Catalog";
40 43
  44 + private boolean taskQueueHandlerRun = false;
  45 +
41 @Autowired 46 @Autowired
42 private ResponseMessageHandler responseMessageHandler; 47 private ResponseMessageHandler responseMessageHandler;
43 48
  49 + private ConcurrentLinkedQueue<HandlerCatchData> taskQueue = new ConcurrentLinkedQueue<>();
  50 +
44 @Autowired 51 @Autowired
45 private IVideoManagerStorage storager; 52 private IVideoManagerStorage storager;
46 53
@@ -63,6 +70,10 @@ public class CatalogResponseMessageHandler extends SIPRequestProcessorParent imp @@ -63,6 +70,10 @@ public class CatalogResponseMessageHandler extends SIPRequestProcessorParent imp
63 @Autowired 70 @Autowired
64 private IRedisCatchStorage redisCatchStorage; 71 private IRedisCatchStorage redisCatchStorage;
65 72
  73 + @Qualifier("taskExecutor")
  74 + @Autowired
  75 + private ThreadPoolTaskExecutor taskExecutor;
  76 +
66 @Override 77 @Override
67 public void afterPropertiesSet() throws Exception { 78 public void afterPropertiesSet() throws Exception {
68 responseMessageHandler.addHandler(cmdType, this); 79 responseMessageHandler.addHandler(cmdType, this);
@@ -70,68 +81,88 @@ public class CatalogResponseMessageHandler extends SIPRequestProcessorParent imp @@ -70,68 +81,88 @@ public class CatalogResponseMessageHandler extends SIPRequestProcessorParent imp
70 81
71 @Override 82 @Override
72 public void handForDevice(RequestEvent evt, Device device, Element element) { 83 public void handForDevice(RequestEvent evt, Device device, Element element) {
73 - String key = DeferredResultHolder.CALLBACK_CMD_CATALOG + device.getDeviceId();  
74 - Element rootElement = null; 84 + taskQueue.offer(new HandlerCatchData(evt, device, element));
  85 + // 回复200 OK
75 try { 86 try {
76 - rootElement = getRootElement(evt, device.getCharset());  
77 - Element deviceListElement = rootElement.element("DeviceList");  
78 - Element sumNumElement = rootElement.element("SumNum");  
79 - Element snElement = rootElement.element("SN");  
80 - if (snElement == null || sumNumElement == null || deviceListElement == null) {  
81 - responseAck(evt, Response.BAD_REQUEST, "xml error");  
82 - return;  
83 - }  
84 - int sumNum = Integer.parseInt(sumNumElement.getText());  
85 -  
86 - if (sumNum == 0) {  
87 - // 数据已经完整接收  
88 - storager.cleanChannelsForDevice(device.getDeviceId());  
89 - catalogDataCatch.setChannelSyncEnd(device.getDeviceId(), null);  
90 - }else {  
91 - Iterator<Element> deviceListIterator = deviceListElement.elementIterator();  
92 - if (deviceListIterator != null) {  
93 - List<DeviceChannel> channelList = new ArrayList<>();  
94 - // 遍历DeviceList  
95 - while (deviceListIterator.hasNext()) {  
96 - Element itemDevice = deviceListIterator.next();  
97 - Element channelDeviceElement = itemDevice.element("DeviceID");  
98 - if (channelDeviceElement == null) {  
99 - continue; 87 + responseAck(evt, Response.OK);
  88 + } catch (SipException e) {
  89 + throw new RuntimeException(e);
  90 + } catch (InvalidArgumentException e) {
  91 + throw new RuntimeException(e);
  92 + } catch (ParseException e) {
  93 + throw new RuntimeException(e);
  94 + }
  95 + if (!taskQueueHandlerRun) {
  96 + taskQueueHandlerRun = true;
  97 + taskExecutor.execute(()-> {
  98 + while (!taskQueue.isEmpty()) {
  99 + HandlerCatchData take = taskQueue.poll();
  100 + String key = DeferredResultHolder.CALLBACK_CMD_CATALOG + take.getDevice().getDeviceId();
  101 + Element rootElement = null;
  102 + try {
  103 + rootElement = getRootElement(take.getEvt(), take.getDevice().getCharset());
  104 + Element deviceListElement = rootElement.element("DeviceList");
  105 + Element sumNumElement = rootElement.element("SumNum");
  106 + Element snElement = rootElement.element("SN");
  107 + if (snElement == null || sumNumElement == null || deviceListElement == null) {
  108 + responseAck(take.getEvt(), Response.BAD_REQUEST, "xml error");
  109 + return;
100 } 110 }
101 - //by brewswang  
102 -// if (NumericUtil.isDouble(XmlUtil.getText(itemDevice, "Longitude"))) {//如果包含位置信息,就更新一下位置  
103 -// processNotifyMobilePosition(evt, itemDevice);  
104 -// }  
105 - DeviceChannel deviceChannel = XmlUtil.channelContentHander(itemDevice);  
106 - deviceChannel.setDeviceId(device.getDeviceId());  
107 -  
108 - channelList.add(deviceChannel);  
109 - }  
110 - int sn = Integer.parseInt(snElement.getText());  
111 - catalogDataCatch.put(device.getDeviceId(), sn, sumNum, device, channelList);  
112 - logger.info("收到来自设备【{}】的通道: {}个,{}/{}", device.getDeviceId(), channelList.size(), catalogDataCatch.get(device.getDeviceId()) == null ? 0 :catalogDataCatch.get(device.getDeviceId()).size(), sumNum);  
113 - if (catalogDataCatch.get(device.getDeviceId()).size() == sumNum) {  
114 - // 数据已经完整接收  
115 - boolean resetChannelsResult = storager.resetChannels(device.getDeviceId(), catalogDataCatch.get(device.getDeviceId()));  
116 - if (!resetChannelsResult) {  
117 - String errorMsg = "接收成功,写入失败,共" + sumNum + "条,已接收" + catalogDataCatch.get(device.getDeviceId()).size() + "条";  
118 - catalogDataCatch.setChannelSyncEnd(device.getDeviceId(), errorMsg); 111 + int sumNum = Integer.parseInt(sumNumElement.getText());
  112 +
  113 + if (sumNum == 0) {
  114 + // 数据已经完整接收
  115 + storager.cleanChannelsForDevice(take.getDevice().getDeviceId());
  116 + catalogDataCatch.setChannelSyncEnd(take.getDevice().getDeviceId(), null);
119 }else { 117 }else {
120 - catalogDataCatch.setChannelSyncEnd(device.getDeviceId(), null); 118 + Iterator<Element> deviceListIterator = deviceListElement.elementIterator();
  119 + if (deviceListIterator != null) {
  120 + List<DeviceChannel> channelList = new ArrayList<>();
  121 + // 遍历DeviceList
  122 + while (deviceListIterator.hasNext()) {
  123 + Element itemDevice = deviceListIterator.next();
  124 + Element channelDeviceElement = itemDevice.element("DeviceID");
  125 + if (channelDeviceElement == null) {
  126 + continue;
  127 + }
  128 + //by brewswang
  129 + // if (NumericUtil.isDouble(XmlUtil.getText(itemDevice, "Longitude"))) {//如果包含位置信息,就更新一下位置
  130 + // processNotifyMobilePosition(evt, itemDevice);
  131 + // }
  132 + DeviceChannel deviceChannel = XmlUtil.channelContentHander(itemDevice);
  133 + deviceChannel.setDeviceId(take.getDevice().getDeviceId());
  134 +
  135 + channelList.add(deviceChannel);
  136 + }
  137 + int sn = Integer.parseInt(snElement.getText());
  138 + catalogDataCatch.put(take.getDevice().getDeviceId(), sn, sumNum, take.getDevice(), channelList);
  139 + logger.info("收到来自设备【{}】的通道: {}个,{}/{}", take.getDevice().getDeviceId(), channelList.size(), catalogDataCatch.get(take.getDevice().getDeviceId()) == null ? 0 :catalogDataCatch.get(take.getDevice().getDeviceId()).size(), sumNum);
  140 + if (catalogDataCatch.get(take.getDevice().getDeviceId()).size() == sumNum) {
  141 + // 数据已经完整接收
  142 + boolean resetChannelsResult = storager.resetChannels(take.getDevice().getDeviceId(), catalogDataCatch.get(take.getDevice().getDeviceId()));
  143 + if (!resetChannelsResult) {
  144 + String errorMsg = "接收成功,写入失败,共" + sumNum + "条,已接收" + catalogDataCatch.get(take.getDevice().getDeviceId()).size() + "条";
  145 + catalogDataCatch.setChannelSyncEnd(take.getDevice().getDeviceId(), errorMsg);
  146 + }else {
  147 + catalogDataCatch.setChannelSyncEnd(take.getDevice().getDeviceId(), null);
  148 + }
  149 + }
  150 + }
  151 +
121 } 152 }
  153 + } catch (DocumentException e) {
  154 + e.printStackTrace();
  155 + } catch (InvalidArgumentException e) {
  156 + e.printStackTrace();
  157 + } catch (ParseException e) {
  158 + e.printStackTrace();
  159 + } catch (SipException e) {
  160 + e.printStackTrace();
122 } 161 }
123 } 162 }
124 - // 回复200 OK  
125 - responseAck(evt, Response.OK);  
126 - }  
127 - } catch (DocumentException e) {  
128 - e.printStackTrace();  
129 - } catch (InvalidArgumentException e) {  
130 - e.printStackTrace();  
131 - } catch (ParseException e) {  
132 - e.printStackTrace();  
133 - } catch (SipException e) {  
134 - e.printStackTrace(); 163 + taskQueueHandlerRun = false;
  164 + });
  165 +
135 } 166 }
136 } 167 }
137 168
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/RecordInfoResponseMessageHandler.java
1 package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.cmd; 1 package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.cmd;
2 2
3 -import com.genersoft.iot.vmp.gb28181.bean.Device;  
4 -import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;  
5 -import com.genersoft.iot.vmp.gb28181.bean.RecordInfo;  
6 -import com.genersoft.iot.vmp.gb28181.bean.RecordItem; 3 +import com.genersoft.iot.vmp.gb28181.bean.*;
7 import com.genersoft.iot.vmp.gb28181.event.EventPublisher; 4 import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
8 import com.genersoft.iot.vmp.gb28181.session.RecordDataCatch; 5 import com.genersoft.iot.vmp.gb28181.session.RecordDataCatch;
9 import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; 6 import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
@@ -19,6 +16,8 @@ import org.slf4j.Logger; @@ -19,6 +16,8 @@ import org.slf4j.Logger;
19 import org.slf4j.LoggerFactory; 16 import org.slf4j.LoggerFactory;
20 import org.springframework.beans.factory.InitializingBean; 17 import org.springframework.beans.factory.InitializingBean;
21 import org.springframework.beans.factory.annotation.Autowired; 18 import org.springframework.beans.factory.annotation.Autowired;
  19 +import org.springframework.beans.factory.annotation.Qualifier;
  20 +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
22 import org.springframework.stereotype.Component; 21 import org.springframework.stereotype.Component;
23 import org.springframework.util.StringUtils; 22 import org.springframework.util.StringUtils;
24 23
@@ -28,6 +27,9 @@ import javax.sip.SipException; @@ -28,6 +27,9 @@ import javax.sip.SipException;
28 import javax.sip.message.Response; 27 import javax.sip.message.Response;
29 import java.text.ParseException; 28 import java.text.ParseException;
30 import java.util.*; 29 import java.util.*;
  30 +import java.util.concurrent.BlockingQueue;
  31 +import java.util.concurrent.ConcurrentLinkedQueue;
  32 +import java.util.concurrent.LinkedBlockingQueue;
31 33
32 import static com.genersoft.iot.vmp.gb28181.utils.XmlUtil.getText; 34 import static com.genersoft.iot.vmp.gb28181.utils.XmlUtil.getText;
33 35
@@ -42,6 +44,9 @@ public class RecordInfoResponseMessageHandler extends SIPRequestProcessorParent @@ -42,6 +44,9 @@ public class RecordInfoResponseMessageHandler extends SIPRequestProcessorParent
42 private final String cmdType = "RecordInfo"; 44 private final String cmdType = "RecordInfo";
43 private final static String CACHE_RECORDINFO_KEY = "CACHE_RECORDINFO_"; 45 private final static String CACHE_RECORDINFO_KEY = "CACHE_RECORDINFO_";
44 46
  47 + private ConcurrentLinkedQueue<HandlerCatchData> taskQueue = new ConcurrentLinkedQueue<>();
  48 +
  49 + private boolean taskQueueHandlerRun = false;
45 @Autowired 50 @Autowired
46 private ResponseMessageHandler responseMessageHandler; 51 private ResponseMessageHandler responseMessageHandler;
47 52
@@ -51,11 +56,13 @@ public class RecordInfoResponseMessageHandler extends SIPRequestProcessorParent @@ -51,11 +56,13 @@ public class RecordInfoResponseMessageHandler extends SIPRequestProcessorParent
51 @Autowired 56 @Autowired
52 private DeferredResultHolder deferredResultHolder; 57 private DeferredResultHolder deferredResultHolder;
53 58
54 -  
55 -  
56 @Autowired 59 @Autowired
57 private EventPublisher eventPublisher; 60 private EventPublisher eventPublisher;
58 61
  62 + @Qualifier("taskExecutor")
  63 + @Autowired
  64 + private ThreadPoolTaskExecutor taskExecutor;
  65 +
59 @Override 66 @Override
60 public void afterPropertiesSet() throws Exception { 67 public void afterPropertiesSet() throws Exception {
61 responseMessageHandler.addHandler(cmdType, this); 68 responseMessageHandler.addHandler(cmdType, this);
@@ -67,75 +74,89 @@ public class RecordInfoResponseMessageHandler extends SIPRequestProcessorParent @@ -67,75 +74,89 @@ public class RecordInfoResponseMessageHandler extends SIPRequestProcessorParent
67 // 回复200 OK 74 // 回复200 OK
68 try { 75 try {
69 responseAck(evt, Response.OK); 76 responseAck(evt, Response.OK);
70 -  
71 - rootElement = getRootElement(evt, device.getCharset());  
72 - String sn = getText(rootElement, "SN");  
73 - RecordInfo recordInfo = new RecordInfo();  
74 - recordInfo.setDeviceId(device.getDeviceId());  
75 - recordInfo.setSn(sn);  
76 - recordInfo.setName(getText(rootElement, "Name"));  
77 - String sumNumStr = getText(rootElement, "SumNum");  
78 - int sumNum = 0;  
79 - if (!StringUtils.isEmpty(sumNumStr)) {  
80 - sumNum = Integer.parseInt(sumNumStr);  
81 - }  
82 - recordInfo.setSumNum(sumNum);  
83 - Element recordListElement = rootElement.element("RecordList");  
84 - if (recordListElement == null || sumNum == 0) {  
85 - logger.info("无录像数据");  
86 - eventPublisher.recordEndEventPush(recordInfo);  
87 - recordDataCatch.put(device.getDeviceId(), sn, sumNum, new ArrayList<>());  
88 - releaseRequest(device.getDeviceId(), sn);  
89 - } else {  
90 - Iterator<Element> recordListIterator = recordListElement.elementIterator();  
91 - if (recordListIterator != null) {  
92 - List<RecordItem> recordList = new ArrayList<>();  
93 - // 遍历DeviceList  
94 - while (recordListIterator.hasNext()) {  
95 - Element itemRecord = recordListIterator.next();  
96 - Element recordElement = itemRecord.element("DeviceID");  
97 - if (recordElement == null) {  
98 - logger.info("记录为空,下一个...");  
99 - continue; 77 + taskQueue.offer(new HandlerCatchData(evt, device, rootElement));
  78 + if (!taskQueueHandlerRun) {
  79 + taskQueueHandlerRun = true;
  80 + taskExecutor.execute(()->{
  81 + try {
  82 + while (!taskQueue.isEmpty()) {
  83 + HandlerCatchData take = taskQueue.poll();
  84 + Element rootElementForCharset = getRootElement(take.getEvt(), take.getDevice().getCharset());
  85 + String sn = getText(rootElementForCharset, "SN");
  86 + String channelId = getText(rootElementForCharset, "DeviceID");
  87 + RecordInfo recordInfo = new RecordInfo();
  88 + recordInfo.setChannelId(channelId);
  89 + recordInfo.setDeviceId(take.getDevice().getDeviceId());
  90 + recordInfo.setSn(sn);
  91 + recordInfo.setName(getText(rootElementForCharset, "Name"));
  92 + String sumNumStr = getText(rootElementForCharset, "SumNum");
  93 + int sumNum = 0;
  94 + if (!StringUtils.isEmpty(sumNumStr)) {
  95 + sumNum = Integer.parseInt(sumNumStr);
  96 + }
  97 + recordInfo.setSumNum(sumNum);
  98 + Element recordListElement = rootElementForCharset.element("RecordList");
  99 + if (recordListElement == null || sumNum == 0) {
  100 + logger.info("无录像数据");
  101 + eventPublisher.recordEndEventPush(recordInfo);
  102 + recordDataCatch.put(take.getDevice().getDeviceId(), sn, sumNum, new ArrayList<>());
  103 + releaseRequest(take.getDevice().getDeviceId(), sn);
  104 + } else {
  105 + Iterator<Element> recordListIterator = recordListElement.elementIterator();
  106 + if (recordListIterator != null) {
  107 + List<RecordItem> recordList = new ArrayList<>();
  108 + // 遍历DeviceList
  109 + while (recordListIterator.hasNext()) {
  110 + Element itemRecord = recordListIterator.next();
  111 + Element recordElement = itemRecord.element("DeviceID");
  112 + if (recordElement == null) {
  113 + logger.info("记录为空,下一个...");
  114 + continue;
  115 + }
  116 + RecordItem record = new RecordItem();
  117 + record.setDeviceId(getText(itemRecord, "DeviceID"));
  118 + record.setName(getText(itemRecord, "Name"));
  119 + record.setFilePath(getText(itemRecord, "FilePath"));
  120 + record.setFileSize(getText(itemRecord, "FileSize"));
  121 + record.setAddress(getText(itemRecord, "Address"));
  122 +
  123 + String startTimeStr = getText(itemRecord, "StartTime");
  124 + record.setStartTime(DateUtil.ISO8601Toyyyy_MM_dd_HH_mm_ss(startTimeStr));
  125 +
  126 + String endTimeStr = getText(itemRecord, "EndTime");
  127 + record.setEndTime(DateUtil.ISO8601Toyyyy_MM_dd_HH_mm_ss(endTimeStr));
  128 +
  129 + record.setSecrecy(itemRecord.element("Secrecy") == null ? 0
  130 + : Integer.parseInt(getText(itemRecord, "Secrecy")));
  131 + record.setType(getText(itemRecord, "Type"));
  132 + record.setRecorderId(getText(itemRecord, "RecorderID"));
  133 + recordList.add(record);
  134 + }
  135 + recordInfo.setRecordList(recordList);
  136 + // 发送消息,如果是上级查询此录像,则会通过这里通知给上级
  137 + eventPublisher.recordEndEventPush(recordInfo);
  138 + int count = recordDataCatch.put(take.getDevice().getDeviceId(), sn, sumNum, recordList);
  139 + logger.info("[国标录像], {}->{}: {}/{}", take.getDevice().getDeviceId(), sn, count, sumNum);
  140 + }
  141 +
  142 + if (recordDataCatch.isComplete(take.getDevice().getDeviceId(), sn)){
  143 + releaseRequest(take.getDevice().getDeviceId(), sn);
  144 + }
  145 + }
100 } 146 }
101 - RecordItem record = new RecordItem();  
102 - record.setDeviceId(getText(itemRecord, "DeviceID"));  
103 - record.setName(getText(itemRecord, "Name"));  
104 - record.setFilePath(getText(itemRecord, "FilePath"));  
105 - record.setFileSize(getText(itemRecord, "FileSize"));  
106 - record.setAddress(getText(itemRecord, "Address"));  
107 -  
108 - String startTimeStr = getText(itemRecord, "StartTime");  
109 - record.setStartTime(DateUtil.ISO8601Toyyyy_MM_dd_HH_mm_ss(startTimeStr));  
110 -  
111 - String endTimeStr = getText(itemRecord, "EndTime");  
112 - record.setEndTime(DateUtil.ISO8601Toyyyy_MM_dd_HH_mm_ss(endTimeStr));  
113 -  
114 - record.setSecrecy(itemRecord.element("Secrecy") == null ? 0  
115 - : Integer.parseInt(getText(itemRecord, "Secrecy")));  
116 - record.setType(getText(itemRecord, "Type"));  
117 - record.setRecorderId(getText(itemRecord, "RecorderID"));  
118 - recordList.add(record); 147 + taskQueueHandlerRun = false;
  148 + }catch (DocumentException e) {
  149 + throw new RuntimeException(e);
119 } 150 }
120 - recordInfo.setRecordList(recordList);  
121 - // 发送消息,如果是上级查询此录像,则会通过这里通知给上级  
122 - eventPublisher.recordEndEventPush(recordInfo);  
123 - int count = recordDataCatch.put(device.getDeviceId(), sn, sumNum, recordList);  
124 - logger.info("[国标录像], {}->{}: {}/{}", device.getDeviceId(), sn, count, sumNum);  
125 - }  
126 -  
127 - if (recordDataCatch.isComplete(device.getDeviceId(), sn)){  
128 - releaseRequest(device.getDeviceId(), sn);  
129 - } 151 + });
130 } 152 }
  153 +
131 } catch (SipException e) { 154 } catch (SipException e) {
132 e.printStackTrace(); 155 e.printStackTrace();
133 } catch (InvalidArgumentException e) { 156 } catch (InvalidArgumentException e) {
134 e.printStackTrace(); 157 e.printStackTrace();
135 } catch (ParseException e) { 158 } catch (ParseException e) {
136 e.printStackTrace(); 159 e.printStackTrace();
137 - } catch (DocumentException e) {  
138 - e.printStackTrace();  
139 } 160 }
140 } 161 }
141 162
src/main/java/com/genersoft/iot/vmp/service/impl/DeviceServiceImpl.java
@@ -4,6 +4,7 @@ import com.genersoft.iot.vmp.conf.DynamicTask; @@ -4,6 +4,7 @@ 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.bean.SsrcTransaction; 5 import com.genersoft.iot.vmp.gb28181.bean.SsrcTransaction;
6 import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; 6 import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
  7 +import com.genersoft.iot.vmp.gb28181.task.ISubscribeTask;
7 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander; 8 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
8 import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.cmd.CatalogResponseMessageHandler; 9 import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.cmd.CatalogResponseMessageHandler;
9 import com.genersoft.iot.vmp.service.IDeviceService; 10 import com.genersoft.iot.vmp.service.IDeviceService;
@@ -95,7 +96,6 @@ public class DeviceServiceImpl implements IDeviceService { @@ -95,7 +96,6 @@ public class DeviceServiceImpl implements IDeviceService {
95 } 96 }
96 // 刷新过期任务 97 // 刷新过期任务
97 String registerExpireTaskKey = registerExpireTaskKeyPrefix + device.getDeviceId(); 98 String registerExpireTaskKey = registerExpireTaskKeyPrefix + device.getDeviceId();
98 - dynamicTask.stop(registerExpireTaskKey);  
99 dynamicTask.startDelay(registerExpireTaskKey, ()-> offline(device.getDeviceId()), device.getExpires() * 1000); 99 dynamicTask.startDelay(registerExpireTaskKey, ()-> offline(device.getDeviceId()), device.getExpires() * 1000);
100 } 100 }
101 101
@@ -144,8 +144,16 @@ public class DeviceServiceImpl implements IDeviceService { @@ -144,8 +144,16 @@ public class DeviceServiceImpl implements IDeviceService {
144 if (device == null || device.getSubscribeCycleForCatalog() < 0) { 144 if (device == null || device.getSubscribeCycleForCatalog() < 0) {
145 return false; 145 return false;
146 } 146 }
147 - logger.info("移除目录订阅: {}", device.getDeviceId());  
148 - dynamicTask.stop(device.getDeviceId() + "catalog"); 147 + logger.info("[移除目录订阅]: {}", device.getDeviceId());
  148 + String taskKey = device.getDeviceId() + "catalog";
  149 + if (device.getOnline() == 1) {
  150 + Runnable runnable = dynamicTask.get(taskKey);
  151 + if (runnable instanceof ISubscribeTask) {
  152 + ISubscribeTask subscribeTask = (ISubscribeTask) runnable;
  153 + subscribeTask.stop();
  154 + }
  155 + }
  156 + dynamicTask.stop(taskKey);
149 return true; 157 return true;
150 } 158 }
151 159
@@ -169,8 +177,16 @@ public class DeviceServiceImpl implements IDeviceService { @@ -169,8 +177,16 @@ public class DeviceServiceImpl implements IDeviceService {
169 if (device == null || device.getSubscribeCycleForCatalog() < 0) { 177 if (device == null || device.getSubscribeCycleForCatalog() < 0) {
170 return false; 178 return false;
171 } 179 }
172 - logger.info("移除移动位置订阅: {}", device.getDeviceId());  
173 - dynamicTask.stop(device.getDeviceId() + "mobile_position"); 180 + logger.info("[移除移动位置订阅]: {}", device.getDeviceId());
  181 + String taskKey = device.getDeviceId() + "mobile_position";
  182 + if (device.getOnline() == 1) {
  183 + Runnable runnable = dynamicTask.get(taskKey);
  184 + if (runnable instanceof ISubscribeTask) {
  185 + ISubscribeTask subscribeTask = (ISubscribeTask) runnable;
  186 + subscribeTask.stop();
  187 + }
  188 + }
  189 + dynamicTask.stop(taskKey);
174 return true; 190 return true;
175 } 191 }
176 192
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceQuery.java
@@ -206,6 +206,11 @@ public class DeviceQuery { @@ -206,6 +206,11 @@ public class DeviceQuery {
206 Set<String> allKeys = dynamicTask.getAllKeys(); 206 Set<String> allKeys = dynamicTask.getAllKeys();
207 for (String key : allKeys) { 207 for (String key : allKeys) {
208 if (key.startsWith(deviceId)) { 208 if (key.startsWith(deviceId)) {
  209 + Runnable runnable = dynamicTask.get(key);
  210 + if (runnable instanceof ISubscribeTask) {
  211 + ISubscribeTask subscribeTask = (ISubscribeTask) runnable;
  212 + subscribeTask.stop();
  213 + }
209 dynamicTask.stop(key); 214 dynamicTask.stop(key);
210 } 215 }
211 } 216 }