diff --git a/pom.xml b/pom.xml index ec4e9c33..528f7655 100644 --- a/pom.xml +++ b/pom.xml @@ -143,6 +143,17 @@ jedis 2.9.0 + + + org.mitre.dsmiley.httpproxy + smiley-http-proxy-servlet + 1.7 + + + com.google.guava + guava + 18.0 + diff --git a/src/main/java/com/genersoft/iot/vmp/common/PageResult.java b/src/main/java/com/genersoft/iot/vmp/common/PageResult.java new file mode 100644 index 00000000..9a420868 --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/common/PageResult.java @@ -0,0 +1,44 @@ +package com.genersoft.iot.vmp.common; + +import java.util.List; + +public class PageResult { + + private int page; + private int count; + private int total; + + private List data; + + public List getData() { + return data; + } + + public void setData(List 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; + } +} diff --git a/src/main/java/com/genersoft/iot/vmp/common/StreamInfo.java b/src/main/java/com/genersoft/iot/vmp/common/StreamInfo.java new file mode 100644 index 00000000..6e876be1 --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/common/StreamInfo.java @@ -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; + } +} diff --git a/src/main/java/com/genersoft/iot/vmp/common/VideoManagerConstants.java b/src/main/java/com/genersoft/iot/vmp/common/VideoManagerConstants.java index 802309d5..98592bd2 100644 --- a/src/main/java/com/genersoft/iot/vmp/common/VideoManagerConstants.java +++ b/src/main/java/com/genersoft/iot/vmp/common/VideoManagerConstants.java @@ -8,10 +8,16 @@ package com.genersoft.iot.vmp.common; */ 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"; diff --git a/src/main/java/com/genersoft/iot/vmp/conf/MediaServerConfig.java b/src/main/java/com/genersoft/iot/vmp/conf/MediaServerConfig.java new file mode 100644 index 00000000..6b04f133 --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/conf/MediaServerConfig.java @@ -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; + } +} diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/Device.java b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/Device.java index 74f86a21..8a88497a 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/Device.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/Device.java @@ -49,7 +49,9 @@ public class Device { /** * 通道列表 */ - private Map channelMap; +// private Map channelMap; + + private int channelCount; public String getDeviceId() { @@ -84,13 +86,13 @@ public class Device { this.host = host; } - public Map getChannelMap() { - return channelMap; - } - - public void setChannelMap(Map channelMap) { - this.channelMap = channelMap; - } +// public Map getChannelMap() { +// return channelMap; +// } +// +// public void setChannelMap(Map channelMap) { +// this.channelMap = channelMap; +// } public String getManufacturer() { return manufacturer; @@ -123,4 +125,12 @@ public class Device { public void setOnline(int online) { this.online = online; } + + public int getChannelCount() { + return channelCount; + } + + public void setChannelCount(int channelCount) { + this.channelCount = channelCount; + } } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/DeviceChannel.java b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/DeviceChannel.java index 1bccad83..5c3989a2 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/DeviceChannel.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/DeviceChannel.java @@ -100,7 +100,12 @@ public class DeviceChannel { /** * 密码 */ - private String password; + private String password; + + /** + * 云台控制 + */ + private int PTZType; /** * 在线/离线 @@ -123,6 +128,11 @@ public class DeviceChannel { */ private double latitude; + /** + * 流唯一编号,存在表示正在直播 + */ + private String ssrc; + public String getChannelId() { return channelId; } @@ -306,4 +316,20 @@ public class DeviceChannel { 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; + } } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java index db93230b..0fdc8975 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java +++ b/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 @@ public interface ISIPCommander { * @param device 视频设备 * @param channelId 预览通道 */ - public String playStreamCmd(Device device,String channelId); + public StreamInfo playStreamCmd(Device device, String channelId); /** * 请求回放视频流 diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java index aaf347db..104fab03 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java @@ -15,8 +15,14 @@ import javax.sip.address.SipURI; 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 @@ public class SIPCommander implements ISIPCommander { @Autowired private VideoStreamSessionManager streamSession; + + @Autowired + private IVideoManagerStorager storager; @Autowired @Qualifier(value="tcpSipProvider") @@ -50,6 +59,9 @@ public class SIPCommander implements ISIPCommander { @Autowired @Qualifier(value="udpSipProvider") private SipProvider udpSipProvider; + + @Value("${media.ip}") + private String mediaIp; /** * 云台方向放控制,使用配置文件中的默认镜头移动速度 @@ -58,7 +70,6 @@ public class SIPCommander implements ISIPCommander { * @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 @@ public class SIPCommander implements ISIPCommander { * @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 @@ public class SIPCommander implements ISIPCommander { 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 @@ public class SIPCommander implements ISIPCommander { /** * 视频流停止 * - * @param device 视频设备 - * @param channelId 预览通道 */ @Override public void streamByeCmd(String ssrc) { diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/MessageRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/MessageRequestProcessor.java index 70385901..e9f59061 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/MessageRequestProcessor.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/MessageRequestProcessor.java @@ -76,8 +76,6 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor { * 处理MESSAGE请求 * * @param evt - * @param layer - * @param transaction */ @Override public void process(RequestEvent evt) { @@ -127,7 +125,7 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor { 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 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor { if (device == null) { return; } - Map channelMap = device.getChannelMap(); - if (channelMap == null) { - channelMap = new HashMap(5); - device.setChannelMap(channelMap); - } // 遍历DeviceList while (deviceListIterator.hasNext()) { Element itemDevice = deviceListIterator.next(); @@ -175,7 +168,7 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor { 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 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor { 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 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor { 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(); diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/RegisterRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/RegisterRequestProcessor.java index a90429ad..62170245 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/RegisterRequestProcessor.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/RegisterRequestProcessor.java @@ -138,7 +138,7 @@ public class RegisterRequestProcessor extends SIPRequestAbstractProcessor { // 下发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) { diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/SolrProxyServletConfiguration.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/SolrProxyServletConfiguration.java new file mode 100644 index 00000000..9a22a184 --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/SolrProxyServletConfiguration.java @@ -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 params = ImmutableMap.of( + "targetUri", target_url, + "log", "true"); + registrationBean.setInitParameters(params); + return registrationBean; + } +} diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java index ae670201..2f5766a1 100644 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java +++ b/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 @@ public class ZLMHttpHookListener { @Autowired private SIPCommander cmder; + + @Autowired + private IVideoManagerStorager storager; /** * 流量统计事件,播放器或推流器断开时并且耗用流量超过特定阈值时会触发此事件,阈值通过配置文件general.flowThreshold配置;此事件对回复不敏感。 @@ -263,6 +272,12 @@ public class ZLMHttpHookListener { if (logger.isDebugEnabled()) { logger.debug("ZLM HOOK on_server_started API调用,参数:" + json.toString()); } + +// String data = json.getString("data"); +// List 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(); diff --git a/src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorager.java b/src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorager.java index 47aa362e..0993c116 100644 --- a/src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorager.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorager.java @@ -2,7 +2,12 @@ package com.genersoft.iot.vmp.storager; 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 @@ import com.genersoft.iot.vmp.gb28181.bean.Device; * @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 @@ public interface IVideoManagerStorager { * @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 @@ public interface IVideoManagerStorager { * @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 queryChannelsByDeviceId(String deviceId); + /** + * 获取某个设备的通道 + * @param deviceId 设备ID + * @param channelId 通道ID + */ + public DeviceChannel queryChannel(String deviceId, String channelId); + /** * 获取多个设备 * * @param deviceIds 设备ID数组 * @return List 设备对象数组 */ + public PageResult queryVideoDeviceList(String[] deviceIds, int page, int count); + + /** + * 获取多个设备 + * + * @param deviceIds 设备ID数组 + * @return List 设备对象数组 + */ public List queryVideoDeviceList(String[] deviceIds); - + /** * 删除设备 * @@ -74,4 +132,35 @@ public interface IVideoManagerStorager { * @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); + + + } diff --git a/src/main/java/com/genersoft/iot/vmp/storager/jdbc/VideoManagerJdbcStoragerImpl.java b/src/main/java/com/genersoft/iot/vmp/storager/jdbc/VideoManagerJdbcStoragerImpl.java index 59ecba00..b4e2ff93 100644 --- a/src/main/java/com/genersoft/iot/vmp/storager/jdbc/VideoManagerJdbcStoragerImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/jdbc/VideoManagerJdbcStoragerImpl.java @@ -2,6 +2,10 @@ package com.genersoft.iot.vmp.storager.jdbc; 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 @@ import com.genersoft.iot.vmp.storager.IVideoManagerStorager; @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,19 +54,18 @@ public class VideoManagerJdbcStoragerImpl implements IVideoManagerStorager { // 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) { + + } + + /** * 获取设备 * @@ -65,6 +78,26 @@ public class VideoManagerJdbcStoragerImpl implements IVideoManagerStorager { return null; } + @Override + public PageResult queryChannelsByDeviceId(String deviceId, int page, int count) { + return null; + } + + @Override + public List queryChannelsByDeviceId(String deviceId) { + return null; + } + + @Override + public DeviceChannel queryChannel(String deviceId, String channelId) { + return null; + } + + @Override + public PageResult queryVideoDeviceList(String[] deviceIds, int page, int count) { + return null; + } + /** * 获取多个设备 * @@ -113,4 +146,19 @@ public class VideoManagerJdbcStoragerImpl implements IVideoManagerStorager { 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; + } + } diff --git a/src/main/java/com/genersoft/iot/vmp/storager/redis/VideoManagerRedisStoragerImpl.java b/src/main/java/com/genersoft/iot/vmp/storager/redis/VideoManagerRedisStoragerImpl.java index d6e4603b..8ea9f7ee 100644 --- a/src/main/java/com/genersoft/iot/vmp/storager/redis/VideoManagerRedisStoragerImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/redis/VideoManagerRedisStoragerImpl.java @@ -3,6 +3,12 @@ package com.genersoft.iot.vmp.storager.redis; 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 @@ public class VideoManagerRedisStoragerImpl implements IVideoManagerStorager { @Autowired private RedisUtil redis; - + + /** * 根据设备ID判断设备是否存在 * @@ -30,7 +37,7 @@ public class VideoManagerRedisStoragerImpl implements IVideoManagerStorager { */ @Override public boolean exists(String deviceId) { - return redis.hasKey(VideoManagerConstants.CACHEKEY_PREFIX+deviceId); + return redis.hasKey(VideoManagerConstants.DEVICE_PREFIX+deviceId); } /** @@ -41,9 +48,11 @@ public class VideoManagerRedisStoragerImpl implements IVideoManagerStorager { */ @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 @@ public class VideoManagerRedisStoragerImpl implements IVideoManagerStorager { * @return true:更新成功 false:更新失败 */ @Override - public boolean update(Device device) { - return redis.set(VideoManagerConstants.CACHEKEY_PREFIX+device.getDeviceId(), device); + public boolean updateDevice(Device device) { + List 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 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 @@ public class VideoManagerRedisStoragerImpl implements IVideoManagerStorager { */ @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 result = new ArrayList<>(); + PageResult pageResult = new PageResult(); + List 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 queryChannelsByDeviceId(String deviceId) { + List result = new ArrayList<>(); + List 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 设备对象数组 */ @Override + public PageResult queryVideoDeviceList(String[] deviceIds, int page, int count) { + List devices = new ArrayList<>(); + PageResult pageResult = new PageResult(); + pageResult.setPage(page); + pageResult.setCount(count); + + if (deviceIds == null || deviceIds.length == 0) { + + List 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 设备对象数组 + */ + @Override public List queryVideoDeviceList(String[] deviceIds) { List devices = new ArrayList<>(); + if (deviceIds == null || deviceIds.length == 0) { - List deviceIdList = redis.keys(VideoManagerConstants.CACHEKEY_PREFIX+"*"); + List 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 @@ public class VideoManagerRedisStoragerImpl implements IVideoManagerStorager { */ @Override public boolean delete(String deviceId) { - return redis.del(VideoManagerConstants.CACHEKEY_PREFIX+deviceId); + return redis.del(VideoManagerConstants.DEVICE_PREFIX+deviceId); } /** @@ -107,9 +202,9 @@ public class VideoManagerRedisStoragerImpl implements IVideoManagerStorager { */ @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 @@ public class VideoManagerRedisStoragerImpl implements IVideoManagerStorager { */ @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); } - } diff --git a/src/main/java/com/genersoft/iot/vmp/utils/redis/RedisUtil.java b/src/main/java/com/genersoft/iot/vmp/utils/redis/RedisUtil.java index f1d1673a..463d9427 100644 --- a/src/main/java/com/genersoft/iot/vmp/utils/redis/RedisUtil.java +++ b/src/main/java/com/genersoft/iot/vmp/utils/redis/RedisUtil.java @@ -8,6 +8,7 @@ import java.util.concurrent.TimeUnit; 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 @@ public class RedisUtil { 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 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> 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 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 zSortRange(String key, int min, int max) { + return redisTemplate.opsForZSet().rangeByScore(key, min, max); + } + // ============================== List ============================== diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/device/DeviceController.java b/src/main/java/com/genersoft/iot/vmp/vmanager/device/DeviceController.java index 6368f822..9b229acd 100644 --- a/src/main/java/com/genersoft/iot/vmp/vmanager/device/DeviceController.java +++ b/src/main/java/com/genersoft/iot/vmp/vmanager/device/DeviceController.java @@ -2,6 +2,8 @@ package com.genersoft.iot.vmp.vmanager.device; 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 @@ public class DeviceController { } @GetMapping("/devices") - public ResponseEntity> devices(){ + public PageResult devices(int page, int count){ if (logger.isDebugEnabled()) { logger.debug("查询所有视频设备API调用"); } - List 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 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") diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/play/PlayController.java b/src/main/java/com/genersoft/iot/vmp/vmanager/play/PlayController.java index c0d2233f..0c4ab634 100644 --- a/src/main/java/com/genersoft/iot/vmp/vmanager/play/PlayController.java +++ b/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 class PlayController { public ResponseEntity 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(json.toString(),HttpStatus.OK); } else { logger.warn("设备预览API调用失败!"); diff --git a/src/main/java/com/genersoft/iot/vmp/web/AuthController.java b/src/main/java/com/genersoft/iot/vmp/web/AuthController.java new file mode 100644 index 00000000..50e4da13 --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/web/AuthController.java @@ -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"; + } + } +} diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 7e6bc405..2784aceb 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -7,27 +7,26 @@ spring: 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 @@ sip: domain: 3701020049 id: 37010200492000000001 # 默认设备认证密码,后续扩展使用设备单独密码 - password: admin123 + password: 12345678 media: # ip: 10.200.64.88 - ip: 192.168.0.102 - port: 10000 \ No newline at end of file + 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 \ No newline at end of file