Commit 2f76fa98bb839ede5b47a3c3e1bb6fe499952203

Authored by 648540858
2 parents aa6bce35 60c4f767

Merge branch 'wvp-28181-2.0'

# Conflicts:
#	src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/AckRequestProcessor.java
#	src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/ByeRequestProcessor.java
#	src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java
Showing 33 changed files with 332 additions and 116 deletions
src/main/java/com/genersoft/iot/vmp/gb28181/bean/ParentPlatform.java
@@ -53,7 +53,7 @@ public class ParentPlatform { @@ -53,7 +53,7 @@ public class ParentPlatform {
53 /** 53 /**
54 * 设备国标编号 54 * 设备国标编号
55 */ 55 */
56 - @Schema(description = "11111") 56 + @Schema(description = "设备国标编号")
57 private String deviceGBId; 57 private String deviceGBId;
58 58
59 /** 59 /**
@@ -113,7 +113,6 @@ public class ParentPlatform { @@ -113,7 +113,6 @@ public class ParentPlatform {
113 113
114 /** 114 /**
115 * RTCP流保活 115 * RTCP流保活
116 - * TODO 预留, 暂不实现  
117 */ 116 */
118 @Schema(description = "RTCP流保活") 117 @Schema(description = "RTCP流保活")
119 private boolean rtcp; 118 private boolean rtcp;
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java
@@ -108,7 +108,7 @@ public interface ISIPCommander { @@ -108,7 +108,7 @@ public interface ISIPCommander {
108 * @param startTime 开始时间,格式要求:yyyy-MM-dd HH:mm:ss 108 * @param startTime 开始时间,格式要求:yyyy-MM-dd HH:mm:ss
109 * @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss 109 * @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss
110 */ 110 */
111 - void playbackStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInf, Device device, String channelId, String startTime, String endTime,InviteStreamCallback inviteStreamCallback, InviteStreamCallback event, SipSubscribe.Event errorEvent); 111 + void playbackStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInf, Device device, String channelId, String startTime, String endTime,InviteStreamCallback inviteStreamCallback, InviteStreamCallback event, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent);
112 112
113 /** 113 /**
114 * 请求历史媒体下载 114 * 请求历史媒体下载
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
@@ -358,7 +358,7 @@ public class SIPCommander implements ISIPCommander { @@ -358,7 +358,7 @@ public class SIPCommander implements ISIPCommander {
358 // String streamMode = device.getStreamMode().toUpperCase(); 358 // String streamMode = device.getStreamMode().toUpperCase();
359 359
360 logger.info("{} 分配的ZLM为: {} [{}:{}]", stream, mediaServerItem.getId(), mediaServerItem.getIp(), ssrcInfo.getPort()); 360 logger.info("{} 分配的ZLM为: {} [{}:{}]", stream, mediaServerItem.getId(), mediaServerItem.getIp(), ssrcInfo.getPort());
361 - HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", stream, true, "rtmp", mediaServerItem.getId()); 361 + HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", stream, true, "rtsp", mediaServerItem.getId());
362 subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, JSONObject json)->{ 362 subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, JSONObject json)->{
363 if (event != null) { 363 if (event != null) {
364 event.response(mediaServerItemInUse, json); 364 event.response(mediaServerItemInUse, json);
@@ -458,7 +458,7 @@ public class SIPCommander implements ISIPCommander { @@ -458,7 +458,7 @@ public class SIPCommander implements ISIPCommander {
458 @Override 458 @Override
459 public void playbackStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, 459 public void playbackStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId,
460 String startTime, String endTime, InviteStreamCallback inviteStreamCallback, InviteStreamCallback hookEvent, 460 String startTime, String endTime, InviteStreamCallback inviteStreamCallback, InviteStreamCallback hookEvent,
461 - SipSubscribe.Event errorEvent) { 461 + SipSubscribe.Event okEvent,SipSubscribe.Event errorEvent) {
462 try { 462 try {
463 463
464 logger.info("{} 分配的ZLM为: {} [{}:{}]", ssrcInfo.getStream(), mediaServerItem.getId(), mediaServerItem.getIp(), ssrcInfo.getPort()); 464 logger.info("{} 分配的ZLM为: {} [{}:{}]", ssrcInfo.getStream(), mediaServerItem.getId(), mediaServerItem.getIp(), ssrcInfo.getPort());
@@ -526,7 +526,7 @@ public class SIPCommander implements ISIPCommander { @@ -526,7 +526,7 @@ public class SIPCommander implements ISIPCommander {
526 526
527 CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId() 527 CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
528 : udpSipProvider.getNewCallId(); 528 : udpSipProvider.getNewCallId();
529 - HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", ssrcInfo.getStream(), true, "rtmp", mediaServerItem.getId()); 529 + HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", ssrcInfo.getStream(), true, "rtsp", mediaServerItem.getId());
530 // 添加订阅 530 // 添加订阅
531 subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, JSONObject json)->{ 531 subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, JSONObject json)->{
532 if (hookEvent != null) { 532 if (hookEvent != null) {
@@ -537,10 +537,11 @@ public class SIPCommander implements ISIPCommander { @@ -537,10 +537,11 @@ public class SIPCommander implements ISIPCommander {
537 }); 537 });
538 Request request = headerProvider.createPlaybackInviteRequest(device, channelId, content.toString(), null, "fromplybck" + tm, null, callIdHeader, ssrcInfo.getSsrc()); 538 Request request = headerProvider.createPlaybackInviteRequest(device, channelId, content.toString(), null, "fromplybck" + tm, null, callIdHeader, ssrcInfo.getSsrc());
539 539
540 - transmitRequest(device, request, errorEvent, okEvent -> {  
541 - ResponseEvent responseEvent = (ResponseEvent) okEvent.event; 540 + transmitRequest(device, request, errorEvent, event -> {
  541 + ResponseEvent responseEvent = (ResponseEvent) event.event;
542 streamSession.put(device.getDeviceId(), channelId, callIdHeader.getCallId(), ssrcInfo.getStream(), ssrcInfo.getSsrc(), mediaServerItem.getId(), responseEvent.getClientTransaction(), VideoStreamSessionManager.SessionType.playback); 542 streamSession.put(device.getDeviceId(), channelId, callIdHeader.getCallId(), ssrcInfo.getStream(), ssrcInfo.getSsrc(), mediaServerItem.getId(), responseEvent.getClientTransaction(), VideoStreamSessionManager.SessionType.playback);
543 - streamSession.put(device.getDeviceId(), channelId, callIdHeader.getCallId(), okEvent.dialog); 543 + streamSession.put(device.getDeviceId(), channelId, callIdHeader.getCallId(), event.dialog);
  544 + okEvent.response(event);
544 }); 545 });
545 if (inviteStreamCallback != null) { 546 if (inviteStreamCallback != null) {
546 inviteStreamCallback.call(new InviteStreamInfo(mediaServerItem, null, callIdHeader.getCallId(), "rtp", ssrcInfo.getStream())); 547 inviteStreamCallback.call(new InviteStreamInfo(mediaServerItem, null, callIdHeader.getCallId(), "rtp", ssrcInfo.getStream()));
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/AckRequestProcessor.java
@@ -121,6 +121,10 @@ public class AckRequestProcessor extends SIPRequestProcessorParent implements In @@ -121,6 +121,10 @@ public class AckRequestProcessor extends SIPRequestProcessorParent implements In
121 param.put("pt", sendRtpItem.getPt()); 121 param.put("pt", sendRtpItem.getPt());
122 param.put("use_ps", sendRtpItem.isUsePs() ? "1" : "0"); 122 param.put("use_ps", sendRtpItem.isUsePs() ? "1" : "0");
123 param.put("only_audio", sendRtpItem.isOnlyAudio() ? "1" : "0"); 123 param.put("only_audio", sendRtpItem.isOnlyAudio() ? "1" : "0");
  124 + if (!sendRtpItem.isTcp() && parentPlatform.isRtcp()) {
  125 + // 开启rtcp保活
  126 + param.put("udp_rtcp_timeout", "1");
  127 + }
124 JSONObject jsonObject; 128 JSONObject jsonObject;
125 if (sendRtpItem.isTcpActive()) { 129 if (sendRtpItem.isTcpActive()) {
126 jsonObject = zlmrtpServerFactory.startSendRtpPassive(mediaInfo, param); 130 jsonObject = zlmrtpServerFactory.startSendRtpPassive(mediaInfo, param);
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/ByeRequestProcessor.java
@@ -104,6 +104,8 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In @@ -104,6 +104,8 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In
104 MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId()); 104 MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId());
105 zlmrtpServerFactory.stopSendRtpStream(mediaInfo, param); 105 zlmrtpServerFactory.stopSendRtpStream(mediaInfo, param);
106 redisCatchStorage.deleteSendRTPServer(platformGbId, sendRtpItem.getChannelId(), callIdHeader.getCallId(), null); 106 redisCatchStorage.deleteSendRTPServer(platformGbId, sendRtpItem.getChannelId(), callIdHeader.getCallId(), null);
  107 + redisCatchStorage.deleteSendRTPServer(platformGbId, channelId, callIdHeader.getCallId(), null);
  108 + zlmrtpServerFactory.stopSendRtpStream(mediaInfo, param);
107 int totalReaderCount = zlmrtpServerFactory.totalReaderCount(mediaInfo, sendRtpItem.getApp(), streamId); 109 int totalReaderCount = zlmrtpServerFactory.totalReaderCount(mediaInfo, sendRtpItem.getApp(), streamId);
108 if (totalReaderCount <= 0) { 110 if (totalReaderCount <= 0) {
109 logger.info("收到bye: {} 无其它观看者,通知设备停止推流", streamId); 111 logger.info("收到bye: {} 无其它观看者,通知设备停止推流", streamId);
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java
@@ -111,6 +111,9 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements @@ -111,6 +111,9 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
111 private ZLMRESTfulUtils zlmresTfulUtils; 111 private ZLMRESTfulUtils zlmresTfulUtils;
112 112
113 @Autowired 113 @Autowired
  114 + private ZlmHttpHookSubscribe zlmHttpHookSubscribe;
  115 +
  116 + @Autowired
114 private SIPProcessorObserver sipProcessorObserver; 117 private SIPProcessorObserver sipProcessorObserver;
115 118
116 @Autowired 119 @Autowired
@@ -430,7 +433,14 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements @@ -430,7 +433,14 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
430 if (playTransaction != null) { 433 if (playTransaction != null) {
431 Boolean streamReady = zlmrtpServerFactory.isStreamReady(mediaServerItem, "rtp", playTransaction.getStream()); 434 Boolean streamReady = zlmrtpServerFactory.isStreamReady(mediaServerItem, "rtp", playTransaction.getStream());
432 if (!streamReady) { 435 if (!streamReady) {
433 - playTransaction = null; 436 + boolean hasRtpServer = mediaServerService.checkRtpServer(mediaServerItem, "rtp", playTransaction.getStream());
  437 + if (hasRtpServer) {
  438 + logger.info("[上级点播]已经开启rtpServer但是尚未收到流,开启监听流的到来");
  439 + HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", playTransaction.getStream(), true, "rtsp", mediaServerItem.getId());
  440 + zlmHttpHookSubscribe.addSubscribe(hookSubscribe, hookEvent);
  441 + }else {
  442 + playTransaction = null;
  443 + }
434 } 444 }
435 } 445 }
436 if (playTransaction == null) { 446 if (playTransaction == null) {
@@ -593,7 +603,8 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements @@ -593,7 +603,8 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
593 responseAck(evt, Response.BAD_REQUEST, "channel [" + gbStream.getGbId() + "] offline"); 603 responseAck(evt, Response.BAD_REQUEST, "channel [" + gbStream.getGbId() + "] offline");
594 } else if ("push".equals(gbStream.getStreamType())) { 604 } else if ("push".equals(gbStream.getStreamType())) {
595 if (!platform.isStartOfflinePush()) { 605 if (!platform.isStartOfflinePush()) {
596 - responseAck(evt, Response.TEMPORARILY_UNAVAILABLE, "channel unavailable"); 606 + // 平台设置中关闭了拉起离线的推流则直接回复
  607 + responseAck(evt, Response.TEMPORARILY_UNAVAILABLE, "channel stream not pushing");
597 return; 608 return;
598 } 609 }
599 // 发送redis消息以使设备上线 610 // 发送redis消息以使设备上线
@@ -629,7 +640,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements @@ -629,7 +640,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
629 app, stream, channelId, mediaTransmissionTCP); 640 app, stream, channelId, mediaTransmissionTCP);
630 641
631 if (sendRtpItem == null) { 642 if (sendRtpItem == null) {
632 - logger.warn("服务器端口资源不足"); 643 + logger.warn("上级点时创建sendRTPItem失败,可能是服务器端口资源不足");
633 try { 644 try {
634 responseAck(evt, Response.BUSY_HERE); 645 responseAck(evt, Response.BUSY_HERE);
635 } catch (SipException e) { 646 } catch (SipException e) {
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/SubscribeRequestProcessor.java
@@ -211,7 +211,6 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme @@ -211,7 +211,6 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme
211 }else if (subscribeInfo.getExpires() == 0) { 211 }else if (subscribeInfo.getExpires() == 0) {
212 subscribeHolder.removeCatalogSubscribe(platformId); 212 subscribeHolder.removeCatalogSubscribe(platformId);
213 } 213 }
214 -  
215 try { 214 try {
216 ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(platformId); 215 ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(platformId);
217 responseXmlAck(evt, resultXml.toString(), parentPlatform); 216 responseXmlAck(evt, resultXml.toString(), parentPlatform);
@@ -219,5 +218,4 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme @@ -219,5 +218,4 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme
219 e.printStackTrace(); 218 e.printStackTrace();
220 } 219 }
221 } 220 }
222 -  
223 } 221 }
src/main/java/com/genersoft/iot/vmp/gb28181/utils/XmlUtil.java
@@ -203,6 +203,12 @@ public class XmlUtil { @@ -203,6 +203,12 @@ public class XmlUtil {
203 return null; 203 return null;
204 } 204 }
205 deviceChannel.setChannelId(channelId); 205 deviceChannel.setChannelId(channelId);
  206 + int channelTypeCode = Integer.parseInt(channelId.substring(10, 13));
  207 + if (channelTypeCode == 136 || channelTypeCode == 137 || channelTypeCode == 138) {
  208 + deviceChannel.setHasAudio(true);
  209 + }else {
  210 + deviceChannel.setHasAudio(false);
  211 + }
206 if (event != null && !event.equals(CatalogEvent.ADD) && !event.equals(CatalogEvent.UPDATE)) { 212 if (event != null && !event.equals(CatalogEvent.ADD) && !event.equals(CatalogEvent.UPDATE)) {
207 // 除了ADD和update情况下需要识别全部内容, 213 // 除了ADD和update情况下需要识别全部内容,
208 return deviceChannel; 214 return deviceChannel;
@@ -396,7 +402,6 @@ public class XmlUtil { @@ -396,7 +402,6 @@ public class XmlUtil {
396 } else { 402 } else {
397 deviceChannel.setPTZType(Integer.parseInt(XmlUtil.getText(itemDevice, "PTZType"))); 403 deviceChannel.setPTZType(Integer.parseInt(XmlUtil.getText(itemDevice, "PTZType")));
398 } 404 }
399 - deviceChannel.setHasAudio(true); // 默认含有音频,播放时再检查是否有音频及是否AAC  
400 return deviceChannel; 405 return deviceChannel;
401 } 406 }
402 } 407 }
403 \ No newline at end of file 408 \ No newline at end of file
src/main/java/com/genersoft/iot/vmp/media/zlm/AssistRESTfulUtils.java
@@ -50,7 +50,7 @@ public class AssistRESTfulUtils { @@ -50,7 +50,7 @@ public class AssistRESTfulUtils {
50 if (mediaServerItem == null) { 50 if (mediaServerItem == null) {
51 return null; 51 return null;
52 } 52 }
53 - if (mediaServerItem.getRecordAssistPort() > 0) { 53 + if (mediaServerItem.getRecordAssistPort() <= 0) {
54 logger.warn("未启用Assist服务"); 54 logger.warn("未启用Assist服务");
55 return null; 55 return null;
56 } 56 }
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java
@@ -19,8 +19,6 @@ import org.slf4j.Logger; @@ -19,8 +19,6 @@ import org.slf4j.Logger;
19 import org.slf4j.LoggerFactory; 19 import org.slf4j.LoggerFactory;
20 import org.springframework.beans.factory.annotation.Autowired; 20 import org.springframework.beans.factory.annotation.Autowired;
21 import org.springframework.beans.factory.annotation.Qualifier; 21 import org.springframework.beans.factory.annotation.Qualifier;
22 -import org.springframework.http.HttpStatus;  
23 -import org.springframework.http.ResponseEntity;  
24 import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; 22 import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
25 import org.springframework.util.ObjectUtils; 23 import org.springframework.util.ObjectUtils;
26 import org.springframework.web.bind.annotation.PostMapping; 24 import org.springframework.web.bind.annotation.PostMapping;
@@ -544,6 +542,8 @@ public class ZLMHttpHookListener { @@ -544,6 +542,8 @@ public class ZLMHttpHookListener {
544 for (SendRtpItem sendRtpItem : sendRtpItems) { 542 for (SendRtpItem sendRtpItem : sendRtpItems) {
545 ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(sendRtpItem.getPlatformId()); 543 ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(sendRtpItem.getPlatformId());
546 commanderFroPlatform.streamByeCmd(parentPlatform, sendRtpItem.getCallId()); 544 commanderFroPlatform.streamByeCmd(parentPlatform, sendRtpItem.getCallId());
  545 + redisCatchStorage.deleteSendRTPServer(parentPlatform.getServerGBId(), sendRtpItem.getChannelId(),
  546 + sendRtpItem.getCallId(), sendRtpItem.getStreamId());
547 } 547 }
548 } 548 }
549 } 549 }
@@ -573,13 +573,19 @@ public class ZLMHttpHookListener { @@ -573,13 +573,19 @@ public class ZLMHttpHookListener {
573 return ret; 573 return ret;
574 }else { 574 }else {
575 StreamProxyItem streamProxyItem = streamProxyService.getStreamProxyByAppAndStream(app, streamId); 575 StreamProxyItem streamProxyItem = streamProxyService.getStreamProxyByAppAndStream(app, streamId);
576 - if (streamProxyItem != null && streamProxyItem.isEnable_remove_none_reader()) {  
577 - ret.put("close", true);  
578 - streamProxyService.del(app, streamId);  
579 - String url = streamProxyItem.getUrl() != null?streamProxyItem.getUrl():streamProxyItem.getSrc_url();  
580 - logger.info("[{}/{}]<-[{}] 拉流代理无人观看已经移除", app, streamId, url);  
581 - }else {  
582 - ret.put("close", false); 576 + if (streamProxyItem != null ) {
  577 + if (streamProxyItem.isEnable_remove_none_reader()) {
  578 + // 无人观看自动移除
  579 + ret.put("close", true);
  580 + streamProxyService.del(app, streamId);
  581 + String url = streamProxyItem.getUrl() != null?streamProxyItem.getUrl():streamProxyItem.getSrc_url();
  582 + logger.info("[{}/{}]<-[{}] 拉流代理无人观看已经移除", app, streamId, url);
  583 + }else if (streamProxyItem.isEnable_disable_none_reader()) {
  584 + // 无人观看停用
  585 + ret.put("close", true);
  586 + }else {
  587 + ret.put("close", false);
  588 + }
583 } 589 }
584 return ret; 590 return ret;
585 } 591 }
@@ -626,7 +632,7 @@ public class ZLMHttpHookListener { @@ -626,7 +632,7 @@ public class ZLMHttpHookListener {
626 @ResponseBody 632 @ResponseBody
627 @PostMapping(value = "/on_server_started", produces = "application/json;charset=UTF-8") 633 @PostMapping(value = "/on_server_started", produces = "application/json;charset=UTF-8")
628 public JSONObject onServerStarted(HttpServletRequest request, @RequestBody JSONObject jsonObject){ 634 public JSONObject onServerStarted(HttpServletRequest request, @RequestBody JSONObject jsonObject){
629 - 635 +
630 if (logger.isDebugEnabled()) { 636 if (logger.isDebugEnabled()) {
631 logger.debug("[ ZLM HOOK ]on_server_started API调用,参数:" + jsonObject.toString()); 637 logger.debug("[ ZLM HOOK ]on_server_started API调用,参数:" + jsonObject.toString());
632 } 638 }
@@ -649,6 +655,39 @@ public class ZLMHttpHookListener { @@ -649,6 +655,39 @@ public class ZLMHttpHookListener {
649 return ret; 655 return ret;
650 } 656 }
651 657
  658 + /**
  659 + * 发送rtp(startSendRtp)被动关闭时回调
  660 + */
  661 + @ResponseBody
  662 + @PostMapping(value = "/on_send_rtp_stopped", produces = "application/json;charset=UTF-8")
  663 + public JSONObject onSendRtpStopped(HttpServletRequest request, @RequestBody JSONObject jsonObject){
  664 +
  665 + logger.info("[ ZLM HOOK ]on_send_rtp_stopped API调用,参数:" + jsonObject);
  666 +
  667 + JSONObject ret = new JSONObject();
  668 + ret.put("code", 0);
  669 + ret.put("msg", "success");
  670 +
  671 + // 查找对应的上级推流,发送停止
  672 + String app = jsonObject.getString("app");
  673 + if (!"rtp".equals(app)) {
  674 + return ret;
  675 + }
  676 + String stream = jsonObject.getString("stream");
  677 + List<SendRtpItem> sendRtpItems = redisCatchStorage.querySendRTPServerByStream(stream);
  678 + if (sendRtpItems.size() > 0) {
  679 + for (SendRtpItem sendRtpItem : sendRtpItems) {
  680 + ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(sendRtpItem.getPlatformId());
  681 + commanderFroPlatform.streamByeCmd(parentPlatform, sendRtpItem.getCallId());
  682 + redisCatchStorage.deleteSendRTPServer(parentPlatform.getServerGBId(), sendRtpItem.getChannelId(),
  683 + sendRtpItem.getCallId(), sendRtpItem.getStreamId());
  684 + }
  685 + }
  686 +
  687 +
  688 + return ret;
  689 + }
  690 +
652 private Map<String, String> urlParamToMap(String params) { 691 private Map<String, String> urlParamToMap(String params) {
653 HashMap<String, String> map = new HashMap<>(); 692 HashMap<String, String> map = new HashMap<>();
654 if (ObjectUtils.isEmpty(params)) { 693 if (ObjectUtils.isEmpty(params)) {
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRTPServerFactory.java
@@ -96,6 +96,10 @@ public class ZLMRTPServerFactory { @@ -96,6 +96,10 @@ public class ZLMRTPServerFactory {
96 if(rtpInfo.getInteger("code") == 0){ 96 if(rtpInfo.getInteger("code") == 0){
97 if (rtpInfo.getBoolean("exist")) { 97 if (rtpInfo.getBoolean("exist")) {
98 result = rtpInfo.getInteger("local_port"); 98 result = rtpInfo.getInteger("local_port");
  99 + if (result == 0) {
  100 + // 此时说明rtpServer已经创建但是流还没有推上来
  101 +
  102 + }
99 return result; 103 return result;
100 } 104 }
101 }else if(rtpInfo.getInteger("code") == -2){ 105 }else if(rtpInfo.getInteger("code") == -2){
src/main/java/com/genersoft/iot/vmp/media/zlm/dto/StreamProxyItem.java
@@ -37,6 +37,9 @@ public class StreamProxyItem extends GbStream { @@ -37,6 +37,9 @@ public class StreamProxyItem extends GbStream {
37 private boolean enable_mp4; 37 private boolean enable_mp4;
38 @Schema(description = "是否 无人观看时删除") 38 @Schema(description = "是否 无人观看时删除")
39 private boolean enable_remove_none_reader; 39 private boolean enable_remove_none_reader;
  40 +
  41 + @Schema(description = "是否 无人观看时不启用")
  42 + private boolean enable_disable_none_reader;
40 @Schema(description = "上级平台国标ID") 43 @Schema(description = "上级平台国标ID")
41 private String platformGbId; 44 private String platformGbId;
42 @Schema(description = "创建时间") 45 @Schema(description = "创建时间")
@@ -177,4 +180,11 @@ public class StreamProxyItem extends GbStream { @@ -177,4 +180,11 @@ public class StreamProxyItem extends GbStream {
177 this.enable_remove_none_reader = enable_remove_none_reader; 180 this.enable_remove_none_reader = enable_remove_none_reader;
178 } 181 }
179 182
  183 + public boolean isEnable_disable_none_reader() {
  184 + return enable_disable_none_reader;
  185 + }
  186 +
  187 + public void setEnable_disable_none_reader(boolean enable_disable_none_reader) {
  188 + this.enable_disable_none_reader = enable_disable_none_reader;
  189 + }
180 } 190 }
src/main/java/com/genersoft/iot/vmp/service/IMediaServerService.java
@@ -82,4 +82,6 @@ public interface IMediaServerService { @@ -82,4 +82,6 @@ public interface IMediaServerService {
82 MediaServerItem getDefaultMediaServer(); 82 MediaServerItem getDefaultMediaServer();
83 83
84 void updateMediaServerKeepalive(String mediaServerId, JSONObject data); 84 void updateMediaServerKeepalive(String mediaServerId, JSONObject data);
  85 +
  86 + boolean checkRtpServer(MediaServerItem mediaServerItem, String rtp, String stream);
85 } 87 }
src/main/java/com/genersoft/iot/vmp/service/impl/MediaServerServiceImpl.java
@@ -152,9 +152,11 @@ public class MediaServerServiceImpl implements IMediaServerService { @@ -152,9 +152,11 @@ public class MediaServerServiceImpl implements IMediaServerService {
152 if (streamId == null) { 152 if (streamId == null) {
153 streamId = String.format("%08x", Integer.parseInt(ssrc)).toUpperCase(); 153 streamId = String.format("%08x", Integer.parseInt(ssrc)).toUpperCase();
154 } 154 }
155 - int rtpServerPort = mediaServerItem.getRtpProxyPort(); 155 + int rtpServerPort;
156 if (mediaServerItem.isRtpEnable()) { 156 if (mediaServerItem.isRtpEnable()) {
157 rtpServerPort = zlmrtpServerFactory.createRTPServer(mediaServerItem, streamId, ssrcCheck?Integer.parseInt(ssrc):0, port); 157 rtpServerPort = zlmrtpServerFactory.createRTPServer(mediaServerItem, streamId, ssrcCheck?Integer.parseInt(ssrc):0, port);
  158 + } else {
  159 + rtpServerPort = mediaServerItem.getRtpProxyPort();
158 } 160 }
159 RedisUtil.set(key, mediaServerItem); 161 RedisUtil.set(key, mediaServerItem);
160 return new SSRCInfo(rtpServerPort, ssrc, streamId); 162 return new SSRCInfo(rtpServerPort, ssrc, streamId);
@@ -537,6 +539,7 @@ public class MediaServerServiceImpl implements IMediaServerService { @@ -537,6 +539,7 @@ public class MediaServerServiceImpl implements IMediaServerService {
537 param.put("hook.on_stream_none_reader",String.format("%s/on_stream_none_reader", hookPrex)); 539 param.put("hook.on_stream_none_reader",String.format("%s/on_stream_none_reader", hookPrex));
538 param.put("hook.on_stream_not_found",String.format("%s/on_stream_not_found", hookPrex)); 540 param.put("hook.on_stream_not_found",String.format("%s/on_stream_not_found", hookPrex));
539 param.put("hook.on_server_keepalive",String.format("%s/on_server_keepalive", hookPrex)); 541 param.put("hook.on_server_keepalive",String.format("%s/on_server_keepalive", hookPrex));
  542 + param.put("hook.on_send_rtp_stopped",String.format("%s/on_send_rtp_stopped", hookPrex));
540 if (mediaServerItem.getRecordAssistPort() > 0) { 543 if (mediaServerItem.getRecordAssistPort() > 0) {
541 param.put("hook.on_record_mp4",String.format("http://127.0.0.1:%s/api/record/on_record_mp4", mediaServerItem.getRecordAssistPort())); 544 param.put("hook.on_record_mp4",String.format("http://127.0.0.1:%s/api/record/on_record_mp4", mediaServerItem.getRecordAssistPort()));
542 }else { 545 }else {
@@ -686,4 +689,13 @@ public class MediaServerServiceImpl implements IMediaServerService { @@ -686,4 +689,13 @@ public class MediaServerServiceImpl implements IMediaServerService {
686 } 689 }
687 } 690 }
688 } 691 }
  692 +
  693 + @Override
  694 + public boolean checkRtpServer(MediaServerItem mediaServerItem, String app, String stream) {
  695 + JSONObject rtpInfo = zlmresTfulUtils.getRtpInfo(mediaServerItem, stream);
  696 + if(rtpInfo.getInteger("code") == 0){
  697 + return rtpInfo.getBoolean("exist");
  698 + }
  699 + return false;
  700 + }
689 } 701 }
src/main/java/com/genersoft/iot/vmp/service/impl/MediaServiceImpl.java
@@ -73,7 +73,6 @@ public class MediaServiceImpl implements IMediaService { @@ -73,7 +73,6 @@ public class MediaServiceImpl implements IMediaService {
73 }else { 73 }else {
74 streamInfo = getStreamInfoByAppAndStream(mediaInfo, app, stream, tracks, addr,null, true); 74 streamInfo = getStreamInfoByAppAndStream(mediaInfo, app, stream, tracks, addr,null, true);
75 } 75 }
76 -  
77 } 76 }
78 } 77 }
79 return streamInfo; 78 return streamInfo;
src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
@@ -193,17 +193,30 @@ public class PlayServiceImpl implements IPlayService { @@ -193,17 +193,30 @@ public class PlayServiceImpl implements IPlayService {
193 JSONObject rtpInfo = zlmresTfulUtils.getRtpInfo(mediaInfo, streamId); 193 JSONObject rtpInfo = zlmresTfulUtils.getRtpInfo(mediaInfo, streamId);
194 if(rtpInfo.getInteger("code") == 0){ 194 if(rtpInfo.getInteger("code") == 0){
195 if (rtpInfo.getBoolean("exist")) { 195 if (rtpInfo.getBoolean("exist")) {
196 -  
197 - WVPResult wvpResult = new WVPResult();  
198 - wvpResult.setCode(ErrorCode.SUCCESS.getCode());  
199 - wvpResult.setMsg(ErrorCode.SUCCESS.getMsg());  
200 - wvpResult.setData(streamInfo);  
201 - msg.setData(wvpResult);  
202 -  
203 - resultHolder.invokeAllResult(msg);  
204 - if (hookEvent != null) {  
205 - hookEvent.response(mediaServerItem, JSONObject.parseObject(JSON.toJSONString(streamInfo))); 196 + int localPort = rtpInfo.getInteger("local_port");
  197 + if (localPort == 0) {
  198 + logger.warn("[点播],点播时发现rtpServerC存在,但是尚未开始推流");
  199 + // 此时说明rtpServer已经创建但是流还没有推上来
  200 + WVPResult wvpResult = new WVPResult();
  201 + wvpResult.setCode(ErrorCode.ERROR100.getCode());
  202 + wvpResult.setMsg("点播已经在进行中,请稍候重试");
  203 + msg.setData(wvpResult);
  204 +
  205 + resultHolder.invokeAllResult(msg);
  206 + return playResult;
  207 + }else {
  208 + WVPResult wvpResult = new WVPResult();
  209 + wvpResult.setCode(ErrorCode.SUCCESS.getCode());
  210 + wvpResult.setMsg(ErrorCode.SUCCESS.getMsg());
  211 + wvpResult.setData(streamInfo);
  212 + msg.setData(wvpResult);
  213 +
  214 + resultHolder.invokeAllResult(msg);
  215 + if (hookEvent != null) {
  216 + hookEvent.response(mediaServerItem, JSONObject.parseObject(JSON.toJSONString(streamInfo)));
  217 + }
206 } 218 }
  219 +
207 }else { 220 }else {
208 redisCatchStorage.stopPlay(streamInfo); 221 redisCatchStorage.stopPlay(streamInfo);
209 storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId()); 222 storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId());
@@ -318,7 +331,7 @@ public class PlayServiceImpl implements IPlayService { @@ -318,7 +331,7 @@ public class PlayServiceImpl implements IPlayService {
318 } 331 }
319 logger.info("[点播消息] 收到invite 200, 发现下级自定义了ssrc: {}", ssrcInResponse ); 332 logger.info("[点播消息] 收到invite 200, 发现下级自定义了ssrc: {}", ssrcInResponse );
320 if (!mediaServerItem.isRtpEnable() || device.isSsrcCheck()) { 333 if (!mediaServerItem.isRtpEnable() || device.isSsrcCheck()) {
321 - logger.info("[SIP 消息] SSRC修正 {}->{}", ssrc, ssrcInResponse); 334 + logger.info("[点播消息] SSRC修正 {}->{}", ssrc, ssrcInResponse);
322 335
323 if (!mediaServerItem.getSsrcConfig().checkSsrc(ssrcInResponse)) { 336 if (!mediaServerItem.getSsrcConfig().checkSsrc(ssrcInResponse)) {
324 // ssrc 不可用 337 // ssrc 不可用
@@ -468,37 +481,92 @@ public class PlayServiceImpl implements IPlayService { @@ -468,37 +481,92 @@ public class PlayServiceImpl implements IPlayService {
468 resultHolder.exist(DeferredResultHolder.CALLBACK_CMD_PLAYBACK + deviceId + channelId, uuid); 481 resultHolder.exist(DeferredResultHolder.CALLBACK_CMD_PLAYBACK + deviceId + channelId, uuid);
469 }, userSetting.getPlayTimeout()); 482 }, userSetting.getPlayTimeout());
470 483
  484 + SipSubscribe.Event errorEvent = event -> {
  485 + dynamicTask.stop(playBackTimeOutTaskKey);
  486 + requestMessage.setData(WVPResult.fail(ErrorCode.ERROR100.getCode(), String.format("回放失败, 错误码: %s, %s", event.statusCode, event.msg)));
  487 + playBackResult.setCode(ErrorCode.ERROR100.getCode());
  488 + playBackResult.setMsg(String.format("回放失败, 错误码: %s, %s", event.statusCode, event.msg));
  489 + playBackResult.setData(requestMessage);
  490 + playBackResult.setEvent(event);
  491 + playBackCallback.call(playBackResult);
  492 + streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream());
  493 + };
  494 +
  495 + InviteStreamCallback hookEvent = (InviteStreamInfo inviteStreamInfo) -> {
  496 + logger.info("收到回放订阅消息: " + inviteStreamInfo.getResponse().toJSONString());
  497 + dynamicTask.stop(playBackTimeOutTaskKey);
  498 + StreamInfo streamInfo = onPublishHandler(inviteStreamInfo.getMediaServerItem(), inviteStreamInfo.getResponse(), deviceId, channelId);
  499 + if (streamInfo == null) {
  500 + logger.warn("设备回放API调用失败!");
  501 + playBackResult.setCode(ErrorCode.ERROR100.getCode());
  502 + playBackResult.setMsg("设备回放API调用失败!");
  503 + playBackCallback.call(playBackResult);
  504 + return;
  505 + }
  506 + redisCatchStorage.startPlayback(streamInfo, inviteStreamInfo.getCallId());
  507 + WVPResult<StreamInfo> success = WVPResult.success(streamInfo);
  508 + requestMessage.setData(success);
  509 + playBackResult.setCode(ErrorCode.SUCCESS.getCode());
  510 + playBackResult.setMsg(ErrorCode.SUCCESS.getMsg());
  511 + playBackResult.setData(requestMessage);
  512 + playBackResult.setMediaServerItem(inviteStreamInfo.getMediaServerItem());
  513 + playBackResult.setResponse(inviteStreamInfo.getResponse());
  514 + playBackCallback.call(playBackResult);
  515 + };
  516 +
471 cmder.playbackStreamCmd(mediaServerItem, ssrcInfo, device, channelId, startTime, endTime, infoCallBack, 517 cmder.playbackStreamCmd(mediaServerItem, ssrcInfo, device, channelId, startTime, endTime, infoCallBack,
472 - (InviteStreamInfo inviteStreamInfo) -> {  
473 - logger.info("收到订阅消息: " + inviteStreamInfo.getResponse().toJSONString());  
474 - dynamicTask.stop(playBackTimeOutTaskKey);  
475 - StreamInfo streamInfo = onPublishHandler(inviteStreamInfo.getMediaServerItem(), inviteStreamInfo.getResponse(), deviceId, channelId);  
476 - if (streamInfo == null) {  
477 - logger.warn("设备回放API调用失败!");  
478 - playBackResult.setCode(ErrorCode.ERROR100.getCode());  
479 - playBackResult.setMsg("设备回放API调用失败!");  
480 - playBackCallback.call(playBackResult);  
481 - return; 518 + hookEvent, eventResult -> {
  519 + if (eventResult.type == SipSubscribe.EventResultType.response) {
  520 + ResponseEvent responseEvent = (ResponseEvent)eventResult.event;
  521 + String contentString = new String(responseEvent.getResponse().getRawContent());
  522 + // 获取ssrc
  523 + int ssrcIndex = contentString.indexOf("y=");
  524 + // 检查是否有y字段
  525 + if (ssrcIndex >= 0) {
  526 + //ssrc规定长度为10字节,不取余下长度以避免后续还有“f=”字段 TODO 后续对不规范的非10位ssrc兼容
  527 + String ssrcInResponse = contentString.substring(ssrcIndex + 2, ssrcIndex + 12);
  528 + // 查询到ssrc不一致且开启了ssrc校验则需要针对处理
  529 + if (ssrcInfo.getSsrc().equals(ssrcInResponse)) {
  530 + return;
  531 + }
  532 + logger.info("[回放消息] 收到invite 200, 发现下级自定义了ssrc: {}", ssrcInResponse );
  533 + if (!mediaServerItem.isRtpEnable() || device.isSsrcCheck()) {
  534 + logger.info("[回放消息] SSRC修正 {}->{}", ssrcInfo.getSsrc(), ssrcInResponse);
  535 +
  536 + if (!mediaServerItem.getSsrcConfig().checkSsrc(ssrcInResponse)) {
  537 + // ssrc 不可用
  538 + // 释放ssrc
  539 + mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc());
  540 + streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream());
  541 + eventResult.msg = "下级自定义了ssrc,但是此ssrc不可用";
  542 + eventResult.statusCode = 400;
  543 + errorEvent.response(eventResult);
  544 + return;
  545 + }
  546 +
  547 + // 单端口模式streamId也有变化,需要重新设置监听
  548 + if (!mediaServerItem.isRtpEnable()) {
  549 + // 添加订阅
  550 + HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", ssrcInfo.getStream(), true, "rtsp", mediaServerItem.getId());
  551 + subscribe.removeSubscribe(hookSubscribe);
  552 + hookSubscribe.getContent().put("stream", String.format("%08x", Integer.parseInt(ssrcInResponse)).toUpperCase());
  553 + subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, JSONObject response)->{
  554 + logger.info("[ZLM HOOK] ssrc修正后收到订阅消息: " + response.toJSONString());
  555 + dynamicTask.stop(playBackTimeOutTaskKey);
  556 + // hook响应
  557 + onPublishHandlerForPlay(mediaServerItemInUse, response, device.getDeviceId(), channelId, uuid);
  558 + hookEvent.call(new InviteStreamInfo(mediaServerItem, null, eventResult.callId, "rtp", ssrcInfo.getStream()));
  559 + });
  560 + }
  561 + // 关闭rtp server
  562 + mediaServerService.closeRTPServer(device.getDeviceId(), channelId, ssrcInfo.getStream());
  563 + // 重新开启ssrc server
  564 + mediaServerService.openRTPServer(mediaServerItem, ssrcInfo.getStream(), ssrcInResponse, device.isSsrcCheck(), true, ssrcInfo.getPort());
  565 + }
  566 + }
482 } 567 }
483 - redisCatchStorage.startPlayback(streamInfo, inviteStreamInfo.getCallId());  
484 - WVPResult<StreamInfo> success = WVPResult.success(streamInfo);  
485 - requestMessage.setData(success);  
486 - playBackResult.setCode(ErrorCode.SUCCESS.getCode());  
487 - playBackResult.setMsg(ErrorCode.SUCCESS.getMsg());  
488 - playBackResult.setData(requestMessage);  
489 - playBackResult.setMediaServerItem(inviteStreamInfo.getMediaServerItem());  
490 - playBackResult.setResponse(inviteStreamInfo.getResponse());  
491 - playBackCallback.call(playBackResult);  
492 - }, event -> {  
493 - dynamicTask.stop(playBackTimeOutTaskKey);  
494 - requestMessage.setData(WVPResult.fail(ErrorCode.ERROR100.getCode(), String.format("回放失败, 错误码: %s, %s", event.statusCode, event.msg)));  
495 - playBackResult.setCode(ErrorCode.ERROR100.getCode());  
496 - playBackResult.setMsg(String.format("回放失败, 错误码: %s, %s", event.statusCode, event.msg));  
497 - playBackResult.setData(requestMessage);  
498 - playBackResult.setEvent(event);  
499 - playBackCallback.call(playBackResult);  
500 - streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream());  
501 - }); 568 +
  569 + }, errorEvent);
502 return result; 570 return result;
503 } 571 }
504 572
src/main/java/com/genersoft/iot/vmp/service/impl/RedisPushStreamListMsgListener.java
@@ -53,7 +53,6 @@ public class RedisPushStreamListMsgListener implements MessageListener { @@ -53,7 +53,6 @@ public class RedisPushStreamListMsgListener implements MessageListener {
53 boolean contains = allAppAndStream.contains(app + stream); 53 boolean contains = allAppAndStream.contains(app + stream);
54 //不存在就添加 54 //不存在就添加
55 if (!contains) { 55 if (!contains) {
56 - streamPushItem.setStatus(false);  
57 streamPushItem.setStreamType("push"); 56 streamPushItem.setStreamType("push");
58 streamPushItem.setCreateTime(DateUtil.getNow()); 57 streamPushItem.setCreateTime(DateUtil.getNow());
59 streamPushItem.setMediaServerId(mediaServerService.getDefaultMediaServer().getId()); 58 streamPushItem.setMediaServerId(mediaServerService.getDefaultMediaServer().getId());
src/main/java/com/genersoft/iot/vmp/service/impl/StreamPushUploadFileHandler.java
@@ -116,7 +116,7 @@ public class StreamPushUploadFileHandler extends AnalysisEventListener&lt;StreamPus @@ -116,7 +116,7 @@ public class StreamPushUploadFileHandler extends AnalysisEventListener&lt;StreamPus
116 streamPushItem.setApp(streamPushExcelDto.getApp()); 116 streamPushItem.setApp(streamPushExcelDto.getApp());
117 streamPushItem.setStream(streamPushExcelDto.getStream()); 117 streamPushItem.setStream(streamPushExcelDto.getStream());
118 streamPushItem.setGbId(streamPushExcelDto.getGbId()); 118 streamPushItem.setGbId(streamPushExcelDto.getGbId());
119 - streamPushItem.setStatus(false); 119 + streamPushItem.setStatus(streamPushExcelDto.getStatus());
120 streamPushItem.setStreamType("push"); 120 streamPushItem.setStreamType("push");
121 streamPushItem.setCreateTime(DateUtil.getNow()); 121 streamPushItem.setCreateTime(DateUtil.getNow());
122 streamPushItem.setMediaServerId(defaultMediaServerId); 122 streamPushItem.setMediaServerId(defaultMediaServerId);
src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java
@@ -236,4 +236,6 @@ public interface IRedisCatchStorage { @@ -236,4 +236,6 @@ public interface IRedisCatchStorage {
236 void sendStreamPushRequestedMsgForStatus(); 236 void sendStreamPushRequestedMsgForStatus();
237 237
238 List<SendRtpItem> querySendRTPServerByChnnelId(String channelId); 238 List<SendRtpItem> querySendRTPServerByChnnelId(String channelId);
  239 +
  240 + List<SendRtpItem> querySendRTPServerByStream(String stream);
239 } 241 }
src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceChannelMapper.java
@@ -143,15 +143,12 @@ public interface DeviceChannelMapper { @@ -143,15 +143,12 @@ public interface DeviceChannelMapper {
143 @Update(value = {"UPDATE device_channel SET status=0 WHERE deviceId=#{deviceId}"}) 143 @Update(value = {"UPDATE device_channel SET status=0 WHERE deviceId=#{deviceId}"})
144 void offlineByDeviceId(String deviceId); 144 void offlineByDeviceId(String deviceId);
145 145
146 - @Update(value = {"UPDATE device_channel SET status=1 WHERE deviceId=#{deviceId} AND channelId=#{channelId}"})  
147 - void online(String deviceId, String channelId);  
148 -  
149 @Insert("<script> " + 146 @Insert("<script> " +
150 "insert into device_channel " + 147 "insert into device_channel " +
151 "(channelId, deviceId, name, manufacture, model, owner, civilCode, block, subCount, " + 148 "(channelId, deviceId, name, manufacture, model, owner, civilCode, block, subCount, " +
152 " address, parental, parentId, safetyWay, registerWay, certNum, certifiable, errCode, secrecy, " + 149 " address, parental, parentId, safetyWay, registerWay, certNum, certifiable, errCode, secrecy, " +
153 " ipAddress, port, password, PTZType, status, streamId, longitude, latitude, longitudeGcj02, latitudeGcj02, " + 150 " ipAddress, port, password, PTZType, status, streamId, longitude, latitude, longitudeGcj02, latitudeGcj02, " +
154 - " longitudeWgs84, latitudeWgs84, createTime, updateTime, businessGroupId, gpsTime) " + 151 + " longitudeWgs84, latitudeWgs84, hasAudio, createTime, updateTime, businessGroupId, gpsTime) " +
155 "values " + 152 "values " +
156 "<foreach collection='addChannels' index='index' item='item' separator=','> " + 153 "<foreach collection='addChannels' index='index' item='item' separator=','> " +
157 "('${item.channelId}', '${item.deviceId}', '${item.name}', '${item.manufacture}', '${item.model}', " + 154 "('${item.channelId}', '${item.deviceId}', '${item.name}', '${item.manufacture}', '${item.model}', " +
@@ -160,7 +157,7 @@ public interface DeviceChannelMapper { @@ -160,7 +157,7 @@ public interface DeviceChannelMapper {
160 "'${item.certNum}', ${item.certifiable}, ${item.errCode}, '${item.secrecy}', " + 157 "'${item.certNum}', ${item.certifiable}, ${item.errCode}, '${item.secrecy}', " +
161 "'${item.ipAddress}', ${item.port}, '${item.password}', ${item.PTZType}, ${item.status}, " + 158 "'${item.ipAddress}', ${item.port}, '${item.password}', ${item.PTZType}, ${item.status}, " +
162 "'${item.streamId}', ${item.longitude}, ${item.latitude},${item.longitudeGcj02}, " + 159 "'${item.streamId}', ${item.longitude}, ${item.latitude},${item.longitudeGcj02}, " +
163 - "${item.latitudeGcj02},${item.longitudeWgs84}, ${item.latitudeWgs84},'${item.createTime}', '${item.updateTime}', " + 160 + "${item.latitudeGcj02},${item.longitudeWgs84}, ${item.latitudeWgs84}, ${item.hasAudio},'${item.createTime}', '${item.updateTime}', " +
164 "'${item.businessGroupId}', '${item.gpsTime}') " + 161 "'${item.businessGroupId}', '${item.gpsTime}') " +
165 "</foreach> " + 162 "</foreach> " +
166 "ON DUPLICATE KEY UPDATE " + 163 "ON DUPLICATE KEY UPDATE " +
@@ -193,11 +190,15 @@ public interface DeviceChannelMapper { @@ -193,11 +190,15 @@ public interface DeviceChannelMapper {
193 "latitudeGcj02=VALUES(latitudeGcj02), " + 190 "latitudeGcj02=VALUES(latitudeGcj02), " +
194 "longitudeWgs84=VALUES(longitudeWgs84), " + 191 "longitudeWgs84=VALUES(longitudeWgs84), " +
195 "latitudeWgs84=VALUES(latitudeWgs84), " + 192 "latitudeWgs84=VALUES(latitudeWgs84), " +
  193 + "hasAudio=VALUES(hasAudio), " +
196 "businessGroupId=VALUES(businessGroupId), " + 194 "businessGroupId=VALUES(businessGroupId), " +
197 "gpsTime=VALUES(gpsTime)" + 195 "gpsTime=VALUES(gpsTime)" +
198 "</script>") 196 "</script>")
199 int batchAdd(List<DeviceChannel> addChannels); 197 int batchAdd(List<DeviceChannel> addChannels);
200 198
  199 + @Update(value = {"UPDATE device_channel SET status=1 WHERE deviceId=#{deviceId} AND channelId=#{channelId}"})
  200 + void online(String deviceId, String channelId);
  201 +
201 @Update({"<script>" + 202 @Update({"<script>" +
202 "<foreach collection='updateChannels' item='item' separator=';'>" + 203 "<foreach collection='updateChannels' item='item' separator=';'>" +
203 " UPDATE" + 204 " UPDATE" +
@@ -341,4 +342,7 @@ public interface DeviceChannelMapper { @@ -341,4 +342,7 @@ public interface DeviceChannelMapper {
341 " left join platform_catalog pc on pgc.catalogId = pc.id and pgc.platformId = pc.platformId" + 342 " left join platform_catalog pc on pgc.catalogId = pc.id and pgc.platformId = pc.platformId" +
342 " where pgc.platformId=#{serverGBId}") 343 " where pgc.platformId=#{serverGBId}")
343 List<DeviceChannel> queryChannelWithCatalog(String serverGBId); 344 List<DeviceChannel> queryChannelWithCatalog(String serverGBId);
  345 +
  346 + @Select("select * from device_channel where deviceId = #{deviceId}")
  347 + List<DeviceChannel> queryAllChannels(String deviceId);
344 } 348 }
src/main/java/com/genersoft/iot/vmp/storager/dao/PlatformGbStreamMapper.java
@@ -23,10 +23,10 @@ public interface PlatformGbStreamMapper { @@ -23,10 +23,10 @@ public interface PlatformGbStreamMapper {
23 23
24 @Insert("<script> " + 24 @Insert("<script> " +
25 "INSERT into platform_gb_stream " + 25 "INSERT into platform_gb_stream " +
26 - "(gbStreamId, platformId, catalogId) " + 26 + "(gbStreamId, platformId, catalogId,status) " +
27 "values " + 27 "values " +
28 "<foreach collection='streamPushItems' index='index' item='item' separator=','> " + 28 "<foreach collection='streamPushItems' index='index' item='item' separator=','> " +
29 - "(${item.gbStreamId}, '${item.platformId}', '${item.catalogId}')" + 29 + "(${item.gbStreamId}, '${item.platformId}', '${item.catalogId}'), '${item.status}')" +
30 "</foreach> " + 30 "</foreach> " +
31 "</script>") 31 "</script>")
32 int batchAdd(List<StreamPushItem> streamPushItems); 32 int batchAdd(List<StreamPushItem> streamPushItems);
src/main/java/com/genersoft/iot/vmp/storager/dao/StreamPushMapper.java
@@ -77,7 +77,7 @@ public interface StreamPushMapper { @@ -77,7 +77,7 @@ public interface StreamPushMapper {
77 "1=1 " + 77 "1=1 " +
78 " <if test='query != null'> AND (st.app LIKE '%${query}%' OR st.stream LIKE '%${query}%' OR gs.gbId LIKE '%${query}%' OR gs.name LIKE '%${query}%')</if> " + 78 " <if test='query != null'> AND (st.app LIKE '%${query}%' OR st.stream LIKE '%${query}%' OR gs.gbId LIKE '%${query}%' OR gs.name LIKE '%${query}%')</if> " +
79 " <if test='pushing == true' > AND (gs.gbId is null OR st.pushIng=1)</if>" + 79 " <if test='pushing == true' > AND (gs.gbId is null OR st.pushIng=1)</if>" +
80 - " <if test='pushing == false' > AND st.pushIng=0</if>" + 80 + " <if test='pushing == false' > AND (gs.pushIng is null OR st.pushIng=0) </if>" +
81 " <if test='mediaServerId != null' > AND st.mediaServerId=#{mediaServerId} </if>" + 81 " <if test='mediaServerId != null' > AND st.mediaServerId=#{mediaServerId} </if>" +
82 "order by st.createTime desc" + 82 "order by st.createTime desc" +
83 " </script>"}) 83 " </script>"})
src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java
@@ -388,6 +388,24 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { @@ -388,6 +388,24 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
388 } 388 }
389 389
390 @Override 390 @Override
  391 + public List<SendRtpItem> querySendRTPServerByStream(String stream) {
  392 + if (stream == null) {
  393 + return null;
  394 + }
  395 + String platformGbId = "*";
  396 + String callId = "*";
  397 + String channelId = "*";
  398 + String key = VideoManagerConstants.PLATFORM_SEND_RTP_INFO_PREFIX + userSetting.getServerId() + "_" + platformGbId
  399 + + "_" + channelId + "_" + stream + "_" + callId;
  400 + List<Object> scan = RedisUtil.scan(key);
  401 + List<SendRtpItem> result = new ArrayList<>();
  402 + for (Object o : scan) {
  403 + result.add((SendRtpItem) RedisUtil.get((String) o));
  404 + }
  405 + return result;
  406 + }
  407 +
  408 + @Override
391 public List<SendRtpItem> querySendRTPServer(String platformGbId) { 409 public List<SendRtpItem> querySendRTPServer(String platformGbId) {
392 if (platformGbId == null) { 410 if (platformGbId == null) {
393 platformGbId = "*"; 411 platformGbId = "*";
src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStorageImpl.java
@@ -111,11 +111,11 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage { @@ -111,11 +111,11 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage {
111 if (CollectionUtils.isEmpty(deviceChannelList)) { 111 if (CollectionUtils.isEmpty(deviceChannelList)) {
112 return false; 112 return false;
113 } 113 }
114 - List<DeviceChannel> allChannelInPlay = deviceChannelMapper.getAllChannelInPlay();  
115 - Map<String,DeviceChannel> allChannelMapInPlay = new ConcurrentHashMap<>();  
116 - if (allChannelInPlay.size() > 0) {  
117 - for (DeviceChannel deviceChannel : allChannelInPlay) {  
118 - allChannelMapInPlay.put(deviceChannel.getChannelId(), deviceChannel); 114 + List<DeviceChannel> allChannels = deviceChannelMapper.queryAllChannels(deviceId);
  115 + Map<String,DeviceChannel> allChannelMap = new ConcurrentHashMap<>();
  116 + if (allChannels.size() > 0) {
  117 + for (DeviceChannel deviceChannel : allChannels) {
  118 + allChannelMap.put(deviceChannel.getChannelId(), deviceChannel);
119 } 119 }
120 } 120 }
121 TransactionStatus transactionStatus = dataSourceTransactionManager.getTransaction(transactionDefinition); 121 TransactionStatus transactionStatus = dataSourceTransactionManager.getTransaction(transactionDefinition);
@@ -123,15 +123,17 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage { @@ -123,15 +123,17 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage {
123 List<DeviceChannel> channels = new ArrayList<>(); 123 List<DeviceChannel> channels = new ArrayList<>();
124 StringBuilder stringBuilder = new StringBuilder(); 124 StringBuilder stringBuilder = new StringBuilder();
125 Map<String, Integer> subContMap = new HashMap<>(); 125 Map<String, Integer> subContMap = new HashMap<>();
126 - if (deviceChannelList.size() > 1) { 126 + if (deviceChannelList.size() > 0) {
127 // 数据去重 127 // 数据去重
128 Set<String> gbIdSet = new HashSet<>(); 128 Set<String> gbIdSet = new HashSet<>();
129 for (DeviceChannel deviceChannel : deviceChannelList) { 129 for (DeviceChannel deviceChannel : deviceChannelList) {
130 if (!gbIdSet.contains(deviceChannel.getChannelId())) { 130 if (!gbIdSet.contains(deviceChannel.getChannelId())) {
131 gbIdSet.add(deviceChannel.getChannelId()); 131 gbIdSet.add(deviceChannel.getChannelId());
132 - if (allChannelMapInPlay.containsKey(deviceChannel.getChannelId())) {  
133 - deviceChannel.setStreamId(allChannelMapInPlay.get(deviceChannel.getChannelId()).getStreamId()); 132 + if (allChannelMap.containsKey(deviceChannel.getChannelId())) {
  133 + deviceChannel.setStreamId(allChannelMap.get(deviceChannel.getChannelId()).getStreamId());
  134 + deviceChannel.setHasAudio(allChannelMap.get(deviceChannel.getChannelId()).isHasAudio());
134 } 135 }
  136 +
135 channels.add(deviceChannel); 137 channels.add(deviceChannel);
136 if (!ObjectUtils.isEmpty(deviceChannel.getParentId())) { 138 if (!ObjectUtils.isEmpty(deviceChannel.getParentId())) {
137 if (subContMap.get(deviceChannel.getParentId()) == null) { 139 if (subContMap.get(deviceChannel.getParentId()) == null) {
@@ -153,8 +155,6 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage { @@ -153,8 +155,6 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage {
153 } 155 }
154 } 156 }
155 157
156 - }else {  
157 - channels = deviceChannelList;  
158 } 158 }
159 if (stringBuilder.length() > 0) { 159 if (stringBuilder.length() > 0) {
160 logger.info("[目录查询]收到的数据存在重复: {}" , stringBuilder); 160 logger.info("[目录查询]收到的数据存在重复: {}" , stringBuilder);
src/main/java/com/genersoft/iot/vmp/vmanager/bean/StreamPushExcelDto.java
@@ -22,6 +22,9 @@ public class StreamPushExcelDto { @@ -22,6 +22,9 @@ public class StreamPushExcelDto {
22 @ExcelProperty("目录ID") 22 @ExcelProperty("目录ID")
23 private String catalogId; 23 private String catalogId;
24 24
  25 + @ExcelProperty("在线状态")
  26 + private boolean status;
  27 +
25 public String getName() { 28 public String getName() {
26 return name; 29 return name;
27 } 30 }
@@ -70,4 +73,16 @@ public class StreamPushExcelDto { @@ -70,4 +73,16 @@ public class StreamPushExcelDto {
70 public void setCatalogId(String catalogId) { 73 public void setCatalogId(String catalogId) {
71 this.catalogId = catalogId; 74 this.catalogId = catalogId;
72 } 75 }
  76 +
  77 + public boolean isStatus() {
  78 + return status;
  79 + }
  80 +
  81 + public boolean getStatus() {
  82 + return status;
  83 + }
  84 +
  85 + public void setStatus(boolean status) {
  86 + this.status = status;
  87 + }
73 } 88 }
src/main/java/com/genersoft/iot/vmp/vmanager/user/UserController.java
@@ -43,6 +43,7 @@ public class UserController { @@ -43,6 +43,7 @@ public class UserController {
43 private IRoleService roleService; 43 private IRoleService roleService;
44 44
45 @GetMapping("/login") 45 @GetMapping("/login")
  46 + @PostMapping("/login")
46 @Operation(summary = "登录") 47 @Operation(summary = "登录")
47 @Parameter(name = "username", description = "用户名", required = true) 48 @Parameter(name = "username", description = "用户名", required = true)
48 @Parameter(name = "password", description = "密码(32位md5加密)", required = true) 49 @Parameter(name = "password", description = "密码(32位md5加密)", required = true)
src/main/resources/logback-spring-local.xml
@@ -98,6 +98,11 @@ @@ -98,6 +98,11 @@
98 <appender-ref ref="STDOUT" /> 98 <appender-ref ref="STDOUT" />
99 </root> 99 </root>
100 100
  101 + <logger name="wvp" level="debug" additivity="true">
  102 + <appender-ref ref="RollingFileError"/>
  103 + <appender-ref ref="RollingFile"/>
  104 + </logger>
  105 +
101 <logger name="GB28181_SIP" level="debug" additivity="true"> 106 <logger name="GB28181_SIP" level="debug" additivity="true">
102 <appender-ref ref="RollingFileError"/> 107 <appender-ref ref="RollingFileError"/>
103 <appender-ref ref="sipRollingFile"/> 108 <appender-ref ref="sipRollingFile"/>
web_src/src/components/ParentPlatformList.vue
@@ -143,7 +143,8 @@ export default { @@ -143,7 +143,8 @@ export default {
143 }); 143 });
144 }, 144 },
145 chooseChannel: function(platform) { 145 chooseChannel: function(platform) {
146 - this.$refs.chooseChannelDialog.openDialog(platform.serverGBId, platform.name, platform.catalogId, platform.treeType, this.initData) 146 + console.log("platform.name: " + platform.name)
  147 + this.$refs.chooseChannelDialog.openDialog(platform.serverGBId,platform.deviceGBId, platform.name, platform.catalogId, platform.treeType, this.initData)
147 }, 148 },
148 initData: function() { 149 initData: function() {
149 this.getPlatformList(); 150 this.getPlatformList();
web_src/src/components/dialog/chooseChannel.vue
@@ -8,7 +8,7 @@ @@ -8,7 +8,7 @@
8 <el-tab-pane label="目录结构" name="catalog"> 8 <el-tab-pane label="目录结构" name="catalog">
9 <el-container> 9 <el-container>
10 <el-main v-bind:style="{backgroundColor: '#FFF', maxHeight: winHeight + 'px'}"> 10 <el-main v-bind:style="{backgroundColor: '#FFF', maxHeight: winHeight + 'px'}">
11 - <chooseChannelForCatalog ref="chooseChannelForCatalog" :platformId=platformId :platformName=platformName :defaultCatalogId=defaultCatalogId :catalogIdChange="catalogIdChange" :treeType=treeType ></chooseChannelForCatalog> 11 + <chooseChannelForCatalog ref="chooseChannelForCatalog" :platformId=platformId :platformDeviceId=platformDeviceId :platformName=platformName :defaultCatalogId=defaultCatalogId :catalogIdChange="catalogIdChange" :treeType=treeType ></chooseChannelForCatalog>
12 </el-main> 12 </el-main>
13 </el-container> 13 </el-container>
14 </el-tab-pane> 14 </el-tab-pane>
@@ -60,6 +60,7 @@ export default { @@ -60,6 +60,7 @@ export default {
60 tabActiveName: "gbChannel", 60 tabActiveName: "gbChannel",
61 catalogTabActiveName: "catalog", 61 catalogTabActiveName: "catalog",
62 platformId: "", 62 platformId: "",
  63 + platformDeviceId: "",
63 catalogId: "", 64 catalogId: "",
64 catalogName: "", 65 catalogName: "",
65 currentCatalogId: "", 66 currentCatalogId: "",
@@ -73,8 +74,10 @@ export default { @@ -73,8 +74,10 @@ export default {
73 }; 74 };
74 }, 75 },
75 methods: { 76 methods: {
76 - openDialog(platformId, platformName, defaultCatalogId, treeType, closeCallback) { 77 + openDialog(platformId, platformDeviceId, platformName, defaultCatalogId, treeType, closeCallback) {
  78 + console.log("defaultCatalogId: " + defaultCatalogId)
77 this.platformId = platformId 79 this.platformId = platformId
  80 + this.platformDeviceId = platformDeviceId
78 this.platformName = platformName 81 this.platformName = platformName
79 this.defaultCatalogId = defaultCatalogId 82 this.defaultCatalogId = defaultCatalogId
80 this.showDialog = true 83 this.showDialog = true
web_src/src/components/dialog/chooseChannelForCatalog.vue
@@ -38,7 +38,7 @@ @@ -38,7 +38,7 @@
38 import catalogEdit from './catalogEdit.vue' 38 import catalogEdit from './catalogEdit.vue'
39 export default { 39 export default {
40 name: 'chooseChannelForCatalog', 40 name: 'chooseChannelForCatalog',
41 - props: ['platformId', 'platformName', 'defaultCatalogId', 'catalogIdChange', 'treeType'], 41 + props: ['platformId', 'platformDeviceId', 'platformName', 'defaultCatalogId', 'catalogIdChange', 'treeType'],
42 created() { 42 created() {
43 this.chooseId = this.defaultCatalogId; 43 this.chooseId = this.defaultCatalogId;
44 this.defaultCatalogIdSign = this.defaultCatalogId; 44 this.defaultCatalogIdSign = this.defaultCatalogId;
@@ -171,6 +171,7 @@ export default { @@ -171,6 +171,7 @@ export default {
171 }); 171 });
172 }, 172 },
173 loadNode: function(node, resolve){ 173 loadNode: function(node, resolve){
  174 + console.log("this.platformDeviceId: " + this.platformDeviceId)
174 if (node.level === 0) { 175 if (node.level === 0) {
175 resolve([ 176 resolve([
176 { 177 {
@@ -179,7 +180,7 @@ export default { @@ -179,7 +180,7 @@ export default {
179 type: -1 180 type: -1
180 },{ 181 },{
181 name: this.platformName, 182 name: this.platformName,
182 - id: this.platformId, 183 + id: this.platformDeviceId,
183 type: 0 184 type: 0
184 } 185 }
185 ]); 186 ]);
@@ -298,6 +299,8 @@ export default { @@ -298,6 +299,8 @@ export default {
298 return false; 299 return false;
299 }, 300 },
300 nodeClickHandler: function (data, node, tree){ 301 nodeClickHandler: function (data, node, tree){
  302 + console.log(data)
  303 + console.log(node)
301 this.chooseId = data.id; 304 this.chooseId = data.id;
302 this.chooseName = data.name; 305 this.chooseName = data.name;
303 if (this.catalogIdChange)this.catalogIdChange(this.chooseId, this.chooseName); 306 if (this.catalogIdChange)this.catalogIdChange(this.chooseId, this.chooseName);
web_src/src/components/dialog/getCatalog.vue
@@ -77,6 +77,7 @@ export default { @@ -77,6 +77,7 @@ export default {
77 }, 77 },
78 methods: { 78 methods: {
79 openDialog(catalogIdResult) { 79 openDialog(catalogIdResult) {
  80 + console.log(this.chooseId)
80 this.showDialog = true 81 this.showDialog = true
81 this.catalogIdResult = catalogIdResult 82 this.catalogIdResult = catalogIdResult
82 }, 83 },
@@ -107,9 +108,6 @@ export default { @@ -107,9 +108,6 @@ export default {
107 108
108 }, 109 },
109 loadNode: function(node, resolve){ 110 loadNode: function(node, resolve){
110 -  
111 -  
112 -  
113 if (node.level === 0) { 111 if (node.level === 0) {
114 this.$axios({ 112 this.$axios({
115 method:"get", 113 method:"get",
@@ -124,7 +122,7 @@ export default { @@ -124,7 +122,7 @@ export default {
124 resolve([ 122 resolve([
125 { 123 {
126 name: this.platformName, 124 name: this.platformName,
127 - id: this.platformId, 125 + id: res.data.data.deviceGBId,
128 type: 0 126 type: 0
129 } 127 }
130 ]); 128 ]);
@@ -142,9 +140,19 @@ export default { @@ -142,9 +140,19 @@ export default {
142 this.chooseId = data.id; 140 this.chooseId = data.id;
143 }, 141 },
144 close: function() { 142 close: function() {
  143 + this.chooseId = null;
145 this.showDialog = false; 144 this.showDialog = false;
146 }, 145 },
147 submit: function() { 146 submit: function() {
  147 + console.log(this.chooseId)
  148 + if (this.chooseId === null) {
  149 + this.$message({
  150 + showClose: true,
  151 + message: '未选择任何节点,',
  152 + type: 'warning'
  153 + });
  154 + return;
  155 + }
148 if (this.catalogIdResult)this.catalogIdResult(this.chooseId) 156 if (this.catalogIdResult)this.catalogIdResult(this.chooseId)
149 this.showDialog = false; 157 this.showDialog = false;
150 }, 158 },
web_src/src/components/dialog/platformEdit.vue
@@ -37,13 +37,13 @@ @@ -37,13 +37,13 @@
37 <el-form-item label="本地端口" prop="devicePort"> 37 <el-form-item label="本地端口" prop="devicePort">
38 <el-input v-model="platform.devicePort" :disabled="true" type="number"></el-input> 38 <el-input v-model="platform.devicePort" :disabled="true" type="number"></el-input>
39 </el-form-item> 39 </el-form-item>
  40 + <el-form-item label="SIP认证用户名" prop="username">
  41 + <el-input v-model="platform.username"></el-input>
  42 + </el-form-item>
40 </el-form> 43 </el-form>
41 </el-col> 44 </el-col>
42 <el-col :span="12"> 45 <el-col :span="12">
43 <el-form ref="platform2" :rules="rules" :model="platform" label-width="160px"> 46 <el-form ref="platform2" :rules="rules" :model="platform" label-width="160px">
44 - <el-form-item label="SIP认证用户名" prop="username">  
45 - <el-input v-model="platform.username"></el-input>  
46 - </el-form-item>  
47 <el-form-item label="行政区划" prop="administrativeDivision"> 47 <el-form-item label="行政区划" prop="administrativeDivision">
48 <el-input v-model="platform.administrativeDivision" clearable></el-input> 48 <el-input v-model="platform.administrativeDivision" clearable></el-input>
49 </el-form-item> 49 </el-form-item>
@@ -79,7 +79,7 @@ @@ -79,7 +79,7 @@
79 </el-select> 79 </el-select>
80 </el-form-item> 80 </el-form-item>
81 <el-form-item label="目录结构" prop="treeType" > 81 <el-form-item label="目录结构" prop="treeType" >
82 - <el-select v-model="platform.treeType" style="width: 100%" > 82 + <el-select v-model="platform.treeType" style="width: 100%" @change="treeTypeChange">
83 <el-option key="WGS84" label="行政区划" value="CivilCode"></el-option> 83 <el-option key="WGS84" label="行政区划" value="CivilCode"></el-option>
84 <el-option key="GCJ02" label="业务分组" value="BusinessGroup"></el-option> 84 <el-option key="GCJ02" label="业务分组" value="BusinessGroup"></el-option>
85 </el-select> 85 </el-select>
@@ -98,6 +98,7 @@ @@ -98,6 +98,7 @@
98 <el-checkbox label="启用" v-model="platform.enable" @change="checkExpires"></el-checkbox> 98 <el-checkbox label="启用" v-model="platform.enable" @change="checkExpires"></el-checkbox>
99 <el-checkbox label="云台控制" v-model="platform.ptz"></el-checkbox> 99 <el-checkbox label="云台控制" v-model="platform.ptz"></el-checkbox>
100 <el-checkbox label="拉起离线推流" v-model="platform.startOfflinePush"></el-checkbox> 100 <el-checkbox label="拉起离线推流" v-model="platform.startOfflinePush"></el-checkbox>
  101 + <el-checkbox label="RTCP保活" v-model="platform.rtcp" @change="rtcpCheckBoxChange"></el-checkbox>
101 </el-form-item> 102 </el-form-item>
102 <el-form-item> 103 <el-form-item>
103 <el-button type="primary" @click="onSubmit">{{ 104 <el-button type="primary" @click="onSubmit">{{
@@ -251,21 +252,7 @@ export default { @@ -251,21 +252,7 @@ export default {
251 252
252 }, 253 },
253 onSubmit: function () { 254 onSubmit: function () {
254 - if (this.onSubmit_text === "保存") {  
255 - this.$confirm("修改目录结构会导致关联目录与通道数据被清空", '提示', {  
256 - dangerouslyUseHTMLString: true,  
257 - confirmButtonText: '确定',  
258 - cancelButtonText: '取消',  
259 - center: true,  
260 - type: 'warning'  
261 - }).then(() => {  
262 - this.saveForm()  
263 - }).catch(() => {  
264 -  
265 - });  
266 - }else {  
267 - this.saveForm()  
268 - } 255 + this.saveForm()
269 }, 256 },
270 saveForm: function (){ 257 saveForm: function (){
271 this.$axios({ 258 this.$axios({
@@ -343,6 +330,22 @@ export default { @@ -343,6 +330,22 @@ export default {
343 if (this.platform.enable && this.platform.expires == "0") { 330 if (this.platform.enable && this.platform.expires == "0") {
344 this.platform.expires = "300"; 331 this.platform.expires = "300";
345 } 332 }
  333 + },
  334 + rtcpCheckBoxChange: function (result){
  335 + if (result) {
  336 + this.$message({
  337 + showClose: true,
  338 + message: "开启RTCP保活需要上级平台支持,可以避免无效推流",
  339 + type: "warning",
  340 + });
  341 + }
  342 + },
  343 + treeTypeChange: function (){
  344 + this.$message({
  345 + showClose: true,
  346 + message: "修改目录结构会导致关联目录与通道数据被清空,保存后生效",
  347 + type: "warning",
  348 + });
346 } 349 }
347 }, 350 },
348 }; 351 };
web_src/static/file/推流通道导入.zip
No preview for this file type