From 4604aaea99925415db8d9efe1d7e68d6f59e93c8 Mon Sep 17 00:00:00 2001
From: 648540858 <648540858@qq.com>
Date: 星期日, 02 七月 2023 13:53:45 +0800
Subject: [PATCH] 优化语音对讲支持根据设备设置释放收到ACK后开始发流

---
 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java |   42 +++-------
 src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceMapper.java                                  |    9 ++
 src/main/java/com/genersoft/iot/vmp/gb28181/bean/Device.java                                        |   11 ++
 web_src/src/components/dialog/deviceEdit.vue                                                        |    1 
 src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java                               |   13 ++-
 src/main/java/com/genersoft/iot/vmp/conf/UserSetting.java                                           |   10 --
 src/main/resources/local.jks                                                                        |    0 
 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/AckRequestProcessor.java    |  139 +++++++++++++++++++++-------------
 src/main/java/com/genersoft/iot/vmp/service/IPlayService.java                                       |    2 
 9 files changed, 127 insertions(+), 100 deletions(-)

diff --git a/src/main/java/com/genersoft/iot/vmp/conf/UserSetting.java b/src/main/java/com/genersoft/iot/vmp/conf/UserSetting.java
index eae96b9..562c864 100644
--- a/src/main/java/com/genersoft/iot/vmp/conf/UserSetting.java
+++ b/src/main/java/com/genersoft/iot/vmp/conf/UserSetting.java
@@ -47,8 +47,6 @@
 
     private Boolean syncChannelOnDeviceOnline = Boolean.FALSE;
 
-    private Boolean pushStreamAfterAck = Boolean.FALSE;
-
     private Boolean sipLog = Boolean.FALSE;
     private Boolean sqlLog = Boolean.FALSE;
     private Boolean sendToPlatformsWhenIdLost = Boolean.FALSE;
@@ -232,14 +230,6 @@
 
     public void setBroadcastForPlatform(String broadcastForPlatform) {
         this.broadcastForPlatform = broadcastForPlatform;
-    }
-
-    public Boolean getPushStreamAfterAck() {
-        return pushStreamAfterAck;
-    }
-
-    public void setPushStreamAfterAck(Boolean pushStreamAfterAck) {
-        this.pushStreamAfterAck = pushStreamAfterAck;
     }
 
     public Boolean getSipUseSourceIpAsRemoteAddress() {
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/Device.java b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/Device.java
index 1318c59..60f5cf6 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/Device.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/Device.java
@@ -188,8 +188,8 @@
 	@Schema(description = "璁惧娉ㄥ唽鐨勪簨鍔′俊鎭�")
 	private SipTransactionInfo sipTransactionInfo;
 
-
-
+	@Schema(description = "鎺у埗璇煶瀵硅娴佺▼锛岄噴鏀炬敹鍒癆CK鍚庡彂娴�")
+	private boolean broadcastPushAfterAck;
 
 	public String getDeviceId() {
 		return deviceId;
@@ -465,4 +465,11 @@
 	/*======================璁惧涓诲瓙鐮佹祦閫昏緫END=========================*/
 
 
+	public boolean isBroadcastPushAfterAck() {
+		return broadcastPushAfterAck;
+	}
+
+	public void setBroadcastPushAfterAck(boolean broadcastPushAfterAck) {
+		this.broadcastPushAfterAck = broadcastPushAfterAck;
+	}
 }
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/AckRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/AckRequestProcessor.java
index cc1f0c0..7ca52ef 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/AckRequestProcessor.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/AckRequestProcessor.java
@@ -3,6 +3,7 @@
 import com.alibaba.fastjson2.JSONObject;
 import com.genersoft.iot.vmp.conf.DynamicTask;
 import com.genersoft.iot.vmp.conf.UserSetting;
+import com.genersoft.iot.vmp.gb28181.bean.Device;
 import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
 import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem;
 import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver;
@@ -10,9 +11,8 @@
 import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
 import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
 import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe;
-import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeFactory;
-import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForRtpServerTimeout;
 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
+import com.genersoft.iot.vmp.service.IDeviceService;
 import com.genersoft.iot.vmp.service.IMediaServerService;
 import com.genersoft.iot.vmp.service.IPlayService;
 import com.genersoft.iot.vmp.service.bean.RequestPushStreamMsg;
@@ -63,6 +63,9 @@
 	private IVideoManagerStorage storager;
 
 	@Autowired
+	private IDeviceService deviceService;
+
+	@Autowired
 	private ZLMRTPServerFactory zlmrtpServerFactory;
 
 	@Autowired
@@ -87,40 +90,23 @@
 	@Override
 	public void process(RequestEvent evt) {
 		CallIdHeader callIdHeader = (CallIdHeader)evt.getRequest().getHeader(CallIdHeader.NAME);
+		String fromUserId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(FromHeader.NAME)).getAddress().getURI()).getUser();
+		String toUserId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(ToHeader.NAME)).getAddress().getURI()).getUser();
+		logger.info("[鏀跺埌ACK]锛� 鏉ヨ嚜->{}", fromUserId);
+		SendRtpItem sendRtpItem =  redisCatchStorage.querySendRTPServer(null, null, null, callIdHeader.getCallId());
+		if (sendRtpItem == null) {
+			logger.warn("[鏀跺埌ACK]锛氭湭鎵惧埌鏉ヨ嚜{}锛岀洰鏍囦负({})鐨勬帹娴佷俊鎭�",fromUserId, toUserId);
+			return;
+		}
+		logger.info("[鏀跺埌ACK]锛歳tp/{}寮�濮嬬骇鎺ㄦ祦, 鐩爣={}:{}锛孲SRC={}, RTCP={}", sendRtpItem.getStream(),
+				sendRtpItem.getIp(), sendRtpItem.getPort(), sendRtpItem.getSsrc(), sendRtpItem.isRtcp());
+		// 鍙栨秷璁剧疆鐨勮秴鏃朵换鍔�
+		dynamicTask.stop(callIdHeader.getCallId());
+		MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId());
+		ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(fromUserId);
 
-		String platformGbId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(FromHeader.NAME)).getAddress().getURI()).getUser();
-		logger.info("[鏀跺埌ACK]锛� platformGbId->{}", platformGbId);
-		if (userSetting.getPushStreamAfterAck()) {
-			ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(platformGbId);
-			// 鍙栨秷璁剧疆鐨勮秴鏃朵换鍔�
-			dynamicTask.stop(callIdHeader.getCallId());
-			String channelId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(ToHeader.NAME)).getAddress().getURI()).getUser();
-			SendRtpItem sendRtpItem =  redisCatchStorage.querySendRTPServer(null, null, null, callIdHeader.getCallId());
-			if (sendRtpItem == null) {
-				logger.warn("[鏀跺埌ACK]锛氭湭鎵惧埌閫氶亾({})鐨勬帹娴佷俊鎭�", channelId);
-				return;
-			}
-			String isUdp = sendRtpItem.isTcp() ? "0" : "1";
-			MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId());
-			logger.info("鏀跺埌ACK锛宺tp/{}寮�濮嬬骇鎺ㄦ祦, 鐩爣={}:{}锛孲SRC={}, RTCP={}", sendRtpItem.getStream(),
-					sendRtpItem.getIp(), sendRtpItem.getPort(), sendRtpItem.getSsrc(), sendRtpItem.isRtcp());
-			Map<String, Object> param = new HashMap<>(12);
-			param.put("vhost","__defaultVhost__");
-			param.put("app",sendRtpItem.getApp());
-			param.put("stream",sendRtpItem.getStream());
-			param.put("ssrc", sendRtpItem.getSsrc());
-			param.put("dst_url",sendRtpItem.getIp());
-			param.put("dst_port", sendRtpItem.getPort());
-			param.put("src_port", sendRtpItem.getLocalPort());
-			param.put("pt", sendRtpItem.getPt());
-			param.put("use_ps", sendRtpItem.isUsePs() ? "1" : "0");
-			param.put("only_audio", sendRtpItem.isOnlyAudio() ? "1" : "0");
-			param.put("is_udp", isUdp);
-			if (!sendRtpItem.isTcp()) {
-				// udp妯″紡涓嬪紑鍚痳tcp淇濇椿
-				param.put("udp_rtcp_timeout", sendRtpItem.isRtcp()? "1":"0");
-			}
-
+		if (parentPlatform != null) {
+			Map<String, Object> param = getSendRtpParam(sendRtpItem);
 			if (mediaInfo == null) {
 				RequestPushStreamMsg requestPushStreamMsg = RequestPushStreamMsg.getInstance(
 						sendRtpItem.getMediaServerId(), sendRtpItem.getApp(), sendRtpItem.getStream(),
@@ -130,30 +116,75 @@
 					playService.startSendRtpStreamHand(sendRtpItem, parentPlatform, json, param, callIdHeader);
 				});
 			} else {
-				// 濡傛灉鏄潪涓ユ牸妯″紡锛岄渶瑕佸叧闂鍙e崰鐢�
-				JSONObject startSendRtpStreamResult = null;
-				if (sendRtpItem.getLocalPort() != 0) {
-					if (sendRtpItem.isTcpActive()) {
-						startSendRtpStreamResult = zlmrtpServerFactory.startSendRtpPassive(mediaInfo, param);
-					}else {
-						param.put("dst_url", sendRtpItem.getIp());
-						param.put("dst_port", sendRtpItem.getPort());
-						startSendRtpStreamResult = zlmrtpServerFactory.startSendRtpStream(mediaInfo, param);
-					}
-				}else {
-					if (sendRtpItem.isTcpActive()) {
-						startSendRtpStreamResult = zlmrtpServerFactory.startSendRtpPassive(mediaInfo, param);
-					}else {
-						param.put("dst_url", sendRtpItem.getIp());
-						param.put("dst_port", sendRtpItem.getPort());
-						startSendRtpStreamResult = zlmrtpServerFactory.startSendRtpStream(mediaInfo, param);
-					}
-				}
+				JSONObject startSendRtpStreamResult = sendRtp(sendRtpItem, mediaInfo, param);
 				if (startSendRtpStreamResult != null) {
 					playService.startSendRtpStreamHand(sendRtpItem, parentPlatform, startSendRtpStreamResult, param, callIdHeader);
 				}
 			}
+		}else {
+			Device device = deviceService.getDevice(fromUserId);
+			if (device == null) {
+				logger.warn("[鏀跺埌ACK]锛氭潵鑷獅}锛岀洰鏍囦负({})鐨勬帹娴佷俊鎭负鎵惧埌娴佷綋鏈嶅姟[{}]淇℃伅",fromUserId, toUserId, sendRtpItem.getMediaServerId());
+				return;
+			}
+			// 璁剧疆涓烘敹鍒癆CK鍚庡彂閫佽闊崇殑璁惧宸茬粡鍦ㄥ彂閫�200OK寮�濮嬪彂娴佷簡
+			if (!device.isBroadcastPushAfterAck()) {
+				return;
+			}
+			if (mediaInfo == null) {
+				logger.warn("[鏀跺埌ACK]锛氭潵鑷獅}锛岀洰鏍囦负({})鐨勬帹娴佷俊鎭负鎵惧埌娴佷綋鏈嶅姟[{}]淇℃伅",fromUserId, toUserId, sendRtpItem.getMediaServerId());
+				return;
+			}
+			Map<String, Object> param = getSendRtpParam(sendRtpItem);
+			JSONObject startSendRtpStreamResult = sendRtp(sendRtpItem, mediaInfo, param);
+			if (startSendRtpStreamResult != null) {
+				playService.startSendRtpStreamHand(sendRtpItem, device, startSendRtpStreamResult, param, callIdHeader);
+			}
 		}
 	}
 
+	private Map<String, Object> getSendRtpParam(SendRtpItem sendRtpItem) {
+		String isUdp = sendRtpItem.isTcp() ? "0" : "1";
+		Map<String, Object> param = new HashMap<>(12);
+		param.put("vhost","__defaultVhost__");
+		param.put("app",sendRtpItem.getApp());
+		param.put("stream",sendRtpItem.getStream());
+		param.put("ssrc", sendRtpItem.getSsrc());
+		param.put("dst_url",sendRtpItem.getIp());
+		param.put("dst_port", sendRtpItem.getPort());
+		param.put("src_port", sendRtpItem.getLocalPort());
+		param.put("pt", sendRtpItem.getPt());
+		param.put("use_ps", sendRtpItem.isUsePs() ? "1" : "0");
+		param.put("only_audio", sendRtpItem.isOnlyAudio() ? "1" : "0");
+		param.put("is_udp", isUdp);
+		if (!sendRtpItem.isTcp()) {
+			// udp妯″紡涓嬪紑鍚痳tcp淇濇椿
+			param.put("udp_rtcp_timeout", sendRtpItem.isRtcp()? "1":"0");
+		}
+		return param;
+	}
+
+	private JSONObject sendRtp(SendRtpItem sendRtpItem, MediaServerItem mediaInfo, Map<String, Object> param){
+		JSONObject startSendRtpStreamResult = null;
+		if (sendRtpItem.getLocalPort() != 0) {
+			if (sendRtpItem.isTcpActive()) {
+				startSendRtpStreamResult = zlmrtpServerFactory.startSendRtpPassive(mediaInfo, param);
+			}else {
+				param.put("dst_url", sendRtpItem.getIp());
+				param.put("dst_port", sendRtpItem.getPort());
+				startSendRtpStreamResult = zlmrtpServerFactory.startSendRtpStream(mediaInfo, param);
+			}
+		}else {
+			if (sendRtpItem.isTcpActive()) {
+				startSendRtpStreamResult = zlmrtpServerFactory.startSendRtpPassive(mediaInfo, param);
+			}else {
+				param.put("dst_url", sendRtpItem.getIp());
+				param.put("dst_port", sendRtpItem.getPort());
+				startSendRtpStreamResult = zlmrtpServerFactory.startSendRtpStream(mediaInfo, param);
+			}
+		}
+		return startSendRtpStreamResult;
+
+	}
+
 }
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java
index 423a3b4..7594b48 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java
@@ -427,23 +427,18 @@
 
                         try {
                             // 瓒呮椂鏈敹鍒癆ck搴旇鍥炲bye,褰撳墠绛夊緟鏃堕棿涓�10绉�
-                            if (userSetting.getPushStreamAfterAck()) {
-                                dynamicTask.startDelay(callIdHeader.getCallId(), () -> {
-                                    logger.info("Ack 绛夊緟瓒呮椂");
-                                    mediaServerService.releaseSsrc(mediaServerItemInUSe.getId(), sendRtpItem.getSsrc());
-                                    // 鍥炲bye
-                                    try {
-                                        cmderFroPlatform.streamByeCmd(platform, callIdHeader.getCallId());
-                                    } catch (SipException | InvalidArgumentException | ParseException e) {
-                                        logger.error("[鍛戒护鍙戦�佸け璐 鍥芥爣绾ц仈 鍙戦�丅YE: {}", e.getMessage());
-                                    }
-                                }, 60 * 1000);
-                            }
+                            dynamicTask.startDelay(callIdHeader.getCallId(), () -> {
+                                logger.info("Ack 绛夊緟瓒呮椂");
+                                mediaServerService.releaseSsrc(mediaServerItemInUSe.getId(), sendRtpItem.getSsrc());
+                                // 鍥炲bye
+                                try {
+                                    cmderFroPlatform.streamByeCmd(platform, callIdHeader.getCallId());
+                                } catch (SipException | InvalidArgumentException | ParseException e) {
+                                    logger.error("[鍛戒护鍙戦�佸け璐 鍥芥爣绾ц仈 鍙戦�丅YE: {}", e.getMessage());
+                                }
+                            }, 60 * 1000);
 
-                            SIPResponse sipResponse = responseSdpAck(request, content.toString(), platform);
-                            if (!userSetting.getPushStreamAfterAck()) {
-                                playService.startPushStream(sendRtpItem, sipResponse, platform, request.getCallIdHeader());
-                            }
+                             responseSdpAck(request, content.toString(), platform);
                         } catch (SipException | InvalidArgumentException | ParseException e) {
                             logger.error("[鍛戒护鍙戦�佸け璐 鍥芥爣绾ц仈 鍥炲SdpAck", e);
                         }
@@ -650,7 +645,6 @@
                 if (response != null) {
                     sendRtpItem.setToTag(response.getToTag());
                 }
-
                 redisCatchStorage.updateSendRTPSever(sendRtpItem);
 
             } else {
@@ -888,16 +882,8 @@
         content.append("f=\r\n");
 
         try {
-            SIPResponse sipResponse = responseSdpAck(request, content.toString(), platform);
-            if (!userSetting.getPushStreamAfterAck()) {
-                playService.startPushStream(sendRtpItem, sipResponse, platform, request.getCallIdHeader());
-            }
-            return sipResponse;
-        } catch (SipException e) {
-            logger.error("鏈鐞嗙殑寮傚父 ", e);
-        } catch (InvalidArgumentException e) {
-            logger.error("鏈鐞嗙殑寮傚父 ", e);
-        } catch (ParseException e) {
+            return responseSdpAck(request, content.toString(), platform);
+        } catch (SipException | InvalidArgumentException | ParseException e) {
             logger.error("鏈鐞嗙殑寮傚父 ", e);
         }
         return null;
@@ -1132,7 +1118,7 @@
             audioBroadcastManager.update(audioBroadcastCatch);
 
             // 寮�鍚彂娴侊紝澶у崕鍦ㄦ敹鍒�200OK鍚庡氨浼氬紑濮嬪缓绔嬭繛鎺�
-            if (!userSetting.getPushStreamAfterAck()) {
+            if (!device.isBroadcastPushAfterAck()) {
                 playService.startPushStream(sendRtpItem, sipResponse, parentPlatform, request.getCallIdHeader());
             }
 
diff --git a/src/main/java/com/genersoft/iot/vmp/service/IPlayService.java b/src/main/java/com/genersoft/iot/vmp/service/IPlayService.java
index 44bf11b..7725e1b 100644
--- a/src/main/java/com/genersoft/iot/vmp/service/IPlayService.java
+++ b/src/main/java/com/genersoft/iot/vmp/service/IPlayService.java
@@ -64,7 +64,7 @@
 
     void startPushStream(SendRtpItem sendRtpItem, SIPResponse sipResponse, ParentPlatform platform, CallIdHeader callIdHeader);
 
-    void startSendRtpStreamHand(SendRtpItem sendRtpItem, ParentPlatform parentPlatform,
+    void startSendRtpStreamHand(SendRtpItem sendRtpItem, Object correlationInfo,
                                 JSONObject jsonObject, Map<String, Object> param, CallIdHeader callIdHeader);
 
     void talkCmd(Device device, String channelId, MediaServerItem mediaServerItem, String stream, AudioBroadcastEvent event);
diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
index 71e9b65..ea998e9 100644
--- a/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
+++ b/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
@@ -1481,7 +1481,7 @@
     }
 
     @Override
-    public void startSendRtpStreamHand(SendRtpItem sendRtpItem, ParentPlatform parentPlatform,
+    public void startSendRtpStreamHand(SendRtpItem sendRtpItem, Object correlationInfo,
                                        JSONObject jsonObject, Map<String, Object> param, CallIdHeader callIdHeader) {
         if (jsonObject == null) {
             logger.error("RTP鎺ㄦ祦澶辫触: 璇锋鏌LM鏈嶅姟");
@@ -1504,10 +1504,13 @@
                 }
             } else {
                 // 鍚戜笂绾у钩鍙�
-                try {
-                    commanderForPlatform.streamByeCmd(parentPlatform, callIdHeader.getCallId());
-                } catch (SipException | InvalidArgumentException | ParseException e) {
-                    logger.error("[鍛戒护鍙戦�佸け璐 鍥芥爣绾ц仈 鍙戦�丅YE: {}", e.getMessage());
+                if (correlationInfo instanceof ParentPlatform) {
+                    try {
+                        ParentPlatform parentPlatform = (ParentPlatform)correlationInfo;
+                        commanderForPlatform.streamByeCmd(parentPlatform, callIdHeader.getCallId());
+                    } catch (SipException | InvalidArgumentException | ParseException e) {
+                        logger.error("[鍛戒护鍙戦�佸け璐 鍥芥爣绾ц仈 鍙戦�丅YE: {}", e.getMessage());
+                    }
                 }
             }
         }
diff --git a/src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceMapper.java b/src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceMapper.java
index 96773fe..e2497a7 100644
--- a/src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceMapper.java
+++ b/src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceMapper.java
@@ -43,6 +43,7 @@
             "on_line," +
             "media_server_id," +
             "switch_primary_sub_stream," +
+            "broadcast_push_after_ack," +
             "(SELECT count(0) FROM wvp_device_channel WHERE device_id=wvp_device.device_id) as channel_count "+
             " FROM wvp_device WHERE device_id = #{deviceId}")
     Device getDeviceByDeviceId(String deviceId);
@@ -73,6 +74,7 @@
                 "subscribe_cycle_for_alarm,"+
                 "ssrc_check,"+
                 "as_message_channel,"+
+                "broadcast_push_after_ack,"+
                 "geo_coord_sys,"+
                 "on_line"+
             ") VALUES (" +
@@ -101,6 +103,7 @@
                 "#{subscribeCycleForAlarm}," +
                 "#{ssrcCheck}," +
                 "#{asMessageChannel}," +
+                "#{broadcastPushAfterAck}," +
                 "#{geoCoordSys}," +
                 "#{onLine}" +
             ")")
@@ -155,6 +158,7 @@
             "subscribe_cycle_for_alarm,"+
             "ssrc_check,"+
             "as_message_channel,"+
+            "broadcast_push_after_ack,"+
             "geo_coord_sys,"+
             "on_line,"+
             "media_server_id,"+
@@ -196,6 +200,7 @@
             "subscribe_cycle_for_alarm,"+
             "ssrc_check,"+
             "as_message_channel,"+
+            "broadcast_push_after_ack,"+
             "geo_coord_sys,"+
             "on_line"+
             " FROM wvp_device WHERE on_line = true")
@@ -226,6 +231,7 @@
             "subscribe_cycle_for_alarm,"+
             "ssrc_check,"+
             "as_message_channel,"+
+            "broadcast_push_after_ack,"+
             "geo_coord_sys,"+
             "on_line"+
             " FROM wvp_device WHERE ip = #{host} AND port=#{port}")
@@ -247,6 +253,7 @@
             "<if test=\"subscribeCycleForAlarm != null\">, subscribe_cycle_for_alarm=#{subscribeCycleForAlarm}</if>" +
             "<if test=\"ssrcCheck != null\">, ssrc_check=#{ssrcCheck}</if>" +
             "<if test=\"asMessageChannel != null\">, as_message_channel=#{asMessageChannel}</if>" +
+            "<if test=\"broadcastPushAfterAck != null\">, broadcast_push_after_ack=#{broadcastPushAfterAck}</if>" +
             "<if test=\"geoCoordSys != null\">, geo_coord_sys=#{geoCoordSys}</if>" +
             "<if test=\"switchPrimarySubStream != null\">, switch_primary_sub_stream=#{switchPrimarySubStream}</if>" +
             "<if test=\"mediaServerId != null\">, media_server_id=#{mediaServerId}</if>" +
@@ -264,6 +271,7 @@
             "charset,"+
             "ssrc_check,"+
             "as_message_channel,"+
+            "broadcastPushAfterAck,"+
             "geo_coord_sys,"+
             "on_line,"+
             "media_server_id,"+
@@ -278,6 +286,7 @@
             "#{charset}," +
             "#{ssrcCheck}," +
             "#{asMessageChannel}," +
+            "#{broadcastPushAfterAck}," +
             "#{geoCoordSys}," +
             "#{onLine}," +
             "#{mediaServerId}," +
diff --git a/src/main/resources/local.jks b/src/main/resources/local.jks
new file mode 100644
index 0000000..529be6b
--- /dev/null
+++ b/src/main/resources/local.jks
Binary files differ
diff --git a/web_src/src/components/dialog/deviceEdit.vue b/web_src/src/components/dialog/deviceEdit.vue
index 499d6ca..7cd3579 100644
--- a/web_src/src/components/dialog/deviceEdit.vue
+++ b/web_src/src/components/dialog/deviceEdit.vue
@@ -70,6 +70,7 @@
           <el-form-item label="鍏朵粬閫夐」">
             <el-checkbox label="SSRC鏍¢獙" v-model="form.ssrcCheck" style="float: left"></el-checkbox>
             <el-checkbox label="浣滀负娑堟伅閫氶亾" v-model="form.asMessageChannel" style="float: left"></el-checkbox>
+            <el-checkbox label="鏀跺埌ACK鍚庡彂娴�" v-model="form.broadcastPushAfterAck" style="float: left"></el-checkbox>
           </el-form-item>
           <el-form-item>
             <div style="float: right;">

--
Gitblit v1.8.0