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 53 /**
54 54 * 设备国标编号
55 55 */
56   - @Schema(description = "11111")
  56 + @Schema(description = "设备国标编号")
57 57 private String deviceGBId;
58 58  
59 59 /**
... ... @@ -113,7 +113,6 @@ public class ParentPlatform {
113 113  
114 114 /**
115 115 * RTCP流保活
116   - * TODO 预留, 暂不实现
117 116 */
118 117 @Schema(description = "RTCP流保活")
119 118 private boolean rtcp;
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java
... ... @@ -108,7 +108,7 @@ public interface ISIPCommander {
108 108 * @param startTime 开始时间,格式要求:yyyy-MM-dd HH:mm:ss
109 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 358 // String streamMode = device.getStreamMode().toUpperCase();
359 359  
360 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 362 subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, JSONObject json)->{
363 363 if (event != null) {
364 364 event.response(mediaServerItemInUse, json);
... ... @@ -458,7 +458,7 @@ public class SIPCommander implements ISIPCommander {
458 458 @Override
459 459 public void playbackStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId,
460 460 String startTime, String endTime, InviteStreamCallback inviteStreamCallback, InviteStreamCallback hookEvent,
461   - SipSubscribe.Event errorEvent) {
  461 + SipSubscribe.Event okEvent,SipSubscribe.Event errorEvent) {
462 462 try {
463 463  
464 464 logger.info("{} 分配的ZLM为: {} [{}:{}]", ssrcInfo.getStream(), mediaServerItem.getId(), mediaServerItem.getIp(), ssrcInfo.getPort());
... ... @@ -526,7 +526,7 @@ public class SIPCommander implements ISIPCommander {
526 526  
527 527 CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
528 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 531 subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, JSONObject json)->{
532 532 if (hookEvent != null) {
... ... @@ -537,10 +537,11 @@ public class SIPCommander implements ISIPCommander {
537 537 });
538 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 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 546 if (inviteStreamCallback != null) {
546 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 121 param.put("pt", sendRtpItem.getPt());
122 122 param.put("use_ps", sendRtpItem.isUsePs() ? "1" : "0");
123 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 128 JSONObject jsonObject;
125 129 if (sendRtpItem.isTcpActive()) {
126 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 104 MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId());
105 105 zlmrtpServerFactory.stopSendRtpStream(mediaInfo, param);
106 106 redisCatchStorage.deleteSendRTPServer(platformGbId, sendRtpItem.getChannelId(), callIdHeader.getCallId(), null);
  107 + redisCatchStorage.deleteSendRTPServer(platformGbId, channelId, callIdHeader.getCallId(), null);
  108 + zlmrtpServerFactory.stopSendRtpStream(mediaInfo, param);
107 109 int totalReaderCount = zlmrtpServerFactory.totalReaderCount(mediaInfo, sendRtpItem.getApp(), streamId);
108 110 if (totalReaderCount <= 0) {
109 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 111 private ZLMRESTfulUtils zlmresTfulUtils;
112 112  
113 113 @Autowired
  114 + private ZlmHttpHookSubscribe zlmHttpHookSubscribe;
  115 +
  116 + @Autowired
114 117 private SIPProcessorObserver sipProcessorObserver;
115 118  
116 119 @Autowired
... ... @@ -430,7 +433,14 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
430 433 if (playTransaction != null) {
431 434 Boolean streamReady = zlmrtpServerFactory.isStreamReady(mediaServerItem, "rtp", playTransaction.getStream());
432 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 446 if (playTransaction == null) {
... ... @@ -593,7 +603,8 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
593 603 responseAck(evt, Response.BAD_REQUEST, "channel [" + gbStream.getGbId() + "] offline");
594 604 } else if ("push".equals(gbStream.getStreamType())) {
595 605 if (!platform.isStartOfflinePush()) {
596   - responseAck(evt, Response.TEMPORARILY_UNAVAILABLE, "channel unavailable");
  606 + // 平台设置中关闭了拉起离线的推流则直接回复
  607 + responseAck(evt, Response.TEMPORARILY_UNAVAILABLE, "channel stream not pushing");
597 608 return;
598 609 }
599 610 // 发送redis消息以使设备上线
... ... @@ -629,7 +640,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
629 640 app, stream, channelId, mediaTransmissionTCP);
630 641  
631 642 if (sendRtpItem == null) {
632   - logger.warn("服务器端口资源不足");
  643 + logger.warn("上级点时创建sendRTPItem失败,可能是服务器端口资源不足");
633 644 try {
634 645 responseAck(evt, Response.BUSY_HERE);
635 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 211 }else if (subscribeInfo.getExpires() == 0) {
212 212 subscribeHolder.removeCatalogSubscribe(platformId);
213 213 }
214   -
215 214 try {
216 215 ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(platformId);
217 216 responseXmlAck(evt, resultXml.toString(), parentPlatform);
... ... @@ -219,5 +218,4 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme
219 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 203 return null;
204 204 }
205 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 212 if (event != null && !event.equals(CatalogEvent.ADD) && !event.equals(CatalogEvent.UPDATE)) {
207 213 // 除了ADD和update情况下需要识别全部内容,
208 214 return deviceChannel;
... ... @@ -396,7 +402,6 @@ public class XmlUtil {
396 402 } else {
397 403 deviceChannel.setPTZType(Integer.parseInt(XmlUtil.getText(itemDevice, "PTZType")));
398 404 }
399   - deviceChannel.setHasAudio(true); // 默认含有音频,播放时再检查是否有音频及是否AAC
400 405 return deviceChannel;
401 406 }
402 407 }
403 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 50 if (mediaServerItem == null) {
51 51 return null;
52 52 }
53   - if (mediaServerItem.getRecordAssistPort() > 0) {
  53 + if (mediaServerItem.getRecordAssistPort() <= 0) {
54 54 logger.warn("未启用Assist服务");
55 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 19 import org.slf4j.LoggerFactory;
20 20 import org.springframework.beans.factory.annotation.Autowired;
21 21 import org.springframework.beans.factory.annotation.Qualifier;
22   -import org.springframework.http.HttpStatus;
23   -import org.springframework.http.ResponseEntity;
24 22 import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
25 23 import org.springframework.util.ObjectUtils;
26 24 import org.springframework.web.bind.annotation.PostMapping;
... ... @@ -544,6 +542,8 @@ public class ZLMHttpHookListener {
544 542 for (SendRtpItem sendRtpItem : sendRtpItems) {
545 543 ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(sendRtpItem.getPlatformId());
546 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 573 return ret;
574 574 }else {
575 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 590 return ret;
585 591 }
... ... @@ -626,7 +632,7 @@ public class ZLMHttpHookListener {
626 632 @ResponseBody
627 633 @PostMapping(value = "/on_server_started", produces = "application/json;charset=UTF-8")
628 634 public JSONObject onServerStarted(HttpServletRequest request, @RequestBody JSONObject jsonObject){
629   -
  635 +
630 636 if (logger.isDebugEnabled()) {
631 637 logger.debug("[ ZLM HOOK ]on_server_started API调用,参数:" + jsonObject.toString());
632 638 }
... ... @@ -649,6 +655,39 @@ public class ZLMHttpHookListener {
649 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 691 private Map<String, String> urlParamToMap(String params) {
653 692 HashMap<String, String> map = new HashMap<>();
654 693 if (ObjectUtils.isEmpty(params)) {
... ...
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRTPServerFactory.java
... ... @@ -96,6 +96,10 @@ public class ZLMRTPServerFactory {
96 96 if(rtpInfo.getInteger("code") == 0){
97 97 if (rtpInfo.getBoolean("exist")) {
98 98 result = rtpInfo.getInteger("local_port");
  99 + if (result == 0) {
  100 + // 此时说明rtpServer已经创建但是流还没有推上来
  101 +
  102 + }
99 103 return result;
100 104 }
101 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 37 private boolean enable_mp4;
38 38 @Schema(description = "是否 无人观看时删除")
39 39 private boolean enable_remove_none_reader;
  40 +
  41 + @Schema(description = "是否 无人观看时不启用")
  42 + private boolean enable_disable_none_reader;
40 43 @Schema(description = "上级平台国标ID")
41 44 private String platformGbId;
42 45 @Schema(description = "创建时间")
... ... @@ -177,4 +180,11 @@ public class StreamProxyItem extends GbStream {
177 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 82 MediaServerItem getDefaultMediaServer();
83 83  
84 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 152 if (streamId == null) {
153 153 streamId = String.format("%08x", Integer.parseInt(ssrc)).toUpperCase();
154 154 }
155   - int rtpServerPort = mediaServerItem.getRtpProxyPort();
  155 + int rtpServerPort;
156 156 if (mediaServerItem.isRtpEnable()) {
157 157 rtpServerPort = zlmrtpServerFactory.createRTPServer(mediaServerItem, streamId, ssrcCheck?Integer.parseInt(ssrc):0, port);
  158 + } else {
  159 + rtpServerPort = mediaServerItem.getRtpProxyPort();
158 160 }
159 161 RedisUtil.set(key, mediaServerItem);
160 162 return new SSRCInfo(rtpServerPort, ssrc, streamId);
... ... @@ -537,6 +539,7 @@ public class MediaServerServiceImpl implements IMediaServerService {
537 539 param.put("hook.on_stream_none_reader",String.format("%s/on_stream_none_reader", hookPrex));
538 540 param.put("hook.on_stream_not_found",String.format("%s/on_stream_not_found", hookPrex));
539 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 543 if (mediaServerItem.getRecordAssistPort() > 0) {
541 544 param.put("hook.on_record_mp4",String.format("http://127.0.0.1:%s/api/record/on_record_mp4", mediaServerItem.getRecordAssistPort()));
542 545 }else {
... ... @@ -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 73 }else {
74 74 streamInfo = getStreamInfoByAppAndStream(mediaInfo, app, stream, tracks, addr,null, true);
75 75 }
76   -
77 76 }
78 77 }
79 78 return streamInfo;
... ...
src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
... ... @@ -193,17 +193,30 @@ public class PlayServiceImpl implements IPlayService {
193 193 JSONObject rtpInfo = zlmresTfulUtils.getRtpInfo(mediaInfo, streamId);
194 194 if(rtpInfo.getInteger("code") == 0){
195 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 220 }else {
208 221 redisCatchStorage.stopPlay(streamInfo);
209 222 storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId());
... ... @@ -318,7 +331,7 @@ public class PlayServiceImpl implements IPlayService {
318 331 }
319 332 logger.info("[点播消息] 收到invite 200, 发现下级自定义了ssrc: {}", ssrcInResponse );
320 333 if (!mediaServerItem.isRtpEnable() || device.isSsrcCheck()) {
321   - logger.info("[SIP 消息] SSRC修正 {}->{}", ssrc, ssrcInResponse);
  334 + logger.info("[点播消息] SSRC修正 {}->{}", ssrc, ssrcInResponse);
322 335  
323 336 if (!mediaServerItem.getSsrcConfig().checkSsrc(ssrcInResponse)) {
324 337 // ssrc 不可用
... ... @@ -468,37 +481,92 @@ public class PlayServiceImpl implements IPlayService {
468 481 resultHolder.exist(DeferredResultHolder.CALLBACK_CMD_PLAYBACK + deviceId + channelId, uuid);
469 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 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 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 53 boolean contains = allAppAndStream.contains(app + stream);
54 54 //不存在就添加
55 55 if (!contains) {
56   - streamPushItem.setStatus(false);
57 56 streamPushItem.setStreamType("push");
58 57 streamPushItem.setCreateTime(DateUtil.getNow());
59 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 116 streamPushItem.setApp(streamPushExcelDto.getApp());
117 117 streamPushItem.setStream(streamPushExcelDto.getStream());
118 118 streamPushItem.setGbId(streamPushExcelDto.getGbId());
119   - streamPushItem.setStatus(false);
  119 + streamPushItem.setStatus(streamPushExcelDto.getStatus());
120 120 streamPushItem.setStreamType("push");
121 121 streamPushItem.setCreateTime(DateUtil.getNow());
122 122 streamPushItem.setMediaServerId(defaultMediaServerId);
... ...
src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java
... ... @@ -236,4 +236,6 @@ public interface IRedisCatchStorage {
236 236 void sendStreamPushRequestedMsgForStatus();
237 237  
238 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 143 @Update(value = {"UPDATE device_channel SET status=0 WHERE deviceId=#{deviceId}"})
144 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 146 @Insert("<script> " +
150 147 "insert into device_channel " +
151 148 "(channelId, deviceId, name, manufacture, model, owner, civilCode, block, subCount, " +
152 149 " address, parental, parentId, safetyWay, registerWay, certNum, certifiable, errCode, secrecy, " +
153 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 152 "values " +
156 153 "<foreach collection='addChannels' index='index' item='item' separator=','> " +
157 154 "('${item.channelId}', '${item.deviceId}', '${item.name}', '${item.manufacture}', '${item.model}', " +
... ... @@ -160,7 +157,7 @@ public interface DeviceChannelMapper {
160 157 "'${item.certNum}', ${item.certifiable}, ${item.errCode}, '${item.secrecy}', " +
161 158 "'${item.ipAddress}', ${item.port}, '${item.password}', ${item.PTZType}, ${item.status}, " +
162 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 161 "'${item.businessGroupId}', '${item.gpsTime}') " +
165 162 "</foreach> " +
166 163 "ON DUPLICATE KEY UPDATE " +
... ... @@ -193,11 +190,15 @@ public interface DeviceChannelMapper {
193 190 "latitudeGcj02=VALUES(latitudeGcj02), " +
194 191 "longitudeWgs84=VALUES(longitudeWgs84), " +
195 192 "latitudeWgs84=VALUES(latitudeWgs84), " +
  193 + "hasAudio=VALUES(hasAudio), " +
196 194 "businessGroupId=VALUES(businessGroupId), " +
197 195 "gpsTime=VALUES(gpsTime)" +
198 196 "</script>")
199 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 202 @Update({"<script>" +
202 203 "<foreach collection='updateChannels' item='item' separator=';'>" +
203 204 " UPDATE" +
... ... @@ -341,4 +342,7 @@ public interface DeviceChannelMapper {
341 342 " left join platform_catalog pc on pgc.catalogId = pc.id and pgc.platformId = pc.platformId" +
342 343 " where pgc.platformId=#{serverGBId}")
343 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 23  
24 24 @Insert("<script> " +
25 25 "INSERT into platform_gb_stream " +
26   - "(gbStreamId, platformId, catalogId) " +
  26 + "(gbStreamId, platformId, catalogId,status) " +
27 27 "values " +
28 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 30 "</foreach> " +
31 31 "</script>")
32 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 77 "1=1 " +
78 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 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 81 " <if test='mediaServerId != null' > AND st.mediaServerId=#{mediaServerId} </if>" +
82 82 "order by st.createTime desc" +
83 83 " </script>"})
... ...
src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java
... ... @@ -388,6 +388,24 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
388 388 }
389 389  
390 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 409 public List<SendRtpItem> querySendRTPServer(String platformGbId) {
392 410 if (platformGbId == null) {
393 411 platformGbId = "*";
... ...
src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStorageImpl.java
... ... @@ -111,11 +111,11 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage {
111 111 if (CollectionUtils.isEmpty(deviceChannelList)) {
112 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 121 TransactionStatus transactionStatus = dataSourceTransactionManager.getTransaction(transactionDefinition);
... ... @@ -123,15 +123,17 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage {
123 123 List<DeviceChannel> channels = new ArrayList<>();
124 124 StringBuilder stringBuilder = new StringBuilder();
125 125 Map<String, Integer> subContMap = new HashMap<>();
126   - if (deviceChannelList.size() > 1) {
  126 + if (deviceChannelList.size() > 0) {
127 127 // 数据去重
128 128 Set<String> gbIdSet = new HashSet<>();
129 129 for (DeviceChannel deviceChannel : deviceChannelList) {
130 130 if (!gbIdSet.contains(deviceChannel.getChannelId())) {
131 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 137 channels.add(deviceChannel);
136 138 if (!ObjectUtils.isEmpty(deviceChannel.getParentId())) {
137 139 if (subContMap.get(deviceChannel.getParentId()) == null) {
... ... @@ -153,8 +155,6 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage {
153 155 }
154 156 }
155 157  
156   - }else {
157   - channels = deviceChannelList;
158 158 }
159 159 if (stringBuilder.length() > 0) {
160 160 logger.info("[目录查询]收到的数据存在重复: {}" , stringBuilder);
... ...
src/main/java/com/genersoft/iot/vmp/vmanager/bean/StreamPushExcelDto.java
... ... @@ -22,6 +22,9 @@ public class StreamPushExcelDto {
22 22 @ExcelProperty("目录ID")
23 23 private String catalogId;
24 24  
  25 + @ExcelProperty("在线状态")
  26 + private boolean status;
  27 +
25 28 public String getName() {
26 29 return name;
27 30 }
... ... @@ -70,4 +73,16 @@ public class StreamPushExcelDto {
70 73 public void setCatalogId(String catalogId) {
71 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 43 private IRoleService roleService;
44 44  
45 45 @GetMapping("/login")
  46 + @PostMapping("/login")
46 47 @Operation(summary = "登录")
47 48 @Parameter(name = "username", description = "用户名", required = true)
48 49 @Parameter(name = "password", description = "密码(32位md5加密)", required = true)
... ...
src/main/resources/logback-spring-local.xml
... ... @@ -98,6 +98,11 @@
98 98 <appender-ref ref="STDOUT" />
99 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 106 <logger name="GB28181_SIP" level="debug" additivity="true">
102 107 <appender-ref ref="RollingFileError"/>
103 108 <appender-ref ref="sipRollingFile"/>
... ...
web_src/src/components/ParentPlatformList.vue
... ... @@ -143,7 +143,8 @@ export default {
143 143 });
144 144 },
145 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 149 initData: function() {
149 150 this.getPlatformList();
... ...
web_src/src/components/dialog/chooseChannel.vue
... ... @@ -8,7 +8,7 @@
8 8 <el-tab-pane label="目录结构" name="catalog">
9 9 <el-container>
10 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 12 </el-main>
13 13 </el-container>
14 14 </el-tab-pane>
... ... @@ -60,6 +60,7 @@ export default {
60 60 tabActiveName: "gbChannel",
61 61 catalogTabActiveName: "catalog",
62 62 platformId: "",
  63 + platformDeviceId: "",
63 64 catalogId: "",
64 65 catalogName: "",
65 66 currentCatalogId: "",
... ... @@ -73,8 +74,10 @@ export default {
73 74 };
74 75 },
75 76 methods: {
76   - openDialog(platformId, platformName, defaultCatalogId, treeType, closeCallback) {
  77 + openDialog(platformId, platformDeviceId, platformName, defaultCatalogId, treeType, closeCallback) {
  78 + console.log("defaultCatalogId: " + defaultCatalogId)
77 79 this.platformId = platformId
  80 + this.platformDeviceId = platformDeviceId
78 81 this.platformName = platformName
79 82 this.defaultCatalogId = defaultCatalogId
80 83 this.showDialog = true
... ...
web_src/src/components/dialog/chooseChannelForCatalog.vue
... ... @@ -38,7 +38,7 @@
38 38 import catalogEdit from './catalogEdit.vue'
39 39 export default {
40 40 name: 'chooseChannelForCatalog',
41   - props: ['platformId', 'platformName', 'defaultCatalogId', 'catalogIdChange', 'treeType'],
  41 + props: ['platformId', 'platformDeviceId', 'platformName', 'defaultCatalogId', 'catalogIdChange', 'treeType'],
42 42 created() {
43 43 this.chooseId = this.defaultCatalogId;
44 44 this.defaultCatalogIdSign = this.defaultCatalogId;
... ... @@ -171,6 +171,7 @@ export default {
171 171 });
172 172 },
173 173 loadNode: function(node, resolve){
  174 + console.log("this.platformDeviceId: " + this.platformDeviceId)
174 175 if (node.level === 0) {
175 176 resolve([
176 177 {
... ... @@ -179,7 +180,7 @@ export default {
179 180 type: -1
180 181 },{
181 182 name: this.platformName,
182   - id: this.platformId,
  183 + id: this.platformDeviceId,
183 184 type: 0
184 185 }
185 186 ]);
... ... @@ -298,6 +299,8 @@ export default {
298 299 return false;
299 300 },
300 301 nodeClickHandler: function (data, node, tree){
  302 + console.log(data)
  303 + console.log(node)
301 304 this.chooseId = data.id;
302 305 this.chooseName = data.name;
303 306 if (this.catalogIdChange)this.catalogIdChange(this.chooseId, this.chooseName);
... ...
web_src/src/components/dialog/getCatalog.vue
... ... @@ -77,6 +77,7 @@ export default {
77 77 },
78 78 methods: {
79 79 openDialog(catalogIdResult) {
  80 + console.log(this.chooseId)
80 81 this.showDialog = true
81 82 this.catalogIdResult = catalogIdResult
82 83 },
... ... @@ -107,9 +108,6 @@ export default {
107 108  
108 109 },
109 110 loadNode: function(node, resolve){
110   -
111   -
112   -
113 111 if (node.level === 0) {
114 112 this.$axios({
115 113 method:"get",
... ... @@ -124,7 +122,7 @@ export default {
124 122 resolve([
125 123 {
126 124 name: this.platformName,
127   - id: this.platformId,
  125 + id: res.data.data.deviceGBId,
128 126 type: 0
129 127 }
130 128 ]);
... ... @@ -142,9 +140,19 @@ export default {
142 140 this.chooseId = data.id;
143 141 },
144 142 close: function() {
  143 + this.chooseId = null;
145 144 this.showDialog = false;
146 145 },
147 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 156 if (this.catalogIdResult)this.catalogIdResult(this.chooseId)
149 157 this.showDialog = false;
150 158 },
... ...
web_src/src/components/dialog/platformEdit.vue
... ... @@ -37,13 +37,13 @@
37 37 <el-form-item label="本地端口" prop="devicePort">
38 38 <el-input v-model="platform.devicePort" :disabled="true" type="number"></el-input>
39 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 43 </el-form>
41 44 </el-col>
42 45 <el-col :span="12">
43 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 47 <el-form-item label="行政区划" prop="administrativeDivision">
48 48 <el-input v-model="platform.administrativeDivision" clearable></el-input>
49 49 </el-form-item>
... ... @@ -79,7 +79,7 @@
79 79 </el-select>
80 80 </el-form-item>
81 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 83 <el-option key="WGS84" label="行政区划" value="CivilCode"></el-option>
84 84 <el-option key="GCJ02" label="业务分组" value="BusinessGroup"></el-option>
85 85 </el-select>
... ... @@ -98,6 +98,7 @@
98 98 <el-checkbox label="启用" v-model="platform.enable" @change="checkExpires"></el-checkbox>
99 99 <el-checkbox label="云台控制" v-model="platform.ptz"></el-checkbox>
100 100 <el-checkbox label="拉起离线推流" v-model="platform.startOfflinePush"></el-checkbox>
  101 + <el-checkbox label="RTCP保活" v-model="platform.rtcp" @change="rtcpCheckBoxChange"></el-checkbox>
101 102 </el-form-item>
102 103 <el-form-item>
103 104 <el-button type="primary" @click="onSubmit">{{
... ... @@ -251,21 +252,7 @@ export default {
251 252  
252 253 },
253 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 257 saveForm: function (){
271 258 this.$axios({
... ... @@ -343,6 +330,22 @@ export default {
343 330 if (this.platform.enable && this.platform.expires == "0") {
344 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