648540858
2020-09-25 da14c7f24c61cf9027a02d8e566ab89116136f19
拆分redis中device与channel的存储方式
支持分页
接口直接返回播放地址
16个文件已修改
5个文件已添加
1523 ■■■■■ 已修改文件
pom.xml 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/common/PageResult.java 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/common/StreamInfo.java 59 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/common/VideoManagerConstants.java 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/conf/MediaServerConfig.java 667 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/bean/Device.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/bean/DeviceChannel.java 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java 36 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/MessageRequestProcessor.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/RegisterRequestProcessor.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/media/zlm/SolrProxyServletConfiguration.java 43 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorager.java 97 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/storager/jdbc/VideoManagerJdbcStoragerImpl.java 68 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/storager/redis/VideoManagerRedisStoragerImpl.java 182 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/utils/redis/RedisUtil.java 116 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/vmanager/device/DeviceController.java 24 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/vmanager/play/PlayController.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/web/AuthController.java 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/application.yml 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pom.xml
@@ -143,6 +143,17 @@
            <artifactId>jedis</artifactId>
            <version>2.9.0</version>
        </dependency>
        <dependency>
            <groupId>org.mitre.dsmiley.httpproxy</groupId>
            <artifactId>smiley-http-proxy-servlet</artifactId>
            <version>1.7</version>
        </dependency>
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>18.0</version>
        </dependency>
        
    </dependencies>
    
src/main/java/com/genersoft/iot/vmp/common/PageResult.java
New file
@@ -0,0 +1,44 @@
package com.genersoft.iot.vmp.common;
import java.util.List;
public class PageResult<T> {
    private int page;
    private int count;
    private int total;
    private List<T> data;
    public List<T> getData() {
        return data;
    }
    public void setData(List<T> data) {
        this.data = data;
    }
    public int getPage() {
        return page;
    }
    public void setPage(int page) {
        this.page = page;
    }
    public int getCount() {
        return count;
    }
    public void setCount(int count) {
        this.count = count;
    }
    public int getTotal() {
        return total;
    }
    public void setTotal(int total) {
        this.total = total;
    }
}
src/main/java/com/genersoft/iot/vmp/common/StreamInfo.java
New file
@@ -0,0 +1,59 @@
package com.genersoft.iot.vmp.common;
public class StreamInfo {
    private String ssrc;
    private String flv;
    private String WS_FLV;
    private String RTMP;
    private String HLS;
    private String RTSP;
    public String getSsrc() {
        return ssrc;
    }
    public void setSsrc(String ssrc) {
        this.ssrc = ssrc;
    }
    public String getFlv() {
        return flv;
    }
    public void setFlv(String flv) {
        this.flv = flv;
    }
    public String getWS_FLV() {
        return WS_FLV;
    }
    public void setWS_FLV(String WS_FLV) {
        this.WS_FLV = WS_FLV;
    }
    public String getRTMP() {
        return RTMP;
    }
    public void setRTMP(String RTMP) {
        this.RTMP = RTMP;
    }
    public String getHLS() {
        return HLS;
    }
    public void setHLS(String HLS) {
        this.HLS = HLS;
    }
    public String getRTSP() {
        return RTSP;
    }
    public void setRTSP(String RTSP) {
        this.RTSP = RTSP;
    }
}
src/main/java/com/genersoft/iot/vmp/common/VideoManagerConstants.java
@@ -8,10 +8,16 @@
 */
public class VideoManagerConstants {
    
    public static final String CACHEKEY_PREFIX = "VMP_deviceId_";
    public static final String MEDIA_SERVER_PREFIX = "VMP_media_server";
    public static final String DEVICE_PREFIX = "VMP_device_";
    public static final String CACHEKEY_PREFIX = "VMP_channel_";
    public static final String KEEPLIVEKEY_PREFIX = "VMP_keeplive_";
    public static final String PLAYER_PREFIX = "VMP_player_";
    public static final String EVENT_ONLINE_REGISTER = "1";
    
    public static final String EVENT_ONLINE_KEEPLIVE = "2";
src/main/java/com/genersoft/iot/vmp/conf/MediaServerConfig.java
New file
@@ -0,0 +1,667 @@
package com.genersoft.iot.vmp.conf;
import com.alibaba.fastjson.annotation.JSONField;
public class MediaServerConfig {
    @JSONField(name = "api.apiDebug")
    private String apiDebug;
    @JSONField(name = "api.secret")
    private String apiSecret;
    @JSONField(name = "ffmpeg.bin")
    private String ffmpegBin;
    @JSONField(name = "ffmpeg.cmd")
    private String ffmpegCmd;
    @JSONField(name = "ffmpeg.log")
    private String ffmpegLog;
    @JSONField(name = "general.enableVhost")
    private String generalEnableVhost;
    @JSONField(name = "general.flowThreshold")
    private String generalFlowThreshold;
    @JSONField(name = "general.maxStreamWaitMS")
    private String generalMaxStreamWaitMS;
    @JSONField(name = "general.streamNoneReaderDelayMS")
    private String generalStreamNoneReaderDelayMS;
    @JSONField(name = "hls.fileBufSize")
    private String hlsFileBufSize;
    @JSONField(name = "hls.filePath")
    private String hlsFilePath;
    @JSONField(name = "hls.segDur")
    private String hlsSegDur;
    @JSONField(name = "hls.segNum")
    private String hlsSegNum;
    @JSONField(name = "hook.access_file_except_hls")
    private String hookAccessFileExceptHLS;
    @JSONField(name = "hook.admin_params")
    private String hookAdminParams;
    @JSONField(name = "hook.enable")
    private String hookEnable;
    @JSONField(name = "hook.on_flow_report")
    private String hookOnFlowReport;
    @JSONField(name = "hook.on_http_access")
    private String hookOnHttpAccess;
    @JSONField(name = "hook.on_play")
    private String hookOnPlay;
    @JSONField(name = "hook.on_publish")
    private String hookOnPublish;
    @JSONField(name = "hook.on_record_mp4")
    private String hookOnRecordMp4;
    @JSONField(name = "hook.on_rtsp_auth")
    private String hookOnRtspAuth;
    @JSONField(name = "hook.on_rtsp_realm")
    private String hookOnRtspRealm;
    @JSONField(name = "hook.on_shell_login")
    private String hookOnShellLogin;
    @JSONField(name = "hook.on_stream_changed")
    private String hookOnStreamChanged;
    @JSONField(name = "hook.on_stream_none_reader")
    private String hookOnStreamNoneReader;
    @JSONField(name = "hook.on_stream_not_found")
    private String hookOnStreamNotFound;
    @JSONField(name = "hook.timeoutSec")
    private String hookTimeoutSec;
    @JSONField(name = "http.charSet")
    private String httpCharSet;
    @JSONField(name = "http.keepAliveSecond")
    private String httpKeepAliveSecond;
    @JSONField(name = "http.maxReqCount")
    private String httpMaxReqCount;
    @JSONField(name = "http.maxReqSize")
    private String httpMaxReqSize;
    @JSONField(name = "http.notFound")
    private String httpNotFound;
    @JSONField(name = "http.port")
    private String httpPort;
    @JSONField(name = "http.rootPath")
    private String httpRootPath;
    @JSONField(name = "http.sendBufSize")
    private String httpSendBufSize;
    @JSONField(name = "http.sslport")
    private String httpSSLport;
    @JSONField(name = "multicast.addrMax")
    private String multicastAddrMax;
    @JSONField(name = "multicast.addrMin")
    private String multicastAddrMin;
    @JSONField(name = "multicast.udpTTL")
    private String multicastUdpTTL;
    @JSONField(name = "record.appName")
    private String recordAppName;
    @JSONField(name = "record.filePath")
    private String recordFilePath;
    @JSONField(name = "record.fileSecond")
    private String recordFileSecond;
    @JSONField(name = "record.sampleMS")
    private String recordFileSampleMS;
    @JSONField(name = "rtmp.handshakeSecond")
    private String rtmpHandshakeSecond;
    @JSONField(name = "rtmp.keepAliveSecond")
    private String rtmpKeepAliveSecond;
    @JSONField(name = "rtmp.modifyStamp")
    private String rtmpModifyStamp;
    @JSONField(name = "rtmp.port")
    private String rtmpPort;
    @JSONField(name = "rtp.audioMtuSize")
    private String rtpAudioMtuSize;
    @JSONField(name = "rtp.clearCount")
    private String rtpClearCount;
    @JSONField(name = "rtp.cycleMS")
    private String rtpCycleMS;
    @JSONField(name = "rtp.maxRtpCount")
    private String rtpMaxRtpCount;
    @JSONField(name = "rtp.videoMtuSize")
    private String rtpVideoMtuSize;
    @JSONField(name = "rtsp.authBasic")
    private String rtspAuthBasic;
    @JSONField(name = "rtsp.handshakeSecond")
    private String rtspHandshakeSecond;
    @JSONField(name = "rtsp.keepAliveSecond")
    private String rtspKeepAliveSecond;
    @JSONField(name = "rtsp.port")
    private String rtspPort;
    @JSONField(name = "rtsp.sslport")
    private String rtspSSlport;
    @JSONField(name = "shell.maxReqSize")
    private String shellMaxReqSize;
    @JSONField(name = "shell.shell")
    private String shellPhell;
    public String getApiDebug() {
        return apiDebug;
    }
    public void setApiDebug(String apiDebug) {
        this.apiDebug = apiDebug;
    }
    public String getApiSecret() {
        return apiSecret;
    }
    public void setApiSecret(String apiSecret) {
        this.apiSecret = apiSecret;
    }
    public String getFfmpegBin() {
        return ffmpegBin;
    }
    public void setFfmpegBin(String ffmpegBin) {
        this.ffmpegBin = ffmpegBin;
    }
    public String getFfmpegCmd() {
        return ffmpegCmd;
    }
    public void setFfmpegCmd(String ffmpegCmd) {
        this.ffmpegCmd = ffmpegCmd;
    }
    public String getFfmpegLog() {
        return ffmpegLog;
    }
    public void setFfmpegLog(String ffmpegLog) {
        this.ffmpegLog = ffmpegLog;
    }
    public String getGeneralEnableVhost() {
        return generalEnableVhost;
    }
    public void setGeneralEnableVhost(String generalEnableVhost) {
        this.generalEnableVhost = generalEnableVhost;
    }
    public String getGeneralFlowThreshold() {
        return generalFlowThreshold;
    }
    public void setGeneralFlowThreshold(String generalFlowThreshold) {
        this.generalFlowThreshold = generalFlowThreshold;
    }
    public String getGeneralMaxStreamWaitMS() {
        return generalMaxStreamWaitMS;
    }
    public void setGeneralMaxStreamWaitMS(String generalMaxStreamWaitMS) {
        this.generalMaxStreamWaitMS = generalMaxStreamWaitMS;
    }
    public String getGeneralStreamNoneReaderDelayMS() {
        return generalStreamNoneReaderDelayMS;
    }
    public void setGeneralStreamNoneReaderDelayMS(String generalStreamNoneReaderDelayMS) {
        this.generalStreamNoneReaderDelayMS = generalStreamNoneReaderDelayMS;
    }
    public String getHlsFileBufSize() {
        return hlsFileBufSize;
    }
    public void setHlsFileBufSize(String hlsFileBufSize) {
        this.hlsFileBufSize = hlsFileBufSize;
    }
    public String getHlsFilePath() {
        return hlsFilePath;
    }
    public void setHlsFilePath(String hlsFilePath) {
        this.hlsFilePath = hlsFilePath;
    }
    public String getHlsSegDur() {
        return hlsSegDur;
    }
    public void setHlsSegDur(String hlsSegDur) {
        this.hlsSegDur = hlsSegDur;
    }
    public String getHlsSegNum() {
        return hlsSegNum;
    }
    public void setHlsSegNum(String hlsSegNum) {
        this.hlsSegNum = hlsSegNum;
    }
    public String getHookAccessFileExceptHLS() {
        return hookAccessFileExceptHLS;
    }
    public void setHookAccessFileExceptHLS(String hookAccessFileExceptHLS) {
        this.hookAccessFileExceptHLS = hookAccessFileExceptHLS;
    }
    public String getHookAdminParams() {
        return hookAdminParams;
    }
    public void setHookAdminParams(String hookAdminParams) {
        this.hookAdminParams = hookAdminParams;
    }
    public String getHookEnable() {
        return hookEnable;
    }
    public void setHookEnable(String hookEnable) {
        this.hookEnable = hookEnable;
    }
    public String getHookOnFlowReport() {
        return hookOnFlowReport;
    }
    public void setHookOnFlowReport(String hookOnFlowReport) {
        this.hookOnFlowReport = hookOnFlowReport;
    }
    public String getHookOnHttpAccess() {
        return hookOnHttpAccess;
    }
    public void setHookOnHttpAccess(String hookOnHttpAccess) {
        this.hookOnHttpAccess = hookOnHttpAccess;
    }
    public String getHookOnPlay() {
        return hookOnPlay;
    }
    public void setHookOnPlay(String hookOnPlay) {
        this.hookOnPlay = hookOnPlay;
    }
    public String getHookOnPublish() {
        return hookOnPublish;
    }
    public void setHookOnPublish(String hookOnPublish) {
        this.hookOnPublish = hookOnPublish;
    }
    public String getHookOnRecordMp4() {
        return hookOnRecordMp4;
    }
    public void setHookOnRecordMp4(String hookOnRecordMp4) {
        this.hookOnRecordMp4 = hookOnRecordMp4;
    }
    public String getHookOnRtspAuth() {
        return hookOnRtspAuth;
    }
    public void setHookOnRtspAuth(String hookOnRtspAuth) {
        this.hookOnRtspAuth = hookOnRtspAuth;
    }
    public String getHookOnRtspRealm() {
        return hookOnRtspRealm;
    }
    public void setHookOnRtspRealm(String hookOnRtspRealm) {
        this.hookOnRtspRealm = hookOnRtspRealm;
    }
    public String getHookOnShellLogin() {
        return hookOnShellLogin;
    }
    public void setHookOnShellLogin(String hookOnShellLogin) {
        this.hookOnShellLogin = hookOnShellLogin;
    }
    public String getHookOnStreamChanged() {
        return hookOnStreamChanged;
    }
    public void setHookOnStreamChanged(String hookOnStreamChanged) {
        this.hookOnStreamChanged = hookOnStreamChanged;
    }
    public String getHookOnStreamNoneReader() {
        return hookOnStreamNoneReader;
    }
    public void setHookOnStreamNoneReader(String hookOnStreamNoneReader) {
        this.hookOnStreamNoneReader = hookOnStreamNoneReader;
    }
    public String getHookOnStreamNotFound() {
        return hookOnStreamNotFound;
    }
    public void setHookOnStreamNotFound(String hookOnStreamNotFound) {
        this.hookOnStreamNotFound = hookOnStreamNotFound;
    }
    public String getHookTimeoutSec() {
        return hookTimeoutSec;
    }
    public void setHookTimeoutSec(String hookTimeoutSec) {
        this.hookTimeoutSec = hookTimeoutSec;
    }
    public String getHttpCharSet() {
        return httpCharSet;
    }
    public void setHttpCharSet(String httpCharSet) {
        this.httpCharSet = httpCharSet;
    }
    public String getHttpKeepAliveSecond() {
        return httpKeepAliveSecond;
    }
    public void setHttpKeepAliveSecond(String httpKeepAliveSecond) {
        this.httpKeepAliveSecond = httpKeepAliveSecond;
    }
    public String getHttpMaxReqCount() {
        return httpMaxReqCount;
    }
    public void setHttpMaxReqCount(String httpMaxReqCount) {
        this.httpMaxReqCount = httpMaxReqCount;
    }
    public String getHttpMaxReqSize() {
        return httpMaxReqSize;
    }
    public void setHttpMaxReqSize(String httpMaxReqSize) {
        this.httpMaxReqSize = httpMaxReqSize;
    }
    public String getHttpNotFound() {
        return httpNotFound;
    }
    public void setHttpNotFound(String httpNotFound) {
        this.httpNotFound = httpNotFound;
    }
    public String getHttpPort() {
        return httpPort;
    }
    public void setHttpPort(String httpPort) {
        this.httpPort = httpPort;
    }
    public String getHttpRootPath() {
        return httpRootPath;
    }
    public void setHttpRootPath(String httpRootPath) {
        this.httpRootPath = httpRootPath;
    }
    public String getHttpSendBufSize() {
        return httpSendBufSize;
    }
    public void setHttpSendBufSize(String httpSendBufSize) {
        this.httpSendBufSize = httpSendBufSize;
    }
    public String getHttpSSLport() {
        return httpSSLport;
    }
    public void setHttpSSLport(String httpSSLport) {
        this.httpSSLport = httpSSLport;
    }
    public String getMulticastAddrMax() {
        return multicastAddrMax;
    }
    public void setMulticastAddrMax(String multicastAddrMax) {
        this.multicastAddrMax = multicastAddrMax;
    }
    public String getMulticastAddrMin() {
        return multicastAddrMin;
    }
    public void setMulticastAddrMin(String multicastAddrMin) {
        this.multicastAddrMin = multicastAddrMin;
    }
    public String getMulticastUdpTTL() {
        return multicastUdpTTL;
    }
    public void setMulticastUdpTTL(String multicastUdpTTL) {
        this.multicastUdpTTL = multicastUdpTTL;
    }
    public String getRecordAppName() {
        return recordAppName;
    }
    public void setRecordAppName(String recordAppName) {
        this.recordAppName = recordAppName;
    }
    public String getRecordFilePath() {
        return recordFilePath;
    }
    public void setRecordFilePath(String recordFilePath) {
        this.recordFilePath = recordFilePath;
    }
    public String getRecordFileSecond() {
        return recordFileSecond;
    }
    public void setRecordFileSecond(String recordFileSecond) {
        this.recordFileSecond = recordFileSecond;
    }
    public String getRecordFileSampleMS() {
        return recordFileSampleMS;
    }
    public void setRecordFileSampleMS(String recordFileSampleMS) {
        this.recordFileSampleMS = recordFileSampleMS;
    }
    public String getRtmpHandshakeSecond() {
        return rtmpHandshakeSecond;
    }
    public void setRtmpHandshakeSecond(String rtmpHandshakeSecond) {
        this.rtmpHandshakeSecond = rtmpHandshakeSecond;
    }
    public String getRtmpKeepAliveSecond() {
        return rtmpKeepAliveSecond;
    }
    public void setRtmpKeepAliveSecond(String rtmpKeepAliveSecond) {
        this.rtmpKeepAliveSecond = rtmpKeepAliveSecond;
    }
    public String getRtmpModifyStamp() {
        return rtmpModifyStamp;
    }
    public void setRtmpModifyStamp(String rtmpModifyStamp) {
        this.rtmpModifyStamp = rtmpModifyStamp;
    }
    public String getRtmpPort() {
        return rtmpPort;
    }
    public void setRtmpPort(String rtmpPort) {
        this.rtmpPort = rtmpPort;
    }
    public String getRtpAudioMtuSize() {
        return rtpAudioMtuSize;
    }
    public void setRtpAudioMtuSize(String rtpAudioMtuSize) {
        this.rtpAudioMtuSize = rtpAudioMtuSize;
    }
    public String getRtpClearCount() {
        return rtpClearCount;
    }
    public void setRtpClearCount(String rtpClearCount) {
        this.rtpClearCount = rtpClearCount;
    }
    public String getRtpCycleMS() {
        return rtpCycleMS;
    }
    public void setRtpCycleMS(String rtpCycleMS) {
        this.rtpCycleMS = rtpCycleMS;
    }
    public String getRtpMaxRtpCount() {
        return rtpMaxRtpCount;
    }
    public void setRtpMaxRtpCount(String rtpMaxRtpCount) {
        this.rtpMaxRtpCount = rtpMaxRtpCount;
    }
    public String getRtpVideoMtuSize() {
        return rtpVideoMtuSize;
    }
    public void setRtpVideoMtuSize(String rtpVideoMtuSize) {
        this.rtpVideoMtuSize = rtpVideoMtuSize;
    }
    public String getRtspAuthBasic() {
        return rtspAuthBasic;
    }
    public void setRtspAuthBasic(String rtspAuthBasic) {
        this.rtspAuthBasic = rtspAuthBasic;
    }
    public String getRtspHandshakeSecond() {
        return rtspHandshakeSecond;
    }
    public void setRtspHandshakeSecond(String rtspHandshakeSecond) {
        this.rtspHandshakeSecond = rtspHandshakeSecond;
    }
    public String getRtspKeepAliveSecond() {
        return rtspKeepAliveSecond;
    }
    public void setRtspKeepAliveSecond(String rtspKeepAliveSecond) {
        this.rtspKeepAliveSecond = rtspKeepAliveSecond;
    }
    public String getRtspPort() {
        return rtspPort;
    }
    public void setRtspPort(String rtspPort) {
        this.rtspPort = rtspPort;
    }
    public String getRtspSSlport() {
        return rtspSSlport;
    }
    public void setRtspSSlport(String rtspSSlport) {
        this.rtspSSlport = rtspSSlport;
    }
    public String getShellMaxReqSize() {
        return shellMaxReqSize;
    }
    public void setShellMaxReqSize(String shellMaxReqSize) {
        this.shellMaxReqSize = shellMaxReqSize;
    }
    public String getShellPhell() {
        return shellPhell;
    }
    public void setShellPhell(String shellPhell) {
        this.shellPhell = shellPhell;
    }
}
src/main/java/com/genersoft/iot/vmp/gb28181/bean/Device.java
@@ -49,7 +49,9 @@
    /**
     * 通道列表
     */
    private Map<String,DeviceChannel> channelMap;
//    private Map<String,DeviceChannel> channelMap;
    private int channelCount;
    public String getDeviceId() {
@@ -84,13 +86,13 @@
        this.host = host;
    }
    public Map<String, DeviceChannel> getChannelMap() {
        return channelMap;
    }
    public void setChannelMap(Map<String, DeviceChannel> channelMap) {
        this.channelMap = channelMap;
    }
//    public Map<String, DeviceChannel> getChannelMap() {
//        return channelMap;
//    }
//
//    public void setChannelMap(Map<String, DeviceChannel> channelMap) {
//        this.channelMap = channelMap;
//    }
    public String getManufacturer() {
        return manufacturer;
@@ -123,4 +125,12 @@
    public void setOnline(int online) {
        this.online = online;
    }
    public int getChannelCount() {
        return channelCount;
    }
    public void setChannelCount(int channelCount) {
        this.channelCount = channelCount;
    }
}
src/main/java/com/genersoft/iot/vmp/gb28181/bean/DeviceChannel.java
@@ -100,7 +100,12 @@
    /**
     * 密码
     */
    private String password;
    private String password;
    /**
     * 云台控制
     */
    private int PTZType;
    
    /**
     * 在线/离线
@@ -122,6 +127,11 @@
     * 纬度
     */
    private double latitude;
    /**
     * 流唯一编号,存在表示正在直播
     */
    private String  ssrc;
    public String getChannelId() {
        return channelId;
@@ -306,4 +316,20 @@
    public void setLatitude(double latitude) {
        this.latitude = latitude;
    }
    public int getPTZType() {
        return PTZType;
    }
    public void setPTZType(int PTZType) {
        this.PTZType = PTZType;
    }
    public String getSsrc() {
        return ssrc;
    }
    public void setSsrc(String ssrc) {
        this.ssrc = ssrc;
    }
}
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java
@@ -1,5 +1,6 @@
package com.genersoft.iot.vmp.gb28181.transmit.cmd;
import com.genersoft.iot.vmp.common.StreamInfo;
import com.genersoft.iot.vmp.gb28181.bean.Device;
/**    
@@ -69,7 +70,7 @@
     * @param device  视频设备
     * @param channelId  预览通道
     */
    public String playStreamCmd(Device device,String channelId);
    public StreamInfo playStreamCmd(Device device, String channelId);
    
    /**
     * 请求回放视频流
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
@@ -15,8 +15,14 @@
import javax.sip.header.ViaHeader;
import javax.sip.message.Request;
import com.alibaba.fastjson.JSONObject;
import com.genersoft.iot.vmp.common.StreamInfo;
import com.genersoft.iot.vmp.conf.MediaServerConfig;
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import com.genersoft.iot.vmp.conf.SipConfig;
@@ -42,6 +48,9 @@
    
    @Autowired
    private VideoStreamSessionManager streamSession;
    @Autowired
    private IVideoManagerStorager storager;
    
    @Autowired
    @Qualifier(value="tcpSipProvider")
@@ -50,6 +59,9 @@
    @Autowired
    @Qualifier(value="udpSipProvider")
    private SipProvider udpSipProvider;
    @Value("${media.ip}")
    private String mediaIp;
    
    /**
     * 云台方向放控制,使用配置文件中的默认镜头移动速度
@@ -58,7 +70,6 @@
     * @param channelId  预览通道
     * @param leftRight  镜头左移右移 0:停止 1:左移 2:右移
     * @param upDown     镜头上移下移 0:停止 1:上移 2:下移
     * @param moveSpeed  镜头移动速度
     */
    @Override
    public boolean ptzdirectCmd(Device device, String channelId, int leftRight, int upDown) {
@@ -191,7 +202,7 @@
     * @param channelId  预览通道
     */  
    @Override
    public String playStreamCmd(Device device, String channelId) {
    public StreamInfo playStreamCmd(Device device, String channelId) {
        try {
            
            String ssrc = streamSession.createPlaySsrc();
@@ -223,7 +234,24 @@
    
            ClientTransaction transaction = transmitRequest(device, request);
            streamSession.put(ssrc, transaction);
            return ssrc;
            DeviceChannel deviceChannel = storager.queryChannel(device.getDeviceId(), channelId);
            if (deviceChannel != null) {
                deviceChannel.setSsrc(ssrc);
                storager.updateChannel(device.getDeviceId(), deviceChannel);
            }
            MediaServerConfig mediaInfo = storager.getMediaInfo();
            StreamInfo streamInfo = new StreamInfo();
            streamInfo.setSsrc(ssrc);
//            String streamId = Integer.toHexString(Integer.parseInt(streamInfo.getSsrc()));
            String streamId = String.format("%08x", Integer.parseInt(streamInfo.getSsrc())).toUpperCase(); // ZLM 要求大写且首位补零
            streamInfo.setFlv(String.format("http://%s:%s/rtp/%s.flv", mediaIp, mediaInfo.getHttpPort(), streamId));
            streamInfo.setWS_FLV(String.format("ws://%s:%s/rtp/%s.flv", mediaIp, mediaInfo.getHttpPort(), streamId));
            streamInfo.setRTMP(String.format("rtmp://%s:%s/rtp/%s", mediaIp, mediaInfo.getRtmpPort(), streamId));
            streamInfo.setHLS(String.format("http://%s:%s/rtp/%s/hls.m3u8", mediaIp, mediaInfo.getHttpPort(), streamId));
            streamInfo.setRTSP(String.format("rtsp://%s:%s/rtp/%s", mediaIp, mediaInfo.getRtspPort(), streamId));
            storager.startPlay(device.getDeviceId(), channelId, streamInfo);
            return streamInfo;
        } catch ( SipException | ParseException | InvalidArgumentException e) {
            e.printStackTrace();
            return null;
@@ -281,8 +309,6 @@
    /**
     * 视频流停止
     * 
     * @param device  视频设备
     * @param channelId  预览通道
     */
    @Override
    public void streamByeCmd(String ssrc) {
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/MessageRequestProcessor.java
@@ -76,8 +76,6 @@
     * 处理MESSAGE请求
     *  
     * @param evt
     * @param layer
     * @param transaction
     */  
    @Override
    public void process(RequestEvent evt) {
@@ -127,7 +125,7 @@
            device.setManufacturer(XmlUtil.getText(rootElement,"Manufacturer"));
            device.setModel(XmlUtil.getText(rootElement,"Model"));
            device.setFirmware(XmlUtil.getText(rootElement,"Firmware"));
            storager.update(device);
            storager.updateDevice(device);
            
            RequestMessage msg = new RequestMessage();
            msg.setDeviceId(deviceId);
@@ -158,11 +156,6 @@
                if (device == null) {
                    return;
                }
                Map<String, DeviceChannel> channelMap = device.getChannelMap();
                if (channelMap == null) {
                    channelMap = new HashMap<String, DeviceChannel>(5);
                    device.setChannelMap(channelMap);
                }
                // 遍历DeviceList
                while (deviceListIterator.hasNext()) {
                    Element itemDevice = deviceListIterator.next();
@@ -175,7 +168,7 @@
                    String channelName = channdelNameElement != null ? channdelNameElement.getText().toString() : "";
                    Element statusElement = itemDevice.element("Status");
                    String status = statusElement != null ? statusElement.getText().toString() : "ON";
                    DeviceChannel deviceChannel = channelMap.containsKey(channelDeviceId) ? channelMap.get(channelDeviceId) : new DeviceChannel();
                    DeviceChannel deviceChannel = new DeviceChannel();
                    deviceChannel.setName(channelName);
                    deviceChannel.setChannelId(channelDeviceId);
                    if(status.equals("ON")) {
@@ -205,10 +198,12 @@
                    deviceChannel.setPassword(XmlUtil.getText(itemDevice,"Password"));
                    deviceChannel.setLongitude(itemDevice.element("Longitude") == null? 0.00:Double.parseDouble(XmlUtil.getText(itemDevice,"Longitude")));
                    deviceChannel.setLatitude(itemDevice.element("Latitude") == null? 0.00:Double.parseDouble(XmlUtil.getText(itemDevice,"Latitude")));
                    channelMap.put(channelDeviceId, deviceChannel);
                    deviceChannel.setPTZType(itemDevice.element("PTZType") == null? 0:Integer.parseInt(XmlUtil.getText(itemDevice,"PTZType")));
                    storager.updateChannel(device.getDeviceId(), deviceChannel);
                }
                // 更新
                storager.update(device);
                storager.updateDevice(device);
                RequestMessage msg = new RequestMessage();
                msg.setDeviceId(deviceId);
                msg.setType(DeferredResultHolder.CALLBACK_CMD_CATALOG);
@@ -232,13 +227,15 @@
            
            Device device = storager.queryVideoDevice(deviceId);
            if (device == null) {
                // TODO 也可能是通道
//                storager.queryChannel(deviceId)
                return;
            }
            device.setName(XmlUtil.getText(rootElement,"DeviceName"));
            device.setManufacturer(XmlUtil.getText(rootElement,"Manufacturer"));
            device.setModel(XmlUtil.getText(rootElement,"Model"));
            device.setFirmware(XmlUtil.getText(rootElement,"Firmware"));
            storager.update(device);
            storager.updateDevice(device);
            cmder.catalogQuery(device);
        } catch (DocumentException e) {
            e.printStackTrace();
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/RegisterRequestProcessor.java
@@ -138,7 +138,7 @@
            // 下发catelog查询目录
            if (registerFlag == 1 && device != null) {
                System.out.println("注册成功! deviceId:" + device.getDeviceId());
                storager.update(device);
                storager.updateDevice(device);
                publisher.onlineEventPublish(device.getDeviceId(), VideoManagerConstants.EVENT_ONLINE_REGISTER);
                handler.onRegister(device);
            } else if (registerFlag == 2) {
src/main/java/com/genersoft/iot/vmp/media/zlm/SolrProxyServletConfiguration.java
New file
@@ -0,0 +1,43 @@
package com.genersoft.iot.vmp.media.zlm;
import com.google.common.collect.ImmutableMap;
import org.mitre.dsmiley.httpproxy.ProxyServlet;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.servlet.Servlet;
import java.util.Map;
/**
 * 对查询流媒体信息的请求进行反向代理
 */
@Configuration
public class SolrProxyServletConfiguration {
    // 读取配置文件中路由设置
    @Value("${proxy.servlet_url}")
    private String servlet_url;
    // 读取配置中代理目标地址
    @Value("${proxy.target_url}")
    private String target_url;
    @Bean
    public Servlet createProxyServlet(){
        // 创建新的ProxyServlet
        return new ProxyServlet();
    }
    @Bean
    public ServletRegistrationBean proxyServletRegistration(){
        ServletRegistrationBean registrationBean = new ServletRegistrationBean(createProxyServlet(), servlet_url);
        //设置网址以及参数
        Map<String, String> params = ImmutableMap.of(
                "targetUri", target_url,
                "log", "true");
        registrationBean.setInitParameters(params);
        return registrationBean;
    }
}
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java
@@ -1,7 +1,13 @@
package com.genersoft.iot.vmp.media.zlm;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.genersoft.iot.vmp.conf.MediaServerConfig;
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@@ -29,6 +35,9 @@
    
    @Autowired
    private SIPCommander cmder;
    @Autowired
    private IVideoManagerStorager storager;
    
    /**
     * 流量统计事件,播放器或推流器断开时并且耗用流量超过特定阈值时会触发此事件,阈值通过配置文件general.flowThreshold配置;此事件对回复不敏感。
@@ -263,6 +272,12 @@
        if (logger.isDebugEnabled()) {
            logger.debug("ZLM HOOK on_server_started API调用,参数:" + json.toString());
        }
//        String data = json.getString("data");
//        List<MediaServerConfig> mediaServerConfigs = JSON.parseArray(JSON.toJSONString(json), MediaServerConfig.class);
//        MediaServerConfig mediaServerConfig = mediaServerConfigs.get(0);
        MediaServerConfig mediaServerConfig = JSON.toJavaObject(json, MediaServerConfig.class);
        storager.updateMediaInfo(mediaServerConfig);
        // TODO Auto-generated method stub
        
        JSONObject ret = new JSONObject();
src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorager.java
@@ -2,7 +2,12 @@
import java.util.List;
import com.alibaba.fastjson.JSONObject;
import com.genersoft.iot.vmp.common.PageResult;
import com.genersoft.iot.vmp.common.StreamInfo;
import com.genersoft.iot.vmp.conf.MediaServerConfig;
import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
/**    
 * @Description:视频设备数据存储接口
@@ -10,7 +15,20 @@
 * @date:   2020年5月6日 下午2:14:31     
 */
public interface IVideoManagerStorager {
    /**
     * 更新流媒体信息
     * @param mediaServerConfig
     * @return
     */
    public boolean updateMediaInfo(MediaServerConfig mediaServerConfig);
    /**
     * 获取流媒体信息
     * @return
     */
    public MediaServerConfig getMediaInfo();
    /**   
     * 根据设备ID判断设备是否存在
     * 
@@ -33,7 +51,15 @@
     * @param device 设备对象
     * @return true:创建成功  false:创建失败
     */
    public boolean update(Device device);
    public boolean updateDevice(Device device);
    /**
     * 添加设备通道
     *
     * @param deviceId 设备id
     * @param channel 通道
     */
    public void updateChannel(String deviceId, DeviceChannel channel);
    
    /**   
     * 获取设备
@@ -42,15 +68,47 @@
     * @return DShadow 设备对象
     */
    public Device queryVideoDevice(String deviceId);
    /**
     * 获取某个设备的通道列表
     *
     * @param deviceId 设备ID
     * @param page 分页 当前页
     * @param count 每页数量
     * @return
     */
    public PageResult queryChannelsByDeviceId(String deviceId, int page, int count);
    /**
     * 获取某个设备的通道列表
     *
     * @param deviceId 设备ID
     * @return
     */
    public List<DeviceChannel> queryChannelsByDeviceId(String deviceId);
    /**
     * 获取某个设备的通道
     * @param deviceId 设备ID
     * @param channelId 通道ID
     */
    public DeviceChannel queryChannel(String deviceId, String channelId);
    /**   
     * 获取多个设备
     * 
     * @param deviceIds 设备ID数组
     * @return List<Device> 设备对象数组
     */
    public PageResult<Device> queryVideoDeviceList(String[] deviceIds, int page, int count);
    /**
     * 获取多个设备
     *
     * @param deviceIds 设备ID数组
     * @return List<Device> 设备对象数组
     */
    public List<Device> queryVideoDeviceList(String[] deviceIds);
    /**   
     * 删除设备
     * 
@@ -74,4 +132,35 @@
     * @return true:更新成功  false:更新失败
     */
    public boolean outline(String deviceId);
    /**
     * 开始播放时将流存入
     *
     * @param deviceId 设备ID
     * @param channelId 通道ID
     * @param stream 流信息
     * @return
     */
    public boolean startPlay(String deviceId, String channelId, StreamInfo stream);
    /**
     * 停止播放时删除
     *
     * @param deviceId 设备ID
     * @param channelId 通道ID
     * @return
     */
    public boolean stopPlay(String deviceId, String channelId);
    /**
     * 查找视频流
     *
     * @param deviceId 设备ID
     * @param channelId 通道ID
     * @return
     */
    public StreamInfo queryPlay(String deviceId, String channelId);
}
src/main/java/com/genersoft/iot/vmp/storager/jdbc/VideoManagerJdbcStoragerImpl.java
@@ -2,6 +2,10 @@
import java.util.List;
import com.genersoft.iot.vmp.common.PageResult;
import com.genersoft.iot.vmp.common.StreamInfo;
import com.genersoft.iot.vmp.conf.MediaServerConfig;
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
@@ -17,7 +21,17 @@
@Component("jdbcStorager")
public class VideoManagerJdbcStoragerImpl implements IVideoManagerStorager {
    /**
    @Override
    public boolean updateMediaInfo(MediaServerConfig mediaServerConfig) {
        return false;
    }
    @Override
    public MediaServerConfig getMediaInfo() {
        return null;
    }
    /**
     * 根据设备ID判断设备是否存在
     * 
     * @param deviceId 设备ID
@@ -40,18 +54,17 @@
        // TODO Auto-generated method stub
        return false;
    }
    /**
     * 视频设备更新
     *
     * @param device 设备对象
     * @return true:更新成功  false:更新失败
     */
    @Override
    public boolean update(Device device) {
        // TODO Auto-generated method stub
    public boolean updateDevice(Device device) {
        return false;
    }
    @Override
    public void updateChannel(String deviceId, DeviceChannel channel) {
    }
    /**   
     * 获取设备
@@ -62,6 +75,26 @@
    @Override
    public Device queryVideoDevice(String deviceId) {
        // TODO Auto-generated method stub
        return null;
    }
    @Override
    public PageResult queryChannelsByDeviceId(String deviceId, int page, int count) {
        return null;
    }
    @Override
    public List<DeviceChannel> queryChannelsByDeviceId(String deviceId) {
        return null;
    }
    @Override
    public DeviceChannel queryChannel(String deviceId, String channelId) {
        return null;
    }
    @Override
    public PageResult<Device> queryVideoDeviceList(String[] deviceIds, int page, int count) {
        return null;
    }
@@ -113,4 +146,19 @@
        return false;
    }
    @Override
    public boolean startPlay(String deviceId, String channelId, StreamInfo stream) {
        return false;
    }
    @Override
    public boolean stopPlay(String deviceId, String channelId) {
        return false;
    }
    @Override
    public StreamInfo queryPlay(String deviceId, String channelId) {
        return null;
    }
}
src/main/java/com/genersoft/iot/vmp/storager/redis/VideoManagerRedisStoragerImpl.java
@@ -3,6 +3,12 @@
import java.util.ArrayList;
import java.util.List;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.genersoft.iot.vmp.common.PageResult;
import com.genersoft.iot.vmp.common.StreamInfo;
import com.genersoft.iot.vmp.conf.MediaServerConfig;
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@@ -21,7 +27,8 @@
    @Autowired
    private RedisUtil redis;
    /**   
     * 根据设备ID判断设备是否存在
     * 
@@ -30,7 +37,7 @@
     */ 
    @Override
    public boolean exists(String deviceId) {
        return redis.hasKey(VideoManagerConstants.CACHEKEY_PREFIX+deviceId);
        return redis.hasKey(VideoManagerConstants.DEVICE_PREFIX+deviceId);
    }
    /**   
@@ -41,9 +48,11 @@
     */ 
    @Override
    public boolean create(Device device) {
        return redis.set(VideoManagerConstants.CACHEKEY_PREFIX+device.getDeviceId(), device);
        return redis.set(VideoManagerConstants.DEVICE_PREFIX+device.getDeviceId(), device);
    }
    /**   
     * 视频设备更新
     * 
@@ -51,8 +60,26 @@
     * @return true:更新成功  false:更新失败
     */  
    @Override
    public boolean update(Device device) {
        return redis.set(VideoManagerConstants.CACHEKEY_PREFIX+device.getDeviceId(), device);
    public boolean updateDevice(Device device) {
        List<Object> deviceChannelList = redis.keys(VideoManagerConstants.CACHEKEY_PREFIX + device.getDeviceId() + "_" + "*");
        // 更新device中的通道数量
        device.setChannelCount(deviceChannelList.size());
        // 存储device
        return redis.set(VideoManagerConstants.DEVICE_PREFIX+device.getDeviceId(), device);
    }
    @Override
    public void updateChannel(String deviceId, DeviceChannel channel) {
        // 存储通道
        redis.set(VideoManagerConstants.CACHEKEY_PREFIX+deviceId + "_" + channel.getChannelId(),
                channel);
        List<Object> deviceChannelList = redis.keys(VideoManagerConstants.CACHEKEY_PREFIX + deviceId + "_" + "*");
        // 更新device中的通道数量
        Device device = (Device)redis.get(VideoManagerConstants.DEVICE_PREFIX+deviceId);
        device.setChannelCount(deviceChannelList.size());
        redis.set(VideoManagerConstants.DEVICE_PREFIX+device.getDeviceId(), device);
    }
    /**   
@@ -63,26 +90,94 @@
     */  
    @Override
    public Device queryVideoDevice(String deviceId) {
        return (Device)redis.get(VideoManagerConstants.CACHEKEY_PREFIX+deviceId);
        return (Device)redis.get(VideoManagerConstants.DEVICE_PREFIX+deviceId);
    }
    /**
    @Override
    public PageResult queryChannelsByDeviceId(String deviceId, int page, int count) {
        List<DeviceChannel> result = new ArrayList<>();
        PageResult pageResult = new PageResult<DeviceChannel>();
        List<Object> deviceChannelList = redis.keys(VideoManagerConstants.CACHEKEY_PREFIX + deviceId + "_" + "*");
        pageResult.setPage(page);
        pageResult.setCount(count);
        pageResult.setTotal(deviceChannelList.size());
        int maxCount = (page + 1 ) * count;
        if (deviceChannelList != null && deviceChannelList.size() > 0 ) {
            for (int i = page * count; i < (pageResult.getTotal() > maxCount ? maxCount : pageResult.getTotal() ); i++) {
                result.add((DeviceChannel)redis.get((String)deviceChannelList.get(i)));
            }
            pageResult.setData(result);
        }
        return pageResult;
    }
    @Override
    public List<DeviceChannel> queryChannelsByDeviceId(String deviceId) {
        List<DeviceChannel> result = new ArrayList<>();
        List<Object> deviceChannelList = redis.keys(VideoManagerConstants.CACHEKEY_PREFIX + deviceId + "_" + "*");
        if (deviceChannelList != null && deviceChannelList.size() > 0 ) {
            for (int i = 0; i < deviceChannelList.size(); i++) {
                result.add((DeviceChannel)redis.get((String)deviceChannelList.get(i)));
            }
        }
        return result;
    }
    @Override
    public DeviceChannel queryChannel(String deviceId, String channelId) {
        return (DeviceChannel)redis.get(VideoManagerConstants.CACHEKEY_PREFIX + deviceId + "_" + channelId);
    }
    /**
     * 获取多个设备
     * 
     * @param deviceIds 设备ID数组
     * @return List<Device> 设备对象数组
     */  
    @Override
    public PageResult<Device> queryVideoDeviceList(String[] deviceIds, int page, int count) {
        List<Device> devices = new ArrayList<>();
        PageResult pageResult = new PageResult<Device>();
        pageResult.setPage(page);
        pageResult.setCount(count);
        if (deviceIds == null || deviceIds.length == 0) {
            List<Object> deviceIdList = redis.keys(VideoManagerConstants.DEVICE_PREFIX+"*");
            pageResult.setTotal(deviceIdList.size());
            int maxCount = (page + 1)* count;
            for (int i = page * count; i < (pageResult.getTotal() > maxCount ? maxCount : pageResult.getTotal() ); i++) {
                devices.add((Device)redis.get((String)deviceIdList.get(i)));
            }
        } else {
            for (int i = 0; i < deviceIds.length; i++) {
                devices.add((Device)redis.get(VideoManagerConstants.DEVICE_PREFIX+deviceIds[i]));
            }
        }
        pageResult.setData(devices);
        return pageResult;
    }
    /**
     * 获取多个设备
     *
     * @param deviceIds 设备ID数组
     * @return List<Device> 设备对象数组
     */
    @Override
    public List<Device> queryVideoDeviceList(String[] deviceIds) {
        List<Device> devices = new ArrayList<>();
        if (deviceIds == null || deviceIds.length == 0) {
            List<Object> deviceIdList = redis.keys(VideoManagerConstants.CACHEKEY_PREFIX+"*");
            List<Object> deviceIdList = redis.keys(VideoManagerConstants.DEVICE_PREFIX+"*");
            for (int i = 0; i < deviceIdList.size(); i++) {
                devices.add((Device)redis.get((String)deviceIdList.get(i)));
            }
        } else {
            for (int i = 0; i < deviceIds.length; i++) {
                devices.add((Device)redis.get(VideoManagerConstants.CACHEKEY_PREFIX+deviceIds[i]));
                devices.add((Device)redis.get(VideoManagerConstants.DEVICE_PREFIX+deviceIds[i]));
            }
        }
        return devices;
@@ -96,7 +191,7 @@
     */  
    @Override
    public boolean delete(String deviceId) {
        return redis.del(VideoManagerConstants.CACHEKEY_PREFIX+deviceId);
        return redis.del(VideoManagerConstants.DEVICE_PREFIX+deviceId);
    }
    /**   
@@ -107,9 +202,9 @@
     */ 
    @Override
    public boolean online(String deviceId) {
        Device device = (Device)redis.get(VideoManagerConstants.CACHEKEY_PREFIX+deviceId);
        Device device = (Device)redis.get(VideoManagerConstants.DEVICE_PREFIX+deviceId);
        device.setOnline(1);
        return redis.set(VideoManagerConstants.CACHEKEY_PREFIX+device.getDeviceId(), device);
        return redis.set(VideoManagerConstants.DEVICE_PREFIX+device.getDeviceId(), device);
    }
    /**   
@@ -120,9 +215,64 @@
     */ 
    @Override
    public boolean outline(String deviceId) {
        Device device = (Device)redis.get(VideoManagerConstants.CACHEKEY_PREFIX+deviceId);
        Device device = (Device)redis.get(VideoManagerConstants.DEVICE_PREFIX+deviceId);
        if (device == null) return false;
        device.setOnline(0);
        return redis.set(VideoManagerConstants.CACHEKEY_PREFIX+device.getDeviceId(), device);
        return redis.set(VideoManagerConstants.DEVICE_PREFIX+device.getDeviceId(), device);
    }
    /**
     * 开始播放时将流存入redis
     *
     * @param deviceId 设备ID
     * @param channelId 通道ID
     * @return
     */
    @Override
    public boolean startPlay(String deviceId, String channelId, StreamInfo stream) {
        return redis.set(String.format("%S_%s_%s", VideoManagerConstants.PLAYER_PREFIX, deviceId, channelId),
                stream);
    }
    /**
     * 停止播放时从redis删除
     *
     * @param deviceId 设备ID
     * @param channelId 通道ID
     * @return
     */
    @Override
    public boolean stopPlay(String deviceId, String channelId) {
        return redis.del(String.format("%S_%s_%s", VideoManagerConstants.PLAYER_PREFIX, deviceId, channelId));
    }
    /**
     * 查询播放列表
     * @param deviceId 设备ID
     * @param channelId 通道ID
     * @return
     */
    @Override
    public StreamInfo queryPlay(String deviceId, String channelId) {
        return (StreamInfo)redis.get(String.format("%S_%s_%s", VideoManagerConstants.PLAYER_PREFIX, deviceId, channelId));
    }
    /**
     * 更新流媒体信息
     * @param mediaServerConfig
     * @return
     */
    @Override
    public boolean updateMediaInfo(MediaServerConfig mediaServerConfig) {
        return redis.set(VideoManagerConstants.MEDIA_SERVER_PREFIX,mediaServerConfig);
    }
    /**
     * 获取流媒体信息
     * @return
     */
    @Override
    public MediaServerConfig getMediaInfo() {
        return (MediaServerConfig)redis.get(VideoManagerConstants.MEDIA_SERVER_PREFIX);
    }
}
src/main/java/com/genersoft/iot/vmp/utils/redis/RedisUtil.java
@@ -8,6 +8,7 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
@@ -389,6 +390,121 @@
            return 0;
        }
    }
//    ============================== ZSet ==============================
    /**
     * 添加一个元素, zset与set最大的区别就是每个元素都有一个score,因此有个排序的辅助功能;  zadd
     *
     * @param key
     * @param value
     * @param score
     */
    public void zAdd(String key, String value, double score) {
        redisTemplate.opsForZSet().add(key, value, score);
    }
    /**
     * 删除元素 zrem
     *
     * @param key
     * @param value
     */
    public void zRemove(String key, String value) {
        redisTemplate.opsForZSet().remove(key, value);
    }
    /**
     * score的增加or减少 zincrby
     *
     * @param key
     * @param value
     * @param score
     */
    public Double zIncrScore(String key, String value, double score) {
        return redisTemplate.opsForZSet().incrementScore(key, value, score);
    }
    /**
     * 查询value对应的score   zscore
     *
     * @param key
     * @param value
     * @return
     */
    public Double zScore(String key, String value) {
        return redisTemplate.opsForZSet().score(key, value);
    }
    /**
     * 判断value在zset中的排名  zrank
     *
     * @param key
     * @param value
     * @return
     */
    public Long zRank(String key, String value) {
        return redisTemplate.opsForZSet().rank(key, value);
    }
    /**
     * 返回集合的长度
     *
     * @param key
     * @return
     */
    public Long zSize(String key) {
        return redisTemplate.opsForZSet().zCard(key);
    }
    /**
     * 查询集合中指定顺序的值, 0 -1 表示获取全部的集合内容  zrange
     *
     * 返回有序的集合,score小的在前面
     *
     * @param key
     * @param start
     * @param end
     * @return
     */
    public Set<String> ZRange(String key, int start, int end) {
        return redisTemplate.opsForZSet().range(key, start, end);
    }
    /**
     * 查询集合中指定顺序的值和score,0, -1 表示获取全部的集合内容
     *
     * @param key
     * @param start
     * @param end
     * @return
     */
    public Set<ZSetOperations.TypedTuple<String>> zRangeWithScore(String key, int start, int end) {
        return redisTemplate.opsForZSet().rangeWithScores(key, start, end);
    }
    /**
     * 查询集合中指定顺序的值  zrevrange
     *
     * 返回有序的集合中,score大的在前面
     *
     * @param key
     * @param start
     * @param end
     * @return
     */
    public Set<String> zRevRange(String key, int start, int end) {
        return redisTemplate.opsForZSet().reverseRange(key, start, end);
    }
    /**
     * 根据score的值,来获取满足条件的集合  zrangebyscore
     *
     * @param key
     * @param min
     * @param max
     * @return
     */
    public Set<String> zSortRange(String key, int min, int max) {
        return redisTemplate.opsForZSet().rangeByScore(key, min, max);
    }
//    ============================== List ==============================
src/main/java/com/genersoft/iot/vmp/vmanager/device/DeviceController.java
@@ -2,6 +2,8 @@
import java.util.List;
import com.genersoft.iot.vmp.common.PageResult;
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@@ -53,14 +55,30 @@
    }
    
    @GetMapping("/devices")
    public ResponseEntity<List<Device>> devices(){
    public PageResult<Device> devices(int page, int count){
        
        if (logger.isDebugEnabled()) {
            logger.debug("查询所有视频设备API调用");
        }
        
        List<Device> deviceList = storager.queryVideoDeviceList(null);
        return new ResponseEntity<>(deviceList,HttpStatus.OK);
        return storager.queryVideoDeviceList(null, page, count);
    }
    /**
     * 分页查询通道数
     * @param deviceId 设备id
     * @param page 当前页
     * @param count 每页条数
     * @return 通道列表
     */
    @GetMapping("devices/{deviceId}/channels")
    public ResponseEntity<PageResult> channels(@PathVariable String deviceId, int page, int count){
        if (logger.isDebugEnabled()) {
            logger.debug("查询所有视频设备API调用");
        }
        PageResult pageResult = storager.queryChannelsByDeviceId(deviceId, page, count);
        return new ResponseEntity<>(pageResult,HttpStatus.OK);
    }
    
    @PostMapping("/devices/{deviceId}/sync")
src/main/java/com/genersoft/iot/vmp/vmanager/play/PlayController.java
@@ -1,5 +1,6 @@
package com.genersoft.iot.vmp.vmanager.play;
import com.genersoft.iot.vmp.common.StreamInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@@ -34,16 +35,16 @@
    public ResponseEntity<String> play(@PathVariable String deviceId,@PathVariable String channelId){
        
        Device device = storager.queryVideoDevice(deviceId);
        String ssrc = cmder.playStreamCmd(device, channelId);
        StreamInfo streamInfo = cmder.playStreamCmd(device, channelId);
        
        if (logger.isDebugEnabled()) {
            logger.debug(String.format("设备预览 API调用,deviceId:%s ,channelId:%s",deviceId, channelId));
            logger.debug("设备预览 API调用,ssrc:"+ssrc+",ZLMedia streamId:"+Integer.toHexString(Integer.parseInt(ssrc)));
            logger.debug("设备预览 API调用,ssrc:"+streamInfo.getSsrc()+",ZLMedia streamId:"+Integer.toHexString(Integer.parseInt(streamInfo.getSsrc())));
        }
        
        if(ssrc!=null) {
        if(streamInfo!=null) {
            JSONObject json = new JSONObject();
            json.put("ssrc", ssrc);
            json.put("ssrc", streamInfo.getSsrc());
            return new ResponseEntity<String>(json.toString(),HttpStatus.OK);
        } else {
            logger.warn("设备预览API调用失败!");
src/main/java/com/genersoft/iot/vmp/web/AuthController.java
New file
@@ -0,0 +1,30 @@
package com.genersoft.iot.vmp.web;
import com.genersoft.iot.vmp.gb28181.bean.Device;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
@CrossOrigin
@RestController
@RequestMapping(value = "/auth")
public class AuthController {
    @Value("${auth.username}")
    private String username;
    @Value("${auth.password}")
    private String password;
    @RequestMapping("/login")
    public Object devices(String username, String password){
        if (!StringUtils.isEmpty(username) && username.equals(username)
                && !StringUtils.isEmpty(password) && password.equals(password)) {
            return "success";
        }else {
            return "fait";
        }
    }
}
src/main/resources/application.yml
@@ -7,27 +7,26 @@
        communicate: http
    redis: 
        # Redis服务器IP
        #host: 10.24.20.63
        host: 127.0.0.1
        host: 192.168.1.141
        #端口号
        port: 6379
        datebase: 0
        database: 6
        #访问密码,若你的redis服务器没有设置密码,就不需要用密码去连接
        password:
        password: 4767cb971b40a1300fa09b7f87b09d1c
        #超时时间
        timeout: 10000
    datasource: 
        name: eiot
        url: jdbc:mysql://10.24.20.63:3306/eiot?useUnicode=true&characterEncoding=UTF8&rewriteBatchedStatements=true
        url: jdbc:mysql://192.168.1.141:3306/eiot?useUnicode=true&characterEncoding=UTF8&rewriteBatchedStatements=true
        username: root
        password: 123456
        password: root
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: com.mysql.jdbc.Driver
server:
    port: 8080
    port: 18080
sip:
#   ip: 10.200.64.63
    ip: 192.168.0.102
    ip: 192.168.1.20
    port: 5060
    # 根据国标6.1.2中规定,domain宜采用ID统一编码的前十位编码。国标附录D中定义前8位为中心编码(由省级、市级、区级、基层编号组成,参照GB/T 2260-2007)
    # 后两位为行业编码,定义参照附录D.3
@@ -35,8 +34,19 @@
    domain: 3701020049
    id: 37010200492000000001
    # 默认设备认证密码,后续扩展使用设备单独密码
    password: admin123
    password: 12345678
media:
#   ip: 10.200.64.88
    ip: 192.168.0.102
    port: 10000
    ip: 192.168.1.20
    port: 10000
# 自定义代理相关配置
# 代理的本地路由
proxy:
     servlet_url: /media/*
        # 要代理的地址
     target_url: http://127.0.0.1:10080
auth: #32位小写md5加密(默认密码为admin)
    username: admin
    password: 21232f297a57a5a743894a0e4a801fc3