From 720231d33f387c6d1bf13bdef653314c5c450809 Mon Sep 17 00:00:00 2001 From: 648540858 <18010473990@163.com> Date: 星期六, 25 九月 2021 22:12:15 +0800 Subject: [PATCH] 添加发送媒体流, 添加媒体服务器节点管理ui,修复修改密码 --- web_src/src/components/service/MediaServer.js | 55 +++ src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRTPServerFactory.java | 26 + src/main/java/com/genersoft/iot/vmp/media/zlm/dto/MediaServerItem.java | 29 + web_src/src/components/CloudRecord.vue | 2 web_src/src/components/dialog/MediaServerEdit.vue | 368 +++++++++++++++++++++++ web_src/static/images/zlm-logo.png | 0 web_src/src/components/dialog/deviceEdit.vue | 2 src/main/java/com/genersoft/iot/vmp/conf/MediaConfig.java | 13 sql/mysql.sql | 1 web_src/src/components/MediaServerManger.vue | 159 +++++++++ src/main/java/com/genersoft/iot/vmp/service/impl/MediaServerServiceImpl.java | 166 ++++++++- src/main/resources/application-dev.yml | 2 web_src/src/components/UiHeader.vue | 1 web_src/src/components/dialog/StreamProxyEdit.vue | 2 web_src/src/components/DeviceList.vue | 2 src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRunner.java | 6 web_src/src/components/dialog/changePassword.vue | 2 src/main/java/com/genersoft/iot/vmp/conf/ApiAccessFilter.java | 3 web_src/static/css/iconfont.css | 10 src/main/resources/wvp.sqlite | 0 web_src/build/webpack.base.conf.js | 1 src/main/java/com/genersoft/iot/vmp/service/IMediaServerService.java | 7 src/main/resources/all-application.yml | 2 src/main/java/com/genersoft/iot/vmp/vmanager/server/ServerController.java | 60 +++ web_src/src/assets/zlm-log.png | 0 web_src/static/css/iconfont.woff2 | 0 src/main/java/com/genersoft/iot/vmp/storager/dao/MediaServerMapper.java | 3 web_src/src/components/control.vue | 2 web_src/src/router/index.js | 6 src/main/java/com/genersoft/iot/vmp/conf/ProxyServletConfig.java | 7 30 files changed, 890 insertions(+), 47 deletions(-) diff --git a/sql/mysql.sql b/sql/mysql.sql index 90393e6..6f44ce8 100644 --- a/sql/mysql.sql +++ b/sql/mysql.sql @@ -140,6 +140,7 @@ streamNoneReaderDelayMS int not null, rtpEnable int not null, rtpPortRange varchar(50) not null, + sendRtpPortRange varchar(50) not null, recordAssistPort int not null, defaultServer int not null, createTime varchar(50) not null, diff --git a/src/main/java/com/genersoft/iot/vmp/conf/ApiAccessFilter.java b/src/main/java/com/genersoft/iot/vmp/conf/ApiAccessFilter.java index 9831ddb..08d030a 100644 --- a/src/main/java/com/genersoft/iot/vmp/conf/ApiAccessFilter.java +++ b/src/main/java/com/genersoft/iot/vmp/conf/ApiAccessFilter.java @@ -18,6 +18,9 @@ import java.io.IOException; import java.text.SimpleDateFormat; +/** + * @author lin + */ @WebFilter(filterName = "ApiAccessFilter", urlPatterns = "/api/*", asyncSupported=true) public class ApiAccessFilter extends OncePerRequestFilter { diff --git a/src/main/java/com/genersoft/iot/vmp/conf/MediaConfig.java b/src/main/java/com/genersoft/iot/vmp/conf/MediaConfig.java index 72cefe1..e608361 100644 --- a/src/main/java/com/genersoft/iot/vmp/conf/MediaConfig.java +++ b/src/main/java/com/genersoft/iot/vmp/conf/MediaConfig.java @@ -68,6 +68,10 @@ @Value("${media.rtp.port-range}") private String rtpPortRange; + + @Value("${media.rtp.send-port-range}") + private String sendRtpPortRange; + @Value("${media.record-assist-port:0}") private Integer recordAssistPort = 0; @@ -165,6 +169,14 @@ } } + public String getSipDomain() { + return sipDomain; + } + + public String getSendRtpPortRange() { + return sendRtpPortRange; + } + public MediaServerItem getMediaSerItem(){ MediaServerItem mediaServerItem = new MediaServerItem(); mediaServerItem.setId(id); @@ -185,6 +197,7 @@ mediaServerItem.setStreamNoneReaderDelayMS(streamNoneReaderDelayMS); mediaServerItem.setRtpEnable(rtpEnable); mediaServerItem.setRtpPortRange(rtpPortRange); + mediaServerItem.setSendRtpPortRange(sendRtpPortRange); mediaServerItem.setRecordAssistPort(recordAssistPort); SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); diff --git a/src/main/java/com/genersoft/iot/vmp/conf/ProxyServletConfig.java b/src/main/java/com/genersoft/iot/vmp/conf/ProxyServletConfig.java index 907e30d..5d8acce 100644 --- a/src/main/java/com/genersoft/iot/vmp/conf/ProxyServletConfig.java +++ b/src/main/java/com/genersoft/iot/vmp/conf/ProxyServletConfig.java @@ -21,6 +21,9 @@ import java.io.IOException; import java.net.ConnectException; +/** + * @author lin + */ @SuppressWarnings(value = {"rawtypes", "unchecked"}) @Configuration public class ProxyServletConfig { @@ -35,7 +38,7 @@ @Bean public ServletRegistrationBean zlmServletRegistrationBean(){ - ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(new ZLMProxySerlet(),"/zlm/*"); + ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(new ZlmProxyServlet(),"/zlm/*"); servletRegistrationBean.setName("zlm_Proxy"); servletRegistrationBean.addInitParameter("targetUri", "http://127.0.0.1:6080"); servletRegistrationBean.addUrlMappings(); @@ -45,7 +48,7 @@ return servletRegistrationBean; } - class ZLMProxySerlet extends ProxyServlet{ + class ZlmProxyServlet extends ProxyServlet{ @Override protected String rewriteQueryStringFromRequest(HttpServletRequest servletRequest, String queryString) { String queryStr = super.rewriteQueryStringFromRequest(servletRequest, queryString); diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRTPServerFactory.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRTPServerFactory.java index bd56401..b4d1048 100644 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRTPServerFactory.java +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRTPServerFactory.java @@ -8,6 +8,7 @@ import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import org.springframework.util.StringUtils; import java.util.HashMap; import java.util.Map; @@ -44,8 +45,15 @@ Map<String, Object> param = new HashMap<>(); int result = -1; - int newPort = getPortFromportRange(mediaServerItem); - param.put("port", newPort); + /** + * 涓嶈缃帹娴佺鍙g鍒欎娇鐢ㄩ殢鏈虹鍙� + */ + if (StringUtils.isEmpty(mediaServerItem.getSendRtpPortRange())){ + param.put("port", 0); + }else { + int newPort = getPortFromportRange(mediaServerItem); + param.put("port", newPort); + } param.put("enable_tcp", 1); param.put("stream_id", streamId); JSONObject openRtpServerResultJson = zlmresTfulUtils.openRtpServer(mediaServerItem, param); @@ -53,24 +61,24 @@ if (openRtpServerResultJson != null) { switch (openRtpServerResultJson.getInteger("code")){ case 0: - result= newPort; + result= openRtpServerResultJson.getInteger("port"); break; case -300: // id宸茬粡瀛樺湪, 鍙兘宸茬粡鍦ㄥ叾浠栫鍙f帹娴� Map<String, Object> closeRtpServerParam = new HashMap<>(); closeRtpServerParam.put("stream_id", streamId); zlmresTfulUtils.closeRtpServer(mediaServerItem, closeRtpServerParam); - result = newPort; + result = createRTPServer(mediaServerItem, streamId);; break; case -400: // 绔彛鍗犵敤 result= createRTPServer(mediaServerItem, streamId); break; default: - logger.error("鍒涘缓RTP Server 澶辫触 {}: " + openRtpServerResultJson.getString("msg"), newPort); + logger.error("鍒涘缓RTP Server 澶辫触 {}: " + openRtpServerResultJson.getString("msg"), param.get("port")); break; } }else { // 妫�鏌LM鐘舵�� - logger.error("鍒涘缓RTP Server 澶辫触 {}: 璇锋鏌LM鏈嶅姟", newPort); + logger.error("鍒涘缓RTP Server 澶辫触 {}: 璇锋鏌LM鏈嶅姟", param.get("port")); } return result; } @@ -98,7 +106,7 @@ private int getPortFromportRange(MediaServerItem mediaServerItem) { int currentPort = mediaServerItem.getCurrentPort(); if (currentPort == 0) { - String[] portRangeStrArray = mediaServerItem.getRtpPortRange().split(","); + String[] portRangeStrArray = mediaServerItem.getSendRtpPortRange().split(","); portRangeArray[0] = Integer.parseInt(portRangeStrArray[0]); portRangeArray[1] = Integer.parseInt(portRangeStrArray[1]); } @@ -229,7 +237,9 @@ */ public int totalReaderCount(MediaServerItem mediaServerItem, String app, String streamId) { JSONObject mediaInfo = zlmresTfulUtils.getMediaInfo(mediaServerItem, app, "rtmp", streamId); - if (mediaInfo == null) return 0; + if (mediaInfo == null) { + return 0; + } return mediaInfo.getInteger("totalReaderCount"); } diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRunner.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRunner.java index 187cbc1..7faebfa 100644 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRunner.java +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRunner.java @@ -108,8 +108,10 @@ } public ZLMServerConfig getMediaServerConfig(MediaServerItem mediaServerItem) { - if (startGetMedia == null) return null; - if ( startGetMedia.get(mediaServerItem.getId()) == null || !startGetMedia.get(mediaServerItem.getId())) return null; + if (startGetMedia == null) { return null;} + if ( startGetMedia.get(mediaServerItem.getId()) == null || !startGetMedia.get(mediaServerItem.getId())) { + return null; + } JSONObject responseJSON = zlmresTfulUtils.getMediaServerConfig(mediaServerItem); ZLMServerConfig ZLMServerConfig = null; if (responseJSON != null) { diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/MediaServerItem.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/MediaServerItem.java index d1578d1..087c10a 100644 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/MediaServerItem.java +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/MediaServerItem.java @@ -41,13 +41,19 @@ private boolean rtpEnable; + private boolean status; + private String rtpPortRange; + + private String sendRtpPortRange; private int recordAssistPort; private String createTime; private String updateTime; + + private String lastKeepaliveTime; private boolean defaultServer; @@ -82,6 +88,7 @@ secret = zlmServerConfig.getApiSecret(); streamNoneReaderDelayMS = zlmServerConfig.getGeneralStreamNoneReaderDelayMS(); rtpEnable = false; // 榛樿浣跨敤鍗曠鍙�;鐩村埌鐢ㄦ埛鑷繁璁剧疆寮�鍚绔彛 + rtpPortRange = "30000,30500"; // 榛樿浣跨敤30000,30500浣滀负绾ц仈鏃跺彂閫佹祦鐨勭鍙e彿 recordAssistPort = 0; // 榛樿鍏抽棴 } @@ -278,5 +285,27 @@ this.currentPort = currentPort; } + public boolean isStatus() { + return status; + } + public void setStatus(boolean status) { + this.status = status; + } + + public String getLastKeepaliveTime() { + return lastKeepaliveTime; + } + + public void setLastKeepaliveTime(String lastKeepaliveTime) { + this.lastKeepaliveTime = lastKeepaliveTime; + } + + public String getSendRtpPortRange() { + return sendRtpPortRange; + } + + public void setSendRtpPortRange(String sendRtpPortRange) { + this.sendRtpPortRange = sendRtpPortRange; + } } diff --git a/src/main/java/com/genersoft/iot/vmp/service/IMediaServerService.java b/src/main/java/com/genersoft/iot/vmp/service/IMediaServerService.java index f65a155..81cf8f1 100644 --- a/src/main/java/com/genersoft/iot/vmp/service/IMediaServerService.java +++ b/src/main/java/com/genersoft/iot/vmp/service/IMediaServerService.java @@ -4,6 +4,7 @@ import com.genersoft.iot.vmp.media.zlm.ZLMServerConfig; import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; import com.genersoft.iot.vmp.service.bean.SSRCInfo; +import com.genersoft.iot.vmp.vmanager.bean.WVPResult; import java.util.List; @@ -49,7 +50,11 @@ void clearMediaServerForOnline(); - void add(MediaServerItem mediaSerItem); + WVPResult<String> add(MediaServerItem mediaSerItem); void resetOnlineServerItem(MediaServerItem serverItem); + + WVPResult<MediaServerItem> checkMediaServer(String ip, int port, String secret); + + boolean checkMediaRecordServer(String ip, int port); } diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/MediaServerServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/MediaServerServiceImpl.java index 33c0051..18c1b93 100644 --- a/src/main/java/com/genersoft/iot/vmp/service/impl/MediaServerServiceImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/service/impl/MediaServerServiceImpl.java @@ -1,5 +1,6 @@ package com.genersoft.iot.vmp.service.impl; +import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.genersoft.iot.vmp.common.VideoManagerConstants; @@ -14,10 +15,11 @@ import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; import com.genersoft.iot.vmp.service.IMediaServerService; import com.genersoft.iot.vmp.service.bean.SSRCInfo; -import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.storager.dao.MediaServerMapper; import com.genersoft.iot.vmp.utils.redis.JedisUtil; import com.genersoft.iot.vmp.utils.redis.RedisUtil; +import com.genersoft.iot.vmp.vmanager.bean.WVPResult; +import okhttp3.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -57,9 +59,6 @@ private MediaServerMapper mediaServerMapper; @Autowired - private IRedisCatchStorage redisCatchStorage; - - @Autowired private VideoStreamSessionManager streamSession; @Autowired @@ -97,7 +96,9 @@ @Override public SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId) { - if (mediaServerItem == null || mediaServerItem.getId() == null) return null; + if (mediaServerItem == null || mediaServerItem.getId() == null) { + return null; + } // 鑾峰彇mediaServer鍙敤鐨剆src String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + mediaServerItem.getId(); @@ -107,7 +108,9 @@ return null; }else { String ssrc = ssrcConfig.getPlaySsrc(); - if (streamId == null) streamId = String.format("%08x", Integer.parseInt(ssrc)).toUpperCase(); + if (streamId == null) { + streamId = String.format("%08x", Integer.parseInt(ssrc)).toUpperCase(); + } int rtpServerPort = mediaServerItem.getRtpProxyPort(); if (mediaServerItem.isRtpEnable()) { rtpServerPort = zlmrtpServerFactory.createRTPServer(mediaServerItem, streamId); @@ -131,7 +134,9 @@ @Override public void releaseSsrc(MediaServerItem mediaServerItem, String ssrc) { - if (mediaServerItem == null || ssrc == null) return; + if (mediaServerItem == null || ssrc == null) { + return; + } SsrcConfig ssrcConfig = mediaServerItem.getSsrcConfig(); ssrcConfig.releaseSsrc(ssrc); mediaServerItem.setSsrcConfig(ssrcConfig); @@ -141,7 +146,6 @@ /** * zlm 閲嶅惎鍚庨噸缃粬鐨勬帹娴佷俊鎭紝 TODO 缁欐鍦ㄤ娇鐢ㄧ殑璁惧鍙戦�佸仠姝㈠懡浠� - * @param mediaServerItem */ @Override public void clearRTPServer(MediaServerItem mediaServerItem) { @@ -174,9 +178,15 @@ public List<MediaServerItem> getAll() { List<MediaServerItem> result = new ArrayList<>(); List<Object> mediaServerKeys = redisUtil.scan(String.format("%S*", VideoManagerConstants.MEDIA_SERVER_PREFIX)); - for (int i = 0; i < mediaServerKeys.size(); i++) { - String key = (String) mediaServerKeys.get(i); - result.add((MediaServerItem)redisUtil.get(key)); + String onlineKey = VideoManagerConstants.MEDIA_SERVERS_ONLINE_PREFIX; + for (Object mediaServerKey : mediaServerKeys) { + String key = (String) mediaServerKey; + MediaServerItem mediaServerItem = (MediaServerItem) redisUtil.get(key); + // 妫�鏌ョ姸鎬� + if (redisUtil.zScore(onlineKey, mediaServerItem.getId()) != null) { + mediaServerItem.setStatus(true); + } + result.add(mediaServerItem); } return result; } @@ -208,7 +218,9 @@ */ @Override public MediaServerItem getOne(String mediaServerId) { - if (mediaServerId == null) return null; + if (mediaServerId == null) { + return null; + } String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + mediaServerId; return (MediaServerItem)redisUtil.get(key); } @@ -225,8 +237,34 @@ } @Override - public void add(MediaServerItem mediaSerItem) { - mediaServerMapper.add(mediaSerItem); + public WVPResult<String> add(MediaServerItem mediaServerItem) { + WVPResult<String> result = new WVPResult<>(); + mediaServerItem.setCreateTime(this.format.format(System.currentTimeMillis())); + mediaServerItem.setUpdateTime(this.format.format(System.currentTimeMillis())); + JSONObject responseJSON = zlmresTfulUtils.getMediaServerConfig(mediaServerItem); + if (responseJSON != null) { + JSONArray data = responseJSON.getJSONArray("data"); + if (data != null && data.size() > 0) { + ZLMServerConfig zlmServerConfig= JSON.parseObject(JSON.toJSONString(data.get(0)), ZLMServerConfig.class); + if (mediaServerMapper.queryOne(zlmServerConfig.getGeneralMediaServerId()) != null) { + result.setCode(-1); + result.setMsg("淇濆瓨澶辫触锛屽獟浣撴湇鍔D [ " + zlmServerConfig.getGeneralMediaServerId() + " ] 宸插瓨鍦紝璇蜂慨鏀瑰獟浣撴湇鍔″櫒閰嶇疆"); + return result; + } + zlmServerConfig.setIp(mediaServerItem.getIp()); + handLeZLMServerConfig(zlmServerConfig); + result.setCode(0); + result.setMsg("success"); + }else { + result.setCode(-1); + result.setMsg("杩炴帴澶辫触"); + } + + }else { + result.setCode(-1); + result.setMsg("杩炴帴澶辫触"); + } + return result; } /** @@ -249,13 +287,27 @@ // docker閮ㄧ讲涓嶄細浣跨敤zlm閰嶇疆鐨勭鍙e彿涓嶆槸榛樿鐨勫垯涓嶅仛鏇存柊锛� 閰嶇疆淇敼闇�瑕佽嚜琛屼慨鏀箂erver閰嶇疆; MediaServerItem serverItemFromConfig = mediaConfig.getMediaSerItem(); serverItemFromConfig.setId(zlmServerConfig.getGeneralMediaServerId()); - if (mediaConfig.getHttpPort() == 0) serverItemFromConfig.setHttpPort(zlmServerConfig.getHttpPort()); - if (mediaConfig.getHttpSSlPort() == 0) serverItemFromConfig.setHttpSSlPort(zlmServerConfig.getHttpSSLport()); - if (mediaConfig.getRtmpPort() == 0) serverItemFromConfig.setRtmpPort(zlmServerConfig.getRtmpPort()); - if (mediaConfig.getRtmpSSlPort() == 0) serverItemFromConfig.setRtmpSSlPort(zlmServerConfig.getRtmpSslPort()); - if (mediaConfig.getRtspPort() == 0) serverItemFromConfig.setRtspPort(zlmServerConfig.getRtspPort()); - if (mediaConfig.getRtspSSLPort() == 0) serverItemFromConfig.setRtspSSLPort(zlmServerConfig.getRtspSSlport()); - if (mediaConfig.getRtpProxyPort() == 0) serverItemFromConfig.setRtpProxyPort(zlmServerConfig.getRtpProxyPort()); + if (mediaConfig.getHttpPort() == 0) { + serverItemFromConfig.setHttpPort(zlmServerConfig.getHttpPort()); + } + if (mediaConfig.getHttpSSlPort() == 0) { + serverItemFromConfig.setHttpSSlPort(zlmServerConfig.getHttpSSLport()); + } + if (mediaConfig.getRtmpPort() == 0) { + serverItemFromConfig.setRtmpPort(zlmServerConfig.getRtmpPort()); + } + if (mediaConfig.getRtmpSSlPort() == 0) { + serverItemFromConfig.setRtmpSSlPort(zlmServerConfig.getRtmpSslPort()); + } + if (mediaConfig.getRtspPort() == 0) { + serverItemFromConfig.setRtspPort(zlmServerConfig.getRtspPort()); + } + if (mediaConfig.getRtspSSLPort() == 0) { + serverItemFromConfig.setRtspSSLPort(zlmServerConfig.getRtspSSlport()); + } + if (mediaConfig.getRtpProxyPort() == 0) { + serverItemFromConfig.setRtpProxyPort(zlmServerConfig.getRtpProxyPort()); + } if (serverItem != null){ mediaServerMapper.delDefault(); mediaServerMapper.add(serverItemFromConfig); @@ -319,9 +371,10 @@ @Override public void addCount(String mediaServerId) { - if (mediaServerId == null) return; + if (mediaServerId == null) { + return; + } String key = VideoManagerConstants.MEDIA_SERVERS_ONLINE_PREFIX; - Double aDouble = redisUtil.zScore(key, mediaServerId); redisUtil.zIncrScore(key, mediaServerId, 1); } @@ -399,4 +452,71 @@ } + @Override + public WVPResult<MediaServerItem> checkMediaServer(String ip, int port, String secret) { + WVPResult<MediaServerItem> result = new WVPResult<>(); + if (mediaServerMapper.queryOneByHostAndPort(ip, port) != null) { + result.setCode(-1); + result.setMsg("姝よ繛鎺ュ凡瀛樺湪"); + return result; + } + MediaServerItem mediaServerItem = new MediaServerItem(); + mediaServerItem.setIp(ip); + mediaServerItem.setHttpPort(port); + mediaServerItem.setSecret(secret); + JSONObject responseJSON = zlmresTfulUtils.getMediaServerConfig(mediaServerItem); + if (responseJSON == null) { + result.setCode(-1); + result.setMsg("杩炴帴澶辫触"); + return result; + } + JSONArray data = responseJSON.getJSONArray("data"); + ZLMServerConfig zlmServerConfig = JSON.parseObject(JSON.toJSONString(data.get(0)), ZLMServerConfig.class); + if (zlmServerConfig == null) { + result.setCode(-1); + result.setMsg("璇诲彇閰嶇疆澶辫触"); + return result; + } + if (mediaServerMapper.queryOne(zlmServerConfig.getGeneralMediaServerId()) != null) { + result.setCode(-1); + result.setMsg("濯掍綋鏈嶅姟ID [" + zlmServerConfig.getGeneralMediaServerId() + " ] 宸插瓨鍦紝璇蜂慨鏀瑰獟浣撴湇鍔″櫒閰嶇疆"); + return result; + } + mediaServerItem.setHttpSSlPort(zlmServerConfig.getHttpPort()); + mediaServerItem.setRtmpPort(zlmServerConfig.getRtmpPort()); + mediaServerItem.setRtmpSSlPort(zlmServerConfig.getRtmpSslPort()); + mediaServerItem.setRtspPort(zlmServerConfig.getRtspPort()); + mediaServerItem.setRtspSSLPort(zlmServerConfig.getRtspSSlport()); + mediaServerItem.setRtpProxyPort(zlmServerConfig.getRtpProxyPort()); + mediaServerItem.setStreamIp(ip); + mediaServerItem.setHookIp(sipConfig.getIp()); + mediaServerItem.setSdpIp(ip); + mediaServerItem.setStreamNoneReaderDelayMS(zlmServerConfig.getGeneralStreamNoneReaderDelayMS()); + result.setCode(0); + result.setMsg("鎴愬姛"); + result.setData(mediaServerItem); + return result; + } + + @Override + public boolean checkMediaRecordServer(String ip, int port) { + boolean result = false; + OkHttpClient client = new OkHttpClient(); + String url = String.format("http://%s:%s/index/api/record", ip, port); + + FormBody.Builder builder = new FormBody.Builder(); + + Request request = new Request.Builder() + .get() + .url(url) + .build(); + try { + Response response = client.newCall(request).execute(); + if (response != null) { + result = true; + } + } catch (Exception e) {} + + return result; + } } diff --git a/src/main/java/com/genersoft/iot/vmp/storager/dao/MediaServerMapper.java b/src/main/java/com/genersoft/iot/vmp/storager/dao/MediaServerMapper.java index 2167c55..8d45b05 100644 --- a/src/main/java/com/genersoft/iot/vmp/storager/dao/MediaServerMapper.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/dao/MediaServerMapper.java @@ -32,6 +32,7 @@ "streamNoneReaderDelayMS, " + "rtpEnable, " + "rtpPortRange, " + + "sendRtpPortRange, " + "recordAssistPort, " + "defaultServer, " + "createTime, " + @@ -55,6 +56,7 @@ "${streamNoneReaderDelayMS}, " + "${rtpEnable}, " + "'${rtpPortRange}', " + + "'${sendRtpPortRange}', " + "${recordAssistPort}, " + "${defaultServer}, " + "'${createTime}', " + @@ -79,6 +81,7 @@ "<if test=\"streamNoneReaderDelayMS != null\">, streamNoneReaderDelayMS=${streamNoneReaderDelayMS}</if>" + "<if test=\"rtpEnable != null\">, rtpEnable=${rtpEnable}</if>" + "<if test=\"rtpPortRange != null\">, rtpPortRange='${rtpPortRange}'</if>" + + "<if test=\"sendRtpPortRange != null\">, sendRtpPortRange='${sendRtpPortRange}'</if>" + "<if test=\"secret != null\">, secret='${secret}'</if>" + "<if test=\"recordAssistPort != null\">, recordAssistPort=${recordAssistPort}</if>" + "WHERE id='${id}'"+ diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/server/ServerController.java b/src/main/java/com/genersoft/iot/vmp/vmanager/server/ServerController.java index 3bfa595..881a20a 100644 --- a/src/main/java/com/genersoft/iot/vmp/vmanager/server/ServerController.java +++ b/src/main/java/com/genersoft/iot/vmp/vmanager/server/ServerController.java @@ -57,7 +57,9 @@ @ApiOperation("娴佸獟浣撴湇鍔″垪琛�") @GetMapping(value = "/media_server/list") @ResponseBody - public WVPResult<List<MediaServerItem>> getMediaServerList(){ + public WVPResult<List<MediaServerItem>> getMediaServerList(boolean detail){ + List<MediaServerItem> all = mediaServerService.getAll(); + WVPResult<List<MediaServerItem>> result = new WVPResult<>(); result.setCode(0); result.setMsg("success"); @@ -86,6 +88,60 @@ result.setData(mediaServerService.getOne(id)); return result; } + + @ApiOperation("娴嬭瘯娴佸獟浣撴湇鍔�") + @ApiImplicitParams({ + @ApiImplicitParam(name="ip", value = "娴佸獟浣撴湇鍔P", dataTypeClass = String.class), + @ApiImplicitParam(name="port", value = "娴佸獟浣撴湇鍔TT绔彛", dataTypeClass = Integer.class), + @ApiImplicitParam(name="secret", value = "娴佸獟浣撴湇鍔ecret", dataTypeClass = String.class), + }) + @GetMapping(value = "/media_server/check") + @ResponseBody + public WVPResult<MediaServerItem> checkMediaServer(@RequestParam String ip, @RequestParam int port, @RequestParam String secret){ + return mediaServerService.checkMediaServer(ip, port, secret); + } + + @ApiOperation("娴嬭瘯娴佸獟浣撳綍鍍忕鐞嗘湇鍔�") + @ApiImplicitParams({ + @ApiImplicitParam(name="ip", value = "娴佸獟浣撴湇鍔P", dataTypeClass = String.class), + @ApiImplicitParam(name="port", value = "娴佸獟浣撴湇鍔TT绔彛", dataTypeClass = Integer.class), + @ApiImplicitParam(name="secret", value = "娴佸獟浣撴湇鍔ecret", dataTypeClass = String.class), + }) + @GetMapping(value = "/media_server/record/check") + @ResponseBody + public WVPResult<String> checkMediaRecordServer(@RequestParam String ip, @RequestParam int port){ + boolean checkResult = mediaServerService.checkMediaRecordServer(ip, port); + WVPResult<String> result = new WVPResult<>(); + if (checkResult) { + result.setCode(0); + result.setMsg("success"); + + }else { + result.setCode(-1); + result.setMsg("杩炴帴澶辫触"); + } + return result; + } + + @ApiOperation("淇濆瓨娴佸獟浣撴湇鍔�") + @ApiImplicitParams({ + @ApiImplicitParam(name="mediaServerItem", value = "娴佸獟浣撲俊鎭�", dataTypeClass = MediaServerItem.class) + }) + @PostMapping(value = "/media_server/save") + @ResponseBody + public WVPResult<String> checkMediaServer(@RequestBody MediaServerItem mediaServerItem){ + if (mediaServerService.getOne(mediaServerItem.getId()) != null) { + mediaServerService.update(mediaServerItem); + }else { + return mediaServerService.add(mediaServerItem); + } + WVPResult<String> result = new WVPResult<>(); + result.setCode(0); + result.setMsg("success"); + return result; + } + + @ApiOperation("閲嶅惎鏈嶅姟") @GetMapping(value = "/restart") @@ -155,6 +211,8 @@ case "base": jsonObject.put("base", userSetup); break; + default: + break; } } result.setData(jsonObject); diff --git a/src/main/resources/all-application.yml b/src/main/resources/all-application.yml index 856d6c5..f2d85ec 100644 --- a/src/main/resources/all-application.yml +++ b/src/main/resources/all-application.yml @@ -119,6 +119,8 @@ enable: true # [鍙�塢 鍦ㄦ鑼冨洿鍐呴�夋嫨绔彛鐢ㄤ簬濯掍綋娴佷紶杈�, port-range: 30000,30500 # 绔彛鑼冨洿 + # [鍙�塢 鍥芥爣绾ц仈鍦ㄦ鑼冨洿鍐呴�夋嫨绔彛鍙戦�佸獟浣撴祦, + send-port-range: 30000,30500 # 绔彛鑼冨洿 # 褰曞儚杈呭姪鏈嶅姟锛� 閮ㄧ讲姝ゆ湇鍔″彲浠ュ疄鐜皕lm褰曞儚鐨勭鐞嗕笌涓嬭浇锛� 0 琛ㄧず涓嶄娇鐢� record-assist-port: 0 diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml index 062f70e..44f70e6 100644 --- a/src/main/resources/application-dev.yml +++ b/src/main/resources/application-dev.yml @@ -63,6 +63,8 @@ enable: true # [鍙�塢 鍦ㄦ鑼冨洿鍐呴�夋嫨绔彛鐢ㄤ簬濯掍綋娴佷紶杈�, port-range: 30000,30500 # 绔彛鑼冨洿 + # [鍙�塢 鍥芥爣绾ц仈鍦ㄦ鑼冨洿鍐呴�夋嫨绔彛鍙戦�佸獟浣撴祦, + send-port-range: 30000,30500 # 绔彛鑼冨洿 # 褰曞儚杈呭姪鏈嶅姟锛� 閮ㄧ讲姝ゆ湇鍔″彲浠ュ疄鐜皕lm褰曞儚鐨勭鐞嗕笌涓嬭浇锛� 0 琛ㄧず涓嶄娇鐢� record-assist-port: 0 diff --git a/src/main/resources/wvp.sqlite b/src/main/resources/wvp.sqlite index b95368d..40bdad8 100644 --- a/src/main/resources/wvp.sqlite +++ b/src/main/resources/wvp.sqlite Binary files differ diff --git a/web_src/build/webpack.base.conf.js b/web_src/build/webpack.base.conf.js index a07e683..72539e3 100644 --- a/web_src/build/webpack.base.conf.js +++ b/web_src/build/webpack.base.conf.js @@ -27,6 +27,7 @@ alias: { 'vue$': 'vue/dist/vue.esm.js', '@': resolve('src'), + '@static': resolve('static'), } }, module: { diff --git a/web_src/src/assets/zlm-log.png b/web_src/src/assets/zlm-log.png new file mode 100644 index 0000000..5f492dc --- /dev/null +++ b/web_src/src/assets/zlm-log.png Binary files differ diff --git a/web_src/src/components/CloudRecord.vue b/web_src/src/components/CloudRecord.vue index e39cd5b..f5d052a 100644 --- a/web_src/src/components/CloudRecord.vue +++ b/web_src/src/components/CloudRecord.vue @@ -111,7 +111,7 @@ }, getMediaServerList: function (){ let that = this; - that.mediaServerObj.getMediaServerList((data)=>{ + that.mediaServerObj.getOnlineMediaServerList((data)=>{ that.mediaServerList = data.data; if (that.mediaServerList.length > 0) { that.mediaServerId = that.mediaServerList[0].id diff --git a/web_src/src/components/DeviceList.vue b/web_src/src/components/DeviceList.vue index 7644a96..8d97833 100644 --- a/web_src/src/components/DeviceList.vue +++ b/web_src/src/components/DeviceList.vue @@ -60,7 +60,7 @@ <el-button-group> <el-button size="mini" icon="el-icon-video-camera-solid" v-bind:disabled="scope.row.online==0" type="primary" @click="showChannelList(scope.row)">閫氶亾</el-button> <el-button size="mini" icon="el-icon-location" v-bind:disabled="scope.row.online==0" type="primary" @click="showDevicePosition(scope.row)">瀹氫綅</el-button> - <el-button size="mini" icon="el-icon-delete" type="primary" @click="edit(scope.row)">缂栬緫</el-button> + <el-button size="mini" icon="el-icon-edit" type="primary" @click="edit(scope.row)">缂栬緫</el-button> <el-button size="mini" icon="el-icon-delete" type="danger" v-if="scope.row.online==0" @click="deleteDevice(scope.row)">鍒犻櫎</el-button> </el-button-group> </template> diff --git a/web_src/src/components/MediaServerManger.vue b/web_src/src/components/MediaServerManger.vue new file mode 100644 index 0000000..19674d1 --- /dev/null +++ b/web_src/src/components/MediaServerManger.vue @@ -0,0 +1,159 @@ +<template> + <div id="mediaServerManger"> + <el-container> + <el-header> + <uiHeader></uiHeader> + </el-header> + <el-main id="msMain"> + <div style="background-color: #FFFFFF; margin-bottom: 1rem; position: relative; padding: 0.5rem; text-align: left;"> + <span style="font-size: 1rem; font-weight: bold;">鑺傜偣鍒楄〃</span> + </div> + <div style="background-color: #FFFFFF; margin-bottom: 1rem; position: relative; padding: 0.5rem; text-align: left;font-size: 14px;"> + <el-button icon="el-icon-plus" size="mini" style="margin-right: 1rem;" type="primary" @click="add">娣诲姞鑺傜偣</el-button> + </div> + + <el-row :gutter="12"> + <el-col :span="num" v-for="item in mediaServerList" :key="item.id"> + <el-card shadow="hover" :body-style="{ padding: '0px'}" class="server-card"> + <div class="card-img-zlm"></div> + <div style="padding: 14px;text-align: left"> + <span style="font-size: 16px">{{item.id}}</span> + <div style="margin-top: 13px; line-height: 12px; "> + <span style="font-size: 14px; color: #999; margin-top: 5px">鍒涘缓鏃堕棿锛� {{item.createTime}}</span> + <el-button icon="el-icon-edit" style="padding: 0;float: right;" type="text" @click="edit(item)">缂栬緫</el-button> + </div> + </div> + <i v-if="item.status" class="iconfont icon-online server-card-status-online" title="鍦ㄧ嚎"></i> + <i v-if="!item.status" class="iconfont icon-online server-card-status-offline" title="绂荤嚎"></i> + </el-card> + </el-col> + </el-row> + <mediaServerEdit ref="mediaServerEdit" ></mediaServerEdit> + </el-main> + </el-container> + </div> +</template> + +<script> + import uiHeader from './UiHeader.vue' + import MediaServer from './service/MediaServer' + import mediaServerEdit from './dialog/MediaServerEdit' + export default { + name: 'mediaServerManger', + components: { + uiHeader,mediaServerEdit + }, + data() { + return { + mediaServerObj : new MediaServer(), + mediaServerList: [], //璁惧鍒楄〃 + winHeight: window.innerHeight - 200, + updateLooper: false, + currentPage:1, + count:15, + num: this.getNumberByWidth(), + total:0, + }; + }, + computed: { + + }, + mounted() { + this.initData(); + this.updateLooper = setInterval(this.initData, 2000); + }, + destroyed() { + clearTimeout(this.updateLooper); + }, + methods: { + initData: function() { + this.getServerList() + }, + currentChange: function(val){ + this.currentPage = val; + this.getServerList(); + }, + handleSizeChange: function(val){ + this.count = val; + this.getServerList(); + }, + getServerList: function(){ + this.mediaServerObj.getMediaServerList((data)=>{ + this.mediaServerList = data.data; + }) + }, + add: function (){ + this.$refs.mediaServerEdit.openDialog(null, this.initData) + }, + edit: function (row){ + this.$refs.mediaServerEdit.openDialog(row, this.initData) + }, + getNumberByWidth(){ + let candidateNums = [1, 2, 3, 4, 6, 8, 12, 24] + let clientWidth = window.innerWidth - 30; + let interval = 20; + let itemWidth = 360; + let num = (clientWidth + interval)/(itemWidth + interval) + let result = Math.ceil(24/num); + let resultVal = 24; + for (let i = 0; i < candidateNums.length; i++) { + let value = candidateNums[i] + if (i + 1 >= candidateNums.length) { + return 24; + } + if (value <= result && candidateNums[i + 1] > result ) { + return value; + } + } + + console.log("aadada: "+ resultVal) + return resultVal; + }, + dateFormat: function(/** timestamp=0 **/) { + var ts = arguments[0] || 0; + var t,y,m,d,h,i,s; + t = ts ? new Date(ts*1000) : new Date(); + y = t.getFullYear(); + m = t.getMonth()+1; + d = t.getDate(); + h = t.getHours(); + i = t.getMinutes(); + s = t.getSeconds(); + // 鍙牴鎹渶瑕佸湪杩欓噷瀹氫箟鏃堕棿鏍煎紡 + return y+'-'+(m<10?'0'+m:m)+'-'+(d<10?'0'+d:d)+' '+(h<10?'0'+h:h)+':'+(i<10?'0'+i:i)+':'+(s<10?'0'+s:s); + } + + } + }; +</script> + +<style> + .server-card{ + position: relative; + margin-bottom: 20px; + } + .card-img-zlm{ + width: 200px; height: 200px; + background: url('~@static/images/zlm-logo.png') no-repeat center; + background-position: center; + background-size: contain; + margin: 0 auto; + } + .server-card-status-online{ + position: absolute; + right: 20px; + top: 20px; + color: #3caf36; + font-size: 18px; + } + .server-card-status-offline{ + position: absolute; + right: 20px; + top: 20px; + color: #808080; + font-size: 18px; + } + .server-card:hover { + border: 1px solid #adadad; + } +</style> diff --git a/web_src/src/components/UiHeader.vue b/web_src/src/components/UiHeader.vue index 4ab4642..b2e9bbb 100644 --- a/web_src/src/components/UiHeader.vue +++ b/web_src/src/components/UiHeader.vue @@ -6,6 +6,7 @@ <el-menu-item index="/pushVideoList">鎺ㄦ祦鍒楄〃</el-menu-item> <el-menu-item index="/streamProxyList">鎷夋祦浠g悊</el-menu-item> <el-menu-item index="/cloudRecord">浜戠褰曞儚</el-menu-item> + <el-menu-item index="/mediaServerManger">鑺傜偣绠$悊</el-menu-item> <el-menu-item index="/parentPlatformList/15/1">鍥芥爣绾ц仈</el-menu-item> <el-menu-item @click="openDoc">鍦ㄧ嚎鏂囨。</el-menu-item> <!-- <el-submenu index="/setting">--> diff --git a/web_src/src/components/control.vue b/web_src/src/components/control.vue index 6326712..a8ee8d4 100644 --- a/web_src/src/components/control.vue +++ b/web_src/src/components/control.vue @@ -139,7 +139,7 @@ this.initTable(); this.updateData(); this.chartInterval = setInterval(this.updateData, 3000); - this.mediaServer.getMediaServerList((data)=>{ + this.mediaServer.getOnlineMediaServerList((data)=>{ this.mediaServerList = data.data; if (this.mediaServerList && this.mediaServerList.length > 0) { this.mediaServerChoose = this.mediaServerList[0].id diff --git a/web_src/src/components/dialog/MediaServerEdit.vue b/web_src/src/components/dialog/MediaServerEdit.vue new file mode 100644 index 0000000..b67daf8 --- /dev/null +++ b/web_src/src/components/dialog/MediaServerEdit.vue @@ -0,0 +1,368 @@ +<template> + <div id="mediaServerEdit" v-loading="isLoging"> + <el-dialog + title="濯掍綋鑺傜偣" + :width="dialogWidth" + top="2rem" + :close-on-click-modal="false" + :visible.sync="showDialog" + :destroy-on-close="true" + @close="close()" + > + <div id="formStep" style="margin-top: 1rem; margin-right: 20px;"> + <el-form v-if="currentStep == 1" ref="mediaServerForm" :rules="rules" :model="mediaServerForm" label-width="140px" > + <el-form-item label="IP" prop="ip"> + <el-input v-model="mediaServerForm.ip" placeholder="濯掍綋鏈嶅姟IP" clearable></el-input> + </el-form-item> + <el-form-item label="HTTP绔彛" prop="port"> + <el-input v-model="mediaServerForm.httpPort" placeholder="濯掍綋鏈嶅姟HTTP绔彛" clearable></el-input> + </el-form-item> + <el-form-item label="SECRET" prop="secret"> + <el-input v-model="mediaServerForm.secret" placeholder="濯掍綋鏈嶅姟SECRET" clearable></el-input> + </el-form-item> + <el-form-item> + <div style="float: right;"> + <el-button type="primary" v-if="currentStep === 1 && serverCheck === 1" @click="next" >涓嬩竴姝�</el-button> + <el-button @click="close">鍙栨秷</el-button> + <el-button type="primary" @click="checkServer" >娴嬭瘯</el-button> + <i v-if="serverCheck === 1" class="el-icon-success" style="color: #3caf36"></i> + <i v-if="serverCheck === -1" class="el-icon-error" style="color: #c80000"></i> + </div> + </el-form-item> + </el-form> + <el-row :gutter="24"> + <el-col :span="12"> + <el-form v-if="currentStep === 2 || currentStep === 3" ref="mediaServerForm1" :rules="rules" :model="mediaServerForm" label-width="140px" > + <el-form-item label="IP" prop="ip"> + <el-input v-if="currentStep === 2" v-model="mediaServerForm.ip" disabled></el-input> + <el-input v-if="currentStep === 3" v-model="mediaServerForm.ip"></el-input> + </el-form-item> + <el-form-item label="HTTP绔彛" prop="port"> + <el-input v-if="currentStep === 2" v-model="mediaServerForm.httpPort" disabled></el-input> + <el-input v-if="currentStep === 3" v-model="mediaServerForm.httpPort"></el-input> + </el-form-item> + <el-form-item label="SECRET" prop="secret"> + <el-input v-if="currentStep === 2" v-model="mediaServerForm.secret" disabled></el-input> + <el-input v-if="currentStep === 3" v-model="mediaServerForm.secret"></el-input> + </el-form-item> + <el-form-item label="HOOK IP" prop="ip"> + <el-input v-model="mediaServerForm.hookIp" placeholder="濯掍綋鏈嶅姟HOOK_IP" clearable></el-input> + </el-form-item> + <el-form-item label="SDP IP" prop="ip"> + <el-input v-model="mediaServerForm.sdpIp" placeholder="濯掍綋鏈嶅姟SDP_IP" clearable></el-input> + </el-form-item> + <el-form-item label="娴両P" prop="ip"> + <el-input v-model="mediaServerForm.streamIp" placeholder="濯掍綋鏈嶅姟娴両P" clearable></el-input> + </el-form-item> + <el-form-item label="HTTPS PORT" prop="port"> + <el-input v-model="mediaServerForm.httpSSlPort" placeholder="濯掍綋鏈嶅姟HTTPS_PORT" clearable></el-input> + </el-form-item> + <el-form-item label="RTSP PORT" prop="port"> + <el-input v-model="mediaServerForm.rtspPort" placeholder="濯掍綋鏈嶅姟RTSP_PORT" clearable></el-input> + </el-form-item> + <el-form-item label="RTSPS PORT" prop="port"> + <el-input v-model="mediaServerForm.rtspSSLPort" placeholder="濯掍綋鏈嶅姟RTSPS_PORT" clearable></el-input> + </el-form-item> + + </el-form> + </el-col> + <el-col :span="12"> + <el-form v-if="currentStep === 2 || currentStep === 3" ref="mediaServerForm2" :rules="rules" :model="mediaServerForm" label-width="180px" > + <el-form-item label="RTMP PORT" prop="port"> + <el-input v-model="mediaServerForm.rtmpPort" placeholder="濯掍綋鏈嶅姟RTMP_PORT" clearable></el-input> + </el-form-item> + <el-form-item label="RTMPS PORT" prop="port"> + <el-input v-model="mediaServerForm.rtmpSSlPort" placeholder="濯掍綋鏈嶅姟RTMPS_PORT" clearable></el-input> + </el-form-item> + <el-form-item label="鑷姩閰嶇疆濯掍綋鏈嶅姟" > + <el-switch v-model="mediaServerForm.autoConfig"></el-switch> + </el-form-item> + <el-form-item label="鏀舵祦绔彛妯″紡" > + <el-switch active-text="澶氱鍙�" inactive-text="鍗曠鍙�" v-model="mediaServerForm.rtpEnable"></el-switch> + </el-form-item> + + <el-form-item v-if="!mediaServerForm.rtpEnable" label="鏀舵祦绔彛" prop="port"> + <el-input v-model.number="mediaServerForm.rtpProxyPort" clearable></el-input> + </el-form-item> + <el-form-item v-if="mediaServerForm.rtpEnable" label="鏀舵祦绔彛" prop="port"> + <el-input v-model="mediaServerForm.rtpPortRange1" placeholder="璧峰" clearable style="width: 100px" prop="port"></el-input> + - + <el-input v-model="mediaServerForm.rtpPortRange2" placeholder="缁堟" clearable style="width: 100px" prop="port"></el-input> + </el-form-item> + <el-form-item label="鎺ㄦ祦绔彛" prop="port"> + <el-input v-model="mediaServerForm.sendRtpPortRange1" placeholder="璧峰" clearable style="width: 100px" prop="port"></el-input> + - + <el-input v-model="mediaServerForm.sendRtpPortRange2" placeholder="缁堟" clearable style="width: 100px" prop="port"></el-input> + </el-form-item> + <el-form-item label="鏃犱汉瑙傜湅澶氫箙鍚庡仠姝㈡媺娴�" > + <el-input v-model.number="mediaServerForm.streamNoneReaderDelayMS" clearable></el-input> + </el-form-item> + <el-form-item label="褰曞儚绠$悊鏈嶅姟绔彛" prop="port"> + <el-input v-model.number="mediaServerForm.recordAssistPort"> +<!-- <el-button v-if="mediaServerForm.recordAssistPort > 0" slot="append" type="primary" @click="checkRecordServer">娴嬭瘯</el-button>--> + <el-button v-if="mediaServerForm.recordAssistPort > 0" class="el-icon-check" slot="append" type="primary" @click="checkRecordServer"></el-button> + </el-input> + <i v-if="recordServerCheck == 1" class="el-icon-success" style="color: #3caf36; position: absolute;top: 14px;"></i> + <i v-if="recordServerCheck == 2" class="el-icon-loading" style="color: #3caf36; position: absolute;top: 14px;"></i> + <i v-if="recordServerCheck === -1" class="el-icon-error" style="color: #c80000; position: absolute;top: 14px;"></i> + </el-form-item> + <el-form-item> + <div style="float: right;"> + <el-button type="primary" @click="onSubmit" >鎻愪氦</el-button> + <el-button @click="close">鍙栨秷</el-button> + </div> + </el-form-item> + </el-form> + </el-col> + </el-row> + + </div> + </el-dialog> + </div> +</template> + +<script> +import MediaServer from './../service/MediaServer' + +export default { + name: "streamProxyEdit", + props: {}, + computed: {}, + created() { + this.setDialogWidth() + }, + data() { + const isValidIp = (rule, value, callback) => { // 鏍¢獙IP鏄惁绗﹀悎瑙勫垯 + var reg = /^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$/ + console.log(this.mediaServerForm.ip) + if (!reg.test(this.mediaServerForm.ip)) { + return callback(new Error('璇疯緭鍏ユ湁鏁堢殑IP鍦板潃')) + } else { + callback() + } + return true + } + const isValidPort = (rule, value, callback) => { // 鏍¢獙IP鏄惁绗﹀悎瑙勫垯 + var reg = /^(([0-9]|[1-9]\d{1,3}|[1-5]\d{4}|6[0-5]{2}[0-3][0-5]))$/ + if (!reg.test(this.mediaServerForm.httpPort)) { + return callback(new Error('璇疯緭鍏ユ湁鏁堢殑绔彛鍙�')) + } else { + callback() + } + return true + } + return { + dialogWidth: 0, + defaultWidth: 1000, + listChangeCallback: null, + showDialog: false, + isLoging: false, + dialogLoading: false, + + currentStep: 1, + platformList: [], + mediaServer: new MediaServer(), + serverCheck: 0, + recordServerCheck: 0, + mediaServerForm: { + id: "", + ip: "", + autoConfig: true, + hookIp: "", + sdpIp: "", + streamIp: "", + streamNoneReaderDelayMS: "", + secret: "035c73f7-bb6b-4889-a715-d9eb2d1925cc", + httpPort: "", + httpSSlPort: "", + recordAssistPort: "", + rtmpPort: "", + rtmpSSlPort: "", + rtpEnable: false, + rtpPortRange: "", + sendRtpPortRange: "", + rtpPortRange1: "", + rtpPortRange2: "", + sendRtpPortRange1: "", + sendRtpPortRange2: "", + rtpProxyPort: "", + rtspPort: "", + rtspSSLPort: "", + }, + + rules: { + ip: [{ required: true, validator: isValidIp, message: '璇疯緭鍏ユ湁鏁堢殑IP鍦板潃', trigger: 'blur' }], + port: [{ required: true, validator: isValidPort, message: '璇疯緭鍏ユ湁鏁堢殑绔彛鍙�', trigger: 'blur' }], + secret: [{ required: true, message: "璇疯緭鍏ecret", trigger: "blur" }], + timeout_ms: [{ required: true, message: "璇疯緭鍏Fmpeg鎺ㄦ祦鎴愬姛瓒呮椂鏃堕棿", trigger: "blur" }], + ffmpeg_cmd_key: [{ required: false, message: "璇疯緭鍏Fmpeg鍛戒护鍙傛暟妯℃澘锛堝彲閫夛級", trigger: "blur" }], + }, + }; + }, + methods: { + setDialogWidth() { + let val = document.body.clientWidth + if (val < this.defaultWidth) { + this.dialogWidth = '100%' + } else { + this.dialogWidth = this.defaultWidth + 'px' + } + }, + openDialog: function (param, callback) { + this.showDialog = true; + this.listChangeCallback = callback; + if (param != null) { + this.mediaServerForm = param; + this.currentStep = 3; + if (param.rtpPortRange) { + let rtpPortRange = this.mediaServerForm.rtpPortRange.split(","); + if (rtpPortRange.length > 0) { + this.mediaServerForm["rtpPortRange1"] = rtpPortRange[0] + this.mediaServerForm["rtpPortRange2"] = rtpPortRange[1] + } + } + let sendRtpPortRange = this.mediaServerForm.sendRtpPortRange.split(","); + this.mediaServerForm["sendRtpPortRange1"] = sendRtpPortRange[0] + this.mediaServerForm["sendRtpPortRange2"] = sendRtpPortRange[1] + } + }, + checkServer: function() { + let that = this; + that.serverCheck = 0; + that.mediaServer.checkServer(that.mediaServerForm, data =>{ + if (data.code === 0) { + if (parseInt(that.mediaServerForm.httpPort) !== parseInt(data.data.httpPort)) { + that.$message({ + showClose: true, + message: '濡傛灉浣犳鍦ㄤ娇鐢╠ocker閮ㄧ讲浣犵殑濯掍綋鏈嶅姟锛岃娉ㄦ剰鐨勭鍙f槧灏勩��', + type: 'warning', + duration: 0 + }); + } + let httpPort = that.mediaServerForm.httpPort; + that.mediaServerForm = data.data; + that.mediaServerForm.httpPort = httpPort; + that.mediaServerForm.autoConfig = true; + that.mediaServerForm.sendRtpPortRange1 = 30000 + that.mediaServerForm.sendRtpPortRange2 = 30500 + that.mediaServerForm.rtpPortRange1 = 30000 + that.mediaServerForm.rtpPortRange2 = 30500 + that.serverCheck = 1; + }else { + that.serverCheck = -1; + that.$message({ + showClose: true, + message: data.msg, + type: "error", + }); + } + + }) + }, + next: function (){ + this.currentStep = 2; + this.defaultWidth = 900; + this.setDialogWidth(); + }, + checkRecordServer: function (){ + let that = this; + that.recordServerCheck = 2; + if (that.mediaServerForm.recordAssistPort <= 0 || that.mediaServerForm.recordAssistPort > 65535 ) { + that.recordServerCheck = -1; + that.$message({ + showClose: true, + message: "绔彛鍙峰簲璇ュ湪-65535涔嬮棿", + type: "error", + }); + return; + } + that.mediaServer.checkRecordServer(that.mediaServerForm, data =>{ + if (data.code === 0) { + that.recordServerCheck = 1; + }else { + that.recordServerCheck = -1; + that.$message({ + showClose: true, + message: data.msg, + type: "error", + }); + } + }) + }, + onSubmit: function () { + this.dialogLoading = true; + let that = this; + if (this.mediaServerForm.rtpEnable) { + this.mediaServerForm.rtpPortRange = this.mediaServerForm.rtpPortRange1 + "," + this.mediaServerForm.rtpPortRange2; + } + this.mediaServerForm.sendRtpPortRange = this.mediaServerForm.sendRtpPortRange1 + "," + this.mediaServerForm.sendRtpPortRange2; + that.mediaServer.addServer(this.mediaServerForm, data => { + if (data.code === 0) { + that.$message({ + showClose: true, + message: "淇濆瓨鎴愬姛", + type: "success", + }); + if (this.listChangeCallback) this.listChangeCallback(); + that.close() + }else { + that.$message({ + showClose: true, + message: data.msg, + type: "error", + }); + } + }) + }, + close: function () { + this.showDialog = false; + this.dialogLoading = false; + this.mediaServerForm = { + id: "", + ip: "", + autoConfig: true, + hookIp: "", + sdpIp: "", + streamIp: "", + streamNoneReaderDelayMS: "", + secret: "035c73f7-bb6b-4889-a715-d9eb2d1925cc", + httpPort: "", + httpSSlPort: "", + recordAssistPort: "", + rtmpPort: "", + rtmpSSlPort: "", + rtpEnable: false, + rtpPortRange: "", + sendRtpPortRange: "", + rtpPortRange1: "", + rtpPortRange2: "", + sendRtpPortRange1: "", + sendRtpPortRange2: "", + rtpProxyPort: "", + rtspPort: "", + rtspSSLPort: "", + }; + this.listChangeCallback = null + this.currentStep = 1; + }, + deviceGBIdExit: async function (deviceGbId) { + var result = false; + var that = this; + await that.$axios({ + method: 'post', + url:`/api/platform/exit/${deviceGbId}` + }).then(function (res) { + result = res.data; + }).catch(function (error) { + console.log(error); + }); + return result; + }, + checkExpires: function() { + if (this.platform.enable && this.platform.expires == "0") { + this.platform.expires = "300"; + } + } + }, +}; +</script> diff --git a/web_src/src/components/dialog/StreamProxyEdit.vue b/web_src/src/components/dialog/StreamProxyEdit.vue index 3310d9c..ea3a64f 100644 --- a/web_src/src/components/dialog/StreamProxyEdit.vue +++ b/web_src/src/components/dialog/StreamProxyEdit.vue @@ -203,7 +203,7 @@ }).catch(function (error) { console.log(error); }); - this.mediaServer.getMediaServerList((data)=>{ + this.mediaServer.getOnlineMediaServerList((data)=>{ this.mediaServerList = data; }) }, diff --git a/web_src/src/components/dialog/changePassword.vue b/web_src/src/components/dialog/changePassword.vue index 39aba8d..eade6a8 100644 --- a/web_src/src/components/dialog/changePassword.vue +++ b/web_src/src/components/dialog/changePassword.vue @@ -89,7 +89,7 @@ method: 'post', url:"/api/user/changePassword", params: { - oldpassword: crypto.createHash('md5').update(this.oldPassword, "utf8").digest('hex'), + oldPassword: crypto.createHash('md5').update(this.oldPassword, "utf8").digest('hex'), password: this.newPassword } }).then((res)=> { diff --git a/web_src/src/components/dialog/deviceEdit.vue b/web_src/src/components/dialog/deviceEdit.vue index 464de02..5d2ffa5 100644 --- a/web_src/src/components/dialog/deviceEdit.vue +++ b/web_src/src/components/dialog/deviceEdit.vue @@ -82,7 +82,7 @@ }, getMediaServerList: function (){ let that = this; - that.mediaServerObj.getMediaServerList((data)=>{ + that.mediaServerObj.getOnlineMediaServerList((data)=>{ that.mediaServerList = data.data; }) }, diff --git a/web_src/src/components/service/MediaServer.js b/web_src/src/components/service/MediaServer.js index b905352..e9de603 100644 --- a/web_src/src/components/service/MediaServer.js +++ b/web_src/src/components/service/MediaServer.js @@ -6,10 +6,20 @@ this.$axios = axios; } - getMediaServerList(callback){ + getOnlineMediaServerList(callback){ this.$axios({ method: 'get', url:`/api/server/media_server/online/list`, + }).then(function (res) { + if (typeof (callback) == "function") callback(res.data) + }).catch(function (error) { + console.log(error); + }); + } + getMediaServerList(callback){ + this.$axios({ + method: 'get', + url:`/api/server/media_server/list`, }).then(function (res) { if (typeof (callback) == "function") callback(res.data) }).catch(function (error) { @@ -27,6 +37,49 @@ console.log(error); }); } + + checkServer(param, callback){ + this.$axios({ + method: 'get', + url:`/api/server/media_server/check`, + params: { + ip: param.ip, + port: param.httpPort, + secret: param.secret + } + }).then(function (res) { + if (typeof (callback) == "function") callback(res.data) + }).catch(function (error) { + console.log(error); + }); + } + + checkRecordServer(param, callback){ + this.$axios({ + method: 'get', + url:`/api/server/media_server/record/check`, + params: { + ip: param.ip, + port: param.recordAssistPort + } + }).then(function (res) { + if (typeof (callback) == "function") callback(res.data) + }).catch(function (error) { + console.log(error); + }); + } + + addServer(param, callback){ + this.$axios({ + method: 'post', + url:`/api/server/media_server/save`, + data: param + }).then(function (res) { + if (typeof (callback) == "function") callback(res.data) + }).catch(function (error) { + console.log(error); + }); + } } export default MediaServer; diff --git a/web_src/src/router/index.js b/web_src/src/router/index.js index 4b0810d..59bbb23 100644 --- a/web_src/src/router/index.js +++ b/web_src/src/router/index.js @@ -10,6 +10,7 @@ import login from '../components/Login.vue' import parentPlatformList from '../components/ParentPlatformList.vue' import cloudRecord from '../components/CloudRecord.vue' +import mediaServerManger from '../components/MediaServerManger.vue' import test from '../components/test.vue' import web from '../components/setting/Web.vue' import sip from '../components/setting/Sip.vue' @@ -71,6 +72,11 @@ component: cloudRecord, }, { + path: '/mediaServerManger', + name: 'mediaServerManger', + component: mediaServerManger, + }, + { path: '/setting/web', name: 'web', component: web, diff --git a/web_src/static/css/iconfont.css b/web_src/static/css/iconfont.css index 972cf6b..0f9b608 100644 --- a/web_src/static/css/iconfont.css +++ b/web_src/static/css/iconfont.css @@ -1,8 +1,8 @@ @font-face { font-family: "iconfont"; /* Project id 1291092 */ - src: url('iconfont.woff2?t=1626163621710') format('woff2'), - url('iconfont.woff?t=1626163621710') format('woff'), - url('iconfont.ttf?t=1626163621710') format('truetype'); + src: url('iconfont.woff2?t=1631767887536') format('woff2'), + url('iconfont.woff?t=1631767887536') format('woff'), + url('iconfont.ttf?t=1631767887536') format('truetype'); } .iconfont { @@ -13,6 +13,10 @@ -moz-osx-font-smoothing: grayscale; } +.icon-online:before { + content: "\e600"; +} + .icon-xiangqing2:before { content: "\e798"; } diff --git a/web_src/static/css/iconfont.woff2 b/web_src/static/css/iconfont.woff2 index c8d7e3d..42e2eca 100644 --- a/web_src/static/css/iconfont.woff2 +++ b/web_src/static/css/iconfont.woff2 Binary files differ diff --git a/web_src/static/images/zlm-logo.png b/web_src/static/images/zlm-logo.png new file mode 100644 index 0000000..5f492dc --- /dev/null +++ b/web_src/static/images/zlm-logo.png Binary files differ -- Gitblit v1.8.0