From 3b21f385cdae7d94fce1ebba6abb06a893f57114 Mon Sep 17 00:00:00 2001
From: 648540858 <648540858@qq.com>
Date: 星期二, 02 十一月 2021 10:40:29 +0800
Subject: [PATCH] 对需要向设备发起请求的http请求,使用缓存,等待设备请求返回的时候一次性释放所有请求

---
 src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/playback/PlaybackController.java             |   15 
 src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceConfig.java                     |   24 +
 src/main/java/com/genersoft/iot/vmp/vmanager/onvif/ONVIFController.java                           |   14 
 src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java                             |   41 +--
 src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceControl.java                    |   74 ++++--
 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/RequestMessage.java                 |   26 -
 src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceQuery.java                      |   52 +++-
 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/DeferredResultHolder.java           |   66 +++++
 src/main/java/com/genersoft/iot/vmp/gb28181/bean/RecordInfo.java                                  |   11 
 src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/playback/DownloadController.java             |   24 +
 src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/ptz/PtzController.java                       |   30 +
 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/CheckForAllRecordsThread.java       |    6 
 web_src/src/components/MediaServerManger.vue                                                      |    1 
 src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/PlayController.java                     |   50 +++-
 src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/record/GBRecordController.java               |   12 
 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/MessageRequestProcessor.java    |  189 ++++++++++++----
 src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/MobilePosition/MobilePositionController.java |   11 
 17 files changed, 436 insertions(+), 210 deletions(-)

diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/RecordInfo.java b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/RecordInfo.java
index 4ec182a..0aaa687 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/RecordInfo.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/RecordInfo.java
@@ -13,7 +13,9 @@
 public class RecordInfo {
 
 	private String deviceId;
-	
+
+	private String channelId;
+
 	private String name;
 	
 	private int sumNum;
@@ -52,4 +54,11 @@
 		this.recordList = recordList;
 	}
 
+	public String getChannelId() {
+		return channelId;
+	}
+
+	public void setChannelId(String channelId) {
+		this.channelId = channelId;
+	}
 }
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/CheckForAllRecordsThread.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/CheckForAllRecordsThread.java
index b9f3f23..ac949e5 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/CheckForAllRecordsThread.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/CheckForAllRecordsThread.java
@@ -54,11 +54,9 @@
         // 鑷劧椤哄簭鎺掑簭, 鍏冪礌杩涜鍗囧簭鎺掑垪
         this.recordInfo.getRecordList().sort(Comparator.naturalOrder());
         RequestMessage msg = new RequestMessage();
-        String deviceId = recordInfo.getDeviceId();
-        msg.setDeviceId(deviceId);
-        msg.setType(DeferredResultHolder.CALLBACK_CMD_RECORDINFO);
+        msg.setKey(DeferredResultHolder.CALLBACK_CMD_RECORDINFO + recordInfo.getDeviceId() + recordInfo.getChannelId());
         msg.setData(recordInfo);
-        deferredResultHolder.invokeResult(msg);
+        deferredResultHolder.invokeAllResult(msg);
         logger.info("澶勭悊瀹屾垚锛岃繑鍥炵粨鏋�");
         MessageRequestProcessor.threadNameList.remove(cacheKey);
     }
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/DeferredResultHolder.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/DeferredResultHolder.java
index e6a7e41..ecfa666 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/DeferredResultHolder.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/DeferredResultHolder.java
@@ -1,6 +1,8 @@
 package com.genersoft.iot.vmp.gb28181.transmit.callback;
 
+import java.util.HashMap;
 import java.util.Map;
+import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 
 import org.springframework.http.HttpStatus;
@@ -45,22 +47,72 @@
 
 	public static final String CALLBACK_CMD_BROADCAST = "CALLBACK_BROADCAST";
 
-	private Map<String, DeferredResult> map = new ConcurrentHashMap<String, DeferredResult>();
+	private Map<String, Map<String, DeferredResult>> map = new ConcurrentHashMap<>();
 
 
-	public void put(String key, DeferredResult result) {
-		map.put(key, result);
+	public void put(String key, String id, DeferredResult result) {
+		Map<String, DeferredResult> deferredResultMap = map.get(key);
+		if (deferredResultMap == null) {
+			deferredResultMap = new ConcurrentHashMap<>();
+			map.put(key, deferredResultMap);
+		}
+		deferredResultMap.put(id, result);
 	}
 	
-	public DeferredResult get(String key) {
-		return map.get(key);
+	public DeferredResult get(String key, String id) {
+		Map<String, DeferredResult> deferredResultMap = map.get(key);
+		if (deferredResultMap == null) return null;
+		return deferredResultMap.get(id);
 	}
-	
+
+	public boolean exist(String key, String id){
+		if (key == null) return false;
+		Map<String, DeferredResult> deferredResultMap = map.get(key);
+		if (id == null) {
+			return deferredResultMap != null;
+		}else {
+			return deferredResultMap != null && deferredResultMap.get(id) != null;
+		}
+	}
+
+	/**
+	 * 閲婃斁鍗曚釜璇锋眰
+	 * @param msg
+	 */
 	public void invokeResult(RequestMessage msg) {
-		DeferredResult result = map.get(msg.getId());
+		Map<String, DeferredResult> deferredResultMap = map.get(msg.getKey());
+		if (deferredResultMap == null) {
+			return;
+		}
+		DeferredResult result = deferredResultMap.get(msg.getId());
 		if (result == null) {
 			return;
 		}
 		result.setResult(new ResponseEntity<>(msg.getData(),HttpStatus.OK));
+		deferredResultMap.remove(msg.getId());
+		if (deferredResultMap.size() == 0) {
+			map.remove(msg.getKey());
+		}
+	}
+
+	/**
+	 * 閲婃斁鎵�鏈夌殑璇锋眰
+	 * @param msg
+	 */
+	public void invokeAllResult(RequestMessage msg) {
+		Map<String, DeferredResult> deferredResultMap = map.get(msg.getKey());
+		if (deferredResultMap == null) {
+			return;
+		}
+		Set<String> ids = deferredResultMap.keySet();
+		for (String id : ids) {
+			DeferredResult result = deferredResultMap.get(id);
+			if (result == null) {
+				return;
+			}
+			result.setResult(new ResponseEntity<>(msg.getData(),HttpStatus.OK));
+		}
+		map.remove(msg.getKey());
+
 	}
 }
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/RequestMessage.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/RequestMessage.java
index 223092f..5a3ae37 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/RequestMessage.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/RequestMessage.java
@@ -9,12 +9,10 @@
 	
 	private String id;
 
-	private String deviceId;
-	
-	private String type;
-	
+	private String key;
+
 	private Object data;
-	
+
 	public String getId() {
 		return id;
 	}
@@ -23,22 +21,12 @@
 		this.id = id;
 	}
 
-	public String getDeviceId() {
-		return deviceId;
+	public void setKey(String key) {
+		this.key = key;
 	}
 
-	public void setDeviceId(String deviceId) {
-		this.deviceId = deviceId;
-		this.id = type + deviceId;
-	}
-
-	public String getType() {
-		return type;
-	}
-
-	public void setType(String type) {
-		this.type = type;
-		this.id = type + deviceId;
+	public String getKey() {
+		return key;
 	}
 
 	public Object getData() {
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/MessageRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/MessageRequestProcessor.java
index f76048c..51aa2df 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/MessageRequestProcessor.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/MessageRequestProcessor.java
@@ -173,12 +173,12 @@
 			Device device = storager.queryVideoDevice(deviceId);
 			if (device == null) {
 				logger.warn("澶勭悊MobilePosition绉诲姩浣嶇疆娑堟伅鏃舵湭鎵惧埌璁惧淇℃伅");
+				response404Ack(evt);
 				return;
 			}
 			Element rootElement = getRootElement(evt, device.getCharset());
 
 			MobilePosition mobilePosition = new MobilePosition();
-			Element deviceIdElement = rootElement.element("DeviceID");
 			if (!StringUtils.isEmpty(device.getName())) {
 				mobilePosition.setDeviceName(device.getName());
 			}
@@ -227,11 +227,17 @@
 	 */
 	private void processMessageDeviceStatus(RequestEvent evt) {
 		try {
+			String deviceId = SipUtils.getUserIdFromFromHeader(evt.getRequest());
+			Device device = storager.queryVideoDevice(deviceId);
+			if (device == null) {
+				logger.warn("澶勭悊DeviceStatus璁惧鐘舵�丮essage鏃舵湭鎵惧埌璁惧淇℃伅");
+				response404Ack(evt);
+				return;
+			}
 			Element rootElement = getRootElement(evt);
 			String name = rootElement.getName();
 			Element deviceIdElement = rootElement.element("DeviceID");
-			String deviceId = deviceIdElement.getText();
-			Device device = storager.queryVideoDevice(deviceId);
+			String channelId = deviceIdElement.getText();
 			if (name.equalsIgnoreCase("Query")) { // 鍖哄垎鏄疪esponse鈥斺�旀煡璇㈠搷搴旓紝杩樻槸Query鈥斺�旀煡璇㈣姹�
 				logger.info("鎺ユ敹鍒癉eviceStatus鏌ヨ娑堟伅");
 				FromHeader fromHeader = (FromHeader) evt.getRequest().getHeader(FromHeader.NAME);
@@ -258,10 +264,9 @@
 						logger.debug(json.toJSONString());
 					}
 					RequestMessage msg = new RequestMessage();
-					msg.setDeviceId(deviceId);
-					msg.setType(DeferredResultHolder.CALLBACK_CMD_DEVICESTATUS);
+					msg.setKey(DeferredResultHolder.CALLBACK_CMD_DEVICESTATUS + deviceId + channelId);
 					msg.setData(json);
-					deferredResultHolder.invokeResult(msg);
+					deferredResultHolder.invokeAllResult(msg);
 
 					if (offLineDetector.isOnline(deviceId)) {
 						publisher.onlineEventPublish(device, VideoManagerConstants.EVENT_ONLINE_MESSAGE);
@@ -282,8 +287,15 @@
 	 */
 	private void processMessageDeviceControl(RequestEvent evt) {
 		try {
+			String deviceId = SipUtils.getUserIdFromFromHeader(evt.getRequest());
+			Device device = storager.queryVideoDevice(deviceId);
+			if (device == null) {
+				logger.warn("澶勭悊DeviceControl璁惧鐘舵�丮essage鏈壘鍒拌澶囦俊鎭�");
+				response404Ack(evt);
+				return;
+			}
 			Element rootElement = getRootElement(evt);
-			String deviceId = XmlUtil.getText(rootElement, "DeviceID");
+			String channelId = XmlUtil.getText(rootElement, "DeviceID");
 			//String result = XmlUtil.getText(rootElement, "Result");
 			// 鍥炲200 OK
 			responseAck(evt);
@@ -295,10 +307,10 @@
 					logger.debug(json.toJSONString());
 				}
 				RequestMessage msg = new RequestMessage();
-				msg.setDeviceId(deviceId);
-				msg.setType(DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL);
+				String key = DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL +  deviceId + channelId;
+				msg.setKey(key);
 				msg.setData(json);
-				deferredResultHolder.invokeResult(msg);
+				deferredResultHolder.invokeAllResult(msg);
 			} else {
 				// 姝ゅ鏄笂绾у彂鍑虹殑DeviceControl鎸囦护
 				String platformId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(FromHeader.NAME)).getAddress().getURI()).getUser();
@@ -344,8 +356,8 @@
 				// 浜戝彴/鍓嶇鎺у埗鍛戒护
 				if (!StringUtils.isEmpty(XmlUtil.getText(rootElement,"PTZCmd")) && !deviceId.equals(targetGBId)) {
 					String cmdString = XmlUtil.getText(rootElement,"PTZCmd");
-					Device device = storager.queryVideoDeviceByPlatformIdAndChannelId(platformId, deviceId);
-					cmder.fronEndCmd(device, deviceId, cmdString);
+					Device deviceForPlatform = storager.queryVideoDeviceByPlatformIdAndChannelId(platformId, deviceId);
+					cmder.fronEndCmd(deviceForPlatform, deviceId, cmdString);
 				}
 			}
 		} catch (ParseException | SipException | InvalidArgumentException | DocumentException e) {
@@ -360,8 +372,16 @@
 	 */
 	private void processMessageDeviceConfig(RequestEvent evt) {
 		try {
+			String deviceId = SipUtils.getUserIdFromFromHeader(evt.getRequest());
+			// 鏌ヨ璁惧鏄惁瀛樺湪
+			Device device = storager.queryVideoDevice(deviceId);
+			if (device == null) {
+				logger.warn("澶勭悊DeviceConfig璁惧鐘舵�丮essage娑堟伅鏃舵湭鎵惧埌璁惧淇℃伅");
+				response404Ack(evt);
+				return;
+			}
 			Element rootElement = getRootElement(evt);
-			String deviceId = XmlUtil.getText(rootElement, "DeviceID");
+			String channelId = XmlUtil.getText(rootElement, "DeviceID");
 			// 鍥炲200 OK
 			responseAck(evt);
 			if (rootElement.getName().equals("Response")) {
@@ -371,11 +391,11 @@
 				if (logger.isDebugEnabled()) {
 					logger.debug(json.toJSONString());
 				}
+				String key = DeferredResultHolder.CALLBACK_CMD_DEVICECONFIG + deviceId + channelId;
 				RequestMessage msg = new RequestMessage();
-				msg.setDeviceId(deviceId);
-				msg.setType(DeferredResultHolder.CALLBACK_CMD_DEVICECONFIG);
+				msg.setKey(key);
 				msg.setData(json);
-				deferredResultHolder.invokeResult(msg);
+				deferredResultHolder.invokeAllResult(msg);
 			} else {
 				// 姝ゅ鏄笂绾у彂鍑虹殑DeviceConfig鎸囦护
 			}
@@ -391,8 +411,17 @@
 	 */
 	private void processMessageConfigDownload(RequestEvent evt) {
 		try {
+			String deviceId = SipUtils.getUserIdFromFromHeader(evt.getRequest());
+			// 鏌ヨ璁惧鏄惁瀛樺湪
+			Device device = storager.queryVideoDevice(deviceId);
+			if (device == null) {
+				logger.warn("澶勭悊ConfigDownload璁惧鐘舵�丮essage鏃舵湭鎵惧埌璁惧淇℃伅");
+				response404Ack(evt);
+				return;
+			}
 			Element rootElement = getRootElement(evt);
-			String deviceId = XmlUtil.getText(rootElement, "DeviceID");
+			String channelId = XmlUtil.getText(rootElement, "DeviceID");
+			String key = DeferredResultHolder.CALLBACK_CMD_CONFIGDOWNLOAD + deviceId + channelId;
 			// 鍥炲200 OK
 			responseAck(evt);
 			if (rootElement.getName().equals("Response")) {
@@ -403,10 +432,9 @@
 					logger.debug(json.toJSONString());
 				}
 				RequestMessage msg = new RequestMessage();
-				msg.setDeviceId(deviceId);
-				msg.setType(DeferredResultHolder.CALLBACK_CMD_CONFIGDOWNLOAD);
+				msg.setKey(key);
 				msg.setData(json);
-				deferredResultHolder.invokeResult(msg);
+				deferredResultHolder.invokeAllResult(msg);
 			} else {
 				// 姝ゅ鏄笂绾у彂鍑虹殑DeviceConfig鎸囦护
 			}
@@ -422,8 +450,17 @@
 	 */
 	private void processMessagePresetQuery(RequestEvent evt) {
 		try {
+			String deviceId = SipUtils.getUserIdFromFromHeader(evt.getRequest());
+			// 鏌ヨ璁惧鏄惁瀛樺湪
+			Device device = storager.queryVideoDevice(deviceId);
+			if (device == null) {
+				logger.warn("澶勭悊PresetQuery棰勭疆浣嶅垪琛∕essage鏃舵湭鎵惧埌璁惧淇℃伅");
+				response404Ack(evt);
+				return;
+			}
 			Element rootElement = getRootElement(evt);
-			String deviceId = XmlUtil.getText(rootElement, "DeviceID");
+			String channelId = XmlUtil.getText(rootElement, "DeviceID");
+			String key = DeferredResultHolder.CALLBACK_CMD_PRESETQUERY + deviceId + channelId;
 			// 鍥炲200 OK
 			responseAck(evt);
 			if (rootElement.getName().equals("Response")) {//   !StringUtils.isEmpty(result)) {
@@ -434,10 +471,9 @@
 					logger.debug(json.toJSONString());
 				}
 				RequestMessage msg = new RequestMessage();
-				msg.setDeviceId(deviceId);
-				msg.setType(DeferredResultHolder.CALLBACK_CMD_PRESETQUERY);
+				msg.setKey(key);
 				msg.setData(json);
-				deferredResultHolder.invokeResult(msg);
+				deferredResultHolder.invokeAllResult(msg);
 			} else {
 				// 姝ゅ鏄笂绾у彂鍑虹殑DeviceControl鎸囦护
 			}
@@ -453,11 +489,19 @@
 	 */
 	private void processMessageDeviceInfo(RequestEvent evt) {
 		try {
+			String deviceId = SipUtils.getUserIdFromFromHeader(evt.getRequest());
+			// 鏌ヨ璁惧鏄惁瀛樺湪
+			Device device = storager.queryVideoDevice(deviceId);
+			if (device == null) {
+				logger.warn("澶勭悊DeviceInfo璁惧淇℃伅Message鏃舵湭鎵惧埌璁惧淇℃伅");
+				response404Ack(evt);
+				return;
+			}
 			Element rootElement = getRootElement(evt);
 			String requestName = rootElement.getName();
 			Element deviceIdElement = rootElement.element("DeviceID");
-			String deviceId = deviceIdElement.getTextTrim();
-			Device device = storager.queryVideoDevice(deviceId);
+			String channelId = deviceIdElement.getTextTrim();
+			String key = DeferredResultHolder.CALLBACK_CMD_DEVICEINFO + deviceId + channelId;
 			if (device != null ) {
 				rootElement = getRootElement(evt, device.getCharset());
 			}
@@ -492,10 +536,9 @@
 				storager.updateDevice(device);
 	
 				RequestMessage msg = new RequestMessage();
-				msg.setDeviceId(deviceId);
-				msg.setType(DeferredResultHolder.CALLBACK_CMD_DEVICEINFO);
+				msg.setKey(key);
 				msg.setData(device);
-				deferredResultHolder.invokeResult(msg);
+				deferredResultHolder.invokeAllResult(msg);
 				// 鍥炲200 OK
 				responseAck(evt);
 				if (offLineDetector.isOnline(deviceId)) {
@@ -514,12 +557,22 @@
 	 */
 	private void processMessageCatalogList(RequestEvent evt) {
 		try {
+
+			String deviceId = SipUtils.getUserIdFromFromHeader(evt.getRequest());
+			// 鏌ヨ璁惧鏄惁瀛樺湪
+			Device device = storager.queryVideoDevice(deviceId);
+			if (device == null) {
+				logger.warn("澶勭悊DeviceInfo璁惧淇℃伅Message鏃舵湭鎵惧埌璁惧淇℃伅");
+				response404Ack(evt);
+				return;
+			}
+
 			Element rootElement = getRootElement(evt);
 			String name = rootElement.getName();
 			Element deviceIdElement = rootElement.element("DeviceID");
-			String deviceId = deviceIdElement.getText();
+			String channelId = deviceIdElement.getText();
 			Element deviceListElement = rootElement.element("DeviceList");
-
+			String key = DeferredResultHolder.CALLBACK_CMD_CATALOG + deviceId;
 			FromHeader fromHeader = (FromHeader) evt.getRequest().getHeader(FromHeader.NAME);
 			AddressImpl address = (AddressImpl) fromHeader.getAddress();
 			SipUri uri = (SipUri) address.getURI();
@@ -581,10 +634,6 @@
 
 
 			} else {
-				Device device = storager.queryVideoDevice(deviceId);
-				if (device == null) {
-					return;
-				}
 				deviceListElement = getRootElement(evt, device.getCharset()).element("DeviceList");
 				Iterator<Element> deviceListIterator = deviceListElement.elementIterator();
 				if (deviceListIterator != null) {
@@ -674,10 +723,9 @@
 					}
 
 					RequestMessage msg = new RequestMessage();
-					msg.setDeviceId(deviceId);
-					msg.setType(DeferredResultHolder.CALLBACK_CMD_CATALOG);
+					msg.setKey(key);
 					msg.setData(device);
-					deferredResultHolder.invokeResult(msg);
+					deferredResultHolder.invokeAllResult(msg);
 					// 鍥炲200 OK
 					responseAck(evt);
 					if (offLineDetector.isOnline(deviceId)) {
@@ -701,11 +749,13 @@
 			Device device = storager.queryVideoDevice(deviceId);
 			if (device == null) {
 				logger.warn("澶勭悊alarm璁惧鎶ヨ淇℃伅鏈壘鍒拌澶囦俊鎭�");
+				response404Ack(evt);
 				return;
 			}
 			Element rootElement = getRootElement(evt, device.getCharset());
 			Element deviceIdElement = rootElement.element("DeviceID");
 			String channelId = deviceIdElement.getText().toString();
+			String key = DeferredResultHolder.CALLBACK_CMD_ALARM + deviceId + channelId;
 			// 鍥炲200 OK
 			responseAck(evt);
 
@@ -770,10 +820,9 @@
 					logger.debug(json.toJSONString());
 				}
 				RequestMessage msg = new RequestMessage();
-				msg.setDeviceId(deviceId);
-				msg.setType(DeferredResultHolder.CALLBACK_CMD_ALARM);
+				msg.setKey(key);
 				msg.setData(json);
-				deferredResultHolder.invokeResult(msg);
+				deferredResultHolder.invokeAllResult(msg);
 			}
 		} catch (DocumentException | SipException | InvalidArgumentException | ParseException e) {
 			e.printStackTrace();
@@ -787,9 +836,13 @@
 	 */
 	private void processMessageKeepAlive(RequestEvent evt) {
 		try {
-			Element rootElement = getRootElement(evt);
-			String deviceId = XmlUtil.getText(rootElement, "DeviceID");
+
+			String deviceId = SipUtils.getUserIdFromFromHeader(evt.getRequest());
+			// 鏌ヨ璁惧鏄惁瀛樺湪
 			Device device = storager.queryVideoDevice(deviceId);
+
+			Element rootElement = getRootElement(evt);
+			String channelId = XmlUtil.getText(rootElement, "DeviceID");
 
 			// 妫�鏌ヨ澶囨槸鍚﹀瓨鍦ㄥ苟鍦ㄧ嚎锛� 涓嶅湪绾垮垯璁剧疆涓哄湪绾�
 			if (device != null ) {
@@ -831,18 +884,29 @@
 	 */
 	private void processMessageRecordInfo(RequestEvent evt) {
 		try {
+
+			String deviceId = SipUtils.getUserIdFromFromHeader(evt.getRequest());
+			// 鏌ヨ璁惧鏄惁瀛樺湪
+			Device device = storager.queryVideoDevice(deviceId);
+			if (device == null) {
+				logger.warn("澶勭悊DeviceInfo璁惧淇℃伅Message鏃舵湭鎵惧埌璁惧淇℃伅");
+				response404Ack(evt);
+				return;
+			}
+
 			// 鍥炲200 OK
 			responseAck(evt);
 			String uuid = UUID.randomUUID().toString().replace("-", "");
 			RecordInfo recordInfo = new RecordInfo();
 			Element rootElement = getRootElement(evt);
 			Element deviceIdElement = rootElement.element("DeviceID");
-			String deviceId = deviceIdElement.getText().toString();
-			Device device = storager.queryVideoDevice(deviceId);
+			String channelId = deviceIdElement.getText().toString();
+			String key = DeferredResultHolder.CALLBACK_CMD_RECORDINFO + deviceId + channelId;
 			if (device != null ) {
 				rootElement = getRootElement(evt, device.getCharset());
 			}
 			recordInfo.setDeviceId(deviceId);
+			recordInfo.setChannelId(channelId);
 			recordInfo.setName(XmlUtil.getText(rootElement, "Name"));
 			if (XmlUtil.getText(rootElement, "SumNum")== null || XmlUtil.getText(rootElement, "SumNum") =="") {
 				recordInfo.setSumNum(0);
@@ -854,10 +918,9 @@
 			if (recordListElement == null || recordInfo.getSumNum() == 0) {
 				logger.info("鏃犲綍鍍忔暟鎹�");
 				RequestMessage msg = new RequestMessage();
-				msg.setDeviceId(deviceId);
-				msg.setType(DeferredResultHolder.CALLBACK_CMD_RECORDINFO);
+				msg.setKey(key);
 				msg.setData(recordInfo);
-				deferredResultHolder.invokeResult(msg);
+				deferredResultHolder.invokeAllResult(msg);
 			} else {
 				Iterator<Element> recordListIterator = recordListElement.elementIterator();
 				List<RecordItem> recordList = new ArrayList<RecordItem>();
@@ -956,10 +1019,20 @@
  	 */
 	private void processMessageMediaStatus(RequestEvent evt){
 		try {
+
+			String deviceId = SipUtils.getUserIdFromFromHeader(evt.getRequest());
+			// 鏌ヨ璁惧鏄惁瀛樺湪
+			Device device = storager.queryVideoDevice(deviceId);
+			if (device == null) {
+				logger.warn("澶勭悊DeviceInfo璁惧淇℃伅Message鏃舵湭鎵惧埌璁惧淇℃伅");
+				response404Ack(evt);
+				return;
+			}
+
 			// 鍥炲200 OK
 			responseAck(evt);
 			Element rootElement = getRootElement(evt);
-			String deviceId = XmlUtil.getText(rootElement, "DeviceID");
+			String channelId = XmlUtil.getText(rootElement, "DeviceID");
 			String NotifyType =XmlUtil.getText(rootElement, "NotifyType");
 			if (NotifyType.equals("121")){
 				logger.info("濯掍綋鎾斁瀹屾瘯锛岄�氱煡鍏虫祦");
@@ -981,8 +1054,19 @@
 	 */
 	private void processMessageBroadcast(RequestEvent evt) {
 		try {
+
+			String deviceId = SipUtils.getUserIdFromFromHeader(evt.getRequest());
+			// 鏌ヨ璁惧鏄惁瀛樺湪
+			Device device = storager.queryVideoDevice(deviceId);
+			if (device == null) {
+				logger.warn("澶勭悊DeviceInfo璁惧淇℃伅Message鏃舵湭鎵惧埌璁惧淇℃伅");
+				response404Ack(evt);
+				return;
+			}
+
 			Element rootElement = getRootElement(evt);
-			String deviceId = XmlUtil.getText(rootElement, "DeviceID");
+			String channelId = XmlUtil.getText(rootElement, "DeviceID");
+			String key = DeferredResultHolder.CALLBACK_CMD_BROADCAST + deviceId + channelId;
 			// 鍥炲200 OK
 			responseAck(evt);
 			if (rootElement.getName().equals("Response")) {
@@ -993,10 +1077,9 @@
 					logger.debug(json.toJSONString());
 				}
 				RequestMessage msg = new RequestMessage();
-				msg.setDeviceId(deviceId);
-				msg.setType(DeferredResultHolder.CALLBACK_CMD_BROADCAST);
+				msg.setKey(key);
 				msg.setData(json);
-				deferredResultHolder.invokeResult(msg);
+				deferredResultHolder.invokeAllResult(msg);
 			} else {
 				// 姝ゅ鏄笂绾у彂鍑虹殑Broadcast鎸囦护
 			}
diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
index 057025b..a22ab8a 100644
--- a/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
+++ b/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
@@ -78,9 +78,11 @@
     @Override
     public PlayResult play(MediaServerItem mediaServerItem, String deviceId, String channelId, ZLMHttpHookSubscribe.Event hookEvent, SipSubscribe.Event errorEvent) {
         PlayResult playResult = new PlayResult();
+        RequestMessage msg = new RequestMessage();
+        String key = DeferredResultHolder.CALLBACK_CMD_PLAY + deviceId + channelId;
+        msg.setKey(key);
+        msg.setId(playResult.getUuid());
         if (mediaServerItem == null) {
-            RequestMessage msg = new RequestMessage();
-            msg.setId(DeferredResultHolder.CALLBACK_CMD_PLAY + playResult.getUuid());
             WVPResult wvpResult = new WVPResult();
             wvpResult.setCode(-1);
             wvpResult.setMsg("鏈壘鍒板彲鐢ㄧ殑zlm");
@@ -88,20 +90,19 @@
             resultHolder.invokeResult(msg);
             return playResult;
         }
+
         Device device = storager.queryVideoDevice(deviceId);
         StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channelId);
         playResult.setDevice(device);
-        UUID uuid = UUID.randomUUID();
-        playResult.setUuid(uuid.toString());
+        String uuid = UUID.randomUUID().toString();
+        playResult.setUuid(uuid);
         DeferredResult<ResponseEntity<String>> result = new DeferredResult<ResponseEntity<String>>(userSetup.getPlayTimeout());
         playResult.setResult(result);
         // 褰曞儚鏌ヨ浠hannelId浣滀负deviceId鏌ヨ
-        resultHolder.put(DeferredResultHolder.CALLBACK_CMD_PLAY + uuid, result);
+        resultHolder.put(key, uuid, result);
         // 瓒呮椂澶勭悊
         result.onTimeout(()->{
             logger.warn(String.format("璁惧鐐规挱瓒呮椂锛宒eviceId锛�%s 锛宑hannelId锛�%s", deviceId, channelId));
-            RequestMessage msg = new RequestMessage();
-            msg.setId(DeferredResultHolder.CALLBACK_CMD_PLAY + playResult.getUuid());
             WVPResult wvpResult = new WVPResult();
             wvpResult.setCode(-1);
             SIPDialog dialog = streamSession.getDialog(deviceId, channelId);
@@ -115,7 +116,8 @@
             cmder.streamByeCmd(device.getDeviceId(), channelId);
             // 閲婃斁rtpserver
             mediaServerService.closeRTPServer(playResult.getDevice(), channelId);
-            resultHolder.invokeResult(msg);
+            // 鍥炲涔嬪墠鎵�鏈夌殑鐐规挱璇锋眰
+            resultHolder.invokeAllResult(msg);
         });
         result.onCompletion(()->{
             // 鐐规挱缁撴潫鏃惰皟鐢ㄦ埅鍥炬帴鍙�
@@ -169,15 +171,13 @@
                 }
             }, (event) -> {
                 // 鐐规挱杩斿洖sip閿欒
-                RequestMessage msg = new RequestMessage();
-                msg.setId(DeferredResultHolder.CALLBACK_CMD_PLAY + uuid);
                 Response response = event.getResponse();
                 mediaServerService.closeRTPServer(playResult.getDevice(), channelId);
                 WVPResult wvpResult = new WVPResult();
                 wvpResult.setCode(-1);
                 wvpResult.setMsg(String.format("鐐规挱澶辫触锛� 閿欒鐮侊細 %s, %s", response.getStatusCode(), response.getReasonPhrase()));
                 msg.setData(wvpResult);
-                resultHolder.invokeResult(msg);
+                resultHolder.invokeAllResult(msg);
                 if (errorEvent != null) {
                     errorEvent.response(event);
                 }
@@ -186,13 +186,11 @@
         } else {
             String streamId = streamInfo.getStreamId();
             if (streamId == null) {
-                RequestMessage msg = new RequestMessage();
-                msg.setId(DeferredResultHolder.CALLBACK_CMD_PLAY + uuid);
                 WVPResult wvpResult = new WVPResult();
                 wvpResult.setCode(-1);
                 wvpResult.setMsg(String.format("鐐规挱澶辫触锛� redis缂撳瓨streamId绛変簬null"));
                 msg.setData(wvpResult);
-                resultHolder.invokeResult(msg);
+                resultHolder.invokeAllResult(msg);
                 return playResult;
             }
             String mediaServerId = streamInfo.getMediaServerId();
@@ -200,8 +198,6 @@
 
             JSONObject rtpInfo = zlmresTfulUtils.getRtpInfo(mediaInfo, streamId);
             if (rtpInfo != null && rtpInfo.getBoolean("exist")) {
-                RequestMessage msg = new RequestMessage();
-                msg.setId(DeferredResultHolder.CALLBACK_CMD_PLAY + uuid);
 
                 WVPResult wvpResult = new WVPResult();
                 wvpResult.setCode(0);
@@ -209,7 +205,7 @@
                 wvpResult.setData(streamInfo);
                 msg.setData(wvpResult);
 
-                resultHolder.invokeResult(msg);
+                resultHolder.invokeAllResult(msg);
                 if (hookEvent != null) {
                     hookEvent.response(mediaServerItem, JSONObject.parseObject(JSON.toJSONString(streamInfo)));
                 }
@@ -229,15 +225,13 @@
                     onPublishHandlerForPlay(mediaServerItemInuse, response, deviceId, channelId, uuid.toString());
                 }, (event) -> {
                     mediaServerService.closeRTPServer(playResult.getDevice(), channelId);
-                    RequestMessage msg = new RequestMessage();
-                    msg.setId(DeferredResultHolder.CALLBACK_CMD_PLAY + uuid);
                     Response response = event.getResponse();
 
                     WVPResult wvpResult = new WVPResult();
                     wvpResult.setCode(-1);
                     wvpResult.setMsg(String.format("鐐规挱澶辫触锛� 閿欒鐮侊細 %s, %s", response.getStatusCode(), response.getReasonPhrase()));
                     msg.setData(wvpResult);
-                    resultHolder.invokeResult(msg);
+                    resultHolder.invokeAllResult(msg);
                 });
             }
         }
@@ -248,7 +242,8 @@
     @Override
     public void onPublishHandlerForPlay(MediaServerItem mediaServerItem, JSONObject resonse, String deviceId, String channelId, String uuid) {
         RequestMessage msg = new RequestMessage();
-        msg.setId(DeferredResultHolder.CALLBACK_CMD_PLAY + uuid);
+        msg.setId(uuid);
+        msg.setKey(DeferredResultHolder.CALLBACK_CMD_PLAY + deviceId + channelId);
         StreamInfo streamInfo = onPublishHandler(mediaServerItem, resonse, deviceId, channelId, uuid);
         if (streamInfo != null) {
             DeviceChannel deviceChannel = storager.queryChannel(deviceId, channelId);
@@ -265,11 +260,11 @@
             wvpResult.setData(streamInfo);
             msg.setData(wvpResult);
 
-            resultHolder.invokeResult(msg);
+            resultHolder.invokeAllResult(msg);
         } else {
             logger.warn("璁惧棰勮API璋冪敤澶辫触锛�");
             msg.setData("璁惧棰勮API璋冪敤澶辫触锛�");
-            resultHolder.invokeResult(msg);
+            resultHolder.invokeAllResult(msg);
         }
     }
 
diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/MobilePosition/MobilePositionController.java b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/MobilePosition/MobilePositionController.java
index 6dd31ee..8d5a37f 100644
--- a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/MobilePosition/MobilePositionController.java
+++ b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/MobilePosition/MobilePositionController.java
@@ -1,6 +1,7 @@
 package com.genersoft.iot.vmp.vmanager.gb28181.MobilePosition;
 
 import java.util.List;
+import java.util.UUID;
 
 import javax.sip.message.Response;
 
@@ -111,10 +112,13 @@
     @GetMapping("/realtime/{deviceId}")
     public DeferredResult<ResponseEntity<MobilePosition>> realTimePosition(@PathVariable String deviceId) {
         Device device = storager.queryVideoDevice(deviceId);
+        String uuid = UUID.randomUUID().toString();
+        String key = DeferredResultHolder.CALLBACK_CMD_MOBILEPOSITION + deviceId;
         cmder.mobilePostitionQuery(device, event -> {
 			Response response = event.getResponse();
 			RequestMessage msg = new RequestMessage();
-			msg.setId(DeferredResultHolder.CALLBACK_CMD_MOBILEPOSITION + deviceId);
+			msg.setId(uuid);
+            msg.setKey(key);
 			msg.setData(String.format("鑾峰彇绉诲姩浣嶇疆淇℃伅澶辫触锛岄敊璇爜锛� %s, %s", response.getStatusCode(), response.getReasonPhrase()));
 			resultHolder.invokeResult(msg);
 		});
@@ -123,11 +127,12 @@
 			logger.warn(String.format("鑾峰彇绉诲姩浣嶇疆淇℃伅瓒呮椂"));
 			// 閲婃斁rtpserver
 			RequestMessage msg = new RequestMessage();
-			msg.setId(DeferredResultHolder.CALLBACK_CMD_CATALOG+deviceId);
+            msg.setId(uuid);
+            msg.setKey(key);
 			msg.setData("Timeout");
 			resultHolder.invokeResult(msg);
 		});
-        resultHolder.put(DeferredResultHolder.CALLBACK_CMD_CATALOG+deviceId, result);
+        resultHolder.put(key, uuid, result);
         return result;
     }
 
diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceConfig.java b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceConfig.java
index daf329b..1aa28cb 100644
--- a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceConfig.java
+++ b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceConfig.java
@@ -28,6 +28,8 @@
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.context.request.async.DeferredResult;
 
+import java.util.UUID;
+
 @Api(tags = "鍥芥爣璁惧閰嶇疆")
 @CrossOrigin
 @RestController
@@ -66,7 +68,7 @@
 			@ApiImplicitParam(name = "heartBeatCount", value ="蹇冭烦璁℃暟" ,dataTypeClass = String.class),
 	})
 	public DeferredResult<ResponseEntity<String>> homePositionApi(@PathVariable String deviceId,
-                                                                @RequestParam(required = false) String channelId,
+                                                               	String channelId,
                                                                 @RequestParam(required = false) String name,
 																@RequestParam(required = false) String expiration,
 																@RequestParam(required = false) String heartBeatInterval,
@@ -75,10 +77,13 @@
 			logger.debug("鎶ヨ澶嶄綅API璋冪敤");
 		}
 		Device device = storager.queryVideoDevice(deviceId);
+		String uuid = UUID.randomUUID().toString();
+		String key = DeferredResultHolder.CALLBACK_CMD_DEVICECONFIG + deviceId + channelId;
 		cmder.deviceBasicConfigCmd(device, channelId, name, expiration, heartBeatInterval, heartBeatCount, event -> {
 			Response response = event.getResponse();
 			RequestMessage msg = new RequestMessage();
-			msg.setId(DeferredResultHolder.CALLBACK_CMD_DEVICECONFIG + (StringUtils.isEmpty(channelId) ? deviceId : channelId));
+			msg.setId(uuid);
+			msg.setKey(key);
 			msg.setData(String.format("璁惧閰嶇疆鎿嶄綔澶辫触锛岄敊璇爜锛� %s, %s", response.getStatusCode(), response.getReasonPhrase()));
 			resultHolder.invokeResult(msg);
 		});
@@ -87,7 +92,8 @@
 			logger.warn(String.format("璁惧閰嶇疆鎿嶄綔瓒呮椂, 璁惧鏈繑鍥炲簲绛旀寚浠�"));
 			// 閲婃斁rtpserver
 			RequestMessage msg = new RequestMessage();
-			msg.setId(DeferredResultHolder.CALLBACK_CMD_DEVICECONFIG + (StringUtils.isEmpty(channelId) ? deviceId : channelId));
+			msg.setId(uuid);
+			msg.setKey(key);
 			JSONObject json = new JSONObject();
 			json.put("DeviceID", deviceId);
 			json.put("Status", "Timeout");
@@ -95,7 +101,7 @@
 			msg.setData(json); //("鐪嬪畧浣嶆帶鍒舵搷浣滆秴鏃�, 璁惧鏈繑鍥炲簲绛旀寚浠�");
 			resultHolder.invokeResult(msg);
 		});
-		resultHolder.put(DeferredResultHolder.CALLBACK_CMD_DEVICECONFIG + (StringUtils.isEmpty(channelId) ? deviceId : channelId), result);
+		resultHolder.put(key, uuid, result);
 		return result;
 	}
 
@@ -119,11 +125,14 @@
 		if (logger.isDebugEnabled()) {
 			logger.debug("璁惧鐘舵�佹煡璇PI璋冪敤");
 		}
+		String key = DeferredResultHolder.CALLBACK_CMD_CONFIGDOWNLOAD + (StringUtils.isEmpty(channelId) ? deviceId : channelId);
+		String uuid = UUID.randomUUID().toString();
 		Device device = storager.queryVideoDevice(deviceId);
 		cmder.deviceConfigQuery(device, channelId, configType, event -> {
 			Response response = event.getResponse();
 			RequestMessage msg = new RequestMessage();
-			msg.setId(DeferredResultHolder.CALLBACK_CMD_CONFIGDOWNLOAD + (StringUtils.isEmpty(channelId) ? deviceId : channelId));
+			msg.setId(uuid);
+			msg.setKey(key);
 			msg.setData(String.format("鑾峰彇璁惧閰嶇疆澶辫触锛岄敊璇爜锛� %s, %s", response.getStatusCode(), response.getReasonPhrase()));
 			resultHolder.invokeResult(msg);
 		});
@@ -132,11 +141,12 @@
 			logger.warn(String.format("鑾峰彇璁惧閰嶇疆瓒呮椂"));
 			// 閲婃斁rtpserver
 			RequestMessage msg = new RequestMessage();
-			msg.setId(DeferredResultHolder.CALLBACK_CMD_CONFIGDOWNLOAD + (StringUtils.isEmpty(channelId) ? deviceId : channelId));
+			msg.setId(uuid);
+			msg.setKey(key);
 			msg.setData("Timeout. Device did not response to this command.");
 			resultHolder.invokeResult(msg);
 		});
-		resultHolder.put(DeferredResultHolder.CALLBACK_CMD_CONFIGDOWNLOAD + (StringUtils.isEmpty(channelId) ? deviceId : channelId), result);
+		resultHolder.put(key, uuid, result);
 		return result;
 	}
 
diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceControl.java b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceControl.java
index 6fb3490..3b34c7d 100644
--- a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceControl.java
+++ b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceControl.java
@@ -29,6 +29,8 @@
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.context.request.async.DeferredResult;
 
+import java.util.UUID;
+
 @Api(tags = "鍥芥爣璁惧鎺у埗")
 @CrossOrigin
 @RestController
@@ -89,28 +91,36 @@
 	})
     @GetMapping("/record/{deviceId}/{recordCmdStr}")
     public DeferredResult<ResponseEntity<String>> recordApi(@PathVariable String deviceId,
-            @PathVariable String recordCmdStr, @RequestParam(required = false) String channelId) {
+            @PathVariable String recordCmdStr, String channelId) {
         if (logger.isDebugEnabled()) {
             logger.debug("寮�濮�/鍋滄褰曞儚API璋冪敤");
         }
         Device device = storager.queryVideoDevice(deviceId);
-        cmder.recordCmd(device, channelId, recordCmdStr, event -> {
-            Response response = event.getResponse();
-            RequestMessage msg = new RequestMessage();
-			msg.setId(DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + (StringUtils.isEmpty(channelId) ? deviceId : channelId));
-			msg.setData(String.format("寮�濮�/鍋滄褰曞儚鎿嶄綔澶辫触锛岄敊璇爜锛� %s, %s", response.getStatusCode(), response.getReasonPhrase()));
-			resultHolder.invokeResult(msg);
-		});
-        DeferredResult<ResponseEntity<String>> result = new DeferredResult<ResponseEntity<String>>(3 * 1000L);
+		String uuid = UUID.randomUUID().toString();
+		String key = DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL +  deviceId + channelId;
+		DeferredResult<ResponseEntity<String>> result = new DeferredResult<ResponseEntity<String>>(3 * 1000L);
 		result.onTimeout(() -> {
 			logger.warn(String.format("寮�濮�/鍋滄褰曞儚鎿嶄綔瓒呮椂, 璁惧鏈繑鍥炲簲绛旀寚浠�"));
 			// 閲婃斁rtpserver
 			RequestMessage msg = new RequestMessage();
-			msg.setId(DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + (StringUtils.isEmpty(channelId) ? deviceId : channelId));
+			msg.setKey(key);
+			msg.setId(uuid);
 			msg.setData("Timeout. Device did not response to this command.");
-			resultHolder.invokeResult(msg);
+			resultHolder.invokeAllResult(msg);
 		});
-		resultHolder.put(DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + (StringUtils.isEmpty(channelId) ? deviceId : channelId), result);
+		resultHolder.put(key, uuid, result);
+		if (resultHolder.exist(key, null)){
+			return result;
+		}
+		cmder.recordCmd(device, channelId, recordCmdStr, event -> {
+            Response response = event.getResponse();
+            RequestMessage msg = new RequestMessage();
+			msg.setId(uuid);
+			msg.setKey(key);
+			msg.setData(String.format("寮�濮�/鍋滄褰曞儚鎿嶄綔澶辫触锛岄敊璇爜锛� %s, %s", response.getStatusCode(), response.getReasonPhrase()));
+			resultHolder.invokeAllResult(msg);
+		});
+
 		return result;
 	}
 
@@ -123,32 +133,38 @@
 	@ApiOperation("甯冮槻/鎾ら槻鍛戒护")
 	@ApiImplicitParams({
 			@ApiImplicitParam(name = "deviceId", value = "璁惧ID", required = true, dataTypeClass = String.class),
+			@ApiImplicitParam(name = "channelId", value ="閫氶亾缂栫爜" ,dataTypeClass = String.class),
 			@ApiImplicitParam(name = "guardCmdStr", value ="鍛戒护锛� 鍙�夊�硷細SetGuard锛堝竷闃诧級锛孯esetGuard锛堟挙闃诧級", required = true,
 					dataTypeClass = String.class)
 	})
 	@GetMapping("/guard/{deviceId}/{guardCmdStr}")
-	public DeferredResult<ResponseEntity<String>> guardApi(@PathVariable String deviceId, @PathVariable String guardCmdStr) {
+	public DeferredResult<ResponseEntity<String>> guardApi(@PathVariable String deviceId, String channelId, @PathVariable String guardCmdStr) {
 		if (logger.isDebugEnabled()) {
 			logger.debug("甯冮槻/鎾ら槻API璋冪敤");
 		}
 		Device device = storager.queryVideoDevice(deviceId);
+		String key = DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + deviceId + channelId;
+		String uuid =UUID.randomUUID().toString();
 		cmder.guardCmd(device, guardCmdStr, event -> {
 			Response response = event.getResponse();
 			RequestMessage msg = new RequestMessage();
-			msg.setId(DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + deviceId);
+			msg.setId(uuid);
+			msg.setKey(key);
 			msg.setData(String.format("甯冮槻/鎾ら槻鎿嶄綔澶辫触锛岄敊璇爜锛� %s, %s", response.getStatusCode(), response.getReasonPhrase()));
 			resultHolder.invokeResult(msg);
 		});
         DeferredResult<ResponseEntity<String>> result = new DeferredResult<ResponseEntity<String>>(3 * 1000L);
+		resultHolder.put(key, uuid, result);
 		result.onTimeout(() -> {
 			logger.warn(String.format("甯冮槻/鎾ら槻鎿嶄綔瓒呮椂, 璁惧鏈繑鍥炲簲绛旀寚浠�"));
 			// 閲婃斁rtpserver
 			RequestMessage msg = new RequestMessage();
-			msg.setId(DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + deviceId);
+			msg.setKey(key);
+			msg.setId(uuid);
 			msg.setData("Timeout. Device did not response to this command.");
 			resultHolder.invokeResult(msg);
 		});
-		resultHolder.put(DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + deviceId, result);
+
 		return result;
 	}
 
@@ -162,21 +178,25 @@
 	@ApiOperation("鎶ヨ澶嶄綅")
 	@ApiImplicitParams({
 			@ApiImplicitParam(name = "deviceId", value = "璁惧ID", required = true, dataTypeClass = String.class),
+			@ApiImplicitParam(name = "channelId", value ="閫氶亾缂栫爜" ,dataTypeClass = String.class),
 			@ApiImplicitParam(name = "alarmMethod", value ="鎶ヨ鏂瑰紡", dataTypeClass = String.class),
 			@ApiImplicitParam(name = "alarmType", value ="鎶ヨ绫诲瀷", dataTypeClass = String.class),
 	})
 	@GetMapping("/reset_alarm/{deviceId}")
-	public DeferredResult<ResponseEntity<String>> resetAlarmApi(@PathVariable String deviceId, 
+	public DeferredResult<ResponseEntity<String>> resetAlarmApi(@PathVariable String deviceId, String channelId,
 																@RequestParam(required = false) String alarmMethod,
 																@RequestParam(required = false) String alarmType) {
 		if (logger.isDebugEnabled()) {
 			logger.debug("鎶ヨ澶嶄綅API璋冪敤");
 		}
 		Device device = storager.queryVideoDevice(deviceId);
+		String uuid = UUID.randomUUID().toString();
+		String key = DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + deviceId + channelId;
 		cmder.alarmCmd(device, alarmMethod, alarmType, event -> {
 			Response response = event.getResponse();
 			RequestMessage msg = new RequestMessage();
-			msg.setId(DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + deviceId);
+			msg.setId(uuid);
+			msg.setKey(key);
 			msg.setData(String.format("鎶ヨ澶嶄綅鎿嶄綔澶辫触锛岄敊璇爜锛� %s, %s", response.getStatusCode(), response.getReasonPhrase()));
 			resultHolder.invokeResult(msg);
 		});
@@ -185,11 +205,12 @@
 			logger.warn(String.format("鎶ヨ澶嶄綅鎿嶄綔瓒呮椂, 璁惧鏈繑鍥炲簲绛旀寚浠�"));
 			// 閲婃斁rtpserver
 			RequestMessage msg = new RequestMessage();
-			msg.setId(DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + deviceId);
+			msg.setId(uuid);
+			msg.setKey(key);
 			msg.setData("Timeout. Device did not response to this command.");
 			resultHolder.invokeResult(msg);
 		});
-		resultHolder.put(DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + deviceId, result);
+		resultHolder.put(key, uuid, result);
 		return result;
 	}
 
@@ -236,6 +257,7 @@
 	@ApiOperation("鐪嬪畧浣嶆帶鍒�")
 	@ApiImplicitParams({
 			@ApiImplicitParam(name = "deviceId", value = "璁惧ID", required = true, dataTypeClass = String.class),
+			@ApiImplicitParam(name = "channelId", value ="閫氶亾缂栫爜" ,dataTypeClass = String.class),
 			@ApiImplicitParam(name = "enabled", value = "鏄惁寮�鍚湅瀹堜綅 1:寮�鍚�,0:鍏抽棴", required = true, dataTypeClass = String.class),
 			@ApiImplicitParam(name = "resetTime", value = "鑷姩褰掍綅鏃堕棿闂撮殧", dataTypeClass = String.class),
 			@ApiImplicitParam(name = "presetIndex", value = "璋冪敤棰勭疆浣嶇紪鍙�", dataTypeClass = String.class),
@@ -246,15 +268,18 @@
 																@PathVariable String enabled,
 																@RequestParam(required = false) String resetTime,
 																@RequestParam(required = false) String presetIndex,
-                                                                @RequestParam(required = false) String channelId) {
+                                                                String channelId) {
         if (logger.isDebugEnabled()) {
 			logger.debug("鎶ヨ澶嶄綅API璋冪敤");
 		}
+		String key = DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + (StringUtils.isEmpty(channelId) ? deviceId : channelId);
+		String uuid = UUID.randomUUID().toString();
 		Device device = storager.queryVideoDevice(deviceId);
 		cmder.homePositionCmd(device, channelId, enabled, resetTime, presetIndex, event -> {
 			Response response = event.getResponse();
 			RequestMessage msg = new RequestMessage();
-			msg.setId(DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + (StringUtils.isEmpty(channelId) ? deviceId : channelId));
+			msg.setId(uuid);
+			msg.setKey(key);
 			msg.setData(String.format("鐪嬪畧浣嶆帶鍒舵搷浣滃け璐ワ紝閿欒鐮侊細 %s, %s", response.getStatusCode(), response.getReasonPhrase()));
 			resultHolder.invokeResult(msg);
 		});
@@ -263,7 +288,8 @@
 			logger.warn(String.format("鐪嬪畧浣嶆帶鍒舵搷浣滆秴鏃�, 璁惧鏈繑鍥炲簲绛旀寚浠�"));
 			// 閲婃斁rtpserver
 			RequestMessage msg = new RequestMessage();
-			msg.setId(DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + (StringUtils.isEmpty(channelId) ? deviceId : channelId));
+			msg.setId(uuid);
+			msg.setKey(key);
 			JSONObject json = new JSONObject();
 			json.put("DeviceID", deviceId);
 			json.put("Status", "Timeout");
@@ -271,7 +297,7 @@
 			msg.setData(json); //("鐪嬪畧浣嶆帶鍒舵搷浣滆秴鏃�, 璁惧鏈繑鍥炲簲绛旀寚浠�");
 			resultHolder.invokeResult(msg);
 		});
-		resultHolder.put(DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + (StringUtils.isEmpty(channelId) ? deviceId : channelId), result);
+		resultHolder.put(key, uuid, result);
 		return result;
 	}
 }
diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceQuery.java b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceQuery.java
index cb08ba3..359fcbe 100644
--- a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceQuery.java
+++ b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceQuery.java
@@ -24,6 +24,7 @@
 
 import javax.sip.message.Response;
 import java.io.UnsupportedEncodingException;
+import java.util.UUID;
 
 @Api(tags = "鍥芥爣璁惧鏌ヨ", value = "鍥芥爣璁惧鏌ヨ")
 @SuppressWarnings("rawtypes")
@@ -143,23 +144,32 @@
 			logger.debug("璁惧閫氶亾淇℃伅鍚屾API璋冪敤锛宒eviceId锛�" + deviceId);
 		}
 		Device device = storager.queryVideoDevice(deviceId);
-        cmder.catalogQuery(device, event -> {
-			Response response = event.getResponse();
-			RequestMessage msg = new RequestMessage();
-			msg.setId(DeferredResultHolder.CALLBACK_CMD_CATALOG+deviceId);
-			msg.setData(String.format("鍚屾閫氶亾澶辫触锛岄敊璇爜锛� %s, %s", response.getStatusCode(), response.getReasonPhrase()));
-			resultHolder.invokeResult(msg);
-		});
-        DeferredResult<ResponseEntity<Device>> result = new DeferredResult<ResponseEntity<Device>>(15*1000L);
+		String key = DeferredResultHolder.CALLBACK_CMD_CATALOG + deviceId;
+		String uuid = UUID.randomUUID().toString();
+		DeferredResult<ResponseEntity<Device>> result = new DeferredResult<ResponseEntity<Device>>(15*1000L);
 		result.onTimeout(()->{
 			logger.warn(String.format("璁惧閫氶亾淇℃伅鍚屾瓒呮椂"));
 			// 閲婃斁rtpserver
 			RequestMessage msg = new RequestMessage();
-			msg.setId(DeferredResultHolder.CALLBACK_CMD_CATALOG+deviceId);
+			msg.setKey(key);
+			msg.setId(uuid);
 			msg.setData("Timeout");
-			resultHolder.invokeResult(msg);
+			resultHolder.invokeAllResult(msg);
 		});
-        resultHolder.put(DeferredResultHolder.CALLBACK_CMD_CATALOG+deviceId, result);
+		// 绛夊緟鍏朵粬鐩稿悓璇锋眰杩斿洖鏃朵竴璧疯繑鍥�
+		if (resultHolder.exist(key, null)) {
+			return result;
+		}
+        cmder.catalogQuery(device, event -> {
+			Response response = event.getResponse();
+			RequestMessage msg = new RequestMessage();
+			msg.setKey(key);
+			msg.setId(uuid);
+			msg.setData(String.format("鍚屾閫氶亾澶辫触锛岄敊璇爜锛� %s, %s", response.getStatusCode(), response.getReasonPhrase()));
+			resultHolder.invokeAllResult(msg);
+		});
+
+        resultHolder.put(key, uuid, result);
         return result;
 	}
 
@@ -316,10 +326,13 @@
 			logger.debug("璁惧鐘舵�佹煡璇PI璋冪敤");
 		}
 		Device device = storager.queryVideoDevice(deviceId);
+		String uuid = UUID.randomUUID().toString();
+		String key = DeferredResultHolder.CALLBACK_CMD_DEVICESTATUS + deviceId;
 		cmder.deviceStatusQuery(device, event -> {
 			Response response = event.getResponse();
 			RequestMessage msg = new RequestMessage();
-			msg.setId(DeferredResultHolder.CALLBACK_CMD_DEVICESTATUS + deviceId);
+			msg.setId(uuid);
+			msg.setKey(key);
 			msg.setData(String.format("鑾峰彇璁惧鐘舵�佸け璐ワ紝閿欒鐮侊細 %s, %s", response.getStatusCode(), response.getReasonPhrase()));
 			resultHolder.invokeResult(msg);
 		});
@@ -328,11 +341,12 @@
 			logger.warn(String.format("鑾峰彇璁惧鐘舵�佽秴鏃�"));
 			// 閲婃斁rtpserver
 			RequestMessage msg = new RequestMessage();
-			msg.setId(DeferredResultHolder.CALLBACK_CMD_DEVICESTATUS + deviceId);
+			msg.setId(uuid);
+			msg.setKey(key);
 			msg.setData("Timeout. Device did not response to this command.");
 			resultHolder.invokeResult(msg);
 		});
-		resultHolder.put(DeferredResultHolder.CALLBACK_CMD_DEVICESTATUS + deviceId, result);
+		resultHolder.put(DeferredResultHolder.CALLBACK_CMD_DEVICESTATUS + deviceId, uuid, result);
 		return result;
 	}
 
@@ -369,10 +383,13 @@
 			logger.debug("璁惧鎶ヨ鏌ヨAPI璋冪敤");
 		}
 		Device device = storager.queryVideoDevice(deviceId);
+		String key = DeferredResultHolder.CALLBACK_CMD_ALARM + deviceId;
+		String uuid = UUID.randomUUID().toString();
 		cmder.alarmInfoQuery(device, startPriority, endPriority, alarmMethod, alarmType, startTime, endTime, event -> {
 			Response response = event.getResponse();
 			RequestMessage msg = new RequestMessage();
-			msg.setId(DeferredResultHolder.CALLBACK_CMD_ALARM + deviceId);
+			msg.setId(uuid);
+			msg.setKey(key);
 			msg.setData(String.format("璁惧鎶ヨ鏌ヨ澶辫触锛岄敊璇爜锛� %s, %s", response.getStatusCode(), response.getReasonPhrase()));
 			resultHolder.invokeResult(msg);
 		});
@@ -381,11 +398,12 @@
 			logger.warn(String.format("璁惧鎶ヨ鏌ヨ瓒呮椂"));
 			// 閲婃斁rtpserver
 			RequestMessage msg = new RequestMessage();
-			msg.setId(DeferredResultHolder.CALLBACK_CMD_ALARM + deviceId);
+			msg.setId(uuid);
+			msg.setKey(key);
 			msg.setData("璁惧鎶ヨ鏌ヨ瓒呮椂");
 			resultHolder.invokeResult(msg);
 		});
-		resultHolder.put(DeferredResultHolder.CALLBACK_CMD_ALARM + deviceId, result);
+		resultHolder.put(DeferredResultHolder.CALLBACK_CMD_ALARM + deviceId, uuid, result);
 		return result;
 	}
 
diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/PlayController.java b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/PlayController.java
index fb31fa0..2346ab3 100644
--- a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/PlayController.java
+++ b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/PlayController.java
@@ -103,28 +103,31 @@
 
 		logger.debug(String.format("璁惧棰勮/鍥炴斁鍋滄API璋冪敤锛宻treamId锛�%s_%s", deviceId, channelId ));
 
-		UUID uuid = UUID.randomUUID();
+		String uuid = UUID.randomUUID().toString();
 		DeferredResult<ResponseEntity<String>> result = new DeferredResult<ResponseEntity<String>>();
 
 		// 褰曞儚鏌ヨ浠hannelId浣滀负deviceId鏌ヨ
-		resultHolder.put(DeferredResultHolder.CALLBACK_CMD_STOP + uuid, result);
+		String key = DeferredResultHolder.CALLBACK_CMD_STOP + deviceId + channelId;
+		resultHolder.put(key, uuid, result);
 		Device device = storager.queryVideoDevice(deviceId);
 		cmder.streamByeCmd(deviceId, channelId, (event) -> {
 			StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channelId);
 			if (streamInfo == null) {
 				RequestMessage msg = new RequestMessage();
-				msg.setId(DeferredResultHolder.CALLBACK_CMD_STOP + uuid);
+				msg.setId(uuid);
+				msg.setKey(key);
 				msg.setData("鐐规挱鏈壘鍒�");
-				resultHolder.invokeResult(msg);
+				resultHolder.invokeAllResult(msg);
 				storager.stopPlay(deviceId, channelId);
 			}else {
 				redisCatchStorage.stopPlay(streamInfo);
 				storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId());
 				RequestMessage msg = new RequestMessage();
-				msg.setId(DeferredResultHolder.CALLBACK_CMD_STOP + uuid);
+				msg.setId(uuid);
+				msg.setKey(key);
 				//Response response = event.getResponse();
 				msg.setData(String.format("success"));
-				resultHolder.invokeResult(msg);
+				resultHolder.invokeAllResult(msg);
 			}
 			mediaServerService.closeRTPServer(device, channelId);
 		});
@@ -134,24 +137,27 @@
 			json.put("deviceId", deviceId);
 			json.put("channelId", channelId);
 			RequestMessage msg = new RequestMessage();
-			msg.setId(DeferredResultHolder.CALLBACK_CMD_PLAY + uuid);
+			msg.setId(uuid);
+			msg.setKey(key);
 			msg.setData(json.toString());
-			resultHolder.invokeResult(msg);
+			resultHolder.invokeAllResult(msg);
 		} else {
 			logger.warn("璁惧棰勮/鍥炴斁鍋滄API璋冪敤澶辫触锛�");
 			RequestMessage msg = new RequestMessage();
-			msg.setId(DeferredResultHolder.CALLBACK_CMD_PLAY + uuid);
+			msg.setId(uuid);
+			msg.setKey(key);
 			msg.setData("streamId null");
-			resultHolder.invokeResult(msg);
+			resultHolder.invokeAllResult(msg);
 		}
 
 		// 瓒呮椂澶勭悊
 		result.onTimeout(()->{
 			logger.warn(String.format("璁惧棰勮/鍥炴斁鍋滄瓒呮椂锛宒eviceId/channelId锛�%s_%s ", deviceId, channelId));
 			RequestMessage msg = new RequestMessage();
-			msg.setId(DeferredResultHolder.CALLBACK_CMD_STOP + uuid);
+			msg.setId(uuid);
+			msg.setKey(key);
 			msg.setData("Timeout");
-			resultHolder.invokeResult(msg);
+			resultHolder.invokeAllResult(msg);
 		});
 		return result;
 	}
@@ -259,10 +265,18 @@
         }
         Device device = storager.queryVideoDevice(deviceId);
 		DeferredResult<ResponseEntity<String>> result = new DeferredResult<ResponseEntity<String>>(3 * 1000L);
+		String key  = DeferredResultHolder.CALLBACK_CMD_BROADCAST + deviceId;
+		if (resultHolder.exist(key, null)) {
+			result.setResult(new ResponseEntity<>("璁惧浣跨敤涓�",HttpStatus.OK));
+			return result;
+		}
+		String uuid  = UUID.randomUUID().toString();
         if (device == null) {
-			resultHolder.put(DeferredResultHolder.CALLBACK_CMD_BROADCAST + deviceId, result);
+
+			resultHolder.put(key, key,  result);
 			RequestMessage msg = new RequestMessage();
-			msg.setId(DeferredResultHolder.CALLBACK_CMD_BROADCAST + deviceId);
+			msg.setKey(key);
+			msg.setId(uuid);
 			JSONObject json = new JSONObject();
 			json.put("DeviceID", deviceId);
 			json.put("CmdType", "Broadcast");
@@ -275,7 +289,8 @@
 		cmder.audioBroadcastCmd(device, (event) -> {
 			Response response = event.getResponse();
 			RequestMessage msg = new RequestMessage();
-			msg.setId(DeferredResultHolder.CALLBACK_CMD_BROADCAST + deviceId);
+			msg.setKey(key);
+			msg.setId(uuid);
 			JSONObject json = new JSONObject();
 			json.put("DeviceID", deviceId);
 			json.put("CmdType", "Broadcast");
@@ -288,7 +303,8 @@
 		result.onTimeout(() -> {
 			logger.warn(String.format("璇煶骞挎挱鎿嶄綔瓒呮椂, 璁惧鏈繑鍥炲簲绛旀寚浠�"));
 			RequestMessage msg = new RequestMessage();
-			msg.setId(DeferredResultHolder.CALLBACK_CMD_BROADCAST + deviceId);
+			msg.setKey(key);
+			msg.setId(uuid);
 			JSONObject json = new JSONObject();
 			json.put("DeviceID", deviceId);
 			json.put("CmdType", "Broadcast");
@@ -297,7 +313,7 @@
 			msg.setData(json);
 			resultHolder.invokeResult(msg);
 		});
-		resultHolder.put(DeferredResultHolder.CALLBACK_CMD_BROADCAST + deviceId, result);
+		resultHolder.put(key, uuid, result);
 		return result;
 	}
 
diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/playback/DownloadController.java b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/playback/DownloadController.java
index 5b244e6..e958827 100644
--- a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/playback/DownloadController.java
+++ b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/playback/DownloadController.java
@@ -76,30 +76,37 @@
 		if (logger.isDebugEnabled()) {
 			logger.debug(String.format("鍘嗗彶濯掍綋涓嬭浇 API璋冪敤锛宒eviceId锛�%s锛宑hannelId锛�%s锛宒ownloadSpeed锛�%s", deviceId, channelId, downloadSpeed));
 		}
-		UUID uuid = UUID.randomUUID();
+		String key = DeferredResultHolder.CALLBACK_CMD_PLAY + deviceId + channelId + startTime + endTime;
+		String uuid = UUID.randomUUID().toString();
 		DeferredResult<ResponseEntity<String>> result = new DeferredResult<ResponseEntity<String>>(30000L);
 		// 瓒呮椂澶勭悊
 		result.onTimeout(()->{
 			logger.warn(String.format("璁惧涓嬭浇鍝嶅簲瓒呮椂锛宒eviceId锛�%s 锛宑hannelId锛�%s", deviceId, channelId));
 			RequestMessage msg = new RequestMessage();
-			msg.setId(DeferredResultHolder.CALLBACK_CMD_PLAY + uuid);
+			msg.setId(uuid);
+			msg.setKey(key);
 			msg.setData("Timeout");
-			resultHolder.invokeResult(msg);
+			resultHolder.invokeAllResult(msg);
 		});
+		resultHolder.put(key, uuid, result);
+		if(resultHolder.exist(key, null)) {
+			return result;
+		}
 		Device device = storager.queryVideoDevice(deviceId);
 		StreamInfo streamInfo = redisCatchStorage.queryPlaybackByDevice(deviceId, channelId);
 		if (streamInfo != null) {
 			// 鍋滄涔嬪墠鐨勪笅杞�
 			cmder.streamByeCmd(deviceId, channelId);
 		}
-		resultHolder.put(DeferredResultHolder.CALLBACK_CMD_PLAY + uuid, result);
+
 		MediaServerItem newMediaServerItem = playService.getNewMediaServerItem(device);
 		if (newMediaServerItem == null) {
 			logger.warn(String.format("璁惧涓嬭浇鍝嶅簲瓒呮椂锛宒eviceId锛�%s 锛宑hannelId锛�%s", deviceId, channelId));
 			RequestMessage msg = new RequestMessage();
-			msg.setId(DeferredResultHolder.CALLBACK_CMD_PLAY + uuid);
+			msg.setId(uuid);
+			msg.setKey(key);
 			msg.setData("Timeout");
-			resultHolder.invokeResult(msg);
+			resultHolder.invokeAllResult(msg);
 			return result;
 		}
 
@@ -111,9 +118,10 @@
 		}, event -> {
 			Response response = event.getResponse();
 			RequestMessage msg = new RequestMessage();
-			msg.setId(DeferredResultHolder.CALLBACK_CMD_PLAY + uuid);
+			msg.setId(uuid);
+			msg.setKey(key);
 			msg.setData(String.format("鍥炴斁澶辫触锛� 閿欒鐮侊細 %s, %s", response.getStatusCode(), response.getReasonPhrase()));
-			resultHolder.invokeResult(msg);
+			resultHolder.invokeAllResult(msg);
 		});
 
 		return result;
diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/playback/PlaybackController.java b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/playback/PlaybackController.java
index 30bca1d..d847bbd 100644
--- a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/playback/PlaybackController.java
+++ b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/playback/PlaybackController.java
@@ -76,9 +76,9 @@
 		if (logger.isDebugEnabled()) {
 			logger.debug(String.format("璁惧鍥炴斁 API璋冪敤锛宒eviceId锛�%s 锛宑hannelId锛�%s", deviceId, channelId));
 		}
-		UUID uuid = UUID.randomUUID();
+		String uuid = UUID.randomUUID().toString();
+		String key = DeferredResultHolder.CALLBACK_CMD_PLAY + deviceId + channelId + startTime + endTime;
 		DeferredResult<ResponseEntity<String>> result = new DeferredResult<ResponseEntity<String>>(30000L);
-
 		Device device = storager.queryVideoDevice(deviceId);
 		if (device == null) {
 			result.setResult(new ResponseEntity<>(HttpStatus.BAD_REQUEST));
@@ -91,7 +91,8 @@
 		result.onTimeout(()->{
 			logger.warn(String.format("璁惧鍥炴斁瓒呮椂锛宒eviceId锛�%s 锛宑hannelId锛�%s", deviceId, channelId));
 			RequestMessage msg = new RequestMessage();
-			msg.setId(DeferredResultHolder.CALLBACK_CMD_PLAY + uuid);
+			msg.setId(uuid);
+			msg.setKey(key);
 			msg.setData("Timeout");
 			resultHolder.invokeResult(msg);
 		});
@@ -101,12 +102,13 @@
 			// 鍋滄涔嬪墠鐨勫洖鏀�
 			cmder.streamByeCmd(deviceId, channelId);
 		}
-		resultHolder.put(DeferredResultHolder.CALLBACK_CMD_PLAY + uuid, result);
+		resultHolder.put(DeferredResultHolder.CALLBACK_CMD_PLAY + deviceId + channelId + startTime + endTime, uuid, result);
 
 		if (newMediaServerItem == null) {
 			logger.warn(String.format("璁惧鍥炴斁瓒呮椂锛宒eviceId锛�%s 锛宑hannelId锛�%s", deviceId, channelId));
 			RequestMessage msg = new RequestMessage();
-			msg.setId(DeferredResultHolder.CALLBACK_CMD_PLAY + uuid);
+			msg.setId(uuid);
+			msg.setKey(key);
 			msg.setData("Timeout");
 			resultHolder.invokeResult(msg);
 			return result;
@@ -118,7 +120,8 @@
 		}, event -> {
 			Response response = event.getResponse();
 			RequestMessage msg = new RequestMessage();
-			msg.setId(DeferredResultHolder.CALLBACK_CMD_PLAY + uuid);
+			msg.setId(uuid);
+			msg.setKey(key);
 			msg.setData(String.format("鍥炴斁澶辫触锛� 閿欒鐮侊細 %s, %s", response.getStatusCode(), response.getReasonPhrase()));
 			resultHolder.invokeResult(msg);
 		});
diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/ptz/PtzController.java b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/ptz/PtzController.java
index 66f88a7..bcf4e4c 100644
--- a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/ptz/PtzController.java
+++ b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/ptz/PtzController.java
@@ -21,6 +21,8 @@
 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
 import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
 
+import java.util.UUID;
+
 @Api(tags = "浜戝彴鎺у埗")
 @CrossOrigin
 @RestController
@@ -101,23 +103,31 @@
 			logger.debug("璁惧棰勭疆浣嶆煡璇PI璋冪敤");
 		}
 		Device device = storager.queryVideoDevice(deviceId);
-		cmder.presetQuery(device, channelId, event -> {
-			Response response = event.getResponse();
-			RequestMessage msg = new RequestMessage();
-			msg.setId(DeferredResultHolder.CALLBACK_CMD_PRESETQUERY + (StringUtils.isEmpty(channelId) ? deviceId : channelId));
-			msg.setData(String.format("鑾峰彇璁惧棰勭疆浣嶅け璐ワ紝閿欒鐮侊細 %s, %s", response.getStatusCode(), response.getReasonPhrase()));
-			resultHolder.invokeResult(msg);
-		});
-        DeferredResult<ResponseEntity<String>> result = new DeferredResult<ResponseEntity<String >> (3 * 1000L);
+		String uuid =  UUID.randomUUID().toString();
+		String key =  DeferredResultHolder.CALLBACK_CMD_PRESETQUERY + (StringUtils.isEmpty(channelId) ? deviceId : channelId);
+		DeferredResult<ResponseEntity<String>> result = new DeferredResult<ResponseEntity<String >> (3 * 1000L);
 		result.onTimeout(()->{
 			logger.warn(String.format("鑾峰彇璁惧棰勭疆浣嶈秴鏃�"));
 			// 閲婃斁rtpserver
 			RequestMessage msg = new RequestMessage();
-			msg.setId(DeferredResultHolder.CALLBACK_CMD_PRESETQUERY + (StringUtils.isEmpty(channelId) ? deviceId : channelId));
+			msg.setId(uuid);
+			msg.setKey(key);
 			msg.setData("鑾峰彇璁惧棰勭疆浣嶈秴鏃�");
 			resultHolder.invokeResult(msg);
 		});
-		resultHolder.put(DeferredResultHolder.CALLBACK_CMD_PRESETQUERY + (StringUtils.isEmpty(channelId) ? deviceId : channelId), result);
+		resultHolder.put(key, uuid, result);
+		if (resultHolder.exist(key, null)) {
+			return result;
+		}
+		cmder.presetQuery(device, channelId, event -> {
+			Response response = event.getResponse();
+			RequestMessage msg = new RequestMessage();
+			msg.setId(uuid);
+			msg.setKey(key);
+			msg.setData(String.format("鑾峰彇璁惧棰勭疆浣嶅け璐ワ紝閿欒鐮侊細 %s, %s", response.getStatusCode(), response.getReasonPhrase()));
+			resultHolder.invokeResult(msg);
+		});
+
 		return result;
 	}
 }
diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/record/GBRecordController.java b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/record/GBRecordController.java
index f1c85cd..4ecb311 100644
--- a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/record/GBRecordController.java
+++ b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/record/GBRecordController.java
@@ -22,6 +22,8 @@
 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
 import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
 
+import java.util.UUID;
+
 @Api(tags = "鍥芥爣褰曞儚")
 @CrossOrigin
 @RestController
@@ -56,13 +58,15 @@
 		Device device = storager.queryVideoDevice(deviceId);
 		cmder.recordInfoQuery(device, channelId, startTime, endTime);
 		// 鎸囧畾瓒呮椂鏃堕棿 1鍒嗛挓30绉�
-		DeferredResult<ResponseEntity<RecordInfo>> result = new DeferredResult<ResponseEntity<RecordInfo>>(90*1000L);
+		DeferredResult<ResponseEntity<RecordInfo>> result = new DeferredResult<>(90*1000L);
+		String uuid = UUID.randomUUID().toString();
+		String key = DeferredResultHolder.CALLBACK_CMD_RECORDINFO + deviceId + channelId;
 		// 褰曞儚鏌ヨ浠hannelId浣滀负deviceId鏌ヨ
-		resultHolder.put(DeferredResultHolder.CALLBACK_CMD_RECORDINFO+channelId, result);
+		resultHolder.put(key, uuid, result);
 		result.onTimeout(()->{
 			RequestMessage msg = new RequestMessage();
-			msg.setDeviceId(deviceId);
-			msg.setType(DeferredResultHolder.CALLBACK_CMD_RECORDINFO);
+			msg.setId(uuid);
+			msg.setKey(key);
 			msg.setData("timeout");
 			resultHolder.invokeResult(msg);
 		});
diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/onvif/ONVIFController.java b/src/main/java/com/genersoft/iot/vmp/vmanager/onvif/ONVIFController.java
index 67bdb97..0fa2f6b 100644
--- a/src/main/java/com/genersoft/iot/vmp/vmanager/onvif/ONVIFController.java
+++ b/src/main/java/com/genersoft/iot/vmp/vmanager/onvif/ONVIFController.java
@@ -40,17 +40,18 @@
     @ResponseBody
     public DeferredResult<ResponseEntity<WVPResult>> search(@RequestParam(required = false)Integer timeout){
         DeferredResult<ResponseEntity<WVPResult>> result = new DeferredResult<>(timeout + 10L);
-        UUID uuid = UUID.randomUUID();
+        String uuid = UUID.randomUUID().toString();
         result.onTimeout(()->{
             RequestMessage msg = new RequestMessage();
-            msg.setId(DeferredResultHolder.CALLBACK_ONVIF + uuid);
+            msg.setKey(DeferredResultHolder.CALLBACK_ONVIF );
+            msg.setId(uuid);
             WVPResult<String> wvpResult = new WVPResult();
             wvpResult.setCode(0);
             wvpResult.setMsg("鎼滅储瓒呮椂");
             msg.setData(wvpResult);
             resultHolder.invokeResult(msg);
         });
-        resultHolder.put(DeferredResultHolder.CALLBACK_ONVIF + uuid, result);
+        resultHolder.put(DeferredResultHolder.CALLBACK_ONVIF, uuid, result);
 
         onvifServer.search(timeout, (errorCode, onvifDevices) ->{
             RequestMessage msg = new RequestMessage();
@@ -87,17 +88,18 @@
                                                                 ){
 
         DeferredResult<ResponseEntity<WVPResult>> result = new DeferredResult<>(timeout + 10L);
-        UUID uuid = UUID.randomUUID();
+        String uuid = UUID.randomUUID().toString();
         result.onTimeout(()->{
             RequestMessage msg = new RequestMessage();
-            msg.setId(DeferredResultHolder.CALLBACK_ONVIF + uuid);
+            msg.setId(uuid);
+            msg.setKey(DeferredResultHolder.CALLBACK_ONVIF);
             WVPResult<String> wvpResult = new WVPResult();
             wvpResult.setCode(0);
             wvpResult.setMsg("鑾峰彇onvif鐨剅tsp鍦板潃瓒呮椂");
             msg.setData(wvpResult);
             resultHolder.invokeResult(msg);
         });
-        resultHolder.put(DeferredResultHolder.CALLBACK_ONVIF + uuid, result);
+        resultHolder.put(DeferredResultHolder.CALLBACK_ONVIF, uuid, result);
         OnvifDevice onvifDevice = new OnvifDevice(hostname, username, password);
         onvifServer.getRTSPUrl(timeout, onvifDevice,  (errorCode, url) ->{
             RequestMessage msg = new RequestMessage();
diff --git a/web_src/src/components/MediaServerManger.vue b/web_src/src/components/MediaServerManger.vue
index 7f6bf22..07b0523 100644
--- a/web_src/src/components/MediaServerManger.vue
+++ b/web_src/src/components/MediaServerManger.vue
@@ -127,7 +127,6 @@
           }
         }
 
-        console.log("aadada:    "+ resultVal)
         return resultVal;
       },
 			dateFormat: function(/** timestamp=0 **/) {

--
Gitblit v1.8.0