From bf7ab3fe2ba246208d729901c33a9402209ee26a Mon Sep 17 00:00:00 2001
From: songww <songww@inspur.com>
Date: 星期五, 08 五月 2020 21:57:07 +0800
Subject: [PATCH] 优化代码结构,提供NVR录像检索接口

---
 src/main/java/com/genersoft/iot/vmp/gb28181/bean/RecordItem.java                                |   99 +++++
 src/main/java/com/genersoft/iot/vmp/vmanager/play/PlayController.java                           |    8 
 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java                 |  126 +++--
 src/main/java/com/genersoft/iot/vmp/conf/RedisConfig.java                                       |   32 -
 src/main/java/com/genersoft/iot/vmp/conf/SipConfig.java                                         |    1 
 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/RequestMessage.java               |   51 ++
 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/DeferredResultHolder.java         |   42 ++
 src/main/java/com/genersoft/iot/vmp/gb28181/utils/DateUtil.java                                 |   40 ++
 src/main/java/com/genersoft/iot/vmp/gb28181/bean/RecordInfo.java                                |   51 ++
 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java                     |   56 +-
 src/main/java/com/genersoft/iot/vmp/vmanager/ptz/PtzController.java                             |    8 
 src/main/java/com/genersoft/iot/vmp/gb28181/SipLayer.java                                       |  173 +++++---
 src/main/java/com/genersoft/iot/vmp/gb28181/auth/RegisterLogicHandler.java                      |   26 +
 src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java                          |  152 ++++++++
 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/RegisterRequestProcessor.java |    6 
 src/main/java/com/genersoft/iot/vmp/vmanager/device/DeviceController.java                       |   34 +
 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/MessageRequestProcessor.java  |  156 +++++--
 src/main/java/com/genersoft/iot/vmp/vmanager/record/RecordController.java                       |   47 ++
 18 files changed, 871 insertions(+), 237 deletions(-)

diff --git a/src/main/java/com/genersoft/iot/vmp/conf/RedisConfig.java b/src/main/java/com/genersoft/iot/vmp/conf/RedisConfig.java
index 914d0c3..3448a2f 100644
--- a/src/main/java/com/genersoft/iot/vmp/conf/RedisConfig.java
+++ b/src/main/java/com/genersoft/iot/vmp/conf/RedisConfig.java
@@ -12,20 +12,19 @@
 import com.genersoft.iot.vmp.utils.redis.FastJsonRedisSerializer;
 
 /**
- * @Description:Redis涓棿浠堕厤缃被
+ * @Description:Redis涓棿浠堕厤缃被锛屼娇鐢╯pring-data-redis闆嗘垚锛岃嚜鍔ㄤ粠application.yml涓姞杞絩edis閰嶇疆
  * @author: songww
  * @date: 2019骞�5鏈�30鏃� 涓婂崍10:58:25
  * 
  */
 @Configuration
-// @EnableCaching
 public class RedisConfig extends CachingConfigurerSupport {
 
 	@Bean("redisTemplate")
 	public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
 		RedisTemplate<Object, Object> template = new RedisTemplate<>();
 		template.setConnectionFactory(redisConnectionFactory);
-		ParserConfig.getGlobalInstance().setAutoTypeSupport(true); 
+		// 浣跨敤fastjson杩涜搴忓垪鍖栧鐞嗭紝鎻愰珮瑙f瀽鏁堢巼
 		FastJsonRedisSerializer<Object> serializer = new FastJsonRedisSerializer<Object>(Object.class);
 		// value鍊肩殑搴忓垪鍖栭噰鐢╢astJsonRedisSerializer
 		template.setValueSerializer(serializer);
@@ -33,8 +32,9 @@
 		// key鐨勫簭鍒楀寲閲囩敤StringRedisSerializer
 		template.setKeySerializer(new StringRedisSerializer());
 		template.setHashKeySerializer(new StringRedisSerializer());
-
 		template.setConnectionFactory(redisConnectionFactory);
+		// 浣跨敤fastjson鏃堕渶璁剧疆姝ら」锛屽惁鍒欎細鎶ュ紓甯竛ot support type
+		ParserConfig.getGlobalInstance().setAutoTypeSupport(true); 
 		return template;
 	}
 
@@ -53,27 +53,5 @@
         container.setConnectionFactory(connectionFactory);
         return container;
     }
-//	@Bean
-//	RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory,
-//			MessageListenerAdapter listenerAdapter) {
-//
-//		RedisMessageListenerContainer container = new RedisMessageListenerContainer();
-//		container.setConnectionFactory(connectionFactory);
-//		// 璁㈤槄浜嗕竴涓彨閫氶亾
-//		container.addMessageListener(listenerAdapter, new PatternTopic(VideoManagerConstants.KEEPLIVEKEY_PREFIX+"*"));
-//		// 杩欎釜container 鍙互娣诲姞澶氫釜 messageListener
-//		return container;
-//	}
-	
-//	/**
-//     * 娑堟伅鐩戝惉鍣ㄩ�傞厤鍣紝缁戝畾娑堟伅澶勭悊鍣紝鍒╃敤鍙嶅皠鎶�鏈皟鐢ㄦ秷鎭鐞嗗櫒鐨勪笟鍔℃柟娉�
-//     * @param receiver
-//     * @return
-//     */
-//    @Bean
-//    MessageListenerAdapter listenerAdapter(MessageReceiver receiver) {
-//        //杩欎釜鍦版柟 鏄粰messageListenerAdapter 浼犲叆涓�涓秷鎭帴鍙楃殑澶勭悊鍣紝鍒╃敤鍙嶅皠鐨勬柟娉曡皟鐢ㄢ�渞eceiveMessage鈥�
-//        //涔熸湁濂藉嚑涓噸杞芥柟娉曪紝杩欒竟榛樿璋冪敤澶勭悊鍣ㄧ殑鏂规硶 鍙玥andleMessage 鍙互鑷繁鍒版簮鐮侀噷闈㈢湅
-//        return new MessageListenerAdapter(receiver, "receiveMessage");
-//    }
+
 }
diff --git a/src/main/java/com/genersoft/iot/vmp/conf/SipConfig.java b/src/main/java/com/genersoft/iot/vmp/conf/SipConfig.java
index e6d23a4..6d53033 100644
--- a/src/main/java/com/genersoft/iot/vmp/conf/SipConfig.java
+++ b/src/main/java/com/genersoft/iot/vmp/conf/SipConfig.java
@@ -16,7 +16,6 @@
 	String sipPassword;
 	@Value("${media.ip}")
 	String mediaIp;
-	
 	@Value("${media.port}")
 	Integer mediaPort;
 	
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/SipLayer.java b/src/main/java/com/genersoft/iot/vmp/gb28181/SipLayer.java
index 4d08fcc..273f4ed 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/SipLayer.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/SipLayer.java
@@ -2,6 +2,7 @@
 
 import java.util.Properties;
 
+import javax.annotation.PostConstruct;
 import javax.sip.DialogTerminatedEvent;
 import javax.sip.IOExceptionEvent;
 import javax.sip.ListeningPoint;
@@ -26,7 +27,6 @@
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.context.annotation.Bean;
 import org.springframework.stereotype.Component;
 
 import com.genersoft.iot.vmp.conf.SipConfig;
@@ -37,70 +37,78 @@
 import gov.nist.javax.sip.SipStackImpl;
 
 @Component
-public class SipLayer implements SipListener{
-	
+public class SipLayer implements SipListener, Runnable {
+
 	private final static Logger logger = LoggerFactory.getLogger(SipLayer.class);
-	
+
 	@Autowired
 	private SipConfig config;
-	
+
 	private SipProvider tcpSipProvider;
-	
+
 	private SipProvider udpSipProvider;
-	
+
 	@Autowired
 	private SIPProcessorFactory processorFactory;
-	
+
 	private SipStack sipStack;
-	
+
 	private AddressFactory addressFactory;
 	private HeaderFactory headerFactory;
 	private MessageFactory messageFactory;
 
-	@Bean
-	private boolean initSipServer() throws Exception {
+	@PostConstruct
+	private void initSipServer() {
+		Thread thread=new Thread(this);
+        thread.setDaemon(true);
+        thread.setName("sip server thread start");
+        thread.start();
+	}
+
+	@Override
+	public void run() {
 		SipFactory sipFactory = SipFactory.getInstance();
 		sipFactory.setPathName("gov.nist");
-		headerFactory = sipFactory.createHeaderFactory();
-		addressFactory = sipFactory.createAddressFactory();
-		messageFactory = sipFactory.createMessageFactory();
-		
-		Properties properties = new Properties();
-		properties.setProperty("javax.sip.STACK_NAME", "GB28181_SIP");
-		properties.setProperty("javax.sip.IP_ADDRESS", config.getSipIp());
-		/**
-		 * sip_server_log.log 鍜� sip_debug_log.log public static final int TRACE_NONE =
-		 * 0; public static final int TRACE_MESSAGES = 16; public static final int
-		 * TRACE_EXCEPTION = 17; public static final int TRACE_DEBUG = 32;
-		 */
-		properties.setProperty("gov.nist.javax.sip.TRACE_LEVEL", "16");
-		properties.setProperty("gov.nist.javax.sip.SERVER_LOG", "sip_server_log");
-		properties.setProperty("gov.nist.javax.sip.DEBUG_LOG", "sip_debug_log");
-		sipStack = (SipStackImpl) sipFactory.createSipStack(properties);
-		
 		try {
+			headerFactory = sipFactory.createHeaderFactory();
+
+			addressFactory = sipFactory.createAddressFactory();
+			messageFactory = sipFactory.createMessageFactory();
+
+			Properties properties = new Properties();
+			properties.setProperty("javax.sip.STACK_NAME", "GB28181_SIP");
+			properties.setProperty("javax.sip.IP_ADDRESS", config.getSipIp());
+			properties.setProperty("gov.nist.javax.sip.LOG_MESSAGE_CONTENT", "false");
+			/**
+			 * sip_server_log.log 鍜� sip_debug_log.log public static final int TRACE_NONE =
+			 * 0; public static final int TRACE_MESSAGES = 16; public static final int
+			 * TRACE_EXCEPTION = 17; public static final int TRACE_DEBUG = 32;
+			 */
+			properties.setProperty("gov.nist.javax.sip.TRACE_LEVEL", "0");
+			properties.setProperty("gov.nist.javax.sip.SERVER_LOG", "sip_server_log");
+			properties.setProperty("gov.nist.javax.sip.DEBUG_LOG", "sip_debug_log");
+			sipStack = (SipStackImpl) sipFactory.createSipStack(properties);
+
 			startTcpListener();
 			startUdpListener();
 		} catch (Exception e) {
-			logger.error("Sip Server 鍚姩澶辫触锛� port {"+config.getSipPort()+"}");
+			logger.error("Sip Server 鍚姩澶辫触锛� port {" + config.getSipPort() + "}");
 			e.printStackTrace();
-			throw e;
 		}
-		logger.info("Sip Server 鍚姩鎴愬姛 port {"+config.getSipPort()+"}");
-		return true;
+		logger.info("Sip Server 鍚姩鎴愬姛 port {" + config.getSipPort() + "}");
 	}
-	
+
 	private void startTcpListener() throws Exception {
 		ListeningPoint tcpListeningPoint = sipStack.createListeningPoint(config.getSipIp(), config.getSipPort(), "TCP");
 		tcpSipProvider = sipStack.createSipProvider(tcpListeningPoint);
 		tcpSipProvider.addSipListener(this);
-    }
-	
-    private void startUdpListener() throws Exception {
+	}
+
+	private void startUdpListener() throws Exception {
 		ListeningPoint udpListeningPoint = sipStack.createListeningPoint(config.getSipIp(), config.getSipPort(), "UDP");
 		udpSipProvider = sipStack.createSipProvider(udpListeningPoint);
 		udpSipProvider.addSipListener(this);
-    }
+	}
 
 	/**
 	 * SIP鏈嶅姟绔帴鏀舵秷鎭殑鏂规硶 Content 閲岄潰鏄疓BK缂栫爜 This method is called by the SIP stack when a
@@ -118,60 +126,80 @@
 		int status = response.getStatusCode();
 		if ((status >= 200) && (status < 300)) { // Success!
 			ISIPResponseProcessor processor = processorFactory.createResponseProcessor(evt);
-			processor.process(evt,this,config);
+			processor.process(evt, this, config);
 		} else {
-			logger.warn("鎺ユ敹鍒板け璐ョ殑response鍝嶅簲锛乻tatus锛�"+status+",message:"+response.getContent().toString());
+			logger.warn("鎺ユ敹鍒板け璐ョ殑response鍝嶅簲锛乻tatus锛�" + status + ",message:" + response.getContent().toString());
 		}
-		//trying涓嶄細鍥炲
-		if(status == Response.TRYING){
+		// trying涓嶄細鍥炲
+		if (status == Response.TRYING) {
 
 		}
 	}
 
-	/**   
-	 * <p>Title: processTimeout</p>   
-	 * <p>Description: </p>   
-	 * @param timeoutEvent    
-	 */  
+	/**
+	 * <p>
+	 * Title: processTimeout
+	 * </p>
+	 * <p>
+	 * Description:
+	 * </p>
+	 * 
+	 * @param timeoutEvent
+	 */
 	@Override
 	public void processTimeout(TimeoutEvent timeoutEvent) {
 		// TODO Auto-generated method stub
-		
+
 	}
 
-	/**   
-	 * <p>Title: processIOException</p>   
-	 * <p>Description: </p>   
-	 * @param exceptionEvent    
-	 */  
+	/**
+	 * <p>
+	 * Title: processIOException
+	 * </p>
+	 * <p>
+	 * Description:
+	 * </p>
+	 * 
+	 * @param exceptionEvent
+	 */
 	@Override
 	public void processIOException(IOExceptionEvent exceptionEvent) {
 		// TODO Auto-generated method stub
-		
+
 	}
 
-	/**   
-	 * <p>Title: processTransactionTerminated</p>   
-	 * <p>Description: </p>   
-	 * @param transactionTerminatedEvent    
-	 */  
+	/**
+	 * <p>
+	 * Title: processTransactionTerminated
+	 * </p>
+	 * <p>
+	 * Description:
+	 * </p>
+	 * 
+	 * @param transactionTerminatedEvent
+	 */
 	@Override
 	public void processTransactionTerminated(TransactionTerminatedEvent transactionTerminatedEvent) {
 		// TODO Auto-generated method stub
-		
+
 	}
 
-	/**   
-	 * <p>Title: processDialogTerminated</p>   
-	 * <p>Description: </p>   
-	 * @param dialogTerminatedEvent    
-	 */  
+	/**
+	 * <p>
+	 * Title: processDialogTerminated
+	 * </p>
+	 * <p>
+	 * Description:
+	 * </p>
+	 * 
+	 * @param dialogTerminatedEvent
+	 */
 	@Override
 	public void processDialogTerminated(DialogTerminatedEvent dialogTerminatedEvent) {
 		// TODO Auto-generated method stub
-		
+
 	}
-	
+
 	private ServerTransaction getServerTransaction(RequestEvent evt) {
 		Request request = evt.getRequest();
 		ServerTransaction serverTransaction = evt.getServerTransaction();
@@ -185,11 +213,11 @@
 
 		if (serverTransaction == null) {
 			try {
-			if (isTcp) {
-				serverTransaction = tcpSipProvider.getNewServerTransaction(request);
-			} else {
-				serverTransaction = udpSipProvider.getNewServerTransaction(request);
-			}
+				if (isTcp) {
+					serverTransaction = tcpSipProvider.getNewServerTransaction(request);
+				} else {
+					serverTransaction = udpSipProvider.getNewServerTransaction(request);
+				}
 			} catch (TransactionAlreadyExistsException e) {
 				e.printStackTrace();
 			} catch (TransactionUnavailableException e) {
@@ -198,7 +226,6 @@
 		}
 		return serverTransaction;
 	}
-
 
 	public AddressFactory getAddressFactory() {
 		return addressFactory;
@@ -219,5 +246,5 @@
 	public SipProvider getUdpSipProvider() {
 		return udpSipProvider;
 	}
-	
+
 }
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/auth/RegisterLogicHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/auth/RegisterLogicHandler.java
new file mode 100644
index 0000000..5d5bf21
--- /dev/null
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/auth/RegisterLogicHandler.java
@@ -0,0 +1,26 @@
+package com.genersoft.iot.vmp.gb28181.auth;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import com.genersoft.iot.vmp.gb28181.bean.Device;
+import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
+
+/**    
+ * @Description:娉ㄥ唽閫昏緫澶勭悊锛屽綋璁惧娉ㄥ唽鍚庤Е鍙戦�昏緫銆�
+ * @author: songww
+ * @date:   2020骞�5鏈�8鏃� 涓嬪崍9:41:46     
+ */
+@Component
+public class RegisterLogicHandler {
+
+	@Autowired
+	private SIPCommander cmder;
+	
+	public void onRegister(Device device) {
+		// TODO 鍚庣画澶勭悊锛屽彧鏈夌涓�娆℃敞鍐屾椂璋冪敤鏌ヨ璁惧淇℃伅锛屽闇�鏇存柊璋冪敤鏇存柊API鎺ュ彛
+		cmder.deviceInfoQuery(device);
+		
+		cmder.catalogQuery(device);
+	}
+}
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
new file mode 100644
index 0000000..2d2ca1e
--- /dev/null
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/RecordInfo.java
@@ -0,0 +1,51 @@
+package com.genersoft.iot.vmp.gb28181.bean;
+
+import java.util.List;
+
+/**    
+ * @Description:璁惧褰曞儚淇℃伅bean 
+ * @author: songww
+ * @date:   2020骞�5鏈�8鏃� 涓嬪崍2:05:56     
+ */
+public class RecordInfo {
+
+	private String deviceId;
+	
+	private String name;
+	
+	private int sumNum;
+	
+	private List<RecordItem> recordList;
+
+	public String getDeviceId() {
+		return deviceId;
+	}
+
+	public void setDeviceId(String deviceId) {
+		this.deviceId = deviceId;
+	}
+
+	public String getName() {
+		return name;
+	}
+
+	public void setName(String name) {
+		this.name = name;
+	}
+
+	public int getSumNum() {
+		return sumNum;
+	}
+
+	public void setSumNum(int sumNum) {
+		this.sumNum = sumNum;
+	}
+
+	public List<RecordItem> getRecordList() {
+		return recordList;
+	}
+
+	public void setRecordList(List<RecordItem> recordList) {
+		this.recordList = recordList;
+	}
+}
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/RecordItem.java b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/RecordItem.java
new file mode 100644
index 0000000..b0e713b
--- /dev/null
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/RecordItem.java
@@ -0,0 +1,99 @@
+package com.genersoft.iot.vmp.gb28181.bean;
+
+/**    
+ * @Description:璁惧褰曞儚bean 
+ * @author: songww
+ * @date:   2020骞�5鏈�8鏃� 涓嬪崍2:06:54     
+ */
+public class RecordItem {
+
+	private String deviceId;
+	
+	private String name;
+	
+	private String filePath;
+	
+	private String address;
+	
+	private String startTime;
+	
+	private String endTime;
+	
+	private int secrecy;
+	
+	private String type;
+	
+	private String recordId;
+
+	public String getDeviceId() {
+		return deviceId;
+	}
+
+	public void setDeviceId(String deviceId) {
+		this.deviceId = deviceId;
+	}
+
+	public String getName() {
+		return name;
+	}
+
+	public void setName(String name) {
+		this.name = name;
+	}
+
+	public String getFilePath() {
+		return filePath;
+	}
+
+	public void setFilePath(String filePath) {
+		this.filePath = filePath;
+	}
+
+	public String getAddress() {
+		return address;
+	}
+
+	public void setAddress(String address) {
+		this.address = address;
+	}
+
+	public String getStartTime() {
+		return startTime;
+	}
+
+	public void setStartTime(String startTime) {
+		this.startTime = startTime;
+	}
+
+	public int getSecrecy() {
+		return secrecy;
+	}
+
+	public void setSecrecy(int secrecy) {
+		this.secrecy = secrecy;
+	}
+
+	public String getType() {
+		return type;
+	}
+
+	public void setType(String type) {
+		this.type = type;
+	}
+
+	public String getRecordId() {
+		return recordId;
+	}
+
+	public void setRecordId(String recordId) {
+		this.recordId = recordId;
+	}
+
+	public String getEndTime() {
+		return endTime;
+	}
+
+	public void setEndTime(String endTime) {
+		this.endTime = endTime;
+	}
+}
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
new file mode 100644
index 0000000..f9c8d25
--- /dev/null
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/DeferredResultHolder.java
@@ -0,0 +1,42 @@
+package com.genersoft.iot.vmp.gb28181.transmit.callback;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Component;
+import org.springframework.web.context.request.async.DeferredResult;
+
+/**    
+ * @Description:TODO(杩欓噷鐢ㄤ竴鍙ヨ瘽鎻忚堪杩欎釜绫荤殑浣滅敤)   
+ * @author: songww
+ * @date:   2020骞�5鏈�8鏃� 涓嬪崍7:59:05     
+ */
+@Component
+public class DeferredResultHolder {
+	
+	public static final String CALLBACK_CMD_DEVICEINFO = "CALLBACK_DEVICEINFO";
+	
+	public static final String CALLBACK_CMD_CATALOG = "CALLBACK_CATALOG";
+	
+	public static final String CALLBACK_CMD_RECORDINFO = "CALLBACK_RECORDINFO";
+
+	private Map<String, DeferredResult> map = new HashMap<String, DeferredResult>();
+	
+	public void put(String key, DeferredResult result) {
+		map.put(key, result);
+	}
+	
+	public DeferredResult get(String key) {
+		return map.get(key);
+	}
+	
+	public void invokeResult(RequestMessage msg) {
+		DeferredResult result = map.get(msg.getId());
+		if (result == null) {
+			return;
+		}
+		result.setResult(new ResponseEntity<>(msg.getData(),HttpStatus.OK));
+	}
+}
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
new file mode 100644
index 0000000..ac95f75
--- /dev/null
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/RequestMessage.java
@@ -0,0 +1,51 @@
+package com.genersoft.iot.vmp.gb28181.transmit.callback;
+
+/**    
+ * @Description:TODO(杩欓噷鐢ㄤ竴鍙ヨ瘽鎻忚堪杩欎釜绫荤殑浣滅敤)   
+ * @author: songww
+ * @date:   2020骞�5鏈�8鏃� 涓嬪崍1:09:18     
+ */
+public class RequestMessage {
+	
+	private String id;
+
+	private String deviceId;
+	
+	private String type;
+	
+	private Object data;
+	
+	public String getId() {
+		return id;
+	}
+
+	public void setId(String id) {
+		this.id = id;
+	}
+
+	public String getDeviceId() {
+		return deviceId;
+	}
+
+	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 Object getData() {
+		return data;
+	}
+
+	public void setData(Object data) {
+		this.data = data;
+	}
+}
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java
index 2fe88ae..f226bf5 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java
@@ -12,48 +12,48 @@
 	/**
 	 * 浜戝彴鏂瑰悜鏀炬帶鍒讹紝浣跨敤閰嶇疆鏂囦欢涓殑榛樿闀滃ご绉诲姩閫熷害
 	 * 
-	 * @param deviceId  鎺у埗璁惧
+	 * @param device  鎺у埗璁惧
 	 * @param channelId  棰勮閫氶亾
 	 * @param leftRight  闀滃ご宸︾Щ鍙崇Щ 0:鍋滄 1:宸︾Щ 2:鍙崇Щ
      * @param upDown     闀滃ご涓婄Щ涓嬬Щ 0:鍋滄 1:涓婄Щ 2:涓嬬Щ
      * @param moveSpeed  闀滃ご绉诲姩閫熷害
 	 */
-	public boolean ptzdirectCmd(String deviceId,String channelId,int leftRight, int upDown);
+	public boolean ptzdirectCmd(Device device,String channelId,int leftRight, int upDown);
 	
 	/**
 	 * 浜戝彴鏂瑰悜鏀炬帶鍒�
 	 * 
-	 * @param deviceId  鎺у埗璁惧
+	 * @param device  鎺у埗璁惧
 	 * @param channelId  棰勮閫氶亾
 	 * @param leftRight  闀滃ご宸︾Щ鍙崇Щ 0:鍋滄 1:宸︾Щ 2:鍙崇Щ
      * @param upDown     闀滃ご涓婄Щ涓嬬Щ 0:鍋滄 1:涓婄Щ 2:涓嬬Щ
      * @param moveSpeed  闀滃ご绉诲姩閫熷害
 	 */
-	public boolean ptzdirectCmd(String deviceId,String channelId,int leftRight, int upDown, int moveSpeed);
+	public boolean ptzdirectCmd(Device device,String channelId,int leftRight, int upDown, int moveSpeed);
 	
 	/**
 	 * 浜戝彴缂╂斁鎺у埗锛屼娇鐢ㄩ厤缃枃浠朵腑鐨勯粯璁ら暅澶寸缉鏀鹃�熷害
 	 * 
-	 * @param deviceId  鎺у埗璁惧
+	 * @param device  鎺у埗璁惧
 	 * @param channelId  棰勮閫氶亾
      * @param inOut      闀滃ご鏀惧ぇ缂╁皬 0:鍋滄 1:缂╁皬 2:鏀惧ぇ
 	 */
-	public boolean ptzZoomCmd(String deviceId,String channelId,int inOut);
+	public boolean ptzZoomCmd(Device device,String channelId,int inOut);
 	
 	/**
 	 * 浜戝彴缂╂斁鎺у埗
 	 * 
-	 * @param deviceId  鎺у埗璁惧
+	 * @param device  鎺у埗璁惧
 	 * @param channelId  棰勮閫氶亾
      * @param inOut      闀滃ご鏀惧ぇ缂╁皬 0:鍋滄 1:缂╁皬 2:鏀惧ぇ
      * @param zoomSpeed  闀滃ご缂╂斁閫熷害
 	 */
-	public boolean ptzZoomCmd(String deviceId,String channelId,int inOut, int moveSpeed);
+	public boolean ptzZoomCmd(Device device,String channelId,int inOut, int moveSpeed);
 	
 	/**
 	 * 浜戝彴鎺у埗锛屾敮鎸佹柟鍚戜笌缂╂斁鎺у埗
 	 * 
-	 * @param deviceId  鎺у埗璁惧
+	 * @param device  鎺у埗璁惧
 	 * @param channelId  棰勮閫氶亾
 	 * @param leftRight  闀滃ご宸︾Щ鍙崇Щ 0:鍋滄 1:宸︾Щ 2:鍙崇Щ
      * @param upDown     闀滃ご涓婄Щ涓嬬Щ 0:鍋滄 1:涓婄Щ 2:涓嬬Щ
@@ -61,67 +61,67 @@
      * @param moveSpeed  闀滃ご绉诲姩閫熷害
      * @param zoomSpeed  闀滃ご缂╂斁閫熷害
 	 */
-	public boolean ptzCmd(String deviceId,String channelId,int leftRight, int upDown, int inOut, int moveSpeed, int zoomSpeed);
+	public boolean ptzCmd(Device device,String channelId,int leftRight, int upDown, int inOut, int moveSpeed, int zoomSpeed);
 	
 	/**
 	 * 璇锋眰棰勮瑙嗛娴�
 	 * 
-	 * @param deviceId  瑙嗛璁惧
+	 * @param device  瑙嗛璁惧
 	 * @param channelId  棰勮閫氶亾
 	 */
-	public String playStreamCmd(String deviceId,String channelId);
+	public String playStreamCmd(Device device,String channelId);
 	
 	/**
 	 * 璇煶骞挎挱
 	 * 
-	 * @param deviceId  瑙嗛璁惧
+	 * @param device  瑙嗛璁惧
 	 * @param channelId  棰勮閫氶亾
 	 */
-	public String audioBroadcastCmd(String deviceId,String channelId);
+	public boolean audioBroadcastCmd(Device device,String channelId);
 	
 	/**
 	 * 闊宠棰戝綍鍍忔帶鍒�
 	 * 
-	 * @param deviceId  瑙嗛璁惧
+	 * @param device  瑙嗛璁惧
 	 * @param channelId  棰勮閫氶亾
 	 */
-	public String recordCmd(String deviceId,String channelId);
+	public boolean recordCmd(Device device,String channelId);
 	
 	/**
 	 * 鎶ヨ甯冮槻/鎾ら槻鍛戒护
 	 * 
-	 * @param deviceId  瑙嗛璁惧
+	 * @param device  瑙嗛璁惧
 	 */
-	public String guardCmd(String deviceId);
+	public boolean guardCmd(Device device);
 	
 	/**
 	 * 鎶ヨ澶嶄綅鍛戒护
 	 * 
-	 * @param deviceId  瑙嗛璁惧
+	 * @param device  瑙嗛璁惧
 	 */
-	public String alarmCmd(String deviceId);
+	public boolean alarmCmd(Device device);
 	
 	/**
 	 * 寮哄埗鍏抽敭甯у懡浠�,璁惧鏀跺埌姝ゅ懡浠ゅ簲绔嬪埢鍙戦�佷竴涓狪DR甯�
 	 * 
-	 * @param deviceId  瑙嗛璁惧
+	 * @param device  瑙嗛璁惧
 	 * @param channelId  棰勮閫氶亾
 	 */
-	public String iFameCmd(String deviceId,String channelId);
+	public boolean iFameCmd(Device device,String channelId);
 	
 	/**
 	 * 鐪嬪畧浣嶆帶鍒跺懡浠�
 	 * 
-	 * @param deviceId  瑙嗛璁惧
+	 * @param device  瑙嗛璁惧
 	 */
-	public String homePositionCmd(String deviceId);
+	public boolean homePositionCmd(Device device);
 	
 	/**
 	 * 璁惧閰嶇疆鍛戒护
 	 * 
-	 * @param deviceId  瑙嗛璁惧
+	 * @param device  瑙嗛璁惧
 	 */
-	public String deviceConfigCmd(String deviceId);
+	public boolean deviceConfigCmd(Device device);
 	
 	
 	/**
@@ -150,8 +150,10 @@
 	 * 鏌ヨ褰曞儚淇℃伅
 	 * 
 	 * @param device 瑙嗛璁惧
+	 * @param startTime 寮�濮嬫椂闂�,鏍煎紡瑕佹眰锛歽yyy-MM-dd HH:mm:ss
+	 * @param endTime 缁撴潫鏃堕棿,鏍煎紡瑕佹眰锛歽yyy-MM-dd HH:mm:ss
 	 */
-	public boolean recordInfoQuery(Device device);
+	public boolean recordInfoQuery(Device device, String startTime, String endTime);
 	
 	/**
 	 * 鏌ヨ鎶ヨ淇℃伅
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
index 09f0934..630d44c 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
@@ -8,6 +8,7 @@
 import javax.sip.message.Request;
 
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationEventPublisher;
 import org.springframework.stereotype.Component;
 
 import com.genersoft.iot.vmp.conf.SipConfig;
@@ -15,7 +16,7 @@
 import com.genersoft.iot.vmp.gb28181.bean.Device;
 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
 import com.genersoft.iot.vmp.gb28181.transmit.cmd.SIPRequestHeaderProvider;
-import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
+import com.genersoft.iot.vmp.gb28181.utils.DateUtil;
 
 /**    
  * @Description:璁惧鑳藉姏鎺ュ彛锛岀敤浜庡畾涔夎澶囩殑鎺у埗銆佹煡璇㈣兘鍔�   
@@ -34,66 +35,63 @@
 	@Autowired
 	private SipLayer sipLayer;
 	
-	@Autowired
-	private IVideoManagerStorager storager;
-	 
 	/**
 	 * 浜戝彴鏂瑰悜鏀炬帶鍒讹紝浣跨敤閰嶇疆鏂囦欢涓殑榛樿闀滃ご绉诲姩閫熷害
 	 * 
-	 * @param deviceId  鎺у埗璁惧
+	 * @param device  鎺у埗璁惧
 	 * @param channelId  棰勮閫氶亾
 	 * @param leftRight  闀滃ご宸︾Щ鍙崇Щ 0:鍋滄 1:宸︾Щ 2:鍙崇Щ
      * @param upDown     闀滃ご涓婄Щ涓嬬Щ 0:鍋滄 1:涓婄Щ 2:涓嬬Щ
      * @param moveSpeed  闀滃ご绉诲姩閫熷害
 	 */
 	@Override
-	public boolean ptzdirectCmd(String deviceId, String channelId, int leftRight, int upDown) {
-		return ptzCmd(deviceId, channelId, leftRight, upDown, 0, config.getSpeed(), 0);
+	public boolean ptzdirectCmd(Device device, String channelId, int leftRight, int upDown) {
+		return ptzCmd(device, channelId, leftRight, upDown, 0, config.getSpeed(), 0);
 	}
 
 	/**
 	 * 浜戝彴鏂瑰悜鏀炬帶鍒�
 	 * 
-	 * @param deviceId  鎺у埗璁惧
+	 * @param device  鎺у埗璁惧
 	 * @param channelId  棰勮閫氶亾
 	 * @param leftRight  闀滃ご宸︾Щ鍙崇Щ 0:鍋滄 1:宸︾Щ 2:鍙崇Щ
      * @param upDown     闀滃ご涓婄Щ涓嬬Щ 0:鍋滄 1:涓婄Щ 2:涓嬬Щ
      * @param moveSpeed  闀滃ご绉诲姩閫熷害
 	 */
 	@Override
-	public boolean ptzdirectCmd(String deviceId, String channelId, int leftRight, int upDown, int moveSpeed) {
-		return ptzCmd(deviceId, channelId, leftRight, upDown, 0, moveSpeed, 0);
+	public boolean ptzdirectCmd(Device device, String channelId, int leftRight, int upDown, int moveSpeed) {
+		return ptzCmd(device, channelId, leftRight, upDown, 0, moveSpeed, 0);
 	}
 
 	/**
 	 * 浜戝彴缂╂斁鎺у埗锛屼娇鐢ㄩ厤缃枃浠朵腑鐨勯粯璁ら暅澶寸缉鏀鹃�熷害
 	 * 
-	 * @param deviceId  鎺у埗璁惧
+	 * @param device  鎺у埗璁惧
 	 * @param channelId  棰勮閫氶亾
      * @param inOut      闀滃ご鏀惧ぇ缂╁皬 0:鍋滄 1:缂╁皬 2:鏀惧ぇ
 	 */  
 	@Override
-	public boolean ptzZoomCmd(String deviceId, String channelId, int inOut) {
-		return ptzCmd(deviceId, channelId, 0, 0, inOut, 0, config.getSpeed());
+	public boolean ptzZoomCmd(Device device, String channelId, int inOut) {
+		return ptzCmd(device, channelId, 0, 0, inOut, 0, config.getSpeed());
 	}
 
 	/**
 	 * 浜戝彴缂╂斁鎺у埗
 	 * 
-	 * @param deviceId  鎺у埗璁惧
+	 * @param device  鎺у埗璁惧
 	 * @param channelId  棰勮閫氶亾
      * @param inOut      闀滃ご鏀惧ぇ缂╁皬 0:鍋滄 1:缂╁皬 2:鏀惧ぇ
      * @param zoomSpeed  闀滃ご缂╂斁閫熷害
 	 */ 
 	@Override
-	public boolean ptzZoomCmd(String deviceId, String channelId, int inOut, int zoomSpeed) {
-		return ptzCmd(deviceId, channelId, 0, 0, inOut, 0, zoomSpeed);
+	public boolean ptzZoomCmd(Device device, String channelId, int inOut, int zoomSpeed) {
+		return ptzCmd(device, channelId, 0, 0, inOut, 0, zoomSpeed);
 	}
   
 	/**
 	 * 浜戝彴鎺у埗锛屾敮鎸佹柟鍚戜笌缂╂斁鎺у埗
 	 * 
-	 * @param deviceId  鎺у埗璁惧
+	 * @param device  鎺у埗璁惧
 	 * @param channelId  棰勮閫氶亾
 	 * @param leftRight  闀滃ご宸︾Щ鍙崇Щ 0:鍋滄 1:宸︾Щ 2:鍙崇Щ
      * @param upDown     闀滃ご涓婄Щ涓嬬Щ 0:鍋滄 1:涓婄Щ 2:涓嬬Щ
@@ -102,10 +100,9 @@
      * @param zoomSpeed  闀滃ご缂╂斁閫熷害
 	 */
 	@Override
-	public boolean ptzCmd(String deviceId, String channelId, int leftRight, int upDown, int inOut, int moveSpeed,
+	public boolean ptzCmd(Device device, String channelId, int leftRight, int upDown, int inOut, int moveSpeed,
 			int zoomSpeed) {
 		try {
-			Device device = storager.queryVideoDevice(deviceId);
 			StringBuffer ptzXml = new StringBuffer(200);
 			ptzXml.append("<?xml version=\"1.0\" ?>");
 			ptzXml.append("<Control>");
@@ -119,7 +116,7 @@
 			
 			Request request = headerProvider.createMessageRequest(device, ptzXml.toString(), "ViaPtzBranch", "FromPtzTag", "ToPtzTag");
 			
-			transmitRequest(device.getTransport(), request);
+			transmitRequest(device, request);
 			
 			return true;
 		} catch (SipException | ParseException | InvalidArgumentException e) {
@@ -131,14 +128,12 @@
 	/**
 	 * 璇锋眰棰勮瑙嗛娴�
 	 * 
-	 * @param deviceId  瑙嗛璁惧
+	 * @param device  瑙嗛璁惧
 	 * @param channelId  棰勮閫氶亾
 	 */  
 	@Override
-	public String playStreamCmd(String deviceId, String channelId) {
+	public String playStreamCmd(Device device, String channelId) {
 		try {
-			
-			Device device = storager.queryVideoDevice(deviceId);
 			
 			//鐢熸垚ssrc鏍囪瘑鏁版嵁娴� 10浣嶆暟瀛�
 			String ssrc = "";
@@ -170,7 +165,7 @@
 	        
 	        Request request = headerProvider.createInviteRequest(device, content.toString(), null, "live", null);
 	
-	        transmitRequest(device.getTransport(), request);
+	        transmitRequest(device, request);
 			return ssrc;
 		} catch ( SipException | ParseException | InvalidArgumentException e) {
 			e.printStackTrace();
@@ -181,81 +176,81 @@
 	/**
 	 * 璇煶骞挎挱
 	 * 
-	 * @param deviceId  瑙嗛璁惧
+	 * @param device  瑙嗛璁惧
 	 * @param channelId  棰勮閫氶亾
 	 */
 	@Override
-	public String audioBroadcastCmd(String deviceId, String channelId) {
+	public boolean audioBroadcastCmd(Device device, String channelId) {
 		// TODO Auto-generated method stub
-		return null;
+		return false;
 	}
 
 	/**
 	 * 闊宠棰戝綍鍍忔帶鍒�
 	 * 
-	 * @param deviceId  瑙嗛璁惧
+	 * @param device  瑙嗛璁惧
 	 * @param channelId  棰勮閫氶亾
 	 */  
 	@Override
-	public String recordCmd(String deviceId, String channelId) {
+	public boolean recordCmd(Device device, String channelId) {
 		// TODO Auto-generated method stub
-		return null;
+		return false;
 	}
 
 	/**
 	 * 鎶ヨ甯冮槻/鎾ら槻鍛戒护
 	 * 
-	 * @param deviceId  瑙嗛璁惧
+	 * @param device  瑙嗛璁惧
 	 */  
 	@Override
-	public String guardCmd(String deviceId) {
+	public boolean guardCmd(Device device) {
 		// TODO Auto-generated method stub
-		return null;
+		return false;
 	}
 
 	/**
 	 * 鎶ヨ澶嶄綅鍛戒护
 	 * 
-	 * @param deviceId  瑙嗛璁惧
+	 * @param device  瑙嗛璁惧
 	 */  
 	@Override
-	public String alarmCmd(String deviceId) {
+	public boolean alarmCmd(Device device) {
 		// TODO Auto-generated method stub
-		return null;
+		return false;
 	}
 
 	/**
 	 * 寮哄埗鍏抽敭甯у懡浠�,璁惧鏀跺埌姝ゅ懡浠ゅ簲绔嬪埢鍙戦�佷竴涓狪DR甯�
 	 * 
-	 * @param deviceId  瑙嗛璁惧
+	 * @param device  瑙嗛璁惧
 	 * @param channelId  棰勮閫氶亾
 	 */ 
 	@Override
-	public String iFameCmd(String deviceId, String channelId) {
+	public boolean iFameCmd(Device device, String channelId) {
 		// TODO Auto-generated method stub
-		return null;
+		return false;
 	}
 
 	/**
 	 * 鐪嬪畧浣嶆帶鍒跺懡浠�
 	 * 
-	 * @param deviceId  瑙嗛璁惧
+	 * @param device  瑙嗛璁惧
 	 */  
 	@Override
-	public String homePositionCmd(String deviceId) {
+	public boolean homePositionCmd(Device device) {
 		// TODO Auto-generated method stub
-		return null;
+		return false;
 	}
 
 	/**
 	 * 璁惧閰嶇疆鍛戒护
 	 * 
-	 * @param deviceId  瑙嗛璁惧
+	 * @param device  瑙嗛璁惧
 	 */  
 	@Override
-	public String deviceConfigCmd(String deviceId) {
+	public boolean deviceConfigCmd(Device device) {
 		// TODO Auto-generated method stub
-		return null;
+		return false;
 	}
 
 	/**
@@ -286,8 +281,8 @@
 			catalogXml.append("</Query>");
 			
 			Request request = headerProvider.createMessageRequest(device, catalogXml.toString(), "ViaDeviceInfoBranch", "FromDeviceInfoTag", "ToDeviceInfoTag");
+			transmitRequest(device, request);
 			
-			transmitRequest(device.getTransport(), request);
 		} catch (SipException | ParseException | InvalidArgumentException e) {
 			e.printStackTrace();
 			return false;
@@ -312,9 +307,7 @@
 			catalogXml.append("</Query>");
 			
 			Request request = headerProvider.createMessageRequest(device, catalogXml.toString(), "ViaCatalogBranch", "FromCatalogTag", "ToCatalogTag");
-			
-			transmitRequest(device.getTransport(), request);
-
+			transmitRequest(device, request);
 		} catch (SipException | ParseException | InvalidArgumentException e) {
 			e.printStackTrace();
 			return false;
@@ -326,11 +319,32 @@
 	 * 鏌ヨ褰曞儚淇℃伅
 	 * 
 	 * @param device 瑙嗛璁惧
+	 * @param startTime 寮�濮嬫椂闂�,鏍煎紡瑕佹眰锛歽yyy-MM-dd HH:mm:ss
+	 * @param endTime 缁撴潫鏃堕棿,鏍煎紡瑕佹眰锛歽yyy-MM-dd HH:mm:ss
 	 */  
 	@Override
-	public boolean recordInfoQuery(Device device) {
-		// TODO Auto-generated method stub
-		return false;
+	public boolean recordInfoQuery(Device device, String startTime, String endTime) {
+		
+		try {
+			StringBuffer catalogXml = new StringBuffer(200);
+			catalogXml.append("<?xml version=\"1.0\" encoding=\"GB2312\"?>");
+			catalogXml.append("<Query>");
+			catalogXml.append("<CmdType>RecordInfo</CmdType>");
+			catalogXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>");
+			catalogXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>");
+			catalogXml.append("<StartTime>" + DateUtil.yyyy_MM_dd_HH_mm_ssToISO8601(startTime) + "</StartTime>");
+			catalogXml.append("<EndTime>" + DateUtil.yyyy_MM_dd_HH_mm_ssToISO8601(endTime) + "</EndTime>");
+			// 澶у崕NVR瑕佹眰蹇呴』澧炲姞涓�涓�间负all鐨勬枃鏈厓绱犺妭鐐筎ype
+			catalogXml.append("<Type>all</Type>");
+			catalogXml.append("</Query>");
+			
+			Request request = headerProvider.createMessageRequest(device, catalogXml.toString(), "ViaRecordInfoBranch", "FromRecordInfoTag", "ToRecordInfoTag");
+			transmitRequest(device, request);
+		} catch (SipException | ParseException | InvalidArgumentException e) {
+			e.printStackTrace();
+			return false;
+		}
+		return true;
 	}
 
 	/**
@@ -377,10 +391,10 @@
 		return false;
 	}
 	
-	private void transmitRequest(String transport, Request request) throws SipException {
-		if(transport.equals("TCP")) {
+	private void transmitRequest(Device device, Request request) throws SipException {
+		if(device.getTransport().equals("TCP")) {
 			sipLayer.getTcpSipProvider().sendRequest(request);
-		} else if(transport.equals("UDP")) {
+		} else if(device.getTransport().equals("UDP")) {
 			sipLayer.getUdpSipProvider().sendRequest(request);
 		}
 	}
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 9a5551b..453420a 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
@@ -2,8 +2,10 @@
 
 import java.io.ByteArrayInputStream;
 import java.text.ParseException;
+import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Iterator;
+import java.util.List;
 import java.util.Map;
 
 import javax.sip.InvalidArgumentException;
@@ -24,9 +26,14 @@
 import com.genersoft.iot.vmp.gb28181.SipLayer;
 import com.genersoft.iot.vmp.gb28181.bean.Device;
 import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
+import com.genersoft.iot.vmp.gb28181.bean.RecordInfo;
+import com.genersoft.iot.vmp.gb28181.bean.RecordItem;
 import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
+import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
+import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
 import com.genersoft.iot.vmp.gb28181.transmit.request.ISIPRequestProcessor;
+import com.genersoft.iot.vmp.gb28181.utils.DateUtil;
 import com.genersoft.iot.vmp.gb28181.utils.XmlUtil;
 import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
 
@@ -51,6 +58,9 @@
 	@Autowired
 	private EventPublisher publisher;
 	
+	@Autowired
+	private DeferredResultHolder deferredResultHolder;
+	
 	/**   
 	 * 澶勭悊MESSAGE璇锋眰
 	 *  
@@ -74,8 +84,40 @@
 			processMessageDeviceInfo(evt);
 		} else if (new String(request.getRawContent()).contains("<CmdType>Alarm</CmdType>")) {
 			processMessageAlarm(evt);
+		} else if (new String(request.getRawContent()).contains("<CmdType>recordInfo</CmdType>")) {
+			processMessageRecordInfo(evt);
 		}
 		
+	}
+	
+	/**
+	 * 鏀跺埌deviceInfo璁惧淇℃伅璇锋眰 澶勭悊
+	 * @param evt
+	 */
+	private void processMessageDeviceInfo(RequestEvent evt) {
+		try {
+			Element rootElement = getRootElement(evt);
+			Element deviceIdElement = rootElement.element("DeviceID");
+			String deviceId = deviceIdElement.getText().toString();
+			
+			Device device = storager.queryVideoDevice(deviceId);
+			if (device == null) {
+				return;
+			}
+			device.setName(XmlUtil.getText(rootElement,"DeviceName"));
+			device.setManufacturer(XmlUtil.getText(rootElement,"Manufacturer"));
+			device.setModel(XmlUtil.getText(rootElement,"Model"));
+			device.setFirmware(XmlUtil.getText(rootElement,"Firmware"));
+			storager.update(device);
+			
+			RequestMessage msg = new RequestMessage();
+			msg.setDeviceId(deviceId);
+			msg.setType(DeferredResultHolder.CALLBACK_CMD_DEVICEINFO);
+			msg.setData(device);
+			deferredResultHolder.invokeResult(msg);
+		} catch (DocumentException e) {
+			e.printStackTrace();
+		}
 	}
 	
 	/***
@@ -84,11 +126,7 @@
 	 */
 	private void processMessageCatalogList(RequestEvent evt) {
 		try {
-			Request request = evt.getRequest();
-			SAXReader reader = new SAXReader();
-			reader.setEncoding("GB2312");
-			Document xml = reader.read(new ByteArrayInputStream(request.getRawContent()));
-			Element rootElement = xml.getRootElement();
+			Element rootElement = getRootElement(evt);
 			Element deviceIdElement = rootElement.element("DeviceID");
 			String deviceId = deviceIdElement.getText().toString();
 			Element deviceListElement = rootElement.element("DeviceList");
@@ -152,36 +190,12 @@
 				}
 				// 鏇存柊
 				storager.update(device);
+				RequestMessage msg = new RequestMessage();
+				msg.setDeviceId(deviceId);
+				msg.setType(DeferredResultHolder.CALLBACK_CMD_CATALOG);
+				msg.setData(device);
+				deferredResultHolder.invokeResult(msg);
 			}
-		} catch (DocumentException e) {
-			e.printStackTrace();
-		}
-	}
-	
-	/***
-	 * 鏀跺埌deviceInfo璁惧淇℃伅璇锋眰 澶勭悊
-	 * @param evt
-	 */
-	private void processMessageDeviceInfo(RequestEvent evt) {
-		try {
-			Request request = evt.getRequest();
-			SAXReader reader = new SAXReader();
-			// reader.setEncoding("GB2312");
-			Document xml = reader.read(new ByteArrayInputStream(request.getRawContent()));
-			Element rootElement = xml.getRootElement();
-			Element deviceIdElement = rootElement.element("DeviceID");
-			String deviceId = deviceIdElement.getText().toString();
-			
-			Device device = storager.queryVideoDevice(deviceId);
-			if (device == null) {
-				return;
-			}
-			device.setName(XmlUtil.getText(rootElement,"DeviceName"));
-			device.setManufacturer(XmlUtil.getText(rootElement,"Manufacturer"));
-			device.setModel(XmlUtil.getText(rootElement,"Model"));
-			device.setFirmware(XmlUtil.getText(rootElement,"Firmware"));
-			storager.update(device);
-			cmder.catalogQuery(device);
 		} catch (DocumentException e) {
 			e.printStackTrace();
 		}
@@ -193,11 +207,7 @@
 	 */
 	private void processMessageAlarm(RequestEvent evt) {
 		try {
-			Request request = evt.getRequest();
-			SAXReader reader = new SAXReader();
-			// reader.setEncoding("GB2312");
-			Document xml = reader.read(new ByteArrayInputStream(request.getRawContent()));
-			Element rootElement = xml.getRootElement();
+			Element rootElement = getRootElement(evt);
 			Element deviceIdElement = rootElement.element("DeviceID");
 			String deviceId = deviceIdElement.getText().toString();
 			
@@ -224,10 +234,7 @@
 		try {
 			Request request = evt.getRequest();
 			Response response = layer.getMessageFactory().createResponse(Response.OK,request);
-			SAXReader reader = new SAXReader();
-			Document xml = reader.read(new ByteArrayInputStream(request.getRawContent()));
-			// reader.setEncoding("GB2312");
-			Element rootElement = xml.getRootElement();
+			Element rootElement = getRootElement(evt);
 			Element deviceIdElement = rootElement.element("DeviceID");
 			transaction.sendResponse(response);
 			publisher.onlineEventPublish(deviceIdElement.getText(), VideoManagerConstants.EVENT_ONLINE_KEEPLIVE);
@@ -235,5 +242,68 @@
 			e.printStackTrace();
 		}
 	}
+	
+	/***
+	 * 鏀跺埌catalog璁惧鐩綍鍒楄〃璇锋眰 澶勭悊
+	 * @param evt
+	 */
+	private void processMessageRecordInfo(RequestEvent evt) {
+		try {
+			RecordInfo recordInfo = new RecordInfo();
+			Element rootElement = getRootElement(evt);
+			Element deviceIdElement = rootElement.element("DeviceID");
+			String deviceId = deviceIdElement.getText().toString();
+			recordInfo.setDeviceId(deviceId);
+			recordInfo.setName(XmlUtil.getText(rootElement,"Name"));
+			recordInfo.setSumNum(Integer.parseInt(XmlUtil.getText(rootElement,"SumNum")));
+			Element recordListElement = rootElement.element("RecordList");
+			if (recordListElement == null) {
+				return;
+			}
+			
+			Iterator<Element> recordListIterator = recordListElement.elementIterator();
+			if (recordListIterator != null) {
+				
+				List<RecordItem> recordList = new ArrayList<RecordItem>();
+				RecordItem record = new RecordItem();
+				// 閬嶅巻DeviceList
+				while (recordListIterator.hasNext()) {
+					Element itemRecord = recordListIterator.next();
+					Element recordElement = itemRecord.element("DeviceID");
+					if (recordElement == null) {
+						continue;
+					}
+					record.setDeviceId(XmlUtil.getText(itemRecord,"DeviceID"));
+					record.setName(XmlUtil.getText(itemRecord,"Name"));
+					record.setFilePath(XmlUtil.getText(itemRecord,"FilePath"));
+					record.setAddress(XmlUtil.getText(itemRecord,"Address"));
+					record.setStartTime(DateUtil.ISO8601Toyyyy_MM_dd_HH_mm_ss(XmlUtil.getText(itemRecord,"StartTime")));
+					record.setEndTime(DateUtil.ISO8601Toyyyy_MM_dd_HH_mm_ss(XmlUtil.getText(itemRecord,"EndTime")));
+					record.setSecrecy(itemRecord.element("Secrecy") == null? 0:Integer.parseInt(XmlUtil.getText(itemRecord,"Secrecy")));
+					record.setType(XmlUtil.getText(itemRecord,"Type"));
+					record.setRecordId(XmlUtil.getText(itemRecord,"RecordID"));
+					recordList.add(record);
+				}
+				recordInfo.setRecordList(recordList);
+			}
+			
+			
+			RequestMessage msg = new RequestMessage();
+			msg.setDeviceId(deviceId);
+			msg.setType(DeferredResultHolder.CALLBACK_CMD_RECORDINFO);
+			msg.setData(recordInfo);
+			deferredResultHolder.invokeResult(msg);
+		} catch (DocumentException e) {
+			e.printStackTrace();
+		}
+	}
+	
+	private Element getRootElement(RequestEvent evt) throws DocumentException {
+		Request request = evt.getRequest();
+		SAXReader reader = new SAXReader();
+		reader.setEncoding("GB2312");
+		Document xml = reader.read(new ByteArrayInputStream(request.getRawContent()));
+		return xml.getRootElement();
+	}
 
 }
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/RegisterRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/RegisterRequestProcessor.java
index 1c7a957..ebb6db4 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/RegisterRequestProcessor.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/RegisterRequestProcessor.java
@@ -25,10 +25,10 @@
 import com.genersoft.iot.vmp.conf.SipConfig;
 import com.genersoft.iot.vmp.gb28181.SipLayer;
 import com.genersoft.iot.vmp.gb28181.auth.DigestServerAuthenticationHelper;
+import com.genersoft.iot.vmp.gb28181.auth.RegisterLogicHandler;
 import com.genersoft.iot.vmp.gb28181.bean.Device;
 import com.genersoft.iot.vmp.gb28181.bean.Host;
 import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
-import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
 import com.genersoft.iot.vmp.gb28181.transmit.request.ISIPRequestProcessor;
 import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
 
@@ -48,7 +48,7 @@
 	private SipConfig config;
 	
 	@Autowired
-	private SIPCommander cmder;
+	private RegisterLogicHandler handler;
 	
 	@Autowired
 	private IVideoManagerStorager storager;
@@ -149,7 +149,7 @@
 				System.out.println("娉ㄥ唽鎴愬姛! deviceId:" + device.getDeviceId());
 				storager.update(device);
 				publisher.onlineEventPublish(device.getDeviceId(), VideoManagerConstants.EVENT_ONLINE_REGISTER);
-				cmder.deviceInfoQuery(device);
+				handler.onRegister(device);
 			} else if (registerFlag == 2) {
 				System.out.println("娉ㄩ攢鎴愬姛! deviceId:" + device.getDeviceId());
 				publisher.outlineEventPublish(device.getDeviceId(), VideoManagerConstants.EVENT_OUTLINE_UNREGISTER);
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/utils/DateUtil.java b/src/main/java/com/genersoft/iot/vmp/gb28181/utils/DateUtil.java
new file mode 100644
index 0000000..e241bd5
--- /dev/null
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/utils/DateUtil.java
@@ -0,0 +1,40 @@
+package com.genersoft.iot.vmp.gb28181.utils;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Locale;
+
+/**    
+ * @Description:鏃堕棿宸ュ叿绫伙紝涓昏澶勭悊ISO 8601鏍煎紡杞崲
+ * @author: songww
+ * @date:   2020骞�5鏈�8鏃� 涓嬪崍3:24:42     
+ */
+public class DateUtil {
+
+	private static final String yyyy_MM_dd_T_HH_mm_ss_SSSXXX = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX";
+    private static final String yyyy_MM_dd_HH_mm_ss = "yyyy-MM-dd HH:mm:ss";
+    
+	public static String yyyy_MM_dd_HH_mm_ssToISO8601(String formatTime) {
+
+        SimpleDateFormat oldsdf = new SimpleDateFormat(yyyy_MM_dd_HH_mm_ss, Locale.getDefault());
+        SimpleDateFormat newsdf = new SimpleDateFormat(yyyy_MM_dd_T_HH_mm_ss_SSSXXX, Locale.getDefault());
+        try {
+            return newsdf.format(oldsdf.parse(formatTime));
+        } catch (ParseException e) {
+            e.printStackTrace();
+        }
+        return "";
+    }
+	
+	public static String ISO8601Toyyyy_MM_dd_HH_mm_ss(String formatTime) {
+
+        SimpleDateFormat oldsdf = new SimpleDateFormat(yyyy_MM_dd_T_HH_mm_ss_SSSXXX, Locale.getDefault());
+        SimpleDateFormat newsdf = new SimpleDateFormat(yyyy_MM_dd_HH_mm_ss, Locale.getDefault());
+        try {
+            return newsdf.format(oldsdf.parse(formatTime));
+        } catch (ParseException e) {
+            e.printStackTrace();
+        }
+        return "";
+    }
+}
diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java
new file mode 100644
index 0000000..0ea162e
--- /dev/null
+++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java
@@ -0,0 +1,152 @@
+package com.genersoft.iot.vmp.media.zlm;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**    
+ * @Description:閽堝 ZLMediaServer鐨刪ook浜嬩欢鐩戝惉
+ * @author: songww
+ * @date:   2020骞�5鏈�8鏃� 涓婂崍10:46:48     
+ */
+@RestController
+@RequestMapping("/hook/zlm")
+public class ZLMHttpHookListener {
+
+	private final static Logger logger = LoggerFactory.getLogger(ZLMHttpHookListener.class);
+	
+	/**
+	 * 娴侀噺缁熻浜嬩欢锛屾挱鏀惧櫒鎴栨帹娴佸櫒鏂紑鏃跺苟涓旇�楃敤娴侀噺瓒呰繃鐗瑰畾闃堝�兼椂浼氳Е鍙戞浜嬩欢锛岄槇鍊奸�氳繃閰嶇疆鏂囦欢general.flowThreshold閰嶇疆锛涙浜嬩欢瀵瑰洖澶嶄笉鏁忔劅銆�
+	 *  
+	 */
+	@PostMapping("/on_flow_report")
+	public ResponseEntity onFlowReport(){
+		// TODO Auto-generated method stub
+		
+		return null;
+	}
+	
+	/**
+	 * 璁块棶http鏂囦欢鏈嶅姟鍣ㄤ笂hls涔嬪鐨勬枃浠舵椂瑙﹀彂銆�
+	 *  
+	 */
+	@PostMapping("/on_http_access")
+	public ResponseEntity onHttpAccess(){
+		// TODO Auto-generated method stub
+		
+		return null;
+	}
+	
+	/**
+	 * 鎾斁鍣ㄩ壌鏉冧簨浠讹紝rtsp/rtmp/http-flv/ws-flv/hls鐨勬挱鏀鹃兘灏嗚Е鍙戞閴存潈浜嬩欢銆�
+	 *  
+	 */
+	@PostMapping("/on_play")
+	public ResponseEntity onPlay(){
+		// TODO Auto-generated method stub
+		
+		return null;
+	}
+	
+	/**
+	 * rtsp/rtmp/rtp鎺ㄦ祦閴存潈浜嬩欢銆�
+	 *  
+	 */
+	@PostMapping("/on_publish")
+	public ResponseEntity onPublish(){
+		// TODO Auto-generated method stub
+		
+		return null;
+	}
+	
+	/**
+	 * 褰曞埗mp4瀹屾垚鍚庨�氱煡浜嬩欢锛涙浜嬩欢瀵瑰洖澶嶄笉鏁忔劅銆�
+	 *  
+	 */
+	@PostMapping("/on_record_mp4")
+	public ResponseEntity onRecordMp4(){
+		// TODO Auto-generated method stub
+		
+		return null;
+	}
+	
+	/**
+	 * 璇tsp娴佹槸鍚﹀紑鍚痳tsp涓撶敤鏂瑰紡鐨勯壌鏉冧簨浠讹紝寮�鍚悗鎵嶄細瑙﹀彂on_rtsp_auth浜嬩欢銆傞渶瑕佹寚鍑虹殑鏄痳tsp涔熸敮鎸乽rl鍙傛暟閴存潈锛屽畠鏀寔涓ょ鏂瑰紡閴存潈銆�
+	 *  
+	 */
+	@PostMapping("/on_rtsp_auth")
+	public ResponseEntity onRtspAuth(){
+		// TODO Auto-generated method stub
+		
+		return null;
+	}
+	
+	/**
+	 * rtsp涓撶敤鐨勯壌鏉冧簨浠讹紝鍏堣Е鍙憃n_rtsp_realm浜嬩欢鐒跺悗鎵嶄細瑙﹀彂on_rtsp_auth浜嬩欢銆�
+	 *  
+	 */
+	@PostMapping("/on_rtsp_realm")
+	public ResponseEntity onRtspRealm(){
+		// TODO Auto-generated method stub
+		
+		return null;
+	}
+	
+	/**
+	 * shell鐧诲綍閴存潈锛孼LMediaKit鎻愪緵绠�鍗曠殑telnet璋冭瘯鏂瑰紡锛屼娇鐢╰elnet 127.0.0.1 9000鑳借繘鍏ediaServer杩涚▼鐨剆hell鐣岄潰銆�
+	 *  
+	 */
+	@PostMapping("/on_shell_login")
+	public ResponseEntity onShellLogin(){
+		// TODO Auto-generated method stub
+		
+		return null;
+	}
+	
+	/**
+	 * rtsp/rtmp娴佹敞鍐屾垨娉ㄩ攢鏃惰Е鍙戞浜嬩欢锛涙浜嬩欢瀵瑰洖澶嶄笉鏁忔劅銆�
+	 *  
+	 */
+	@PostMapping("/on_stream_changed")
+	public ResponseEntity onStreamChanged(){
+		// TODO Auto-generated method stub
+		
+		return null;
+	}
+	
+	/**
+	 * 娴佹棤浜鸿鐪嬫椂浜嬩欢锛岀敤鎴峰彲浠ラ�氳繃姝や簨浠堕�夋嫨鏄惁鍏抽棴鏃犱汉鐪嬬殑娴併��
+	 *  
+	 */
+	@PostMapping("/on_stream_none_reader")
+	public ResponseEntity onStreamNoneReader(){
+		// TODO Auto-generated method stub
+		
+		return null;
+	}
+	
+	/**
+	 * 娴佹湭鎵惧埌浜嬩欢锛岀敤鎴峰彲浠ュ湪姝や簨浠惰Е鍙戞椂锛岀珛鍗冲幓鎷夋祦锛岃繖鏍峰彲浠ュ疄鐜版寜闇�鎷夋祦锛涙浜嬩欢瀵瑰洖澶嶄笉鏁忔劅銆�
+	 *  
+	 */
+	@PostMapping("/on_stream_not_found")
+	public ResponseEntity onStreamNotFound(){
+		// TODO Auto-generated method stub
+		
+		return null;
+	}
+	
+	/**
+	 * 鏈嶅姟鍣ㄥ惎鍔ㄤ簨浠讹紝鍙互鐢ㄤ簬鐩戝惉鏈嶅姟鍣ㄥ穿婧冮噸鍚紱姝や簨浠跺鍥炲涓嶆晱鎰熴��
+	 *  
+	 */
+	@PostMapping("/on_server_started")
+	public ResponseEntity onServerStarted(){
+		// TODO Auto-generated method stub
+		
+		return null;
+	}
+}
diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/device/DeviceController.java b/src/main/java/com/genersoft/iot/vmp/vmanager/device/DeviceController.java
index 993ddf7..ce86910 100644
--- a/src/main/java/com/genersoft/iot/vmp/vmanager/device/DeviceController.java
+++ b/src/main/java/com/genersoft/iot/vmp/vmanager/device/DeviceController.java
@@ -1,7 +1,8 @@
 package com.genersoft.iot.vmp.vmanager.device;
 
-import java.util.ArrayList;
 import java.util.List;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -10,10 +11,14 @@
 import org.springframework.http.ResponseEntity;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.context.request.async.DeferredResult;
 
 import com.genersoft.iot.vmp.gb28181.bean.Device;
+import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
+import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
 import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
 
 @RestController
@@ -25,16 +30,21 @@
 	@Autowired
 	private IVideoManagerStorager storager;
 	
+	@Autowired
+	private SIPCommander cmder;
+	
+	@Autowired
+	private DeferredResultHolder resultHolder;
+	
 	@GetMapping("/devices/{deviceId}")
-	public ResponseEntity<List<Device>> devices(@PathVariable String deviceId){
+	public ResponseEntity<Device> devices(@PathVariable String deviceId){
 		
 		if (logger.isDebugEnabled()) {
 			logger.debug("鏌ヨ瑙嗛璁惧API璋冪敤锛宒eviceId锛�" + deviceId);
 		}
 		
-		List<Device> deviceList = new ArrayList<>();
-		deviceList.add(storager.queryVideoDevice(deviceId));
-		return new ResponseEntity<>(deviceList,HttpStatus.OK);
+		Device device = storager.queryVideoDevice(deviceId);
+		return new ResponseEntity<>(device,HttpStatus.OK);
 	}
 	
 	@GetMapping("/devices")
@@ -47,4 +57,18 @@
 		List<Device> deviceList = storager.queryVideoDeviceList(null);
 		return new ResponseEntity<>(deviceList,HttpStatus.OK);
 	}
+	
+	@PostMapping("/devices/{deviceId}/sync")
+	public DeferredResult<ResponseEntity<Device>> devicesSync(@PathVariable String deviceId){
+		
+		if (logger.isDebugEnabled()) {
+			logger.debug("璁惧淇℃伅鍚屾API璋冪敤锛宒eviceId锛�" + deviceId);
+		}
+		
+		Device device = storager.queryVideoDevice(deviceId);
+        cmder.catalogQuery(device);
+        DeferredResult<ResponseEntity<Device>> result = new DeferredResult<ResponseEntity<Device>>();
+        resultHolder.put(DeferredResultHolder.CALLBACK_CMD_CATALOG+deviceId, result);
+        return result;
+	}
 }
diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/play/PlayController.java b/src/main/java/com/genersoft/iot/vmp/vmanager/play/PlayController.java
index d8b7305..9fe78c3 100644
--- a/src/main/java/com/genersoft/iot/vmp/vmanager/play/PlayController.java
+++ b/src/main/java/com/genersoft/iot/vmp/vmanager/play/PlayController.java
@@ -10,7 +10,9 @@
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
 
+import com.genersoft.iot.vmp.gb28181.bean.Device;
 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
+import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
 
 @RestController
 @RequestMapping("/api")
@@ -21,10 +23,14 @@
 	@Autowired
 	private SIPCommander cmder;
 	
+	@Autowired
+	private IVideoManagerStorager storager;
+	
 	@GetMapping("/play/{deviceId}_{channelId}")
 	public ResponseEntity<String> play(@PathVariable String deviceId,@PathVariable String channelId){
 		
-		String ssrc = cmder.playStreamCmd(deviceId, channelId);
+		Device device = storager.queryVideoDevice(deviceId);
+		String ssrc = cmder.playStreamCmd(device, channelId);
 		
 		if (logger.isDebugEnabled()) {
 			logger.debug(String.format("璁惧棰勮 API璋冪敤锛宒eviceId锛�%s 锛宑hannelId锛�%s",deviceId, channelId));
diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/ptz/PtzController.java b/src/main/java/com/genersoft/iot/vmp/vmanager/ptz/PtzController.java
index 842d2a8..bc9792e 100644
--- a/src/main/java/com/genersoft/iot/vmp/vmanager/ptz/PtzController.java
+++ b/src/main/java/com/genersoft/iot/vmp/vmanager/ptz/PtzController.java
@@ -10,7 +10,9 @@
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
 
+import com.genersoft.iot.vmp.gb28181.bean.Device;
 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
+import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
 
 @RestController
 @RequestMapping("/api")
@@ -20,6 +22,9 @@
 	
 	@Autowired
 	private SIPCommander cmder;
+	
+	@Autowired
+	private IVideoManagerStorager storager;
 
 	/***
 	 * http://localhost:8080/api/ptz/34020000001320000002_34020000001320000008?leftRight=1&upDown=0&inOut=0&moveSpeed=50&zoomSpeed=0
@@ -38,8 +43,9 @@
 		if (logger.isDebugEnabled()) {
 			logger.debug(String.format("璁惧浜戝彴鎺у埗 API璋冪敤锛宒eviceId锛�%s 锛宑hannelId锛�%s 锛宭eftRight锛�%d 锛寀pDown锛�%d 锛宨nOut锛�%d 锛宮oveSpeed锛�%d 锛寊oomSpeed锛�%d",deviceId, channelId, leftRight, upDown, inOut, moveSpeed, zoomSpeed));
 		}
+		Device device = storager.queryVideoDevice(deviceId);
 		
-		cmder.ptzCmd(deviceId, channelId, leftRight, upDown, inOut, moveSpeed, zoomSpeed);
+		cmder.ptzCmd(device, channelId, leftRight, upDown, inOut, moveSpeed, zoomSpeed);
 		return new ResponseEntity<String>("success",HttpStatus.OK);
 	}
 }
diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/record/RecordController.java b/src/main/java/com/genersoft/iot/vmp/vmanager/record/RecordController.java
new file mode 100644
index 0000000..c115dd0
--- /dev/null
+++ b/src/main/java/com/genersoft/iot/vmp/vmanager/record/RecordController.java
@@ -0,0 +1,47 @@
+package com.genersoft.iot.vmp.vmanager.record;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.context.request.async.DeferredResult;
+
+import com.genersoft.iot.vmp.gb28181.bean.Device;
+import com.genersoft.iot.vmp.gb28181.bean.RecordInfo;
+import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
+import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
+import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
+
+@RestController
+@RequestMapping("/api")
+public class RecordController {
+	
+	private final static Logger logger = LoggerFactory.getLogger(RecordController.class);
+	
+	@Autowired
+	private SIPCommander cmder;
+	
+	@Autowired
+	private IVideoManagerStorager storager;
+	
+	@Autowired
+	private DeferredResultHolder resultHolder;
+	
+	@GetMapping("/recordinfo/{deviceId}")
+	public DeferredResult<ResponseEntity<RecordInfo>> recordinfo(@PathVariable String deviceId, String startTime,  String endTime){
+		
+		if (logger.isDebugEnabled()) {
+			logger.debug(String.format("褰曞儚淇℃伅 API璋冪敤锛宒eviceId锛�%s 锛宻tartTime锛�%s锛� startTime锛�%s",deviceId, startTime, endTime));
+		}
+		
+		Device device = storager.queryVideoDevice(deviceId);
+		cmder.recordInfoQuery(device, startTime, endTime);
+		DeferredResult<ResponseEntity<RecordInfo>> result = new DeferredResult<ResponseEntity<RecordInfo>>();
+		resultHolder.put(DeferredResultHolder.CALLBACK_CMD_CATALOG+deviceId, result);
+        return result;
+	}
+}

--
Gitblit v1.8.0