648540858
2024-05-23 2c89fae49a7655105b4e9e0138155485e6ba83b2
Merge branch 'refs/heads/2.7.1'

# Conflicts:
# pom.xml
# src/main/java/com/genersoft/iot/vmp/conf/security/WebSecurityConfig.java
# src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/NotifyRequestForMobilePositionProcessor.java
# src/main/java/com/genersoft/iot/vmp/media/bean/MediaServer.java
# src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java
# src/main/java/com/genersoft/iot/vmp/service/ICloudRecordService.java
# src/main/java/com/genersoft/iot/vmp/service/bean/CloudRecordItem.java
# src/main/java/com/genersoft/iot/vmp/service/impl/CloudRecordServiceImpl.java
# src/main/java/com/genersoft/iot/vmp/service/impl/MediaServerServiceImpl.java
# src/main/java/com/genersoft/iot/vmp/service/impl/MediaServiceImpl.java
# src/main/java/com/genersoft/iot/vmp/service/impl/StreamProxyServiceImpl.java
# src/main/java/com/genersoft/iot/vmp/storager/dao/CloudRecordServiceMapper.java
# src/main/java/com/genersoft/iot/vmp/storager/dao/MediaServerMapper.java
28个文件已修改
8个文件已添加
1353 ■■■■■ 已修改文件
src/main/java/com/genersoft/iot/vmp/conf/SpringDocConfig.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/conf/UserSetting.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/conf/redis/RedisTemplateConfig.java 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/conf/security/JwtAuthenticationFilter.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/conf/security/WebSecurityConfig.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommanderFroPlatform.java 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/NotifyRequestForMobilePositionProcessor.java 41 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/media/bean/MediaServer.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/media/zlm/SendRtpPortManager.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/media/zlm/dto/ZLMServerConfig.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/media/zlm/dto/hook/OnRecordMp4HookParam.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/service/ICloudRecordService.java 9 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/service/IMobilePositionService.java 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/service/bean/CloudRecordItem.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/service/impl/CloudRecordServiceImpl.java 45 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/service/impl/MediaServiceImpl.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/service/impl/MobilePositionServiceImpl.java 95 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/service/impl/StreamProxyServiceImpl.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/storager/dao/CloudRecordServiceMapper.java 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceChannelMapper.java 37 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceMobilePositionMapper.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/storager/dao/MediaServerMapper.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/utils/DateUtil.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/utils/MediaServerUtils.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/vmanager/cloudRecord/CloudRecordController.java 229 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/vmanager/cloudRecord/bean/CloudRecordUrl.java 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/PlayController.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/all-application.yml 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/application-dev.yml 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
数据库/2.7.1/初始化-mysql-2.7.1.sql 325 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
数据库/2.7.1/初始化-postgresql-kingbase-2.7.1.sql 325 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
数据库/2.7.1/更新-mysql-2.7.1.sql 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
数据库/2.7.1/更新-postgresql-kingbase-2.7.1.sql 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/conf/SpringDocConfig.java
@@ -7,6 +7,7 @@
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.info.License;
import io.swagger.v3.oas.models.security.SecurityScheme;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.core.annotation.Order;
import org.springdoc.core.GroupedOpenApi;
import org.springframework.beans.factory.annotation.Value;
@@ -18,6 +19,7 @@
 */
@Configuration
@Order(1)
@ConditionalOnProperty(value = "user-settings.doc-enable", havingValue = "true", matchIfMissing = true)
public class SpringDocConfig {
    @Value("${doc.enabled: true}")
src/main/java/com/genersoft/iot/vmp/conf/UserSetting.java
@@ -54,6 +54,8 @@
    private Boolean deviceStatusNotify = Boolean.TRUE;
    private Boolean useCustomSsrcForParentInvite = Boolean.TRUE;
    private Boolean docEnable = Boolean.TRUE;
    private String serverId = "000000";
    private String thirdPartyGBIdReg = "[\\s\\S]*";
@@ -315,4 +317,12 @@
    public void setRegisterKeepIntDialog(boolean registerKeepIntDialog) {
        this.registerKeepIntDialog = registerKeepIntDialog;
    }
    public Boolean getDocEnable() {
        return docEnable;
    }
    public void setDocEnable(Boolean docEnable) {
        this.docEnable = docEnable;
    }
}
src/main/java/com/genersoft/iot/vmp/conf/redis/RedisTemplateConfig.java
@@ -1,6 +1,7 @@
package com.genersoft.iot.vmp.conf.redis;
import com.alibaba.fastjson2.support.spring.data.redis.GenericFastJsonRedisSerializer;
import com.genersoft.iot.vmp.gb28181.bean.MobilePosition;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
@@ -25,4 +26,20 @@
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        return redisTemplate;
    }
    @Bean
    public RedisTemplate<String, MobilePosition> getRedisTemplateForMobilePosition(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate<String, MobilePosition> redisTemplate = new RedisTemplate<>();
        // ä½¿ç”¨fastJson序列化
        GenericFastJsonRedisSerializer fastJsonRedisSerializer = new GenericFastJsonRedisSerializer();
        // value值的序列化采用fastJsonRedisSerializer
        redisTemplate.setValueSerializer(fastJsonRedisSerializer);
        redisTemplate.setHashValueSerializer(fastJsonRedisSerializer);
        // key的序列化采用StringRedisSerializer
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        return redisTemplate;
    }
}
src/main/java/com/genersoft/iot/vmp/conf/security/JwtAuthenticationFilter.java
@@ -35,10 +35,15 @@
        // å¿½ç•¥ç™»å½•请求的token验证
        String requestURI = request.getRequestURI();
        if ((requestURI.startsWith("/doc.html") || requestURI.startsWith("/swagger-ui") ) && !userSetting.getDocEnable()) {
            response.setStatus(HttpServletResponse.SC_NOT_FOUND);
            return;
        }
        if (requestURI.equalsIgnoreCase("/api/user/login")) {
            chain.doFilter(request, response);
            return;
        }
        if (!userSetting.isInterfaceAuthentication()) {
            UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(null, null, new ArrayList<>() );
            SecurityContextHolder.getContext().setAuthentication(token);
src/main/java/com/genersoft/iot/vmp/conf/security/WebSecurityConfig.java
@@ -117,7 +117,7 @@
                .authorizeRequests()
                .requestMatchers(CorsUtils::isPreFlightRequest).permitAll()
                .antMatchers(userSetting.getInterfaceAuthenticationExcludes().toArray(new String[0])).permitAll()
                .antMatchers("/api/user/login", "/index/hook/**","/index/hook/abl/**", "/swagger-ui/**", "/doc.html").permitAll()
                .antMatchers("/api/user/login", "/index/hook/**","/index/hook/abl/**", "/swagger-ui/**", "/doc.html#/**").permitAll()
                .anyRequest().authenticated()
                // å¼‚常处理器
                .and()
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java
@@ -168,6 +168,7 @@
        // via
        ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>();
        ViaHeader viaHeader = SipFactory.getInstance().createHeaderFactory().createViaHeader(sipLayer.getLocalIp(device.getLocalIp()), sipConfig.getPort(), device.getTransport(), SipUtils.getNewViaTag());
//        viaHeader.setRPort();
        viaHeaders.add(viaHeader);
        //from
        SipURI fromSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(),sipConfig.getDomain());
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommanderFroPlatform.java
@@ -515,9 +515,7 @@
        if (parentPlatform == null) {
            return;
        }
        if (logger.isDebugEnabled()) {
            logger.debug("[发送 ç§»åŠ¨ä½ç½®è®¢é˜…] {}/{}->{},{}", parentPlatform.getServerGBId(), gpsMsgInfo.getId(), gpsMsgInfo.getLng(), gpsMsgInfo.getLat());
        }
        logger.info("[发送 ç§»åŠ¨ä½ç½®è®¢é˜…] {}/{}->{},{}", parentPlatform.getServerGBId(), gpsMsgInfo.getId(), gpsMsgInfo.getLng(), gpsMsgInfo.getLat());
        String characterSet = parentPlatform.getCharacterSet();
        StringBuffer deviceStatusXml = new StringBuffer(600);
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/NotifyRequestForMobilePositionProcessor.java
@@ -11,6 +11,7 @@
import com.genersoft.iot.vmp.gb28181.utils.NumericUtil;
import com.genersoft.iot.vmp.gb28181.utils.SipUtils;
import com.genersoft.iot.vmp.service.IDeviceChannelService;
import com.genersoft.iot.vmp.service.IMobilePositionService;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import com.genersoft.iot.vmp.utils.DateUtil;
import org.dom4j.DocumentException;
@@ -20,15 +21,11 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;
import javax.sip.RequestEvent;
import javax.sip.header.FromHeader;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
/**
@@ -54,6 +51,9 @@
    @Autowired
    private IDeviceChannelService deviceChannelService;
    @Autowired
    private IMobilePositionService mobilePositionService;
    public void process(RequestEvent evt) {
        if (taskQueue.size() >= userSetting.getMaxNotifyCountQueue()) {
@@ -64,13 +64,10 @@
    }
    @Scheduled(fixedRate = 200) //每200毫秒执行一次
    @Transactional
    public void executeTaskQueue() {
        if (taskQueue.isEmpty()) {
            return;
        }
        Map<String, DeviceChannel> updateChannelMap = new ConcurrentHashMap<>();
        List<MobilePosition> addMobilePositionList = new ArrayList<>();
        for (HandlerCatchData take : taskQueue) {
            if (take == null) {
                continue;
@@ -146,20 +143,11 @@
                    }
                }
//            logger.info("[收到移动位置订阅通知]:{}/{}->{}.{}, æ—¶é—´ï¼š {}", mobilePosition.getDeviceId(), mobilePosition.getChannelId(),
//                    mobilePosition.getLongitude(), mobilePosition.getLatitude(), System.currentTimeMillis() - startTime);
            logger.debug("[收到移动位置订阅通知]:{}/{}->{}.{}, æ—¶é—´ï¼š {}", mobilePosition.getDeviceId(), mobilePosition.getChannelId(),
                    mobilePosition.getLongitude(), mobilePosition.getLatitude(), System.currentTimeMillis() - startTime);
                mobilePosition.setReportSource("Mobile Position");
                // æ›´æ–°device channel çš„经纬度
                DeviceChannel deviceChannel = new DeviceChannel();
                deviceChannel.setDeviceId(device.getDeviceId());
                deviceChannel.setLongitude(mobilePosition.getLongitude());
                deviceChannel.setLatitude(mobilePosition.getLatitude());
                deviceChannel.setGpsTime(mobilePosition.getTime());
                updateChannelMap.put(deviceId + mobilePosition.getChannelId(), deviceChannel);
                addMobilePositionList.add(mobilePosition);
                mobilePositionService.add(mobilePosition);
                // å‘关联了该通道并且开启移动位置订阅的上级平台发送移动位置订阅消息
                try {
                    eventPublisher.mobilePositionEventPublish(mobilePosition);
@@ -199,21 +187,6 @@
            }
        }
        taskQueue.clear();
        if(!updateChannelMap.isEmpty()) {
            List<DeviceChannel>  channels = new ArrayList<>(updateChannelMap.values());
            logger.info("[移动位置订阅]更新通道位置: {}", channels.size());
            deviceChannelService.batchUpdateChannel(channels);
            updateChannelMap.clear();
        }
        if (userSetting.isSavePositionHistory() && !addMobilePositionList.isEmpty()) {
            try {
                logger.info("[移动位置订阅] æ·»åŠ é€šé“è½¨è¿¹ç‚¹ä½ï¼š {}", addMobilePositionList.size());
                deviceChannelService.batchAddMobilePosition(addMobilePositionList);
            }catch (Exception e) {
                logger.info("[移动位置订阅] b添加通道轨迹点位保存失败: {}", addMobilePositionList.size());
            }
            addMobilePositionList.clear();
        }
    }
    @Scheduled(fixedRate = 10000)
    public void execute(){
src/main/java/com/genersoft/iot/vmp/media/bean/MediaServer.java
@@ -100,6 +100,9 @@
    @Schema(description = "类型: zlm/abl")
    private String type;
    @Schema(description = "转码的前缀")
    private String transcodeSuffix;
    public MediaServer() {
    }
@@ -126,6 +129,7 @@
        rtpEnable = false; // é»˜è®¤ä½¿ç”¨å•端口;直到用户自己设置开启多端口
        rtpPortRange = zlmServerConfig.getPortRange().replace("_",","); // é»˜è®¤ä½¿ç”¨30000,30500作为级联时发送流的端口号
        recordAssistPort = 0; // é»˜è®¤å…³é—­
        transcodeSuffix = zlmServerConfig.getTranscodeSuffix();
    }
@@ -376,4 +380,12 @@
    public void setWsFlvSSLPort(int wsFlvSSLPort) {
        this.wsFlvSSLPort = wsFlvSSLPort;
    }
    public String getTranscodeSuffix() {
        return transcodeSuffix;
    }
    public void setTranscodeSuffix(String transcodeSuffix) {
        this.transcodeSuffix = transcodeSuffix;
    }
}
src/main/java/com/genersoft/iot/vmp/media/zlm/SendRtpPortManager.java
@@ -104,7 +104,6 @@
                return port;
            }
        }
    }
    interface CheckPortCallback{
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java
@@ -24,6 +24,12 @@
import com.genersoft.iot.vmp.service.redisMsg.IRedisRpcService;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
import com.genersoft.iot.vmp.utils.DateUtil;
import com.genersoft.iot.vmp.utils.MediaServerUtils;
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
import com.genersoft.iot.vmp.vmanager.bean.OtherPsSendInfo;
import com.genersoft.iot.vmp.vmanager.bean.OtherRtpSendInfo;
import com.genersoft.iot.vmp.vmanager.bean.StreamContent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@@ -36,6 +42,10 @@
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import javax.sip.InvalidArgumentException;
import javax.sip.SipException;
import java.text.ParseException;
import java.util.List;
import java.util.Map;
/**
@@ -202,6 +212,11 @@
        if (mediaServer == null) {
            return HookResult.SUCCESS();
        }
        if (!ObjectUtils.isEmpty(mediaServer.getTranscodeSuffix())
                && !"null".equalsIgnoreCase(mediaServer.getTranscodeSuffix())
                && param.getStream().endsWith(mediaServer.getTranscodeSuffix())  ) {
            return;
        }
        if (param.getSchema().equalsIgnoreCase("rtsp")) {
            if (param.isRegist()) {
                logger.info("[ZLM HOOK] æµæ³¨å†Œ, {}->{}->{}/{}", param.getMediaServerId(), param.getSchema(), param.getApp(), param.getStream());
@@ -226,6 +241,19 @@
        logger.info("[ZLM HOOK]流无人观看:{}->{}->{}/{}", param.getMediaServerId(), param.getSchema(),
                param.getApp(), param.getStream());
        MediaServerItem mediaInfo = mediaServerService.getOne(param.getMediaServerId());
        if (mediaInfo == null) {
            JSONObject ret = new JSONObject();
            ret.put("code", 0);
            return ret;
        }
        if (!ObjectUtils.isEmpty(mediaInfo.getTranscodeSuffix())
                && !"null".equalsIgnoreCase(mediaInfo.getTranscodeSuffix())
                && param.getStream().endsWith(mediaInfo.getTranscodeSuffix())  ) {
            param.setStream(param.getStream().substring(0, param.getStream().lastIndexOf(mediaInfo.getTranscodeSuffix()) -1 ));
        }
        JSONObject ret = new JSONObject();
        boolean close = mediaService.closeStreamOnNoneReader(param.getMediaServerId(), param.getApp(), param.getStream(), param.getSchema());
        ret.put("code", 0);
@@ -347,23 +375,5 @@
        }
        return HookResult.SUCCESS();
    }
    private Map<String, String> urlParamToMap(String params) {
        HashMap<String, String> map = new HashMap<>();
        if (ObjectUtils.isEmpty(params)) {
            return map;
        }
        String[] paramsArray = params.split("&");
        if (paramsArray.length == 0) {
            return map;
        }
        for (String param : paramsArray) {
            String[] paramArray = param.split("=");
            if (paramArray.length == 2) {
                map.put(paramArray[0], paramArray[1]);
            }
        }
        return map;
    }
}
src/main/java/com/genersoft/iot/vmp/media/zlm/dto/ZLMServerConfig.java
@@ -331,6 +331,9 @@
    @JSONField(name = "shell.shell")
    private String shellPhell;
    @JSONField(name = "transcode.suffix")
    private String transcodeSuffix;
    public String getHookIp() {
        return hookIp;
@@ -1211,4 +1214,12 @@
    public void setHookOnRtpServerTimeout(String hookOnRtpServerTimeout) {
        this.hookOnRtpServerTimeout = hookOnRtpServerTimeout;
    }
    public String getTranscodeSuffix() {
        return transcodeSuffix;
    }
    public void setTranscodeSuffix(String transcodeSuffix) {
        this.transcodeSuffix = transcodeSuffix;
    }
}
src/main/java/com/genersoft/iot/vmp/media/zlm/dto/hook/OnRecordMp4HookParam.java
@@ -15,6 +15,7 @@
    private String vhost;
    private long start_time;
    private double time_len;
    private String params;
    public String getApp() {
        return app;
@@ -96,6 +97,14 @@
        this.time_len = time_len;
    }
    public String getParams() {
        return params;
    }
    public void setParams(String params) {
        this.params = params;
    }
    @Override
    public String toString() {
        return "OnRecordMp4HookParam{" +
@@ -109,6 +118,7 @@
                ", vhost='" + vhost + '\'' +
                ", start_time=" + start_time +
                ", time_len=" + time_len +
                ", params=" + params +
                '}';
    }
}
src/main/java/com/genersoft/iot/vmp/service/ICloudRecordService.java
@@ -17,7 +17,12 @@
    /**
     * åˆ†é¡µå›žåŽ»äº‘ç«¯å½•åƒåˆ—è¡¨
     */
    PageInfo<CloudRecordItem> getList(int page, int count, String query,  String app, String stream, String startTime, String endTime, List<MediaServer> mediaServerItems);
    PageInfo<CloudRecordItem> getList(int page, int count, String query,  String app, String stream, String startTime, String endTime, List<MediaServer> mediaServerItems, String callId);
    /**
     * æ ¹æ®hook消息增加一条记录
     */
    void addRecord(OnRecordMp4HookParam param);
    /**
     * èŽ·å–æ‰€æœ‰çš„æ—¥æœŸ
@@ -50,4 +55,6 @@
     * èŽ·å–æ’­æ”¾åœ°å€
     */
    DownloadFileInfo getPlayUrlPath(Integer recordId);
    List<CloudRecordItem> getAllList(String query, String app, String stream, String startTime, String endTime, List<MediaServerItem> mediaServerItems, String callId, List<Integer> ids);
}
src/main/java/com/genersoft/iot/vmp/service/IMobilePositionService.java
New file
@@ -0,0 +1,13 @@
package com.genersoft.iot.vmp.service;
import com.genersoft.iot.vmp.gb28181.bean.MobilePosition;
import java.util.List;
public interface IMobilePositionService {
    void add(List<MobilePosition> mobilePositionList);
    void add(MobilePosition mobilePosition);
}
src/main/java/com/genersoft/iot/vmp/service/bean/CloudRecordItem.java
@@ -2,6 +2,9 @@
import com.genersoft.iot.vmp.media.event.media.MediaRecordMp4Event;
import com.genersoft.iot.vmp.media.zlm.dto.hook.OnRecordMp4HookParam;
import com.genersoft.iot.vmp.utils.MediaServerUtils;
import java.util.Map;
/**
 * äº‘端录像数据
@@ -89,6 +92,10 @@
        cloudRecordItem.setMediaServerId(param.getMediaServer().getId());
        cloudRecordItem.setTimeLen((long) param.getRecordInfo().getTimeLen() * 1000);
        cloudRecordItem.setEndTime((param.getRecordInfo().getStartTime() + (long)param.getRecordInfo().getTimeLen()) * 1000);
        Map<String, String> paramsMap = MediaServerUtils.urlParamToMap(param.getParams());
        if (paramsMap.get("callId") != null) {
            cloudRecordItem.setCallId(paramsMap.get("callId"));
        }
        return cloudRecordItem;
    }
src/main/java/com/genersoft/iot/vmp/service/impl/CloudRecordServiceImpl.java
@@ -9,6 +9,8 @@
import com.genersoft.iot.vmp.media.zlm.AssistRESTfulUtils;
import com.genersoft.iot.vmp.media.bean.MediaServer;
import com.genersoft.iot.vmp.media.zlm.dto.StreamAuthorityInfo;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.media.zlm.dto.hook.OnRecordMp4HookParam;
import com.genersoft.iot.vmp.service.ICloudRecordService;
import com.genersoft.iot.vmp.media.service.IMediaServerService;
import com.genersoft.iot.vmp.service.bean.CloudRecordItem;
@@ -28,8 +30,12 @@
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import java.time.*;
import java.util.*;
import java.time.LocalDate;
import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@Service
@DS("share")
@@ -53,7 +59,7 @@
    private VideoStreamSessionManager streamSession;
    @Override
    public PageInfo<CloudRecordItem> getList(int page, int count, String query, String app, String stream, String startTime, String endTime, List<MediaServer> mediaServerItems) {
    public PageInfo<CloudRecordItem> getList(int page, int count, String query, String app, String stream, String startTime, String endTime, List<MediaServerItem> mediaServerItems, String callId) {
        // å¼€å§‹æ—¶é—´å’Œç»“束时间在数据库中都是以秒为单位的
        Long startTimeStamp = null;
        Long endTimeStamp = null;
@@ -73,7 +79,7 @@
        }
        PageHelper.startPage(page, count);
        List<CloudRecordItem> all = cloudRecordServiceMapper.getList(query, app, stream, startTimeStamp, endTimeStamp,
                null, mediaServerItems);
                callId, mediaServerItems, null);
        return new PageInfo<>(all);
    }
@@ -89,7 +95,7 @@
        long startTimeStamp = startDate.atStartOfDay().toInstant(ZoneOffset.ofHours(8)).getEpochSecond() * 1000;
        long endTimeStamp = endDate.atStartOfDay().toInstant(ZoneOffset.ofHours(8)).getEpochSecond() * 1000;
        List<CloudRecordItem> cloudRecordItemList = cloudRecordServiceMapper.getList(null, app, stream, startTimeStamp,
                endTimeStamp, null, mediaServerItems);
                endTimeStamp, null, mediaServerItems, null);
        if (cloudRecordItemList.isEmpty()) {
            return new ArrayList<>();
        }
@@ -105,10 +111,6 @@
    @EventListener
    public void onApplicationEvent(MediaRecordMp4Event event) {
        CloudRecordItem cloudRecordItem = CloudRecordItem.getInstance(event);
        StreamAuthorityInfo streamAuthorityInfo = redisCatchStorage.getStreamAuthorityInfo(event.getApp(), event.getStream());
        if (streamAuthorityInfo != null) {
            cloudRecordItem.setCallId(streamAuthorityInfo.getCallId());
        }
        logger.info("[添加录像记录] {}/{} å†…容:{}", event.getApp(), event.getStream(), event.getRecordInfo());
        cloudRecordServiceMapper.add(cloudRecordItem);
    }
@@ -199,7 +201,7 @@
        }
        List<CloudRecordItem> all = cloudRecordServiceMapper.getList(null, app, stream, startTimeStamp, endTimeStamp,
                callId, mediaServerItems);
                callId, mediaServerItems, null);
        if (all.isEmpty()) {
            throw new ControllerException(ErrorCode.ERROR100.getCode(), "未找到待收藏的视频");
        }
@@ -235,4 +237,27 @@
        MediaServer mediaServerItem = mediaServerService.getOne(recordItem.getMediaServerId());
        return CloudRecordUtils.getDownloadFilePath(mediaServerItem, filePath);
    }
    @Override
    public List<CloudRecordItem> getAllList(String query, String app, String stream, String startTime, String endTime, List<MediaServerItem> mediaServerItems, String callId, List<Integer> ids) {
        // å¼€å§‹æ—¶é—´å’Œç»“束时间在数据库中都是以秒为单位的
        Long startTimeStamp = null;
        Long endTimeStamp = null;
        if (startTime != null ) {
            if (!DateUtil.verification(startTime, DateUtil.formatter)) {
                throw new ControllerException(ErrorCode.ERROR100.getCode(), "开始时间格式错误,正确格式为: " + DateUtil.formatter);
            }
            startTimeStamp = DateUtil.yyyy_MM_dd_HH_mm_ssToTimestampMs(startTime);
        }
        if (endTime != null ) {
            if (!DateUtil.verification(endTime, DateUtil.formatter)) {
                throw new ControllerException(ErrorCode.ERROR100.getCode(), "结束时间格式错误,正确格式为: " + DateUtil.formatter);
            }
            endTimeStamp = DateUtil.yyyy_MM_dd_HH_mm_ssToTimestampMs(endTime);
        }
        return cloudRecordServiceMapper.getList(query, app, stream, startTimeStamp, endTimeStamp,
                callId, mediaServerItems, ids);
    }
}
src/main/java/com/genersoft/iot/vmp/service/impl/MediaServiceImpl.java
@@ -12,6 +12,12 @@
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
import com.genersoft.iot.vmp.media.bean.MediaServer;
import com.genersoft.iot.vmp.media.bean.ResultForOnPublish;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.genersoft.iot.vmp.common.StreamInfo;
import com.genersoft.iot.vmp.conf.MediaConfig;
import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.media.zlm.dto.StreamAuthorityInfo;
import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem;
import com.genersoft.iot.vmp.service.*;
src/main/java/com/genersoft/iot/vmp/service/impl/MobilePositionServiceImpl.java
New file
@@ -0,0 +1,95 @@
package com.genersoft.iot.vmp.service.impl;
import com.genersoft.iot.vmp.conf.UserSetting;
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
import com.genersoft.iot.vmp.gb28181.bean.MobilePosition;
import com.genersoft.iot.vmp.service.IMobilePositionService;
import com.genersoft.iot.vmp.storager.dao.DeviceChannelMapper;
import com.genersoft.iot.vmp.storager.dao.DeviceMobilePositionMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Service
public class MobilePositionServiceImpl implements IMobilePositionService {
    @Autowired
    private DeviceChannelMapper channelMapper;
    @Autowired
    private DeviceMobilePositionMapper mobilePositionMapper;
    @Autowired
    private UserSetting userSetting;
    @Autowired
    private RedisTemplate<String, MobilePosition> redisTemplate;
    private final static Logger logger = LoggerFactory.getLogger(MobilePositionServiceImpl.class);
    private final String REDIS_MOBILE_POSITION_LIST = "redis_mobile_position_list";
    @Override
    public void add(MobilePosition mobilePosition) {
        List<MobilePosition> list = new ArrayList<>();
        list.add(mobilePosition);
        add(list);
    }
    @Override
    public void add(List<MobilePosition> mobilePositionList) {
        redisTemplate.opsForList().leftPushAll(REDIS_MOBILE_POSITION_LIST, mobilePositionList);
    }
    private List<MobilePosition> get(int length) {
        Long size = redisTemplate.opsForList().size(REDIS_MOBILE_POSITION_LIST);
        if (size == null || size == 0) {
            return new ArrayList<>();
        }
        List<MobilePosition> mobilePositions;
        if (size > length) {
            mobilePositions = redisTemplate.opsForList().rightPop(REDIS_MOBILE_POSITION_LIST, length);
        }else {
            mobilePositions = redisTemplate.opsForList().rightPop(REDIS_MOBILE_POSITION_LIST, size);
        }
        return  mobilePositions;
    }
    @Scheduled(fixedRate = 1000)
    @Transactional
    public void executeTaskQueue() {
        int countLimit = 3000;
        List<MobilePosition> mobilePositions = get(countLimit);
        if (mobilePositions == null || mobilePositions.isEmpty()) {
            return;
        }
        if (userSetting.getSavePositionHistory()) {
            mobilePositionMapper.batchadd(mobilePositions);
        }
        logger.info("[移动位置订阅]更新通道位置: {}", mobilePositions.size());
        Map<String, DeviceChannel> updateChannelMap = new HashMap<>();
        for (MobilePosition mobilePosition : mobilePositions) {
            DeviceChannel deviceChannel = new DeviceChannel();
            deviceChannel.setDeviceId(mobilePosition.getDeviceId());
            deviceChannel.setLongitude(mobilePosition.getLongitude());
            deviceChannel.setLatitude(mobilePosition.getLatitude());
            deviceChannel.setGpsTime(mobilePosition.getTime());
            updateChannelMap.put(mobilePosition.getDeviceId() + mobilePosition.getChannelId(), deviceChannel);
        }
        List<DeviceChannel> channels = new ArrayList<>(updateChannelMap.values());
        channelMapper.batchUpdatePosition(channels);
    }
}
src/main/java/com/genersoft/iot/vmp/service/impl/StreamProxyServiceImpl.java
@@ -349,6 +349,9 @@
        }
        String msgResult;
        if ("ffmpeg".equalsIgnoreCase(param.getType())){
            if (param.getTimeoutMs() == 0) {
                param.setTimeoutMs(15);
            }
            result = mediaServerService.addFFmpegSource(mediaServer, param.getSrcUrl().trim(), param.getDstUrl(),
                    param.getTimeoutMs(), param.isEnableAudio(), param.isEnableMp4(),
                    param.getFfmpegCmdKey());
@@ -406,6 +409,7 @@
            gbStreamMapper.del(app, stream);
            videoManagerStorager.deleteStreamProxy(app, stream);
            redisCatchStorage.removeStream(streamProxyItem.getMediaServerId(), "PULL", app, stream);
            redisCatchStorage.removeStream(streamProxyItem.getMediaServerId(), "PUSH", app, stream);
            Boolean result = removeStreamProxyFromZlm(streamProxyItem);
            if (result != null && result) {
                logger.info("[移除代理]: ä»£ç†ï¼š {}/{}, ä»Žzlm移除成功", app, stream);
src/main/java/com/genersoft/iot/vmp/storager/dao/CloudRecordServiceMapper.java
@@ -50,12 +50,15 @@
            " <if test= 'mediaServerItemList != null  ' > and media_server_id in " +
            " <foreach collection='mediaServerItemList'  item='item'  open='(' separator=',' close=')' > #{item.id}</foreach>" +
            " </if>" +
            " <if test= 'ids != null  ' > and id in " +
            " <foreach collection='ids'  item='item'  open='(' separator=',' close=')' > #{item}</foreach>" +
            " </if>" +
            " order by start_time DESC" +
            " </script>")
    List<CloudRecordItem> getList(@Param("query") String query, @Param("app") String app, @Param("stream") String stream,
                                  @Param("startTimeStamp")Long startTimeStamp, @Param("endTimeStamp")Long endTimeStamp,
                                  @Param("callId")String callId, List<MediaServer> mediaServerItemList);
                                  @Param("callId")String callId, List<MediaServer> mediaServerItemList,
                                  List<Integer> ids);
    @Select(" <script>" +
src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceChannelMapper.java
@@ -402,23 +402,6 @@
            " </script>"})
    int updatePosition(DeviceChannel deviceChannel);
    @Update({"<script>" +
            "<foreach collection='deviceChannelList' item='item' separator=';'>" +
            " UPDATE" +
            " wvp_device_channel" +
            " SET gps_time=#{item.gpsTime}" +
            "<if test='item.longitude != null'>, longitude=#{item.longitude}</if>" +
            "<if test='item.latitude != null'>, latitude=#{item.latitude}</if>" +
            "<if test='item.longitudeGcj02 != null'>, longitude_gcj02=#{item.longitudeGcj02}</if>" +
            "<if test='item.latitudeGcj02 != null'>, latitude_gcj02=#{item.latitudeGcj02}</if>" +
            "<if test='item.longitudeWgs84 != null'>, longitude_wgs84=#{item.longitudeWgs84}</if>" +
            "<if test='item.latitudeWgs84 != null'>, latitude_wgs84=#{item.latitudeWgs84}</if>" +
            "WHERE device_id=#{item.deviceId} " +
            " <if test='item.channelId != null' > AND channel_id=#{item.channelId}</if>" +
            "</foreach>" +
            "</script>"})
    int batchUpdatePosition(List<DeviceChannel> deviceChannelList);
    @Select("SELECT * FROM wvp_device_channel WHERE length(trim(stream_id)) > 0")
    List<DeviceChannel> getAllChannelInPlay();
@@ -572,4 +555,24 @@
            " <if test='channelId != null'> and channel_id = #{channelId} </if>" +
            "</script>")
    void updateChannelStreamIdentification(DeviceChannel channel);
    @Update({"<script>" +
            "<foreach collection='channelList' item='item' separator=';'>" +
            " UPDATE" +
            " wvp_device_channel" +
            " SET update_time=#{item.updateTime}" +
            "<if test='item.longitude != null'>, longitude=#{item.longitude}</if>" +
            "<if test='item.latitude != null'>, latitude=#{item.latitude}</if>" +
            "<if test='item.longitudeGcj02 != null'>, longitude_gcj02=#{item.longitudeGcj02}</if>" +
            "<if test='item.latitudeGcj02 != null'>, latitude_gcj02=#{item.latitudeGcj02}</if>" +
            "<if test='item.longitudeWgs84 != null'>, longitude_wgs84=#{item.longitudeWgs84}</if>" +
            "<if test='item.latitudeWgs84 != null'>, latitude_wgs84=#{item.latitudeWgs84}</if>" +
            "<if test='item.gpsTime != null'>, gps_time=#{item.gpsTime}</if>" +
            "<if test='item.id > 0'>WHERE id=#{item.id}</if>" +
            "<if test='item.id == 0'>WHERE device_id=#{item.deviceId} AND channel_id=#{item.channelId}</if>" +
            "</foreach>" +
            "</script>"})
    void batchUpdatePosition(List<DeviceChannel> channelList);
}
src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceMobilePositionMapper.java
@@ -49,7 +49,7 @@
    void batchadd2(List<MobilePosition> mobilePositions);
    @Insert("<script> " +
            "<foreach collection='mobilePositions' index='index' item='item' separator=','> " +
            "<foreach collection='mobilePositions' index='index' item='item' separator=';'> " +
            "insert into wvp_device_mobile_position " +
            "(device_id,channel_id, device_name,time,longitude,latitude,altitude,speed,direction,report_source," +
            "longitude_gcj02,latitude_gcj02,longitude_wgs84,latitude_wgs84,create_time)"+
@@ -57,7 +57,7 @@
            "(#{item.deviceId}, #{item.channelId}, #{item.deviceName}, #{item.time}, #{item.longitude}, " +
            "#{item.latitude}, #{item.altitude}, #{item.speed},#{item.direction}," +
            "#{item.reportSource}, #{item.longitudeGcj02}, #{item.latitudeGcj02}, #{item.longitudeWgs84}, #{item.latitudeWgs84}, " +
            "#{item.createTime}); " +
            "#{item.createTime}) " +
            "</foreach> " +
            "</script>")
    void batchadd(List<MobilePosition> mobilePositions);
src/main/java/com/genersoft/iot/vmp/storager/dao/MediaServerMapper.java
@@ -41,6 +41,7 @@
            "type,"+
            "create_time,"+
            "update_time,"+
            "transcode_suffix,"+
            "hook_alive_interval"+
            ") VALUES " +
            "(" +
@@ -72,6 +73,7 @@
            "#{type}, " +
            "#{createTime}, " +
            "#{updateTime}, " +
            "#{transcodeSuffix}, " +
            "#{hookAliveInterval})")
    int add(MediaServer mediaServerItem);
@@ -102,6 +104,7 @@
            "<if test=\"hookAliveInterval != null\">, hook_alive_interval=#{hookAliveInterval}</if>" +
            "<if test=\"recordDay != null\">, record_day=#{recordDay}</if>" +
            "<if test=\"recordPath != null\">, record_path=#{recordPath}</if>" +
            "<if test=\"transcodeSuffix != null\">, transcode_suffix=#{transcodeSuffix}</if>" +
            "<if test=\"type != null\">, type=#{type}</if>" +
            "WHERE id=#{id}"+
            " </script>"})
@@ -133,6 +136,7 @@
            "<if test=\"recordDay != null\">, record_day=#{recordDay}</if>" +
            "<if test=\"recordPath != null\">, record_path=#{recordPath}</if>" +
            "<if test=\"type != null\">, type=#{type}</if>" +
            "<if test=\"transcodeSuffix != null\">, transcode_suffix=#{transcodeSuffix}</if>" +
            "<if test=\"hookAliveInterval != null\">, hook_alive_interval=#{hookAliveInterval}</if>" +
            "WHERE ip=#{ip} and http_port=#{httpPort}"+
            " </script>"})
src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java
@@ -576,7 +576,7 @@
    @Override
    public void sendMobilePositionMsg(JSONObject jsonObject) {
        String key = VideoManagerConstants.VM_MSG_SUBSCRIBE_MOBILE_POSITION;
//        logger.info("[redis发送通知] å‘送 ç§»åŠ¨ä½ç½® {}: {}", key, jsonObject.toString());
        logger.debug("[redis发送通知] å‘送 ç§»åŠ¨ä½ç½® {}: {}", key, jsonObject.toString());
        redisTemplate.convertAndSend(key, jsonObject);
    }
src/main/java/com/genersoft/iot/vmp/utils/DateUtil.java
@@ -107,6 +107,14 @@
    }
    /**
     * æ—¶é—´æˆ³ è½¬ yyyy_MM_dd_HH_mm_ss
     */
    public static String timestampMsToUrlToyyyy_MM_dd_HH_mm_ss(long timestamp) {
        Instant instant = Instant.ofEpochMilli(timestamp);
        return urlFormatter.format(LocalDateTime.ofInstant(instant, ZoneId.of(zoneStr)));
    }
    /**
     * yyyy_MM_dd_HH_mm_ss è½¬æ—¶é—´æˆ³ï¼ˆæ¯«ç§’)
     *
     * @param formatTime
src/main/java/com/genersoft/iot/vmp/utils/MediaServerUtils.java
New file
@@ -0,0 +1,26 @@
package com.genersoft.iot.vmp.utils;
import org.springframework.util.ObjectUtils;
import java.util.HashMap;
import java.util.Map;
public class MediaServerUtils {
    public static Map<String, String> urlParamToMap(String params) {
        HashMap<String, String> map = new HashMap<>();
        if (ObjectUtils.isEmpty(params)) {
            return map;
        }
        String[] paramsArray = params.split("&");
        if (paramsArray.length == 0) {
            return map;
        }
        for (String param : paramsArray) {
            String[] paramArray = param.split("=");
            if (paramArray.length == 2) {
                map.put(paramArray[0], paramArray[1]);
            }
        }
        return map;
    }
}
src/main/java/com/genersoft/iot/vmp/vmanager/cloudRecord/CloudRecordController.java
@@ -8,7 +8,9 @@
import com.genersoft.iot.vmp.media.service.IMediaServerService;
import com.genersoft.iot.vmp.service.bean.CloudRecordItem;
import com.genersoft.iot.vmp.service.bean.DownloadFileInfo;
import com.genersoft.iot.vmp.utils.DateUtil;
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
import com.genersoft.iot.vmp.vmanager.cloudRecord.bean.CloudRecordUrl;
import com.github.pagehelper.PageInfo;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
@@ -21,9 +23,15 @@
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
@SuppressWarnings("rawtypes")
@Tag(name = "云端录像接口")
@@ -96,6 +104,7 @@
    @Parameter(name = "startTime", description = "开始时间(yyyy-MM-dd HH:mm:ss)", required = false)
    @Parameter(name = "endTime", description = "结束时间(yyyy-MM-dd HH:mm:ss)", required = false)
    @Parameter(name = "mediaServerId", description = "流媒体ID,置空则查询全部流媒体", required = false)
    @Parameter(name = "callId", description = "每次录像的唯一标识,置空则查询全部流媒体", required = false)
    public PageInfo<CloudRecordItem> openRtpServer(
            @RequestParam(required = false)  String query,
            @RequestParam(required = false)  String app,
@@ -104,11 +113,12 @@
            @RequestParam int count,
            @RequestParam(required = false)  String startTime,
            @RequestParam(required = false)  String endTime,
            @RequestParam(required = false) String mediaServerId
            @RequestParam(required = false) String mediaServerId,
            @RequestParam(required = false) String callId
    ) {
        logger.info("[云端录像] æŸ¥è¯¢ app->{}, stream->{}, mediaServerId->{}, page->{}, count->{}, startTime->{}, endTime->{}",
                app, stream, mediaServerId, page, count, startTime, endTime);
        logger.info("[云端录像] æŸ¥è¯¢ app->{}, stream->{}, mediaServerId->{}, page->{}, count->{}, startTime->{}, endTime->{}, callId->{}",
                app, stream, mediaServerId, page, count, startTime, endTime, callId);
        List<MediaServer> mediaServerItems;
        if (!ObjectUtils.isEmpty(mediaServerId)) {
@@ -139,7 +149,10 @@
        if (endTime != null && ObjectUtils.isEmpty(endTime.trim())) {
            endTime = null;
        }
        return cloudRecordService.getList(page, count, query, app, stream, startTime, endTime, mediaServerItems);
        if (callId != null && ObjectUtils.isEmpty(callId.trim())) {
            callId = null;
        }
        return cloudRecordService.getList(page, count, query, app, stream, startTime, endTime, mediaServerItems, callId);
    }
    @ResponseBody
@@ -265,4 +278,212 @@
    ){
        return cloudRecordService.getPlayUrlPath(recordId);
    }
    /************************* ä»¥ä¸‹è¿™äº›æŽ¥å£åªé€‚合wvp和zlm部署在同一台服务器的情况,且wvp只有一个zlm节点的情况 ***************************************/
    /**
     * ä¸‹è½½æŒ‡å®šå½•像文件的压缩包
     * @param query æ£€ç´¢å†…容
     * @param app åº”用名
     * @param stream æµID
     * @param startTime å¼€å§‹æ—¶é—´(yyyy-MM-dd HH:mm:ss)
     * @param endTime ç»“束时间(yyyy-MM-dd HH:mm:ss)
     * @param mediaServerId æµåª’体ID,置空则查询全部流媒体
     * @param callId æ¯æ¬¡å½•像的唯一标识,置空则查询全部流媒体
     * @param ids æŒ‡å®šçš„Id
     */
    @ResponseBody
    @GetMapping("/zip")
    public void downloadZipFile(
            HttpServletResponse response,
            @RequestParam(required = false) String query,
            @RequestParam(required = false) String app,
            @RequestParam(required = false) String stream,
            @RequestParam(required = false) String startTime,
            @RequestParam(required = false) String endTime,
            @RequestParam(required = false) String mediaServerId,
            @RequestParam(required = false) String callId,
            @RequestParam(required = false) List<Integer> ids
    ) {
        logger.info("[下载指定录像文件的压缩包] æŸ¥è¯¢ app->{}, stream->{}, mediaServerId->{}, startTime->{}, endTime->{}, callId->{}",
                app, stream, mediaServerId, startTime, endTime, callId);
        List<MediaServerItem> mediaServerItems;
        if (!ObjectUtils.isEmpty(mediaServerId)) {
            mediaServerItems = new ArrayList<>();
            MediaServerItem mediaServerItem = mediaServerService.getOne(mediaServerId);
            if (mediaServerItem == null) {
                throw new ControllerException(ErrorCode.ERROR100.getCode(), "未找到流媒体: " + mediaServerId);
            }
            mediaServerItems.add(mediaServerItem);
        } else {
            mediaServerItems = mediaServerService.getAll();
        }
        if (mediaServerItems.isEmpty()) {
            throw new ControllerException(ErrorCode.ERROR100.getCode(), "当前无流媒体");
        }
        if (query != null && ObjectUtils.isEmpty(query.trim())) {
            query = null;
        }
        if (app != null && ObjectUtils.isEmpty(app.trim())) {
            app = null;
        }
        if (stream != null && ObjectUtils.isEmpty(stream.trim())) {
            stream = null;
        }
        if (startTime != null && ObjectUtils.isEmpty(startTime.trim())) {
            startTime = null;
        }
        if (endTime != null && ObjectUtils.isEmpty(endTime.trim())) {
            endTime = null;
        }
        if (callId != null && ObjectUtils.isEmpty(callId.trim())) {
            callId = null;
        }
        if (stream != null && callId != null) {
            response.addHeader( "Content-Disposition", "attachment;filename=" + stream + "_" + callId + ".zip" );
        }
        List<CloudRecordItem> cloudRecordItemList = cloudRecordService.getAllList(query, app, stream, startTime, endTime, mediaServerItems, callId, ids);
        if (ObjectUtils.isEmpty(cloudRecordItemList)) {
            return;
        }
        try {
            ZipOutputStream zos = new ZipOutputStream(response.getOutputStream());
            for (CloudRecordItem cloudRecordItem : cloudRecordItemList) {
                zos.putNextEntry(new ZipEntry(DateUtil.timestampMsToUrlToyyyy_MM_dd_HH_mm_ss(cloudRecordItem.getStartTime()) + ".mp4"));
                File file = new File(cloudRecordItem.getFilePath());
                if (!file.exists() || file.isDirectory()) {
                    continue;
                }
                FileInputStream fis = new FileInputStream(cloudRecordItem.getFilePath());
                byte[] buf = new byte[2*1024];
                int len;
                while ((len = fis.read(buf)) != -1){
                    zos.write(buf, 0, len);
                }
                zos.closeEntry();
                fis.close();
            }
            zos.close();
        } catch (IOException e) {
            logger.error("[下载指定录像文件的压缩包] å¤±è´¥ï¼š æŸ¥è¯¢ app->{}, stream->{}, mediaServerId->{}, startTime->{}, endTime->{}, callId->{}",
                    app, stream, mediaServerId, startTime, endTime, callId, e);
        }
    }
    /**
     *
     * @param query æ£€ç´¢å†…容
     * @param app åº”用名
     * @param stream æµID
     * @param startTime å¼€å§‹æ—¶é—´(yyyy-MM-dd HH:mm:ss)
     * @param endTime ç»“束时间(yyyy-MM-dd HH:mm:ss)
     * @param mediaServerId æµåª’体ID,置空则查询全部流媒体
     * @param callId æ¯æ¬¡å½•像的唯一标识,置空则查询全部流媒体
     * @param remoteHost æ‹¼æŽ¥æ’­æ”¾åœ°å€æ—¶ä½¿ç”¨çš„远程地址
     */
    @ResponseBody
    @GetMapping("/list-url")
    @Operation(summary = "分页查询云端录像", security = @SecurityRequirement(name = JwtUtils.HEADER))
    @Parameter(name = "query", description = "检索内容", required = false)
    @Parameter(name = "app", description = "应用名", required = false)
    @Parameter(name = "stream", description = "流ID", required = false)
    @Parameter(name = "page", description = "当前页", required = true)
    @Parameter(name = "count", description = "每页查询数量", required = true)
    @Parameter(name = "startTime", description = "开始时间(yyyy-MM-dd HH:mm:ss)", required = false)
    @Parameter(name = "endTime", description = "结束时间(yyyy-MM-dd HH:mm:ss)", required = false)
    @Parameter(name = "mediaServerId", description = "流媒体ID,置空则查询全部流媒体", required = false)
    @Parameter(name = "callId", description = "每次录像的唯一标识,置空则查询全部流媒体", required = false)
    public PageInfo<CloudRecordUrl> getListWithUrl(
            HttpServletRequest request,
            @RequestParam(required = false)  String query,
            @RequestParam(required = false)  String app,
            @RequestParam(required = false)  String stream,
            @RequestParam int page,
            @RequestParam int count,
            @RequestParam(required = false)  String startTime,
            @RequestParam(required = false)  String endTime,
            @RequestParam(required = false) String mediaServerId,
            @RequestParam(required = false) String callId,
            @RequestParam(required = false) String remoteHost
    ) {
        logger.info("[云端录像] æŸ¥è¯¢URL app->{}, stream->{}, mediaServerId->{}, page->{}, count->{}, startTime->{}, endTime->{}, callId->{}",
                app, stream, mediaServerId, page, count, startTime, endTime, callId);
        List<MediaServerItem> mediaServerItems;
        if (!ObjectUtils.isEmpty(mediaServerId)) {
            mediaServerItems = new ArrayList<>();
            MediaServerItem mediaServerItem = mediaServerService.getOne(mediaServerId);
            if (mediaServerItem == null) {
                throw new ControllerException(ErrorCode.ERROR100.getCode(), "未找到流媒体: " + mediaServerId);
            }
            mediaServerItems.add(mediaServerItem);
        } else {
            mediaServerItems = mediaServerService.getAll();
        }
        if (mediaServerItems.isEmpty()) {
            throw new ControllerException(ErrorCode.ERROR100.getCode(), "当前无流媒体");
        }
        if (query != null && ObjectUtils.isEmpty(query.trim())) {
            query = null;
        }
        if (app != null && ObjectUtils.isEmpty(app.trim())) {
            app = null;
        }
        if (stream != null && ObjectUtils.isEmpty(stream.trim())) {
            stream = null;
        }
        if (startTime != null && ObjectUtils.isEmpty(startTime.trim())) {
            startTime = null;
        }
        if (endTime != null && ObjectUtils.isEmpty(endTime.trim())) {
            endTime = null;
        }
        if (callId != null && ObjectUtils.isEmpty(callId.trim())) {
            callId = null;
        }
        MediaServerItem mediaServerItem = mediaServerService.getDefaultMediaServer();
        if (mediaServerItem == null) {
            throw new ControllerException(ErrorCode.ERROR100.getCode(), "未找到流媒体节点");
        }
        if (remoteHost == null) {
            remoteHost = request.getScheme() + "://" + request.getLocalAddr() + ":" +
                    (request.getScheme().equals("https")? mediaServerItem.getHttpSSlPort() : mediaServerItem.getHttpPort());
        }
        PageInfo<CloudRecordItem> cloudRecordItemPageInfo = cloudRecordService.getList(page, count, query, app, stream, startTime, endTime, mediaServerItems, callId);
        PageInfo<CloudRecordUrl> cloudRecordUrlPageInfo = new PageInfo<>();
        if (!ObjectUtils.isEmpty(cloudRecordItemPageInfo)) {
            cloudRecordUrlPageInfo.setPageNum(cloudRecordItemPageInfo.getPageNum());
            cloudRecordUrlPageInfo.setPageSize(cloudRecordItemPageInfo.getPageSize());
            cloudRecordUrlPageInfo.setSize(cloudRecordItemPageInfo.getSize());
            cloudRecordUrlPageInfo.setEndRow(cloudRecordItemPageInfo.getEndRow());
            cloudRecordUrlPageInfo.setStartRow(cloudRecordItemPageInfo.getStartRow());
            cloudRecordUrlPageInfo.setPages(cloudRecordItemPageInfo.getPages());
            cloudRecordUrlPageInfo.setPrePage(cloudRecordItemPageInfo.getPrePage());
            cloudRecordUrlPageInfo.setNextPage(cloudRecordItemPageInfo.getNextPage());
            cloudRecordUrlPageInfo.setIsFirstPage(cloudRecordItemPageInfo.isIsFirstPage());
            cloudRecordUrlPageInfo.setIsLastPage(cloudRecordItemPageInfo.isIsLastPage());
            cloudRecordUrlPageInfo.setHasPreviousPage(cloudRecordItemPageInfo.isHasPreviousPage());
            cloudRecordUrlPageInfo.setHasNextPage(cloudRecordItemPageInfo.isHasNextPage());
            cloudRecordUrlPageInfo.setNavigatePages(cloudRecordItemPageInfo.getNavigatePages());
            cloudRecordUrlPageInfo.setNavigateFirstPage(cloudRecordItemPageInfo.getNavigateFirstPage());
            cloudRecordUrlPageInfo.setNavigateLastPage(cloudRecordItemPageInfo.getNavigateLastPage());
            cloudRecordUrlPageInfo.setNavigatepageNums(cloudRecordItemPageInfo.getNavigatepageNums());
            cloudRecordUrlPageInfo.setTotal(cloudRecordItemPageInfo.getTotal());
            List<CloudRecordUrl> cloudRecordUrlList = new ArrayList<>(cloudRecordItemPageInfo.getList().size());
            List<CloudRecordItem> cloudRecordItemList = cloudRecordItemPageInfo.getList();
            for (CloudRecordItem cloudRecordItem : cloudRecordItemList) {
                CloudRecordUrl cloudRecordUrl = new CloudRecordUrl();
                cloudRecordUrl.setId(cloudRecordItem.getId());
                cloudRecordUrl.setDownloadUrl(remoteHost + "/index/api/downloadFile?file_path=" + cloudRecordItem.getFilePath()
                        + "&save_name=" + cloudRecordItem.getStream() + "_" + cloudRecordItem.getCallId() + "_" + DateUtil.timestampMsToUrlToyyyy_MM_dd_HH_mm_ss(cloudRecordItem.getStartTime()) );
                cloudRecordUrl.setPlayUrl(remoteHost + "/index/api/downloadFile?file_path=" + cloudRecordItem.getFilePath());
                cloudRecordUrlList.add(cloudRecordUrl);
            }
            cloudRecordUrlPageInfo.setList(cloudRecordUrlList);
        }
        return cloudRecordUrlPageInfo;
    }
}
src/main/java/com/genersoft/iot/vmp/vmanager/cloudRecord/bean/CloudRecordUrl.java
New file
@@ -0,0 +1,32 @@
package com.genersoft.iot.vmp.vmanager.cloudRecord.bean;
public class CloudRecordUrl {
    private String playUrl;
    private String downloadUrl;
    private int id;
    public String getPlayUrl() {
        return playUrl;
    }
    public void setPlayUrl(String playUrl) {
        this.playUrl = playUrl;
    }
    public String getDownloadUrl() {
        return downloadUrl;
    }
    public void setDownloadUrl(String downloadUrl) {
        this.downloadUrl = downloadUrl;
    }
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
}
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/PlayController.java
@@ -31,6 +31,7 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.context.request.async.DeferredResult;
@@ -129,6 +130,9 @@
                        }
                        streamInfo.channgeStreamIp(host);
                    }
                    if (!ObjectUtils.isEmpty(newMediaServerItem.getTranscodeSuffix()) && !"null".equalsIgnoreCase(newMediaServerItem.getTranscodeSuffix())) {
                        streamInfo.setStream(streamInfo.getStream() + "_" + newMediaServerItem.getTranscodeSuffix());
                    }
                    wvpResult.setData(new StreamContent(streamInfo));
                }else {
                    wvpResult.setCode(code);
src/main/resources/all-application.yml
@@ -241,6 +241,8 @@
    register-again-after-time: 60
    # å›½æ ‡ç»­è®¢æ–¹å¼ï¼Œtrue为续订,每次注册在同一个会话里,false为重新注册,每次使用新的会话
    register-keep-int-dialog: false
    # å¼€å¯æŽ¥å£æ–‡æ¡£é¡µé¢ã€‚ é»˜è®¤å¼€å¯ï¼Œç”Ÿäº§çŽ¯å¢ƒå»ºè®®å…³é—­ï¼Œé‡åˆ°swagger相关的漏洞时也可以关闭
    doc-enable: true
    # è·¨åŸŸé…ç½®ï¼Œä¸é…ç½®æ­¤é¡¹åˆ™å…è®¸æ‰€æœ‰è·¨åŸŸè¯·æ±‚,配置后则只允许配置的页面的地址请求, å¯ä»¥é…ç½®å¤šä¸ª
    allowed-origins:
        - http://localhost:8008
src/main/resources/application-dev.yml
@@ -112,7 +112,4 @@
  auto-apply-play: true
  # è®¾å¤‡/通道状态变化时发送消息
  device-status-notify: true
# [可选] æ—¥å¿—配置, ä¸€èˆ¬ä¸éœ€è¦æ”¹
logging:
  config: classpath:logback-spring.xml
Êý¾Ý¿â/2.7.1/³õʼ»¯-mysql-2.7.1.sql
New file
@@ -0,0 +1,325 @@
/*建表*/
create table wvp_device (
                            id serial primary key ,
                            device_id character varying(50) not null ,
                            name character varying(255),
                            manufacturer character varying(255),
                            model character varying(255),
                            firmware character varying(255),
                            transport character varying(50),
                            stream_mode character varying(50),
                            on_line bool default false,
                            register_time character varying(50),
                            keepalive_time character varying(50),
                            ip character varying(50),
                            create_time character varying(50),
                            update_time character varying(50),
                            port integer,
                            expires integer,
                            subscribe_cycle_for_catalog integer DEFAULT 0,
                            subscribe_cycle_for_mobile_position integer DEFAULT 0,
                            mobile_position_submission_interval integer DEFAULT 5,
                            subscribe_cycle_for_alarm integer DEFAULT 0,
                            host_address character varying(50),
                            charset character varying(50),
                            ssrc_check bool default false,
                            geo_coord_sys character varying(50),
                            media_server_id character varying(50),
                            custom_name character varying(255),
                            sdp_ip character varying(50),
                            local_ip character varying(50),
                            password character varying(255),
                            as_message_channel bool default false,
                            keepalive_interval_time integer,
                            broadcast_push_after_ack bool default false,
                            constraint uk_device_device unique (device_id)
);
create table wvp_device_alarm (
                                  id serial primary key ,
                                  device_id character varying(50) not null,
                                  channel_id character varying(50) not null,
                                  alarm_priority character varying(50),
                                  alarm_method character varying(50),
                                  alarm_time character varying(50),
                                  alarm_description character varying(255),
                                  longitude double precision,
                                  latitude double precision,
                                  alarm_type character varying(50),
                                  create_time character varying(50) not null
);
create table wvp_device_channel (
                                    id serial primary key ,
                                    channel_id character varying(50) not null,
                                    name character varying(255),
                                    custom_name character varying(255),
                                    manufacture character varying(50),
                                    model character varying(50),
                                    owner character varying(50),
                                    civil_code character varying(50),
                                    block character varying(50),
                                    address character varying(50),
                                    parent_id character varying(50),
                                    safety_way integer,
                                    register_way integer,
                                    cert_num character varying(50),
                                    certifiable integer,
                                    err_code integer,
                                    end_time character varying(50),
                                    secrecy character varying(50),
                                    ip_address character varying(50),
                                    port integer,
                                    password character varying(255),
                                    ptz_type integer,
                                    custom_ptz_type integer,
                                    status bool default false,
                                    longitude double precision,
                                    custom_longitude double precision,
                                    latitude double precision,
                                    custom_latitude double precision,
                                    stream_id character varying(255),
                                    device_id character varying(50) not null,
                                    parental character varying(50),
                                    has_audio bool default false,
                                    create_time character varying(50) not null,
                                    update_time character varying(50) not null,
                                    sub_count integer,
                                    longitude_gcj02 double precision,
                                    latitude_gcj02 double precision,
                                    longitude_wgs84 double precision,
                                    latitude_wgs84 double precision,
                                    business_group_id character varying(50),
                                    gps_time character varying(50),
                                    stream_identification character varying(50),
                                    constraint uk_wvp_device_channel_unique_device_channel unique (device_id, channel_id)
);
create table wvp_device_mobile_position (
                                            id serial primary key,
                                            device_id character varying(50) not null,
                                            channel_id character varying(50) not null,
                                            device_name character varying(255),
                                            time character varying(50),
                                            longitude double precision,
                                            latitude double precision,
                                            altitude double precision,
                                            speed double precision,
                                            direction double precision,
                                            report_source character varying(50),
                                            longitude_gcj02 double precision,
                                            latitude_gcj02 double precision,
                                            longitude_wgs84 double precision,
                                            latitude_wgs84 double precision,
                                            create_time character varying(50)
);
create table wvp_gb_stream (
                               gb_stream_id serial primary key,
                               app character varying(255) not null,
                               stream character varying(255) not null,
                               gb_id character varying(50) not null,
                               name character varying(255),
                               longitude double precision,
                               latitude double precision,
                               stream_type character varying(50),
                               media_server_id character varying(50),
                               create_time character varying(50),
                               constraint uk_gb_stream_unique_gb_id unique (gb_id),
                               constraint uk_gb_stream_unique_app_stream unique (app, stream)
);
create table wvp_log (
                         id serial primary key ,
                         name character varying(50),
                         type character varying(50),
                         uri character varying(200),
                         address character varying(50),
                         result character varying(50),
                         timing bigint,
                         username character varying(50),
                         create_time character varying(50)
);
create table wvp_media_server (
                                  id character varying(255) primary key ,
                                  ip character varying(50),
                                  hook_ip character varying(50),
                                  sdp_ip character varying(50),
                                  stream_ip character varying(50),
                                  http_port integer,
                                  http_ssl_port integer,
                                  rtmp_port integer,
                                  rtmp_ssl_port integer,
                                  rtp_proxy_port integer,
                                  rtsp_port integer,
                                  rtsp_ssl_port integer,
                                  auto_config bool default false,
                                  secret character varying(50),
                                  rtp_enable bool default false,
                                  rtp_port_range character varying(50),
                                  send_rtp_port_range character varying(50),
                                  record_assist_port integer,
                                  default_server bool default false,
                                  create_time character varying(50),
                                  update_time character varying(50),
                                  hook_alive_interval integer,
                                  record_path character varying(255),
                                  record_day integer default 7,
                                  transcode_suffix character varying(255),
                                  constraint uk_media_server_unique_ip_http_port unique (ip, http_port)
);
create table wvp_platform (
                              id serial primary key ,
                              enable bool default false,
                              name character varying(255),
                              server_gb_id character varying(50),
                              server_gb_domain character varying(50),
                              server_ip character varying(50),
                              server_port integer,
                              device_gb_id character varying(50),
                              device_ip character varying(50),
                              device_port character varying(50),
                              username character varying(255),
                              password character varying(50),
                              expires character varying(50),
                              keep_timeout character varying(50),
                              transport character varying(50),
                              character_set character varying(50),
                              catalog_id character varying(50),
                              ptz bool default false,
                              rtcp bool default false,
                              status bool default false,
                              start_offline_push bool default false,
                              administrative_division character varying(50),
                              catalog_group integer,
                              create_time character varying(50),
                              update_time character varying(50),
                              as_message_channel bool default false,
                              auto_push_channel bool default false,
                              send_stream_ip character varying(50),
                              constraint uk_platform_unique_server_gb_id unique (server_gb_id)
);
create table wvp_platform_catalog (
                                      id character varying(50),
                                      platform_id character varying(50),
                                      name character varying(255),
                                      parent_id character varying(50),
                                      civil_code character varying(50),
                                      business_group_id character varying(50),
                                      constraint uk_platform_catalog_id_platform_id unique (id, platform_id)
);
create table wvp_platform_gb_channel (
                                         id serial primary key ,
                                         platform_id character varying(50),
                                         catalog_id character varying(50),
                                         device_channel_id integer,
                                         constraint uk_platform_gb_channel_platform_id_catalog_id_device_channel_id unique (platform_id, catalog_id, device_channel_id)
);
create table wvp_platform_gb_stream (
                                        id serial primary key,
                                        platform_id character varying(50),
                                        catalog_id character varying(50),
                                        gb_stream_id integer,
                                        constraint uk_platform_gb_stream_platform_id_catalog_id_gb_stream_id unique (platform_id, catalog_id, gb_stream_id)
);
create table wvp_stream_proxy (
                                  id serial primary key,
                                  type character varying(50),
                                  app character varying(255),
                                  stream character varying(255),
                                  url character varying(255),
                                  src_url character varying(255),
                                  dst_url character varying(255),
                                  timeout_ms integer,
                                  ffmpeg_cmd_key character varying(255),
                                  rtp_type character varying(50),
                                  media_server_id character varying(50),
                                  enable_audio bool default false,
                                  enable_mp4 bool default false,
                                  enable bool default false,
                                  status boolean,
                                  enable_remove_none_reader bool default false,
                                  create_time character varying(50),
                                  name character varying(255),
                                  update_time character varying(50),
                                  stream_key character varying(255),
                                  enable_disable_none_reader bool default false,
                                  constraint uk_stream_proxy_app_stream unique (app, stream)
);
create table wvp_stream_push (
                                 id serial primary key,
                                 app character varying(255),
                                 stream character varying(255),
                                 total_reader_count character varying(50),
                                 origin_type integer,
                                 origin_type_str character varying(50),
                                 create_time character varying(50),
                                 alive_second integer,
                                 media_server_id character varying(50),
                                 server_id character varying(50),
                                 push_time character varying(50),
                                 status bool default false,
                                 update_time character varying(50),
                                 push_ing bool default false,
                                 self bool default false,
                                 constraint uk_stream_push_app_stream unique (app, stream)
);
create table wvp_cloud_record (
                                  id serial primary key,
                                  app character varying(255),
                                  stream character varying(255),
                                  call_id character varying(255),
                                  start_time bigint,
                                  end_time bigint,
                                  media_server_id character varying(50),
                                  file_name character varying(255),
                                  folder character varying(255),
                                  file_path character varying(255),
                                  collect bool default false,
                                  file_size bigint,
                                  time_len bigint,
                                  constraint uk_stream_push_app_stream_path unique (app, stream, file_path)
);
create table wvp_user (
                          id serial primary key,
                          username character varying(255),
                          password character varying(255),
                          role_id integer,
                          create_time character varying(50),
                          update_time character varying(50),
                          push_key character varying(50),
                          constraint uk_user_username unique (username)
);
create table wvp_user_role (
                               id serial primary key,
                               name character varying(50),
                               authority character varying(50),
                               create_time character varying(50),
                               update_time character varying(50)
);
create table wvp_resources_tree (
                                    id serial primary key ,
                                    is_catalog bool default true,
                                    device_channel_id integer ,
                                    gb_stream_id integer,
                                    name character varying(255),
                                    parentId integer,
                                    path character varying(255)
);
/*初始数据*/
INSERT INTO wvp_user VALUES (1, 'admin','21232f297a57a5a743894a0e4a801fc3',1,'2021-04-13 14:14:57','2021-04-13 14:14:57','3e80d1762a324d5b0ff636e0bd16f1e3');
INSERT INTO wvp_user_role VALUES (1, 'admin','0','2021-04-13 14:14:57','2021-04-13 14:14:57');
Êý¾Ý¿â/2.7.1/³õʼ»¯-postgresql-kingbase-2.7.1.sql
New file
@@ -0,0 +1,325 @@
/*建表*/
create table wvp_device (
                            id serial primary key ,
                            device_id character varying(50) not null ,
                            name character varying(255),
                            manufacturer character varying(255),
                            model character varying(255),
                            firmware character varying(255),
                            transport character varying(50),
                            stream_mode character varying(50),
                            on_line bool default false,
                            register_time character varying(50),
                            keepalive_time character varying(50),
                            ip character varying(50),
                            create_time character varying(50),
                            update_time character varying(50),
                            port integer,
                            expires integer,
                            subscribe_cycle_for_catalog integer DEFAULT 0,
                            subscribe_cycle_for_mobile_position integer DEFAULT 0,
                            mobile_position_submission_interval integer DEFAULT 5,
                            subscribe_cycle_for_alarm integer DEFAULT 0,
                            host_address character varying(50),
                            charset character varying(50),
                            ssrc_check bool default false,
                            geo_coord_sys character varying(50),
                            media_server_id character varying(50),
                            custom_name character varying(255),
                            sdp_ip character varying(50),
                            local_ip character varying(50),
                            password character varying(255),
                            as_message_channel bool default false,
                            keepalive_interval_time integer,
                            broadcast_push_after_ack bool default false,
                            constraint uk_device_device unique (device_id)
);
create table wvp_device_alarm (
                                  id serial primary key ,
                                  device_id character varying(50) not null,
                                  channel_id character varying(50) not null,
                                  alarm_priority character varying(50),
                                  alarm_method character varying(50),
                                  alarm_time character varying(50),
                                  alarm_description character varying(255),
                                  longitude double precision,
                                  latitude double precision,
                                  alarm_type character varying(50),
                                  create_time character varying(50) not null
);
create table wvp_device_channel (
                                    id serial primary key ,
                                    channel_id character varying(50) not null,
                                    name character varying(255),
                                    custom_name character varying(255),
                                    manufacture character varying(50),
                                    model character varying(50),
                                    owner character varying(50),
                                    civil_code character varying(50),
                                    block character varying(50),
                                    address character varying(50),
                                    parent_id character varying(50),
                                    safety_way integer,
                                    register_way integer,
                                    cert_num character varying(50),
                                    certifiable integer,
                                    err_code integer,
                                    end_time character varying(50),
                                    secrecy character varying(50),
                                    ip_address character varying(50),
                                    port integer,
                                    password character varying(255),
                                    ptz_type integer,
                                    custom_ptz_type integer,
                                    status bool default false,
                                    longitude double precision,
                                    custom_longitude double precision,
                                    latitude double precision,
                                    custom_latitude double precision,
                                    stream_id character varying(255),
                                    device_id character varying(50) not null,
                                    parental character varying(50),
                                    has_audio bool default false,
                                    create_time character varying(50) not null,
                                    update_time character varying(50) not null,
                                    sub_count integer,
                                    longitude_gcj02 double precision,
                                    latitude_gcj02 double precision,
                                    longitude_wgs84 double precision,
                                    latitude_wgs84 double precision,
                                    business_group_id character varying(50),
                                    gps_time character varying(50),
                                    stream_identification character varying(50),
                                    constraint uk_wvp_device_channel_unique_device_channel unique (device_id, channel_id)
);
create table wvp_device_mobile_position (
                                            id serial primary key,
                                            device_id character varying(50) not null,
                                            channel_id character varying(50) not null,
                                            device_name character varying(255),
                                            time character varying(50),
                                            longitude double precision,
                                            latitude double precision,
                                            altitude double precision,
                                            speed double precision,
                                            direction double precision,
                                            report_source character varying(50),
                                            longitude_gcj02 double precision,
                                            latitude_gcj02 double precision,
                                            longitude_wgs84 double precision,
                                            latitude_wgs84 double precision,
                                            create_time character varying(50)
);
create table wvp_gb_stream (
                               gb_stream_id serial primary key,
                               app character varying(255) not null,
                               stream character varying(255) not null,
                               gb_id character varying(50) not null,
                               name character varying(255),
                               longitude double precision,
                               latitude double precision,
                               stream_type character varying(50),
                               media_server_id character varying(50),
                               create_time character varying(50),
                               constraint uk_gb_stream_unique_gb_id unique (gb_id),
                               constraint uk_gb_stream_unique_app_stream unique (app, stream)
);
create table wvp_log (
                         id serial primary key ,
                         name character varying(50),
                         type character varying(50),
                         uri character varying(200),
                         address character varying(50),
                         result character varying(50),
                         timing bigint,
                         username character varying(50),
                         create_time character varying(50)
);
create table wvp_media_server (
                                  id character varying(255) primary key ,
                                  ip character varying(50),
                                  hook_ip character varying(50),
                                  sdp_ip character varying(50),
                                  stream_ip character varying(50),
                                  http_port integer,
                                  http_ssl_port integer,
                                  rtmp_port integer,
                                  rtmp_ssl_port integer,
                                  rtp_proxy_port integer,
                                  rtsp_port integer,
                                  rtsp_ssl_port integer,
                                  auto_config bool default false,
                                  secret character varying(50),
                                  rtp_enable bool default false,
                                  rtp_port_range character varying(50),
                                  send_rtp_port_range character varying(50),
                                  record_assist_port integer,
                                  default_server bool default false,
                                  create_time character varying(50),
                                  update_time character varying(50),
                                  hook_alive_interval integer,
                                  record_path character varying(255),
                                  record_day integer default 7,
                                  transcode_suffix character varying(255),
                                  constraint uk_media_server_unique_ip_http_port unique (ip, http_port)
);
create table wvp_platform (
                              id serial primary key ,
                              enable bool default false,
                              name character varying(255),
                              server_gb_id character varying(50),
                              server_gb_domain character varying(50),
                              server_ip character varying(50),
                              server_port integer,
                              device_gb_id character varying(50),
                              device_ip character varying(50),
                              device_port character varying(50),
                              username character varying(255),
                              password character varying(50),
                              expires character varying(50),
                              keep_timeout character varying(50),
                              transport character varying(50),
                              character_set character varying(50),
                              catalog_id character varying(50),
                              ptz bool default false,
                              rtcp bool default false,
                              status bool default false,
                              start_offline_push bool default false,
                              administrative_division character varying(50),
                              catalog_group integer,
                              create_time character varying(50),
                              update_time character varying(50),
                              as_message_channel bool default false,
                              auto_push_channel bool default false,
                              send_stream_ip character varying(50),
                              constraint uk_platform_unique_server_gb_id unique (server_gb_id)
);
create table wvp_platform_catalog (
                                      id character varying(50),
                                      platform_id character varying(50),
                                      name character varying(255),
                                      parent_id character varying(50),
                                      civil_code character varying(50),
                                      business_group_id character varying(50),
                                      constraint uk_platform_catalog_id_platform_id unique (id, platform_id)
);
create table wvp_platform_gb_channel (
                                         id serial primary key ,
                                         platform_id character varying(50),
                                         catalog_id character varying(50),
                                         device_channel_id integer,
                                         constraint uk_platform_gb_channel_platform_id_catalog_id_device_channel_id unique (platform_id, catalog_id, device_channel_id)
);
create table wvp_platform_gb_stream (
                                        id serial primary key,
                                        platform_id character varying(50),
                                        catalog_id character varying(50),
                                        gb_stream_id integer,
                                        constraint uk_platform_gb_stream_platform_id_catalog_id_gb_stream_id unique (platform_id, catalog_id, gb_stream_id)
);
create table wvp_stream_proxy (
                                  id serial primary key,
                                  type character varying(50),
                                  app character varying(255),
                                  stream character varying(255),
                                  url character varying(255),
                                  src_url character varying(255),
                                  dst_url character varying(255),
                                  timeout_ms integer,
                                  ffmpeg_cmd_key character varying(255),
                                  rtp_type character varying(50),
                                  media_server_id character varying(50),
                                  enable_audio bool default false,
                                  enable_mp4 bool default false,
                                  enable bool default false,
                                  status boolean,
                                  enable_remove_none_reader bool default false,
                                  create_time character varying(50),
                                  name character varying(255),
                                  update_time character varying(50),
                                  stream_key character varying(255),
                                  enable_disable_none_reader bool default false,
                                  constraint uk_stream_proxy_app_stream unique (app, stream)
);
create table wvp_stream_push (
                                 id serial primary key,
                                 app character varying(255),
                                 stream character varying(255),
                                 total_reader_count character varying(50),
                                 origin_type integer,
                                 origin_type_str character varying(50),
                                 create_time character varying(50),
                                 alive_second integer,
                                 media_server_id character varying(50),
                                 server_id character varying(50),
                                 push_time character varying(50),
                                 status bool default false,
                                 update_time character varying(50),
                                 push_ing bool default false,
                                 self bool default false,
                                 constraint uk_stream_push_app_stream unique (app, stream)
);
create table wvp_cloud_record (
                                  id serial primary key,
                                  app character varying(255),
                                  stream character varying(255),
                                  call_id character varying(255),
                                  start_time int8,
                                  end_time int8,
                                  media_server_id character varying(50),
                                  file_name character varying(255),
                                  folder character varying(255),
                                  file_path character varying(255),
                                  collect bool default false,
                                  file_size int8,
                                  time_len int8,
                                  constraint uk_stream_push_app_stream_path unique (app, stream, file_path)
);
create table wvp_user (
                          id serial primary key,
                          username character varying(255),
                          password character varying(255),
                          role_id integer,
                          create_time character varying(50),
                          update_time character varying(50),
                          push_key character varying(50),
                          constraint uk_user_username unique (username)
);
create table wvp_user_role (
                               id serial primary key,
                               name character varying(50),
                               authority character varying(50),
                               create_time character varying(50),
                               update_time character varying(50)
);
create table wvp_resources_tree (
                                    id serial primary key ,
                                    is_catalog bool default true,
                                    device_channel_id integer ,
                                    gb_stream_id integer,
                                    name character varying(255),
                                    parentId integer,
                                    path character varying(255)
);
/*初始数据*/
INSERT INTO wvp_user VALUES (1, 'admin','21232f297a57a5a743894a0e4a801fc3',1,'2021-04-13 14:14:57','2021-04-13 14:14:57','3e80d1762a324d5b0ff636e0bd16f1e3');
INSERT INTO wvp_user_role VALUES (1, 'admin','0','2021-04-13 14:14:57','2021-04-13 14:14:57');
Êý¾Ý¿â/2.7.1/¸üÐÂ-mysql-2.7.1.sql
New file
@@ -0,0 +1,2 @@
alter table wvp_media_server
    add transcode_suffix character varying(255);
Êý¾Ý¿â/2.7.1/¸üÐÂ-postgresql-kingbase-2.7.1.sql
New file
@@ -0,0 +1,2 @@
alter table wvp_media_server
    add transcode_suffix character varying(255);