diff --git a/sql/mysql.sql b/sql/mysql.sql index 90393e67..6f44ce85 100644 --- a/sql/mysql.sql +++ b/sql/mysql.sql @@ -140,6 +140,7 @@ create table media_server 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 9831ddb5..08d030a8 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 javax.servlet.http.HttpServletResponse; 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 72cefe1c..e6083614 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 @@ public class MediaConfig{ @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 class MediaConfig{ } } + public String getSipDomain() { + return sipDomain; + } + + public String getSendRtpPortRange() { + return sendRtpPortRange; + } + public MediaServerItem getMediaSerItem(){ MediaServerItem mediaServerItem = new MediaServerItem(); mediaServerItem.setId(id); @@ -185,6 +197,7 @@ public class MediaConfig{ 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 907e30d3..5d8acce9 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 javax.servlet.http.HttpServletRequest; import java.io.IOException; import java.net.ConnectException; +/** + * @author lin + */ @SuppressWarnings(value = {"rawtypes", "unchecked"}) @Configuration public class ProxyServletConfig { @@ -35,7 +38,7 @@ public class ProxyServletConfig { @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 @@ public class ProxyServletConfig { 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 bd564015..b4d10483 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.Logger; 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 @@ public class ZLMRTPServerFactory { Map param = new HashMap<>(); int result = -1; - int newPort = getPortFromportRange(mediaServerItem); - param.put("port", newPort); + /** + * 不设置推流端口端则使用随机端口 + */ + 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 @@ public class ZLMRTPServerFactory { if (openRtpServerResultJson != null) { switch (openRtpServerResultJson.getInteger("code")){ case 0: - result= newPort; + result= openRtpServerResultJson.getInteger("port"); break; case -300: // id已经存在, 可能已经在其他端口推流 Map 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 { // 检查ZLM状态 - logger.error("创建RTP Server 失败 {}: 请检查ZLM服务", newPort); + logger.error("创建RTP Server 失败 {}: 请检查ZLM服务", param.get("port")); } return result; } @@ -98,7 +106,7 @@ public class ZLMRTPServerFactory { 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 class ZLMRTPServerFactory { */ 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 187cbc1b..7faebfa8 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 class ZLMRunner implements CommandLineRunner { } 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 d1578d17..087c10af 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,14 +41,20 @@ public class MediaServerItem{ 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; private SsrcConfig ssrcConfig; @@ -82,6 +88,7 @@ public class MediaServerItem{ secret = zlmServerConfig.getApiSecret(); streamNoneReaderDelayMS = zlmServerConfig.getGeneralStreamNoneReaderDelayMS(); rtpEnable = false; // 默认使用单端口;直到用户自己设置开启多端口 + rtpPortRange = "30000,30500"; // 默认使用30000,30500作为级联时发送流的端口号 recordAssistPort = 0; // 默认关闭 } @@ -278,5 +285,27 @@ public class MediaServerItem{ 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 f65a1557..81cf8f1a 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.gb28181.bean.Device; 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 @@ public interface IMediaServerService { void clearMediaServerForOnline(); - void add(MediaServerItem mediaSerItem); + WVPResult add(MediaServerItem mediaSerItem); void resetOnlineServerItem(MediaServerItem serverItem); + + WVPResult 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 33c00515..18c1b934 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.ZLMServerConfig; 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; @@ -56,9 +58,6 @@ public class MediaServerServiceImpl implements IMediaServerService, CommandLineR @Autowired private MediaServerMapper mediaServerMapper; - @Autowired - private IRedisCatchStorage redisCatchStorage; - @Autowired private VideoStreamSessionManager streamSession; @@ -97,7 +96,9 @@ public class MediaServerServiceImpl implements IMediaServerService, CommandLineR @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可用的ssrc String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + mediaServerItem.getId(); @@ -107,7 +108,9 @@ public class MediaServerServiceImpl implements IMediaServerService, CommandLineR 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 @@ public class MediaServerServiceImpl implements IMediaServerService, CommandLineR @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 @@ public class MediaServerServiceImpl implements IMediaServerService, CommandLineR /** * zlm 重启后重置他的推流信息, TODO 给正在使用的设备发送停止命令 - * @param mediaServerItem */ @Override public void clearRTPServer(MediaServerItem mediaServerItem) { @@ -174,9 +178,15 @@ public class MediaServerServiceImpl implements IMediaServerService, CommandLineR public List getAll() { List result = new ArrayList<>(); List 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 @@ public class MediaServerServiceImpl implements IMediaServerService, CommandLineR */ @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 @@ public class MediaServerServiceImpl implements IMediaServerService, CommandLineR } @Override - public void add(MediaServerItem mediaSerItem) { - mediaServerMapper.add(mediaSerItem); + public WVPResult add(MediaServerItem mediaServerItem) { + WVPResult 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("保存失败,媒体服务ID [ " + 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 @@ public class MediaServerServiceImpl implements IMediaServerService, CommandLineR // docker部署不会使用zlm配置的端口号不是默认的则不做更新, 配置修改需要自行修改server配置; 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 @@ public class MediaServerServiceImpl implements IMediaServerService, CommandLineR @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 @@ public class MediaServerServiceImpl implements IMediaServerService, CommandLineR } + @Override + public WVPResult checkMediaServer(String ip, int port, String secret) { + WVPResult 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 2167c553..8d45b054 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 @@ public interface MediaServerMapper { "streamNoneReaderDelayMS, " + "rtpEnable, " + "rtpPortRange, " + + "sendRtpPortRange, " + "recordAssistPort, " + "defaultServer, " + "createTime, " + @@ -55,6 +56,7 @@ public interface MediaServerMapper { "${streamNoneReaderDelayMS}, " + "${rtpEnable}, " + "'${rtpPortRange}', " + + "'${sendRtpPortRange}', " + "${recordAssistPort}, " + "${defaultServer}, " + "'${createTime}', " + @@ -79,6 +81,7 @@ public interface MediaServerMapper { ", streamNoneReaderDelayMS=${streamNoneReaderDelayMS}" + ", rtpEnable=${rtpEnable}" + ", rtpPortRange='${rtpPortRange}'" + + ", sendRtpPortRange='${sendRtpPortRange}'" + ", secret='${secret}'" + ", recordAssistPort=${recordAssistPort}" + "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 3bfa5957..881a20a6 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 @@ public class ServerController { @ApiOperation("流媒体服务列表") @GetMapping(value = "/media_server/list") @ResponseBody - public WVPResult> getMediaServerList(){ + public WVPResult> getMediaServerList(boolean detail){ + List all = mediaServerService.getAll(); + WVPResult> result = new WVPResult<>(); result.setCode(0); result.setMsg("success"); @@ -87,6 +89,60 @@ public class ServerController { return result; } + @ApiOperation("测试流媒体服务") + @ApiImplicitParams({ + @ApiImplicitParam(name="ip", value = "流媒体服务IP", dataTypeClass = String.class), + @ApiImplicitParam(name="port", value = "流媒体服务HTT端口", dataTypeClass = Integer.class), + @ApiImplicitParam(name="secret", value = "流媒体服务secret", dataTypeClass = String.class), + }) + @GetMapping(value = "/media_server/check") + @ResponseBody + public WVPResult checkMediaServer(@RequestParam String ip, @RequestParam int port, @RequestParam String secret){ + return mediaServerService.checkMediaServer(ip, port, secret); + } + + @ApiOperation("测试流媒体录像管理服务") + @ApiImplicitParams({ + @ApiImplicitParam(name="ip", value = "流媒体服务IP", dataTypeClass = String.class), + @ApiImplicitParam(name="port", value = "流媒体服务HTT端口", dataTypeClass = Integer.class), + @ApiImplicitParam(name="secret", value = "流媒体服务secret", dataTypeClass = String.class), + }) + @GetMapping(value = "/media_server/record/check") + @ResponseBody + public WVPResult checkMediaRecordServer(@RequestParam String ip, @RequestParam int port){ + boolean checkResult = mediaServerService.checkMediaRecordServer(ip, port); + WVPResult 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 checkMediaServer(@RequestBody MediaServerItem mediaServerItem){ + if (mediaServerService.getOne(mediaServerItem.getId()) != null) { + mediaServerService.update(mediaServerItem); + }else { + return mediaServerService.add(mediaServerItem); + } + WVPResult result = new WVPResult<>(); + result.setCode(0); + result.setMsg("success"); + return result; + } + + + @ApiOperation("重启服务") @GetMapping(value = "/restart") @ResponseBody @@ -155,6 +211,8 @@ public class ServerController { 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 856d6c5f..f2d85ec0 100644 --- a/src/main/resources/all-application.yml +++ b/src/main/resources/all-application.yml @@ -119,6 +119,8 @@ media: enable: true # [可选] 在此范围内选择端口用于媒体流传输, port-range: 30000,30500 # 端口范围 + # [可选] 国标级联在此范围内选择端口发送媒体流, + send-port-range: 30000,30500 # 端口范围 # 录像辅助服务, 部署此服务可以实现zlm录像的管理与下载, 0 表示不使用 record-assist-port: 0 diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml index 062f70e6..44f70e6e 100644 --- a/src/main/resources/application-dev.yml +++ b/src/main/resources/application-dev.yml @@ -63,6 +63,8 @@ media: enable: true # [可选] 在此范围内选择端口用于媒体流传输, port-range: 30000,30500 # 端口范围 + # [可选] 国标级联在此范围内选择端口发送媒体流, + send-port-range: 30000,30500 # 端口范围 # 录像辅助服务, 部署此服务可以实现zlm录像的管理与下载, 0 表示不使用 record-assist-port: 0 diff --git a/src/main/resources/wvp.sqlite b/src/main/resources/wvp.sqlite index b95368d3..40bdad87 100644 Binary files a/src/main/resources/wvp.sqlite and b/src/main/resources/wvp.sqlite differ diff --git a/web_src/build/webpack.base.conf.js b/web_src/build/webpack.base.conf.js index a07e6836..72539e37 100644 --- a/web_src/build/webpack.base.conf.js +++ b/web_src/build/webpack.base.conf.js @@ -27,6 +27,7 @@ module.exports = { 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 00000000..5f492dcd Binary files /dev/null and b/web_src/src/assets/zlm-log.png differ diff --git a/web_src/src/components/CloudRecord.vue b/web_src/src/components/CloudRecord.vue index e39cd5b6..f5d052a3 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 7644a963..8d978339 100644 --- a/web_src/src/components/DeviceList.vue +++ b/web_src/src/components/DeviceList.vue @@ -60,7 +60,7 @@ 通道 定位 - 编辑 + 编辑 删除 diff --git a/web_src/src/components/MediaServerManger.vue b/web_src/src/components/MediaServerManger.vue new file mode 100644 index 00000000..19674d13 --- /dev/null +++ b/web_src/src/components/MediaServerManger.vue @@ -0,0 +1,159 @@ + + + + + diff --git a/web_src/src/components/UiHeader.vue b/web_src/src/components/UiHeader.vue index 4ab46422..b2e9bbbd 100644 --- a/web_src/src/components/UiHeader.vue +++ b/web_src/src/components/UiHeader.vue @@ -6,6 +6,7 @@ 推流列表 拉流代理 云端录像 + 节点管理 国标级联 在线文档 diff --git a/web_src/src/components/control.vue b/web_src/src/components/control.vue index 63267128..a8ee8d41 100644 --- a/web_src/src/components/control.vue +++ b/web_src/src/components/control.vue @@ -139,7 +139,7 @@ export default { 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 00000000..b67daf84 --- /dev/null +++ b/web_src/src/components/dialog/MediaServerEdit.vue @@ -0,0 +1,368 @@ + + + diff --git a/web_src/src/components/dialog/StreamProxyEdit.vue b/web_src/src/components/dialog/StreamProxyEdit.vue index 3310d9ce..ea3a64f9 100644 --- a/web_src/src/components/dialog/StreamProxyEdit.vue +++ b/web_src/src/components/dialog/StreamProxyEdit.vue @@ -203,7 +203,7 @@ export default { }).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 39aba8d3..eade6a8b 100644 --- a/web_src/src/components/dialog/changePassword.vue +++ b/web_src/src/components/dialog/changePassword.vue @@ -89,7 +89,7 @@ export default { 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 464de027..5d2ffa56 100644 --- a/web_src/src/components/dialog/deviceEdit.vue +++ b/web_src/src/components/dialog/deviceEdit.vue @@ -82,7 +82,7 @@ export default { }, 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 b9053528..e9de6039 100644 --- a/web_src/src/components/service/MediaServer.js +++ b/web_src/src/components/service/MediaServer.js @@ -6,7 +6,7 @@ class MediaServer{ this.$axios = axios; } - getMediaServerList(callback){ + getOnlineMediaServerList(callback){ this.$axios({ method: 'get', url:`/api/server/media_server/online/list`, @@ -16,6 +16,16 @@ class MediaServer{ 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) { + console.log(error); + }); + } getMediaServer(id, callback){ this.$axios({ @@ -27,6 +37,49 @@ class MediaServer{ 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 4b0810d3..59bbb236 100644 --- a/web_src/src/router/index.js +++ b/web_src/src/router/index.js @@ -10,6 +10,7 @@ import devicePosition from '../components/devicePosition.vue' 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' @@ -70,6 +71,11 @@ export default new VueRouter({ name: 'cloudRecord', component: cloudRecord, }, + { + path: '/mediaServerManger', + name: 'mediaServerManger', + component: mediaServerManger, + }, { path: '/setting/web', name: 'web', diff --git a/web_src/static/css/iconfont.css b/web_src/static/css/iconfont.css index 972cf6bc..0f9b6085 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 c8d7e3dd..42e2ecae 100644 Binary files a/web_src/static/css/iconfont.woff2 and b/web_src/static/css/iconfont.woff2 differ diff --git a/web_src/static/images/zlm-logo.png b/web_src/static/images/zlm-logo.png new file mode 100644 index 00000000..5f492dcd Binary files /dev/null and b/web_src/static/images/zlm-logo.png differ