From bb22908cf7cf698853a06d51593a22eaa64e789d Mon Sep 17 00:00:00 2001
From: 648540858 <648540858@qq.com>
Date: 星期三, 24 三月 2021 15:39:47 +0800
Subject: [PATCH] Merge pull request #67 from lawrencehj/wvp-28181-2.0

---
 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java                   |   52 ++++-
 src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRTPServerFactory.java                            |   10 +
 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/ByeRequestProcessor.java        |   35 ++-
 src/main/java/com/genersoft/iot/vmp/VManageBootstrap.java                                         |   12 +
 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/AckRequestProcessor.java        |   14 
 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java                       |    8 
 README.md                                                                                         |   11 
 src/main/java/com/genersoft/iot/vmp/gb28181/session/VideoStreamSessionManager.java                |   17 +
 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/InviteRequestProcessor.java     |   18 -
 src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java                            |   25 +-
 src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java                      |   26 ++
 src/main/java/com/genersoft/iot/vmp/vmanager/service/impl/PlayServiceImpl.java                    |    3 
 src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java                              |   13 +
 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorFactory.java                     |    1 
 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommanderFroPlatform.java        |   70 +++++++
 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommanderForPlatform.java            |   19 ++
 src/main/java/com/genersoft/iot/vmp/vmanager/platform/PlatformController.java                     |   14 
 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/response/impl/RegisterResponseProcessor.java |   14 +
 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/MessageRequestProcessor.java    |  129 ++++++++++++--
 19 files changed, 392 insertions(+), 99 deletions(-)

diff --git a/README.md b/README.md
index 8912045..26d0728 100644
--- a/README.md
+++ b/README.md
@@ -60,21 +60,24 @@
 15. 鏀寔璁㈤槄涓庨�氱煡鏂规硶
    -  [X] 绉诲姩浣嶇疆璁㈤槄
    -  [X] 绉诲姩浣嶇疆閫氱煡澶勭悊
-   -  [ ] 鎶ヨ浜嬩欢璁㈤槄
+   -  [X] 鎶ヨ浜嬩欢璁㈤槄
    -  [X] 鎶ヨ浜嬩欢閫氱煡澶勭悊
    -  [ ] 璁惧鐩綍璁㈤槄
    -  [X] 璁惧鐩綍閫氱煡澶勭悊
 16. 绉诲姩浣嶇疆鏌ヨ鍜屾樉绀猴紝鍙�氳繃閰嶇疆鏂囦欢璁剧疆绉诲姩浣嶇疆鍘嗗彶鏄惁瀛樺偍
 
 # 2.0 鏀寔鐗规��
-- [ ] 鍥芥爣閫氶亾鍚戜笂绾ц仈
+- [X] 鍥芥爣閫氶亾鍚戜笂绾ц仈
     - [X] WEB娣诲姞涓婄骇骞冲彴
     - [X] 娉ㄥ唽
     - [X] 蹇冭烦淇濇椿
     - [X] 閫氶亾閫夋嫨
     - [X] 閫氶亾鎺ㄩ��
-    - [ ] 鐐规挱
-    - [ ] 浜戝彴鎺у埗
+    - [X] 鐐规挱
+    - [X] 浜戝彴鎺у埗
+    - [X] 骞冲彴鐘舵�佹煡璇�
+    - [X] 骞冲彴淇℃伅鏌ヨ
+    - [X] 骞冲彴杩滅▼鍚姩
 - [ ] 娣诲姞RTSP瑙嗛
 - [ ] 娣诲姞ONVIF鎺㈡祴灞�鍩熺綉鍐呯殑璁惧
 - [ ] 娣诲姞RTMP瑙嗛
diff --git a/src/main/java/com/genersoft/iot/vmp/VManageBootstrap.java b/src/main/java/com/genersoft/iot/vmp/VManageBootstrap.java
index 4a92e09..d237b16 100644
--- a/src/main/java/com/genersoft/iot/vmp/VManageBootstrap.java
+++ b/src/main/java/com/genersoft/iot/vmp/VManageBootstrap.java
@@ -4,10 +4,20 @@
 
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.ConfigurableApplicationContext;
 
 @SpringBootApplication
 public class VManageBootstrap extends LogManager {
+	private static String[] args;
+	private static ConfigurableApplicationContext context;
 	public static void main(String[] args) {
-		SpringApplication.run(VManageBootstrap.class, args);
+		VManageBootstrap.args = args;
+		VManageBootstrap.context = SpringApplication.run(VManageBootstrap.class, args);
+	}
+	// 椤圭洰閲嶅惎
+	public static void restart() {
+		context.close();
+		VManageBootstrap.context = SpringApplication.run(VManageBootstrap.class, args);
+ 
 	}
 }
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/session/VideoStreamSessionManager.java b/src/main/java/com/genersoft/iot/vmp/gb28181/session/VideoStreamSessionManager.java
index c69faf9..65e1e5f 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/session/VideoStreamSessionManager.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/session/VideoStreamSessionManager.java
@@ -15,6 +15,7 @@
 public class VideoStreamSessionManager {
 
 	private ConcurrentHashMap<String, ClientTransaction> sessionMap = new ConcurrentHashMap<>();
+	private ConcurrentHashMap<String, String> ssrcMap = new ConcurrentHashMap<>();
 
 	public String createPlaySsrc(){
 		return SsrcUtil.getPlaySsrc();
@@ -24,16 +25,18 @@
 		return SsrcUtil.getPlayBackSsrc();
 	}
 	
-	public void put(String ssrc,ClientTransaction transaction){
-		sessionMap.put(ssrc, transaction);
+	public void put(String streamId,String ssrc,ClientTransaction transaction){
+		sessionMap.put(streamId, transaction);
+		ssrcMap.put(streamId, ssrc);
 	}
 	
-	public ClientTransaction get(String ssrc){
-		return sessionMap.get(ssrc);
+	public ClientTransaction get(String streamId){
+		return sessionMap.get(streamId);
 	}
 	
-	public void remove(String ssrc) {
-		sessionMap.remove(ssrc);
-		SsrcUtil.releaseSsrc(ssrc);
+	public void remove(String streamId) {
+		sessionMap.remove(streamId);
+		SsrcUtil.releaseSsrc(ssrcMap.get(streamId));
+		ssrcMap.remove(streamId);
 	}
 }
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorFactory.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorFactory.java
index b3b2fba..de9d837 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorFactory.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorFactory.java
@@ -156,6 +156,7 @@
 			processor.setRequestEvent(evt);
 			processor.setRedisCatchStorage(redisCatchStorage);
 			processor.setZlmrtpServerFactory(zlmrtpServerFactory);
+			processor.setSIPCommander(cmder);
 			return processor;
 		} else if (Request.CANCEL.equals(method)) {
 			CancelRequestProcessor processor = new CancelRequestProcessor();
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 6fa4eca..27000bb 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
@@ -78,6 +78,14 @@
 	boolean frontEndCmd(Device device, String channelId, int cmdCode, int parameter1, int parameter2, int combineCode2);
 	
 	/**
+	 * 鍓嶇鎺у埗鎸囦护锛堢敤浜庤浆鍙戜笂绾ф寚浠わ級
+	 * @param device		鎺у埗璁惧
+	 * @param channelId		棰勮閫氶亾
+	 * @param cmdString		鍓嶇鎺у埗鎸囦护涓�
+	 */
+	boolean fronEndCmd(Device device, String channelId, String cmdString);
+
+	/**
 	 * 璇锋眰棰勮瑙嗛娴�
 	 * 
 	 * @param device  瑙嗛璁惧
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommanderForPlatform.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommanderForPlatform.java
index 5c4b8af..1751ede 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommanderForPlatform.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommanderForPlatform.java
@@ -42,4 +42,23 @@
      * @return
      */
     boolean catalogQuery(DeviceChannel channel, ParentPlatform parentPlatform, String sn, String fromTag, int size);
+
+    /**
+     * 鍚戜笂绾у洖澶岲eviceInfo鏌ヨ淇℃伅
+     * @param parentPlatform 骞冲彴淇℃伅
+     * @param sn
+     * @param fromTag
+     * @return
+     */
+    boolean deviceInfoResponse(ParentPlatform parentPlatform, String sn, String fromTag);
+
+    /**
+     * 鍚戜笂绾у洖澶岲eviceStatus鏌ヨ淇℃伅
+     * @param parentPlatform 骞冲彴淇℃伅
+     * @param sn
+     * @param fromTag
+     * @return
+     */
+    boolean deviceStatusResponse(ParentPlatform parentPlatform, String sn, String fromTag);
+
 }
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 912189c..e941a8b 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
@@ -235,7 +235,7 @@
 			ptzXml.append("</Control>\r\n");
 			
 			String tm = Long.toString(System.currentTimeMillis());
-			Request request = headerProvider.createMessageRequest(device, ptzXml.toString(), "ViaPtzBranch", "FromPtz" + tm, null);
+			Request request = headerProvider.createMessageRequest(device, ptzXml.toString(), "z9hG4bK-ViaPtz-" + tm, "FromPtz" + tm, null);
 			
 			transmitRequest(device, request);
 			return true;
@@ -272,7 +272,7 @@
 			ptzXml.append("</Control>\r\n");
 			
 			String tm = Long.toString(System.currentTimeMillis());
-			Request request = headerProvider.createMessageRequest(device, ptzXml.toString(), "ViaPtzBranch", "FromPtz" + tm, null);
+			Request request = headerProvider.createMessageRequest(device, ptzXml.toString(), "z9hG4bK-ViaPtz-" + tm, "FromPtz" + tm, null);
 			transmitRequest(device, request);
 			return true;
 		} catch (SipException | ParseException | InvalidArgumentException e) {
@@ -282,6 +282,36 @@
 	}
 
 	/**
+	 * 鍓嶇鎺у埗鎸囦护锛堢敤浜庤浆鍙戜笂绾ф寚浠わ級
+	 * @param device		鎺у埗璁惧
+	 * @param channelId		棰勮閫氶亾
+	 * @param cmdString		鍓嶇鎺у埗鎸囦护涓�
+	 */
+	@Override
+	public boolean fronEndCmd(Device device, String channelId, String cmdString) {
+		try {
+			StringBuffer ptzXml = new StringBuffer(200);
+			ptzXml.append("<?xml version=\"1.0\" ?>\r\n");
+			ptzXml.append("<Control>\r\n");
+			ptzXml.append("<CmdType>DeviceControl</CmdType>\r\n");
+			ptzXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
+			ptzXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n");
+			ptzXml.append("<PTZCmd>" + cmdString + "</PTZCmd>\r\n");
+			ptzXml.append("<Info>\r\n");
+			ptzXml.append("</Info>\r\n");
+			ptzXml.append("</Control>\r\n");
+			
+			String tm = Long.toString(System.currentTimeMillis());
+			Request request = headerProvider.createMessageRequest(device, ptzXml.toString(), "z9hG4bK-ViaPtz-" + tm, "FromPtz" + tm, null);
+			transmitRequest(device, request);
+			return true;
+		} catch (SipException | ParseException | InvalidArgumentException e) {
+			e.printStackTrace();
+		} 
+		return false;
+	}
+	
+	 /**
 	 * 	璇锋眰棰勮瑙嗛娴�
 	 * @param device  瑙嗛璁惧
 	 * @param channelId  棰勮閫氶亾
@@ -387,9 +417,7 @@
 			Request request = headerProvider.createInviteRequest(device, channelId, content.toString(), null, "FromInvt" + tm, null, ssrc);
 
 			ClientTransaction transaction = transmitRequest(device, request, errorEvent);
-			streamSession.put(streamId, transaction);
-
-
+			streamSession.put(streamId,ssrc, transaction);
 
 		} catch ( SipException | ParseException | InvalidArgumentException e) {
 			e.printStackTrace();
@@ -487,7 +515,7 @@
 	        Request request = headerProvider.createPlaybackInviteRequest(device, channelId, content.toString(), null, "fromplybck" + tm, null);
 
 	        ClientTransaction transaction = transmitRequest(device, request, errorEvent);
-	        streamSession.put(streamId, transaction);
+	        streamSession.put(streamId, ssrc, transaction);
 
 		} catch ( SipException | ParseException | InvalidArgumentException e) {
 			e.printStackTrace();
@@ -893,7 +921,7 @@
 			catalogXml.append("</Query>\r\n");
 			
 			String tm = Long.toString(System.currentTimeMillis());
-			Request request = headerProvider.createMessageRequest(device, catalogXml.toString(), "z9hG4bK-ViaDeviceInfo" + tm, "FromDev" + tm, null);
+			Request request = headerProvider.createMessageRequest(device, catalogXml.toString(), "z9hG4bK-ViaDeviceInfo-" + tm, "FromDev" + tm, null);
 
 			transmitRequest(device, request);
 			
@@ -923,7 +951,7 @@
 			catalogXml.append("</Query>\r\n");
 			
 			String tm = Long.toString(System.currentTimeMillis());
-			Request request = headerProvider.createMessageRequest(device, catalogXml.toString(), "z9hG4bK-ViaCatalog" + tm, "FromCat" + tm, null);
+			Request request = headerProvider.createMessageRequest(device, catalogXml.toString(), "z9hG4bK-ViaCatalog-" + tm, "FromCat" + tm, null);
 
 			transmitRequest(device, request, errorEvent);
 		} catch (SipException | ParseException | InvalidArgumentException e) {
@@ -958,7 +986,7 @@
 			recordInfoXml.append("</Query>\r\n");
 			
 			String tm = Long.toString(System.currentTimeMillis());
-			Request request = headerProvider.createMessageRequest(device, recordInfoXml.toString(), "ViaRecordInfoBranch", "fromRec" + tm, null);
+			Request request = headerProvider.createMessageRequest(device, recordInfoXml.toString(), "z9hG4bK-ViaRecordInfo-" + tm, "fromRec" + tm, null);
 
 			transmitRequest(device, request);
 		} catch (SipException | ParseException | InvalidArgumentException e) {
@@ -1101,7 +1129,7 @@
 			mobilePostitionXml.append("</Query>\r\n");
 			
 			String tm = Long.toString(System.currentTimeMillis());
-			Request request = headerProvider.createMessageRequest(device, mobilePostitionXml.toString(), "viaTagPos" + tm, "fromTagPos" + tm, null);
+			Request request = headerProvider.createMessageRequest(device, mobilePostitionXml.toString(), "z9hG4bK-viaPos-" + tm, "fromTagPos" + tm, null);
 
 			transmitRequest(device, request, errorEvent);
 			
@@ -1134,7 +1162,7 @@
 			subscribePostitionXml.append("</Query>\r\n");
 
 			String tm = Long.toString(System.currentTimeMillis());
-			Request request = headerProvider.createSubscribeRequest(device, subscribePostitionXml.toString(), "viaTagPos" + tm, "fromTagPos" + tm, null, expires, "presence" ); //Position;id=" + tm.substring(tm.length() - 4));
+			Request request = headerProvider.createSubscribeRequest(device, subscribePostitionXml.toString(), "z9hG4bK-viaPos-" + tm, "fromTagPos" + tm, null, expires, "presence" ); //Position;id=" + tm.substring(tm.length() - 4));
 			transmitRequest(device, request);
 
 			return true;
@@ -1187,7 +1215,7 @@
 			cmdXml.append("</Query>\r\n");
 
 			String tm = Long.toString(System.currentTimeMillis());
-			Request request = headerProvider.createSubscribeRequest(device, cmdXml.toString(), "viaTagPos" + tm, "fromTagPos" + tm, null, expires, "presence" ); 
+			Request request = headerProvider.createSubscribeRequest(device, cmdXml.toString(), "z9hG4bK-viaPos-" + tm, "fromTagPos" + tm, null, expires, "presence" ); 
 			transmitRequest(device, request);
 
 			return true;
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommanderFroPlatform.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommanderFroPlatform.java
index 28761ed..d5e380b 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommanderFroPlatform.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommanderFroPlatform.java
@@ -118,7 +118,7 @@
         try {
 
             StringBuffer keepaliveXml = new StringBuffer(200);
-            keepaliveXml.append("<?xml version=\"1.0\"?>\r\n");//" encoding=\"GB2312\"?>\r\n");
+            keepaliveXml.append("<?xml version=\"1.0\"?>\r\n");
             keepaliveXml.append("<Notify>\r\n");
             keepaliveXml.append("<CmdType>Keepalive</CmdType>\r\n");
             keepaliveXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
@@ -217,4 +217,72 @@
         }
         return true;
     }
+
+    /**
+     * 鍚戜笂绾у洖澶岲eviceInfo鏌ヨ淇℃伅
+     * @param parentPlatform 骞冲彴淇℃伅
+     * @param sn
+     * @param fromTag
+     * @return
+     */
+    @Override
+    public boolean deviceInfoResponse(ParentPlatform parentPlatform, String sn, String fromTag) {
+        if (parentPlatform == null) {
+            return false;
+        }
+        try {
+            StringBuffer deviceInfoXml = new StringBuffer(600);
+            deviceInfoXml.append("<?xml version=\"1.0\" encoding=\"GB2312\"?>\r\n");
+            deviceInfoXml.append("<Response>\r\n");
+            deviceInfoXml.append("<CmdType>DeviceInfo</CmdType>\r\n");
+            deviceInfoXml.append("<SN>" +sn + "</SN>\r\n");
+            deviceInfoXml.append("<DeviceID>" + parentPlatform.getDeviceGBId() + "</DeviceID>\r\n");
+            deviceInfoXml.append("<DeviceName>GB28181 Video Platform</DeviceName>\r\n");
+            deviceInfoXml.append("<Manufacturer>Manufacturer</Manufacturer>\r\n");
+            deviceInfoXml.append("<Model>wvp-28181</Model>\r\n");
+            deviceInfoXml.append("<Firmware>2.0.202103</Firmware>\r\n");
+            deviceInfoXml.append("<Result>OK</Result>\r\n");
+            deviceInfoXml.append("</Response>\r\n");
+            Request request = headerProviderPlarformProvider.createMessageRequest(parentPlatform, deviceInfoXml.toString(), fromTag);
+            transmitRequest(parentPlatform, request);
+
+        } catch (SipException | ParseException | InvalidArgumentException e) {
+            e.printStackTrace();
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * 鍚戜笂绾у洖澶岲eviceStatus鏌ヨ淇℃伅
+     * @param parentPlatform 骞冲彴淇℃伅
+     * @param sn
+     * @param fromTag
+     * @return
+     */
+    @Override
+    public boolean deviceStatusResponse(ParentPlatform parentPlatform, String sn, String fromTag) {
+        if (parentPlatform == null) {
+            return false;
+        }
+        try {
+            StringBuffer deviceStatusXml = new StringBuffer(600);
+            deviceStatusXml.append("<?xml version=\"1.0\" encoding=\"GB2312\"?>\r\n");
+            deviceStatusXml.append("<Response>\r\n");
+            deviceStatusXml.append("<CmdType>DeviceStatus</CmdType>\r\n");
+            deviceStatusXml.append("<SN>" +sn + "</SN>\r\n");
+            deviceStatusXml.append("<DeviceID>" + parentPlatform.getDeviceGBId() + "</DeviceID>\r\n");
+            deviceStatusXml.append("<Result>OK</Result>\r\n");
+            deviceStatusXml.append("<Online>ONLINE</Online>\r\n");
+            deviceStatusXml.append("<Status>OK</Status>\r\n");
+            deviceStatusXml.append("</Response>\r\n");
+            Request request = headerProviderPlarformProvider.createMessageRequest(parentPlatform, deviceStatusXml.toString(), fromTag);
+            transmitRequest(parentPlatform, request);
+
+        } catch (SipException | ParseException | InvalidArgumentException e) {
+            e.printStackTrace();
+            return false;
+        }
+        return true;
+    }
 }
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/AckRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/AckRequestProcessor.java
index ad7b070..72a4d8c 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/AckRequestProcessor.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/AckRequestProcessor.java
@@ -4,7 +4,10 @@
 import java.util.Map;
 
 import javax.sip.*;
-//import javax.sip.message.Request;
+import javax.sip.address.SipURI;
+import javax.sip.header.FromHeader;
+import javax.sip.header.HeaderAddress;
+import javax.sip.header.ToHeader;
 
 import com.genersoft.iot.vmp.common.StreamInfo;
 import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem;
@@ -12,14 +15,11 @@
 import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
 
-import org.springframework.stereotype.Component;
-
 /**    
  * @Description:ACK璇锋眰澶勭悊鍣�  
  * @author: swwheihei
  * @date:   2020骞�5鏈�3鏃� 涓嬪崍5:31:45     
  */
-@Component
 public class AckRequestProcessor extends SIPRequestAbstractProcessor {
 
     private IRedisCatchStorage redisCatchStorage;
@@ -38,10 +38,8 @@
 		if (dialog == null) return;
 		//DialogState state = dialog.getState();
 		if (/*request.getMethod().equals(Request.INVITE) &&*/ dialog.getState()== DialogState.CONFIRMED) {
-			String remoteUri = dialog.getRemoteParty().getURI().toString();
-			String localUri = dialog.getLocalParty().getURI().toString();
-			String platformGbId = remoteUri.substring(remoteUri.indexOf(":") + 1, remoteUri.indexOf("@"));
-			String channelId = localUri.substring(remoteUri.indexOf(":") + 1, remoteUri.indexOf("@"));
+			String platformGbId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(FromHeader.NAME)).getAddress().getURI()).getUser();
+			String channelId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(ToHeader.NAME)).getAddress().getURI()).getUser();
 			SendRtpItem sendRtpItem =  redisCatchStorage.querySendRTPServer(platformGbId, channelId);
 			String is_Udp = sendRtpItem.isTcp() ? "0" : "1";
 			String deviceId = sendRtpItem.getDeviceId();
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/ByeRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/ByeRequestProcessor.java
index a14a4cc..c96501d 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/ByeRequestProcessor.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/ByeRequestProcessor.java
@@ -1,13 +1,18 @@
 package com.genersoft.iot.vmp.gb28181.transmit.request.impl;
 
+import javax.sip.address.SipURI;
 import javax.sip.Dialog;
 import javax.sip.DialogState;
 import javax.sip.InvalidArgumentException;
 import javax.sip.RequestEvent;
 import javax.sip.SipException;
+import javax.sip.header.FromHeader;
+import javax.sip.header.HeaderAddress;
+import javax.sip.header.ToHeader;
 import javax.sip.message.Response;
 
 import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem;
+import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
 import com.genersoft.iot.vmp.gb28181.transmit.request.SIPRequestAbstractProcessor;
 import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
@@ -18,12 +23,14 @@
 
 /**    
  * @Description: BYE璇锋眰澶勭悊鍣�
- * @author: swwheihei
- * @date:   2020骞�5鏈�3鏃� 涓嬪崍5:32:05     
+ * @author: lawrencehj
+ * @date:   2021骞�3鏈�9鏃�     
  */
 public class ByeRequestProcessor extends SIPRequestAbstractProcessor {
 
-    private IRedisCatchStorage redisCatchStorage;
+	private ISIPCommander cmder;
+
+	private IRedisCatchStorage redisCatchStorage;
 
 	private ZLMRTPServerFactory zlmrtpServerFactory;
 
@@ -38,10 +45,8 @@
 			Dialog dialog = evt.getDialog();
 			if (dialog == null) return;
 			if (dialog.getState().equals(DialogState.TERMINATED)) {
-				String remoteUri = dialog.getRemoteParty().getURI().toString();
-				String localUri = dialog.getLocalParty().getURI().toString();
-				String platformGbId = remoteUri.substring(remoteUri.indexOf(":") + 1, remoteUri.indexOf("@"));
-				String channelId = localUri.substring(remoteUri.indexOf(":") + 1, remoteUri.indexOf("@"));
+				String platformGbId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(FromHeader.NAME)).getAddress().getURI()).getUser();
+				String channelId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(ToHeader.NAME)).getAddress().getURI()).getUser();
 				SendRtpItem sendRtpItem =  redisCatchStorage.querySendRTPServer(platformGbId, channelId);
 				String streamId = sendRtpItem.getStreamId();
 				Map<String, Object> param = new HashMap<>();
@@ -50,6 +55,11 @@
 				param.put("stream",streamId);
 				System.out.println("鍋滄鍚戜笂绾ф帹娴侊細" + streamId);
 				zlmrtpServerFactory.stopSendRtpStream(param);
+				redisCatchStorage.deleteSendRTPServer(platformGbId, channelId);
+				if (zlmrtpServerFactory.totalReaderCount(streamId) == 0) {
+					System.out.println(streamId + "鏃犲叾瀹冭鐪嬭�咃紝閫氱煡璁惧鍋滄鎺ㄦ祦");
+					cmder.streamByeCmd(streamId);
+				}
 			}
 		} catch (SipException e) {
 			e.printStackTrace();
@@ -58,8 +68,6 @@
 		} catch (ParseException e) {
 			e.printStackTrace();
 		}
-		// TODO 浼樺厛绾�99 Bye Request娑堟伅瀹炵幇锛屾娑堟伅涓�鑸负绾ц仈娑堟伅锛屼笂绾х粰涓嬬骇鍙戦�佽棰戝仠姝㈡寚浠�
-		
 	}
 
 	/***
@@ -89,4 +97,13 @@
 	public void setZlmrtpServerFactory(ZLMRTPServerFactory zlmrtpServerFactory) {
 		this.zlmrtpServerFactory = zlmrtpServerFactory;
 	}
+
+	public ISIPCommander getSIPCommander() {
+		return cmder;
+	}
+
+	public void setSIPCommander(ISIPCommander cmder) {
+		this.cmder = cmder;
+	}
+
 }
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/InviteRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/InviteRequestProcessor.java
index 0c3f127..dc41fe7 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/InviteRequestProcessor.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/InviteRequestProcessor.java
@@ -75,20 +75,6 @@
 			SipURI sipURI = (SipURI) request.getRequestURI();
 			String channelId = sipURI.getUser();
 			String platformId = null;
-//			SubjectHeader subjectHeader = (SubjectHeader)request.getHeader(SubjectHeader.NAME);
-//			// 鏌ヨ閫氶亾鏄惁瀛樺湪 涓嶅瓨鍦ㄥ洖澶�404
-//			if (subjectHeader != null) { // 瀛樺湪鍒欎粠subjectHeader 鑾峰彇骞冲彴淇℃伅
-//				String subject = subjectHeader.getSubject();
-//				if (subject != null) {
-//					String[] info1 = subject.split(",");
-//					if (info1 != null && info1 .length == 2) {
-//						String[] info2 = info1[1].split(":");
-//						if (info2 != null && info2.length == 2) {
-//							platformId = info2[0];
-//						}
-//					}
-//				}
-//			}
 
 			FromHeader fromHeader = (FromHeader)request.getHeader(FromHeader.NAME);
 			AddressImpl address = (AddressImpl) fromHeader.getAddress();
@@ -224,7 +210,9 @@
 					e.printStackTrace();
 				}
 			}));
-			playResult.getResult();
+			if (logger.isDebugEnabled()) {
+				logger.debug(playResult.getResult().toString());
+			}
 
 		} catch (SipException | InvalidArgumentException | ParseException e) {
 			e.printStackTrace();
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 a2b3709..e97629b 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
@@ -4,14 +4,22 @@
 import java.text.ParseException;
 import java.util.*;
 
+import javax.sip.address.SipURI;
+
 import javax.sip.header.FromHeader;
+import javax.sip.header.HeaderAddress;
+import javax.sip.header.ToHeader;
 import javax.sip.InvalidArgumentException;
+import javax.sip.ListeningPoint;
+import javax.sip.ObjectInUseException;
 import javax.sip.RequestEvent;
 import javax.sip.SipException;
+import javax.sip.SipProvider;
 import javax.sip.message.Request;
 import javax.sip.message.Response;
 
 import com.alibaba.fastjson.JSONObject;
+import com.genersoft.iot.vmp.VManageBootstrap;
 import com.genersoft.iot.vmp.common.StreamInfo;
 import com.genersoft.iot.vmp.common.VideoManagerConstants;
 import com.genersoft.iot.vmp.conf.UserSetup;
@@ -34,6 +42,7 @@
 import com.genersoft.iot.vmp.utils.redis.RedisUtil;
 import com.genersoft.iot.vmp.vmanager.platform.bean.ChannelReduce;
 
+import gov.nist.javax.sip.SipStackImpl;
 import gov.nist.javax.sip.address.AddressImpl;
 import gov.nist.javax.sip.address.SipUri;
 
@@ -114,10 +123,10 @@
 				logger.info("鎺ユ敹鍒癈atalog娑堟伅");
 				processMessageCatalogList(evt);
 			} else if (MESSAGE_DEVICE_INFO.equals(cmd)) {
-				logger.info("鎺ユ敹鍒癉eviceInfo娑堟伅");
+				//DeviceInfo娑堟伅澶勭悊
 				processMessageDeviceInfo(evt);
 			} else if (MESSAGE_DEVICE_STATUS.equals(cmd)) {
-				logger.info("鎺ユ敹鍒癉eviceStatus娑堟伅");
+				// DeviceStatus娑堟伅澶勭悊
 				processMessageDeviceStatus(evt);
 			} else if (MESSAGE_DEVICE_CONTROL.equals(cmd)) {
 				logger.info("鎺ユ敹鍒癉eviceControl娑堟伅");
@@ -211,27 +220,48 @@
 	private void processMessageDeviceStatus(RequestEvent evt) {
 		try {
 			Element rootElement = getRootElement(evt);
-			String deviceId = XmlUtil.getText(rootElement, "DeviceID");
-			// 妫�鏌ヨ澶囨槸鍚﹀瓨鍦紝 涓嶅瓨鍦ㄥ垯涓嶅洖澶�
-			if (storager.exists(deviceId)) {
-				// 鍥炲200 OK
-				responseAck(evt);
-				JSONObject json = new JSONObject();
-				XmlUtil.node2Json(rootElement, json);
-				if (logger.isDebugEnabled()) {
-					logger.debug(json.toJSONString());
-				}
-				RequestMessage msg = new RequestMessage();
-				msg.setDeviceId(deviceId);
-				msg.setType(DeferredResultHolder.CALLBACK_CMD_DEVICESTATUS);
-				msg.setData(json);
-				deferredResultHolder.invokeResult(msg);
+			String name = rootElement.getName();
+			Element deviceIdElement = rootElement.element("DeviceID");
+			String deviceId = deviceIdElement.getText();
 
-				if (offLineDetector.isOnline(deviceId)) {
-					publisher.onlineEventPublish(deviceId, VideoManagerConstants.EVENT_ONLINE_KEEPLIVE);
+			if (name.equalsIgnoreCase("Query")) { // 鍖哄垎鏄疪esponse鈥斺�旀煡璇㈠搷搴旓紝杩樻槸Query鈥斺�旀煡璇㈣姹�
+				logger.info("鎺ユ敹鍒癉eviceStatus鏌ヨ娑堟伅");
+				FromHeader fromHeader = (FromHeader) evt.getRequest().getHeader(FromHeader.NAME);
+				String platformId = ((SipUri) fromHeader.getAddress().getURI()).getUser();
+					if (platformId == null) {
+					response404Ack(evt);
+					return;
 				} else {
+					// 鍥炲200 OK
+					responseAck(evt);
+					String sn = rootElement.element("SN").getText();
+					ParentPlatform parentPlatform = storager.queryParentPlatById(platformId);
+					cmderFroPlatform.deviceStatusResponse(parentPlatform, sn, fromHeader.getTag());
+				}
+			} else {
+				logger.info("鎺ユ敹鍒癉eviceStatus搴旂瓟娑堟伅");
+				// 妫�鏌ヨ澶囨槸鍚﹀瓨鍦紝 涓嶅瓨鍦ㄥ垯涓嶅洖澶�
+				if (storager.exists(deviceId)) {
+					// 鍥炲200 OK
+					responseAck(evt);
+					JSONObject json = new JSONObject();
+					XmlUtil.node2Json(rootElement, json);
+					if (logger.isDebugEnabled()) {
+						logger.debug(json.toJSONString());
+					}
+					RequestMessage msg = new RequestMessage();
+					msg.setDeviceId(deviceId);
+					msg.setType(DeferredResultHolder.CALLBACK_CMD_DEVICESTATUS);
+					msg.setData(json);
+					deferredResultHolder.invokeResult(msg);
+
+					if (offLineDetector.isOnline(deviceId)) {
+						publisher.onlineEventPublish(deviceId, VideoManagerConstants.EVENT_ONLINE_KEEPLIVE);
+					} else {
+					}
 				}
 			}
+
 		} catch (ParseException | SipException | InvalidArgumentException | DocumentException e) {
 			e.printStackTrace();
 		}
@@ -263,6 +293,51 @@
 				deferredResultHolder.invokeResult(msg);
 			} else {
 				// 姝ゅ鏄笂绾у彂鍑虹殑DeviceControl鎸囦护
+				String platformId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(FromHeader.NAME)).getAddress().getURI()).getUser();
+				String targetGBId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(ToHeader.NAME)).getAddress().getURI()).getUser();
+				// 杩滅▼鍚姩鍔熻兘
+				if (!XmlUtil.isEmpty(XmlUtil.getText(rootElement, "TeleBoot"))) {
+					if (deviceId.equals(targetGBId)) {
+						// 杩滅▼鍚姩鍔熻兘锛氶渶瑕佸湪閲嶆柊鍚姩绋嬪簭鍚庡厛瀵筍ipStack瑙g粦
+						logger.info("鎵ц杩滅▼鍚姩鏈钩鍙板懡浠�");
+						ParentPlatform parentPlatform = storager.queryParentPlatById(platformId);
+						cmderFroPlatform.unregister(parentPlatform, null, null);
+	
+						Thread restartThread = new Thread(new Runnable() {
+							@Override
+							public void run() {
+								try {
+									Thread.sleep(3000);
+									SipProvider up = (SipProvider) SpringBeanFactory.getBean("udpSipProvider");
+									SipStackImpl stack = (SipStackImpl)up.getSipStack();
+									stack.stop();
+									Iterator listener = stack.getListeningPoints();
+									while (listener.hasNext()) {
+										stack.deleteListeningPoint((ListeningPoint) listener.next());
+									}
+									Iterator providers = stack.getSipProviders();
+									while (providers.hasNext()) {
+										stack.deleteSipProvider((SipProvider) providers.next());
+									}
+									VManageBootstrap.restart();
+								} catch (InterruptedException ignored) {
+								} catch (ObjectInUseException e) {
+									e.printStackTrace();
+								}
+							}
+						});
+			
+						restartThread.setDaemon(false);
+						restartThread.start();
+					} else {
+						// 杩滅▼鍚姩鎸囧畾璁惧
+					}
+				}
+				if (!XmlUtil.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);
+				}
 			}
 		} catch (ParseException | SipException | InvalidArgumentException | DocumentException e) {
 			e.printStackTrace();
@@ -374,9 +449,21 @@
 			Element deviceIdElement = rootElement.element("DeviceID");
 			String deviceId = deviceIdElement.getTextTrim().toString();
 			if (requestName.equals("Query")) {
-				// 鍥炲200 OK
-				responseAck(evt);
+				logger.info("鎺ユ敹鍒癉eviceInfo鏌ヨ娑堟伅");
+				FromHeader fromHeader = (FromHeader) evt.getRequest().getHeader(FromHeader.NAME);
+				String platformId = ((SipUri) fromHeader.getAddress().getURI()).getUser();
+					if (platformId == null) {
+					response404Ack(evt);
+					return;
+				} else {
+					// 鍥炲200 OK
+					responseAck(evt);
+					String sn = rootElement.element("SN").getText();
+					ParentPlatform parentPlatform = storager.queryParentPlatById(platformId);
+					cmderFroPlatform.deviceInfoResponse(parentPlatform, sn, fromHeader.getTag());
+				}
 			} else {
+				logger.info("鎺ユ敹鍒癉eviceInfo搴旂瓟娑堟伅");
 				Device device = storager.queryVideoDevice(deviceId);
 				if (device == null) {
 					return;
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/response/impl/RegisterResponseProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/response/impl/RegisterResponseProcessor.java
index aa6b5ab..a3952ff 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/response/impl/RegisterResponseProcessor.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/response/impl/RegisterResponseProcessor.java
@@ -60,16 +60,17 @@
 			logger.info(String.format("鏈壘鍒癱allId锛� %s 鐨勬敞鍐�/娉ㄩ攢骞冲彴id", callId ));
 			return;
 		}
-		logger.info(String.format("鏀跺埌 %s 鐨勬敞鍐�/娉ㄩ攢%S鍝嶅簲", platformGBId, response.getStatusCode() ));
 
 		ParentPlatformCatch parentPlatformCatch = redisCatchStorage.queryPlatformCatchInfo(platformGBId);
 		if (parentPlatformCatch == null) {
 			logger.warn(String.format("鏀跺埌 %s 鐨勬敞鍐�/娉ㄩ攢%S璇锋眰, 浣嗘槸骞冲彴缂撳瓨淇℃伅鏈煡璇㈠埌!!!", platformGBId, response.getStatusCode()));
 			return;
 		}
+		String action = parentPlatformCatch.getParentPlatform().getExpires().equals("0") ? "娉ㄩ攢" : "娉ㄥ唽";
+		logger.info(String.format("鏀跺埌 %s %s鐨�%S鍝嶅簲", platformGBId, action, response.getStatusCode() ));
 		ParentPlatform parentPlatform = parentPlatformCatch.getParentPlatform();
 		if (parentPlatform == null) {
-			logger.warn(String.format("鏀跺埌 %s 鐨勬敞鍐�/娉ㄩ攢%S璇锋眰, 浣嗘槸骞冲彴淇℃伅鏈煡璇㈠埌!!!", platformGBId, response.getStatusCode()));
+			logger.warn(String.format("鏀跺埌 %s %s鐨�%S璇锋眰, 浣嗘槸骞冲彴淇℃伅鏈煡璇㈠埌!!!", platformGBId, action, response.getStatusCode()));
 			return;
 		}
 
@@ -77,11 +78,16 @@
 			WWWAuthenticateHeader www = (WWWAuthenticateHeader)response.getHeader(WWWAuthenticateHeader.NAME);
 			sipCommanderForPlatform.register(parentPlatform, callId, www, null, null);
 		}else if (response.getStatusCode() == 200){
-			// 娉ㄥ唽鎴愬姛
-			logger.info(String.format("%s 娉ㄥ唽鎴愬姛", platformGBId ));
+			// 娉ㄥ唽/娉ㄩ攢鎴愬姛
+			logger.info(String.format("%s %s鎴愬姛", platformGBId, action));
 			redisCatchStorage.delPlatformRegisterInfo(callId);
 			parentPlatform.setStatus(true);
+			// 鍙栧洖Expires璁剧疆锛岄伩鍏嶆敞閿�杩囩▼涓缃负0
+			ParentPlatform parentPlatformTmp = storager.queryParentPlatById(platformGBId);
+			String expires = parentPlatformTmp.getExpires();
+			parentPlatform.setExpires(expires);
 			storager.updateParentPlatform(parentPlatform);
+
 			redisCatchStorage.updatePlatformRegister(parentPlatform);
 
 			redisCatchStorage.updatePlatformKeepalive(parentPlatform);
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
index 90b5369..51f61ef 100644
--- a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java
+++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java
@@ -267,20 +267,25 @@
 		}
 		
 		String streamId = json.getString("stream");
-
-		cmder.streamByeCmd(streamId);
 		StreamInfo streamInfo = redisCatchStorage.queryPlayByStreamId(streamId);
-		if (streamInfo!=null){
-			redisCatchStorage.stopPlay(streamInfo);
-			storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId());
-		}else{
-			streamInfo = redisCatchStorage.queryPlaybackByStreamId(streamId);
-			redisCatchStorage.stopPlayback(streamInfo);
-		}
-		
+
 		JSONObject ret = new JSONObject();
 		ret.put("code", 0);
 		ret.put("close", true);
+
+		if (streamInfo != null) {
+			if (redisCatchStorage.isChannelSendingRTP(streamInfo.getChannelId())) {
+				ret.put("close", false);
+			} else {
+				cmder.streamByeCmd(streamId);
+				redisCatchStorage.stopPlay(streamInfo);
+				storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId());
+			}
+		}else{
+			cmder.streamByeCmd(streamId);
+			streamInfo = redisCatchStorage.queryPlaybackByStreamId(streamId);
+			redisCatchStorage.stopPlayback(streamInfo);
+		}
 		return new ResponseEntity<String>(ret.toString(),HttpStatus.OK);
 	}
 	
diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRTPServerFactory.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRTPServerFactory.java
index 00951ba..1f1693d 100644
--- a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRTPServerFactory.java
+++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRTPServerFactory.java
@@ -153,6 +153,16 @@
     }
 
     /**
+     * 鏌ヨ杞帹鐨勬祦鏄惁鏈夊叾瀹冭鐪嬭��
+     * @param streamId
+     * @return
+     */
+    public int totalReaderCount(String streamId) {
+        JSONObject mediaInfo = zlmresTfulUtils.getMediaInfo("rtp", "rtmp", streamId);
+        return mediaInfo.getInteger("totalReaderCount");
+    }
+
+    /**
      * 璋冪敤zlm RESTful API 鈥斺�� stopSendRtp
      */
     public Boolean stopSendRtpStream(Map<String, Object>param) {
diff --git a/src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java b/src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java
index ca70620..9061184 100644
--- a/src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java
+++ b/src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java
@@ -89,4 +89,17 @@
      */
     SendRtpItem querySendRTPServer(String platformGbId, String channelId);
 
+    /**
+     * 鍒犻櫎RTP鎺ㄩ�佷俊鎭紦瀛�
+     * @param platformGbId
+     * @param channelId
+     */
+    void deleteSendRTPServer(String platformGbId, String channelId);
+
+    /**
+     * 鏌ヨ鏌愪釜閫氶亾鏄惁瀛樺湪涓婄骇鐐规挱锛圧TP鎺ㄩ�侊級
+     * @param channelId
+     */
+    boolean isChannelSendingRTP(String channelId);
+
 }
diff --git a/src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java b/src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java
index 6153e5f..3feb347 100644
--- a/src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java
+++ b/src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java
@@ -225,4 +225,30 @@
         return (SendRtpItem)redis.get(key);
     }
 
+    /**
+     * 鍒犻櫎RTP鎺ㄩ�佷俊鎭紦瀛�
+     * @param platformGbId
+     * @param channelId
+     */
+    @Override
+    public void deleteSendRTPServer(String platformGbId, String channelId) {
+        String key = VideoManagerConstants.PLATFORM_SEND_RTP_INFO_PREFIX + platformGbId + "_" + channelId;
+        redis.del(key);
+    }
+
+    /**
+     * 鏌ヨ鏌愪釜閫氶亾鏄惁瀛樺湪涓婄骇鐐规挱锛圧TP鎺ㄩ�侊級
+     * @param channelId
+     */
+    @Override
+    public boolean isChannelSendingRTP(String channelId) {
+        String key = VideoManagerConstants.PLATFORM_SEND_RTP_INFO_PREFIX + "*_" + channelId;
+        List<Object> RtpStreams = redis.scan(key);
+        if (RtpStreams.size() > 0) {
+            return true;
+        } else {
+            return false;
+        }
+    }
+
 }
diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/platform/PlatformController.java b/src/main/java/com/genersoft/iot/vmp/vmanager/platform/PlatformController.java
index ef617a6..279a031 100644
--- a/src/main/java/com/genersoft/iot/vmp/vmanager/platform/PlatformController.java
+++ b/src/main/java/com/genersoft/iot/vmp/vmanager/platform/PlatformController.java
@@ -60,7 +60,7 @@
     public ResponseEntity<String> savePlatform(@RequestBody ParentPlatform parentPlatform){
 
         if (logger.isDebugEnabled()) {
-            logger.debug("鏌ヨ鎵�鏈変笂绾ц澶嘇PI璋冪敤");
+            logger.debug("淇濆瓨涓婄骇骞冲彴淇℃伅API璋冪敤");
         }
         if (StringUtils.isEmpty(parentPlatform.getName())
                 ||StringUtils.isEmpty(parentPlatform.getServerGBId())
@@ -87,13 +87,13 @@
             if (parentPlatform.isEnable()) {
                 //  鍙淇濆瓨灏卞彂閫佹敞鍐�
                 commanderForPlatform.register(parentPlatform);
-            }else if (parentPlatformOld != null && parentPlatformOld.isEnable() && !parentPlatform.isEnable()){ // 鍏抽棴鍚敤鏃舵敞閿�
+            } else if (parentPlatformOld != null && parentPlatformOld.isEnable() && !parentPlatform.isEnable()){ // 鍏抽棴鍚敤鏃舵敞閿�
                 commanderForPlatform.unregister(parentPlatform, null, null);
             }
 
-
+ 
             return new ResponseEntity<>("success", HttpStatus.OK);
-        }else {
+        } else {
             return new ResponseEntity<>("fail", HttpStatus.OK);
         }
     }
@@ -103,7 +103,7 @@
     public ResponseEntity<String> deletePlatform(@RequestBody ParentPlatform parentPlatform){
 
         if (logger.isDebugEnabled()) {
-            logger.debug("鏌ヨ鎵�鏈変笂绾ц澶嘇PI璋冪敤");
+            logger.debug("鍒犻櫎涓婄骇骞冲彴API璋冪敤");
         }
         if (StringUtils.isEmpty(parentPlatform.getServerGBId())
         ){
@@ -138,7 +138,7 @@
     public ResponseEntity<String> exitPlatform(@PathVariable String deviceGbId){
 
         if (logger.isDebugEnabled()) {
-            logger.debug("鏌ヨ鎵�鏈変笂绾ц澶嘇PI璋冪敤");
+            logger.debug("鏌ヨ涓婄骇骞冲彴鏄惁瀛樺湪API璋冪敤锛�" + deviceGbId);
         }
         ParentPlatform parentPlatform = storager.queryParentPlatById(deviceGbId);
         return new ResponseEntity<>(String.valueOf(parentPlatform != null), HttpStatus.OK);
@@ -184,7 +184,7 @@
     public ResponseEntity<String> delChannelForGB(@RequestBody UpdateChannelParam param){
 
         if (logger.isDebugEnabled()) {
-            logger.debug("缁欎笂绾у钩鍙版坊鍔犲浗鏍囬�氶亾API璋冪敤");
+            logger.debug("缁欎笂绾у钩鍙板垹闄ゅ浗鏍囬�氶亾API璋冪敤");
         }
         int result = storager.delChannelForGB(param.getPlatformId(), param.getChannelReduces());
 
diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/service/impl/PlayServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/vmanager/service/impl/PlayServiceImpl.java
index db1e345..376040a 100644
--- a/src/main/java/com/genersoft/iot/vmp/vmanager/service/impl/PlayServiceImpl.java
+++ b/src/main/java/com/genersoft/iot/vmp/vmanager/service/impl/PlayServiceImpl.java
@@ -86,6 +86,9 @@
                 msg.setId(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid);
                 msg.setData(JSON.toJSONString(streamInfo));
                 resultHolder.invokeResult(msg);
+                if (hookEvent != null) {
+                    hookEvent.response(JSONObject.parseObject(JSON.toJSONString(streamInfo)));
+                }
             } else {
                 redisCatchStorage.stopPlay(streamInfo);
                 storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId());

--
Gitblit v1.8.0