diff --git a/.gitignore b/.gitignore index d1cb0635..d57aa37c 100644 --- a/.gitignore +++ b/.gitignore @@ -26,5 +26,6 @@ hs_err_pid* /.idea/* /target/* /.idea/ +/logs/ /target/ diff --git a/pom.xml b/pom.xml index 53f3198b..a55c94f3 100644 --- a/pom.xml +++ b/pom.xml @@ -1,225 +1,220 @@ - - 4.0.0 - - org.springframework.boot - spring-boot-starter-parent - 2.3.5.RELEASE - - - com.genersoft - wvp - web video platform - - - UTF-8 - - 2.1.4 - 1.2.3 - 8.0.22 - 3.32.3.2 - 3.1.0 - 1.2.10 - 2.9.2 - 2.6.1 - 1.3.0-91 - 1.2.17 - 2.1.3 - 1.2.73 - 30.0-jre - 1.18.12 - 3.7 - 2.6 - 4.9.0 - - ${project.build.directory}/generated-snippets - ${project.basedir}/docs/asciidoc - ${project.build.directory}/asciidoc - ${project.build.directory}/asciidoc/html - ${project.build.directory}/asciidoc/pdf - - - - - nexus-aliyun - Nexus aliyun - https://maven.aliyun.com/repository/public - default - - false - - - true - - - - - - nexus-aliyun - Nexus aliyun - https://maven.aliyun.com/repository/public - - false - - - true - - - - - - - - org.springframework.boot - spring-boot-starter-data-redis - - - org.springframework.boot - spring-boot-starter-web - - - org.mybatis.spring.boot - mybatis-spring-boot-starter - ${mybatis-spring-boot-starter-version} - - - - - com.alibaba - druid - ${druid-version} - - - - - mysql - mysql-connector-java - ${mysql-connector-java-version} - - - - - org.xerial - sqlite-jdbc - ${sqlite-jdbc-version} - - - - - com.github.pagehelper - pagehelper-spring-boot-starter - ${pagehelper-spring-boot-starter-version} - - - - redis.clients - jedis - ${jedis-version} - - - - - - io.springfox - springfox-swagger2 - ${springfox-swagger2-version} - - - io.springfox - springfox-swagger-ui - ${springfox-swagger-ui-version} - - - javax.validation - validation-api - - - - - org.springframework.boot - spring-boot-starter-aop - - - - - javax.sip - jain-sip-ri - ${jain-sip-ri-version} - - - - log4j - log4j - ${log4j-version} - - - - - org.dom4j - dom4j - ${dom4j-version} - - - - - com.alibaba - fastjson - ${fastjson-version} - - - - - com.google.guava - guava - ${guava-version} - - - org.projectlombok - lombok - ${lombok-version} - - - org.apache.commons - commons-lang3 - ${commons-lang3-version} - - - commons-io - commons-io - ${commons-io-version} - - - - - com.squareup.okhttp3 - okhttp - ${okhttp-version} - + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 2.3.5.RELEASE + + + com.genersoft + wvp + web video platform + + + UTF-8 + + 2.1.4 + 1.2.3 + 8.0.22 + 3.32.3.2 + 3.1.0 + 1.2.10 + 2.9.2 + 2.6.1 + 1.3.0-91 + 1.2.17 + 2.1.3 + 1.2.73 + 30.0-jre + 1.18.12 + 3.7 + 2.6 + 4.9.0 + + ${project.build.directory}/generated-snippets + ${project.basedir}/docs/asciidoc + ${project.build.directory}/asciidoc + ${project.build.directory}/asciidoc/html + ${project.build.directory}/asciidoc/pdf + + + + + nexus-aliyun + Nexus aliyun + https://maven.aliyun.com/repository/public + default + + false + + + true + + + + + + nexus-aliyun + Nexus aliyun + https://maven.aliyun.com/repository/public + + false + + + true + + + + + + + + org.springframework.boot + spring-boot-starter-data-redis + + + org.springframework.boot + spring-boot-starter-web + + + org.mybatis.spring.boot + mybatis-spring-boot-starter + ${mybatis-spring-boot-starter-version} + + + + + com.alibaba + druid + ${druid-version} + + + + + mysql + mysql-connector-java + ${mysql-connector-java-version} + + + + + org.xerial + sqlite-jdbc + ${sqlite-jdbc-version} + + + + + com.github.pagehelper + pagehelper-spring-boot-starter + ${pagehelper-spring-boot-starter-version} + + + + redis.clients + jedis + ${jedis-version} + + + + + + io.springfox + springfox-swagger2 + ${springfox-swagger2-version} + + + io.springfox + springfox-swagger-ui + ${springfox-swagger-ui-version} + + + javax.validation + validation-api + + + + + org.springframework.boot + spring-boot-starter-aop + + + + + javax.sip + jain-sip-ri + ${jain-sip-ri-version} + + + + log4j + log4j + ${log4j-version} + + + + + org.dom4j + dom4j + ${dom4j-version} + + + + + com.alibaba + fastjson + ${fastjson-version} + + + + + com.google.guava + guava + ${guava-version} + + + org.apache.commons + commons-lang3 + ${commons-lang3-version} + + + commons-io + commons-io + ${commons-io-version} + + + + + com.squareup.okhttp3 + okhttp + ${okhttp-version} + - - - wvp-2.5.8 - - - org.springframework.boot - spring-boot-maven-plugin - - - org.apache.maven.plugins - maven-compiler-plugin - - 1.8 - 1.8 - - - - - org.apache.maven.plugins - maven-surefire-plugin - - - - + + + wvp-2.5.8 + + + org.springframework.boot + spring-boot-maven-plugin + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.8 + 1.8 + + + + + org.apache.maven.plugins + maven-surefire-plugin + + + + diff --git a/src/main/java/com/genersoft/iot/vmp/VManageBootstrap.java b/src/main/java/com/genersoft/iot/vmp/VManageBootstrap.java index 1b7dabdf..e5921f2a 100644 --- a/src/main/java/com/genersoft/iot/vmp/VManageBootstrap.java +++ b/src/main/java/com/genersoft/iot/vmp/VManageBootstrap.java @@ -5,17 +5,18 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ConfigurableApplicationContext; @SpringBootApplication -public class VManageBootstrap extends LogManager { - private static String[] args; - private static ConfigurableApplicationContext context; - public static void main(String[] args) { - VManageBootstrap.args = args; - VManageBootstrap.context = SpringApplication.run(VManageBootstrap.class, args); - } - // 项目重启 - public static void restart() { - context.close(); - VManageBootstrap.context = SpringApplication.run(VManageBootstrap.class, args); +public class VManageBootstrap { + private static String[] args; + private static ConfigurableApplicationContext context; - } + public static void main(String[] args) { + VManageBootstrap.args = args; + VManageBootstrap.context = SpringApplication.run(VManageBootstrap.class, args); + } + + // 项目重启 + public static void restart() { + context.close(); + VManageBootstrap.context = SpringApplication.run(VManageBootstrap.class, args); + } } diff --git a/src/main/java/com/genersoft/iot/vmp/common/StreamInfo.java b/src/main/java/com/genersoft/iot/vmp/common/StreamInfo.java index 272afba7..4db62955 100644 --- a/src/main/java/com/genersoft/iot/vmp/common/StreamInfo.java +++ b/src/main/java/com/genersoft/iot/vmp/common/StreamInfo.java @@ -1,9 +1,10 @@ package com.genersoft.iot.vmp.common; import com.alibaba.fastjson.JSONArray; -import lombok.Data; -@Data +/** + * @author skywsp + */ public class StreamInfo { /** @@ -25,4 +26,132 @@ public class StreamInfo { private String rtmp; private String rtsp; private JSONArray tracks; + + public String getMediaServerIp() { + return mediaServerIp; + } + + public void setMediaServerIp(String mediaServerIp) { + this.mediaServerIp = mediaServerIp; + } + + public String getSsrc() { + return ssrc; + } + + public void setSsrc(String ssrc) { + this.ssrc = ssrc; + } + + public String getDeviceID() { + return deviceID; + } + + public void setDeviceID(String deviceID) { + this.deviceID = deviceID; + } + + public String getChannelId() { + return channelId; + } + + public void setChannelId(String channelId) { + this.channelId = channelId; + } + + 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; + } + + public JSONArray getTracks() { + return tracks; + } + + public void setTracks(JSONArray tracks) { + this.tracks = tracks; + } + + public String getFmp4() { + return fmp4; + } + + public void setFmp4(String fmp4) { + this.fmp4 = fmp4; + } + + public String getWs_fmp4() { + return ws_fmp4; + } + + public void setWs_fmp4(String ws_fmp4) { + this.ws_fmp4 = ws_fmp4; + } + + public String getWs_hls() { + return ws_hls; + } + + public void setWs_hls(String ws_hls) { + this.ws_hls = ws_hls; + } + + public String getTs() { + return ts; + } + + public void setTs(String ts) { + this.ts = ts; + } + + public String getWs_ts() { + return ws_ts; + } + + public void setWs_ts(String ws_ts) { + this.ws_ts = ws_ts; + } + + public String getStreamId() { + return streamId; + } + + public void setStreamId(String streamId) { + this.streamId = streamId; + } } diff --git a/src/main/java/com/genersoft/iot/vmp/conf/MediaConfig.java b/src/main/java/com/genersoft/iot/vmp/conf/MediaConfig.java index 73cad4c6..3f9f4a05 100644 --- a/src/main/java/com/genersoft/iot/vmp/conf/MediaConfig.java +++ b/src/main/java/com/genersoft/iot/vmp/conf/MediaConfig.java @@ -1,6 +1,5 @@ package com.genersoft.iot.vmp.conf; -import lombok.Data; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Configuration; @@ -11,7 +10,6 @@ import java.util.HashMap; * 对配置文件进行校验 */ @Configuration("mediaConfig") -@Data public class MediaConfig { @Value("${media.ip}") private String mediaIp; @@ -50,4 +48,99 @@ public class MediaConfig { */ private HashMap mediaServerSsrcMap; + public String getMediaIp() { + return mediaIp; + } + + public void setMediaIp(String mediaIp) { + this.mediaIp = mediaIp; + } + + public String[] getMediaIpArr() { + return mediaIpArr; + } + + public void setMediaIpArr(String[] mediaIpArr) { + this.mediaIpArr = mediaIpArr; + } + + public String getMediaHookIp() { + return mediaHookIp; + } + + public void setMediaHookIp(String mediaHookIp) { + this.mediaHookIp = mediaHookIp; + } + + public Integer getMediaPort() { + return mediaPort; + } + + public void setMediaPort(Integer mediaPort) { + this.mediaPort = mediaPort; + } + + public Boolean getAutoConfig() { + return autoConfig; + } + + public void setAutoConfig(Boolean autoConfig) { + this.autoConfig = autoConfig; + } + + public String getMediaSecret() { + return mediaSecret; + } + + public void setMediaSecret(String mediaSecret) { + this.mediaSecret = mediaSecret; + } + + public String getStreamNoneReaderDelayMS() { + return streamNoneReaderDelayMS; + } + + public void setStreamNoneReaderDelayMS(String streamNoneReaderDelayMS) { + this.streamNoneReaderDelayMS = streamNoneReaderDelayMS; + } + + public Boolean getAutoApplyPlay() { + return autoApplyPlay; + } + + public void setAutoApplyPlay(Boolean autoApplyPlay) { + this.autoApplyPlay = autoApplyPlay; + } + + public Boolean getSeniorSdp() { + return seniorSdp; + } + + public void setSeniorSdp(Boolean seniorSdp) { + this.seniorSdp = seniorSdp; + } + + public Boolean getRtpEnable() { + return rtpEnable; + } + + public void setRtpEnable(Boolean rtpEnable) { + this.rtpEnable = rtpEnable; + } + + public String getUdpPortRange() { + return udpPortRange; + } + + public void setUdpPortRange(String udpPortRange) { + this.udpPortRange = udpPortRange; + } + + public HashMap getMediaServerSsrcMap() { + return mediaServerSsrcMap; + } + + public void setMediaServerSsrcMap(HashMap mediaServerSsrcMap) { + this.mediaServerSsrcMap = mediaServerSsrcMap; + } } diff --git a/src/main/java/com/genersoft/iot/vmp/conf/MediaServerConfig.java b/src/main/java/com/genersoft/iot/vmp/conf/MediaServerConfig.java index 16629393..76390e43 100644 --- a/src/main/java/com/genersoft/iot/vmp/conf/MediaServerConfig.java +++ b/src/main/java/com/genersoft/iot/vmp/conf/MediaServerConfig.java @@ -1,9 +1,7 @@ package com.genersoft.iot.vmp.conf; import com.alibaba.fastjson.annotation.JSONField; -import lombok.Data; -@Data public class MediaServerConfig { @JSONField(name = "api.apiDebug") @@ -33,6 +31,10 @@ public class MediaServerConfig { @JSONField(name = "general.streamNoneReaderDelayMS") private String generalStreamNoneReaderDelayMS; + private String localIP; + + private String wanIp; + @JSONField(name = "hls.fileBufSize") private String hlsFileBufSize; @@ -197,4 +199,533 @@ public class MediaServerConfig { @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 getLocalIP() { + return localIP; + } + + public void setLocalIP(String localIP) { + this.localIP = localIP; + } + + 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 getRtpProxyCheckSource() { + return rtpProxyCheckSource; + } + + public void setRtpProxyCheckSource(String rtpProxyCheckSource) { + this.rtpProxyCheckSource = rtpProxyCheckSource; + } + + public String getRtpProxyDumpDir() { + return rtpProxyDumpDir; + } + + public void setRtpProxyDumpDir(String rtpProxyDumpDir) { + this.rtpProxyDumpDir = rtpProxyDumpDir; + } + + public String getRtpProxyPort() { + return rtpProxyPort; + } + + public void setRtpProxyPort(String rtpProxyPort) { + this.rtpProxyPort = rtpProxyPort; + } + + public String getRtpProxyTimeoutSec() { + return rtpProxyTimeoutSec; + } + + public void setRtpProxyTimeoutSec(String rtpProxyTimeoutSec) { + this.rtpProxyTimeoutSec = rtpProxyTimeoutSec; + } + + 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; + } + + public String getWanIp() { + return wanIp; + } + + public void setWanIp(String wanIp) { + this.wanIp = wanIp; + } } diff --git a/src/main/java/com/genersoft/iot/vmp/conf/SsrcConfig.java b/src/main/java/com/genersoft/iot/vmp/conf/SsrcConfig.java index 55979592..8e035c1a 100644 --- a/src/main/java/com/genersoft/iot/vmp/conf/SsrcConfig.java +++ b/src/main/java/com/genersoft/iot/vmp/conf/SsrcConfig.java @@ -1,7 +1,6 @@ package com.genersoft.iot.vmp.conf; import com.genersoft.iot.vmp.utils.ConfigConst; -import lombok.Data; import java.util.ArrayList; import java.util.List; @@ -10,12 +9,11 @@ import java.util.Set; /** * 每一个zlm流媒体服务器,都设置MAX_STRTEAM_COUNT个可用同步信源(SSRC) */ -@Data public class SsrcConfig { /** * zlm流媒体服务器IP */ - String mediaServerIp; + private String mediaServerIp; /** * zlm流媒体服务器已用会话句柄 */ @@ -25,6 +23,18 @@ public class SsrcConfig { */ private List notUsed; + public String getMediaServerIp() { + return mediaServerIp; + } + + public List getIsUsed() { + return isUsed; + } + + public List getNotUsed() { + return notUsed; + } + public void init(String mediaServerIp, Set usedSet) { this.mediaServerIp = mediaServerIp; this.isUsed = new ArrayList<>(); diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/SipLayer.java b/src/main/java/com/genersoft/iot/vmp/gb28181/SipLayer.java index 72c4a27f..06830613 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/SipLayer.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/SipLayer.java @@ -153,42 +153,42 @@ public class SipLayer implements SipListener { }); } - @Override - public void processResponse(ResponseEvent evt) { - Response response = evt.getResponse(); - logger.debug(evt.getResponse().toString()); - int status = response.getStatusCode(); - if (((status >= 200) && (status < 300)) || status == 401) { // Success! - ISIPResponseProcessor processor = processorFactory.createResponseProcessor(evt); - try { - processor.process(evt, this, sipConfig); - } catch (ParseException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - if (evt.getResponse() != null && sipSubscribe.getOkSubscribesSize() > 0 ) { - CallIdHeader callIdHeader = (CallIdHeader)evt.getResponse().getHeader(CallIdHeader.NAME); - if (callIdHeader != null) { - SipSubscribe.Event subscribe = sipSubscribe.getOkSubscribe(callIdHeader.getCallId()); - if (subscribe != null) { - subscribe.response(evt); - } - } - } - } else if ((status >= 100) && (status < 200)) { - // 增加其它无需回复的响应,如101、180等 - } else { - logger.warn("接收到失败的response响应!status:" + status + ",message:" + response.getReasonPhrase()/* .getContent().toString()*/); - if (evt.getResponse() != null && sipSubscribe.getErrorSubscribesSize() > 0 ) { - CallIdHeader callIdHeader = (CallIdHeader)evt.getResponse().getHeader(CallIdHeader.NAME); - if (callIdHeader != null) { - SipSubscribe.Event subscribe = sipSubscribe.getErrorSubscribe(callIdHeader.getCallId()); - if (subscribe != null) { - subscribe.response(evt); - } - } - } - } + @Override + public void processResponse(ResponseEvent evt) { + Response response = evt.getResponse(); + logger.debug(evt.getResponse().toString()); + int status = response.getStatusCode(); + if (((status >= 200) && (status < 300)) || status == 401) { // Success! + ISIPResponseProcessor processor = processorFactory.createResponseProcessor(evt); + try { + processor.process(evt, this, sipConfig); + } catch (ParseException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + if (evt.getResponse() != null && sipSubscribe.getOkSubscribesSize() > 0) { + CallIdHeader callIdHeader = (CallIdHeader) evt.getResponse().getHeader(CallIdHeader.NAME); + if (callIdHeader != null) { + SipSubscribe.Event subscribe = sipSubscribe.getOkSubscribe(callIdHeader.getCallId()); + if (subscribe != null) { + subscribe.response(evt); + } + } + } + } else if ((status >= 100) && (status < 200)) { + // 增加其它无需回复的响应,如101、180等 + } else { + logger.warn("接收到失败的response响应!status:" + status + ",message:" + response.getReasonPhrase()/* .getContent().toString()*/); + if (evt.getResponse() != null && sipSubscribe.getErrorSubscribesSize() > 0) { + CallIdHeader callIdHeader = (CallIdHeader) evt.getResponse().getHeader(CallIdHeader.NAME); + if (callIdHeader != null) { + SipSubscribe.Event subscribe = sipSubscribe.getErrorSubscribe(callIdHeader.getCallId()); + if (subscribe != null) { + subscribe.response(evt); + } + } + } + } } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/session/VideoStreamSessionManager.java b/src/main/java/com/genersoft/iot/vmp/gb28181/session/VideoStreamSessionManager.java index 5a8dfb3f..ceacb83f 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/session/VideoStreamSessionManager.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/session/VideoStreamSessionManager.java @@ -9,8 +9,9 @@ import com.genersoft.iot.vmp.conf.SsrcConfig; import com.genersoft.iot.vmp.gb28181.bean.Device; import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.utils.redis.JedisUtil; -import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -27,7 +28,6 @@ import java.util.concurrent.ConcurrentHashMap; * @author: swwheihei * @date: 2020年5月13日 下午4:03:02 */ -@Slf4j @Component public class VideoStreamSessionManager { /** @@ -37,6 +37,8 @@ public class VideoStreamSessionManager { private ConcurrentHashMap sessionMap = new ConcurrentHashMap<>(); private String ssrcPrefix; + private final Logger logger = LoggerFactory.getLogger(VideoStreamSessionManager.class); + @Autowired private SipConfig sipConfig; @Autowired @@ -190,7 +192,7 @@ public class VideoStreamSessionManager { public StreamInfo getPlayStreamInfo(String channelId) { if (StringUtils.isBlank(channelId)) { - log.error("getPlayStreamInfo channelId can not be null!!!"); + logger.error("getPlayStreamInfo channelId can not be null!!!"); return null; } return redisCatchStorage.queryPlayByChannel(channelId); @@ -198,7 +200,7 @@ public class VideoStreamSessionManager { public StreamInfo getPlayBackStreamInfo(String channelId) { if (StringUtils.isBlank(channelId)) { - log.error("getPlayBackStreamInfo channelId can not be null!!!"); + logger.error("getPlayBackStreamInfo channelId can not be null!!!"); return null; } return redisCatchStorage.queryPlaybackByChannel(channelId); @@ -206,7 +208,7 @@ public class VideoStreamSessionManager { public StreamInfo getStreamInfo(String channelId, String streamId) { if (StringUtils.isBlank(channelId) || StringUtils.isBlank(streamId)) { - log.error("getStreamInfo channelId and streamId can not be null!!!"); + logger.error("getStreamInfo channelId and streamId can not be null!!!"); return null; } StreamInfo streamInfo = getStreamInfo(channelId, streamId, PlayTypeEnum.PLAY); @@ -218,7 +220,7 @@ public class VideoStreamSessionManager { private StreamInfo getStreamInfo(String channelId, String streamId, PlayTypeEnum playType) { if (StringUtils.isBlank(channelId) || StringUtils.isBlank(streamId)) { - log.error("getStreamInfo channelId and streamId can not be null!!!"); + logger.error("getStreamInfo channelId and streamId can not be null!!!"); return null; } // TODO channelId diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorFactory.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorFactory.java index 22d394e8..416ad866 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorFactory.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorFactory.java @@ -1,231 +1,219 @@ package com.genersoft.iot.vmp.gb28181.transmit; -import javax.sip.RequestEvent; -import javax.sip.ResponseEvent; -import javax.sip.SipProvider; -import javax.sip.header.CSeqHeader; -import javax.sip.message.Request; -import javax.sip.message.Response; - -import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform; -import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; -import com.genersoft.iot.vmp.storager.IRedisCatchStorage; -import com.genersoft.iot.vmp.gb28181.transmit.response.impl.*; -import com.genersoft.iot.vmp.vmanager.service.IPlayService; -// import org.slf4j.Logger; -// import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Lazy; -import org.springframework.stereotype.Component; - import com.genersoft.iot.vmp.conf.SipConfig; import com.genersoft.iot.vmp.gb28181.auth.RegisterLogicHandler; import com.genersoft.iot.vmp.gb28181.event.DeviceOffLineDetector; import com.genersoft.iot.vmp.gb28181.event.EventPublisher; import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; +import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform; import com.genersoft.iot.vmp.gb28181.transmit.request.ISIPRequestProcessor; -import com.genersoft.iot.vmp.gb28181.transmit.request.impl.AckRequestProcessor; -import com.genersoft.iot.vmp.gb28181.transmit.request.impl.ByeRequestProcessor; -import com.genersoft.iot.vmp.gb28181.transmit.request.impl.CancelRequestProcessor; -import com.genersoft.iot.vmp.gb28181.transmit.request.impl.InviteRequestProcessor; -import com.genersoft.iot.vmp.gb28181.transmit.request.impl.MessageRequestProcessor; -import com.genersoft.iot.vmp.gb28181.transmit.request.impl.NotifyRequestProcessor; -import com.genersoft.iot.vmp.gb28181.transmit.request.impl.OtherRequestProcessor; -import com.genersoft.iot.vmp.gb28181.transmit.request.impl.RegisterRequestProcessor; -import com.genersoft.iot.vmp.gb28181.transmit.request.impl.SubscribeRequestProcessor; +import com.genersoft.iot.vmp.gb28181.transmit.request.impl.*; import com.genersoft.iot.vmp.gb28181.transmit.response.ISIPResponseProcessor; -import com.genersoft.iot.vmp.gb28181.transmit.response.impl.ByeResponseProcessor; -import com.genersoft.iot.vmp.gb28181.transmit.response.impl.CancelResponseProcessor; -import com.genersoft.iot.vmp.gb28181.transmit.response.impl.InviteResponseProcessor; -import com.genersoft.iot.vmp.gb28181.transmit.response.impl.OtherResponseProcessor; +import com.genersoft.iot.vmp.gb28181.transmit.response.impl.*; +import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; +import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.storager.IVideoManagerStorager; import com.genersoft.iot.vmp.utils.SpringBeanFactory; import com.genersoft.iot.vmp.utils.redis.RedisUtil; +import com.genersoft.iot.vmp.vmanager.service.IPlayService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Component; + +import javax.sip.RequestEvent; +import javax.sip.ResponseEvent; +import javax.sip.SipProvider; +import javax.sip.header.CSeqHeader; +import javax.sip.message.Request; +import javax.sip.message.Response; -/** +// import org.slf4j.Logger; +// import org.slf4j.LoggerFactory; + +/** * @Description: SIP信令处理分配 * @author: swwheihei - * @date: 2020年5月3日 下午4:24:37 + * @date: 2020年5月3日 下午4:24:37 */ @Component public class SIPProcessorFactory { - - // private final static Logger logger = LoggerFactory.getLogger(SIPProcessorFactory.class); - - @Autowired - private SipConfig sipConfig; - - @Autowired - private RegisterLogicHandler handler; - - @Autowired - private IVideoManagerStorager storager; - @Autowired - private IRedisCatchStorage redisCatchStorage; + // private final static Logger logger = LoggerFactory.getLogger(SIPProcessorFactory.class); + + @Autowired + private SipConfig sipConfig; + + @Autowired + private RegisterLogicHandler handler; - @Autowired - private EventPublisher publisher; + @Autowired + private IVideoManagerStorager storager; - @Autowired - private SIPCommander cmder; + @Autowired + private IRedisCatchStorage redisCatchStorage; - @Autowired - private SIPCommanderFroPlatform cmderFroPlatform; + @Autowired + private EventPublisher publisher; - @Autowired - private RedisUtil redis; + @Autowired + private SIPCommander cmder; - @Autowired - private DeferredResultHolder deferredResultHolder; + @Autowired + private SIPCommanderFroPlatform cmderFroPlatform; - @Autowired - private DeviceOffLineDetector offLineDetector; + @Autowired + private RedisUtil redis; - @Autowired - private InviteResponseProcessor inviteResponseProcessor; + @Autowired + private DeferredResultHolder deferredResultHolder; - @Autowired - private ByeResponseProcessor byeResponseProcessor; + @Autowired + private DeviceOffLineDetector offLineDetector; - @Autowired - private CancelResponseProcessor cancelResponseProcessor; + @Autowired + private InviteResponseProcessor inviteResponseProcessor; - @Autowired - @Lazy - private RegisterResponseProcessor registerResponseProcessor; + @Autowired + private ByeResponseProcessor byeResponseProcessor; + @Autowired + private CancelResponseProcessor cancelResponseProcessor; - @Autowired - private OtherResponseProcessor otherResponseProcessor; + @Autowired + @Lazy + private RegisterResponseProcessor registerResponseProcessor; - @Autowired - private IPlayService playService; - @Autowired - private ZLMRTPServerFactory zlmrtpServerFactory; + @Autowired + private OtherResponseProcessor otherResponseProcessor; + @Autowired + private IPlayService playService; - // 注:这里使用注解会导致循环依赖注入,暂用springBean - private SipProvider tcpSipProvider; - - // 注:这里使用注解会导致循环依赖注入,暂用springBean - private SipProvider udpSipProvider; - - public ISIPRequestProcessor createRequestProcessor(RequestEvent evt) { - Request request = evt.getRequest(); - String method = request.getMethod(); + @Autowired + private ZLMRTPServerFactory zlmrtpServerFactory; + + + // 注:这里使用注解会导致循环依赖注入,暂用springBean + private SipProvider tcpSipProvider; + + // 注:这里使用注解会导致循环依赖注入,暂用springBean + private SipProvider udpSipProvider; + + public ISIPRequestProcessor createRequestProcessor(RequestEvent evt) { + Request request = evt.getRequest(); + String method = request.getMethod(); // logger.info("接收到消息:"+request.getMethod()); // sipSubscribe.getSubscribe(evt.getServerTransaction().getBranchId()).response(evt); - if (Request.INVITE.equals(method)) { - InviteRequestProcessor processor = new InviteRequestProcessor(); - processor.setRequestEvent(evt); - processor.setTcpSipProvider(getTcpSipProvider()); - processor.setUdpSipProvider(getUdpSipProvider()); - - processor.setCmder(cmder); - processor.setCmderFroPlatform(cmderFroPlatform); - processor.setPlayService(playService); - processor.setStorager(storager); - processor.setRedisCatchStorage(redisCatchStorage); - processor.setZlmrtpServerFactory(zlmrtpServerFactory); - return processor; - } else if (Request.REGISTER.equals(method)) { - RegisterRequestProcessor processor = new RegisterRequestProcessor(); - processor.setRequestEvent(evt); - processor.setTcpSipProvider(getTcpSipProvider()); - processor.setUdpSipProvider(getUdpSipProvider()); - processor.setHandler(handler); - processor.setPublisher(publisher); - processor.setSipConfig(sipConfig); - processor.setVideoManagerStorager(storager); - return processor; - } else if (Request.SUBSCRIBE.equals(method)) { - SubscribeRequestProcessor processor = new SubscribeRequestProcessor(); - processor.setRequestEvent(evt); - return processor; - } else if (Request.ACK.equals(method)) { - AckRequestProcessor processor = new AckRequestProcessor(); - processor.setRequestEvent(evt); - processor.setRedisCatchStorage(redisCatchStorage); - processor.setZlmrtpServerFactory(zlmrtpServerFactory); - return processor; - } else if (Request.BYE.equals(method)) { - ByeRequestProcessor processor = new ByeRequestProcessor(); - processor.setRequestEvent(evt); - processor.setRedisCatchStorage(redisCatchStorage); - processor.setZlmrtpServerFactory(zlmrtpServerFactory); - processor.setSIPCommander(cmder); - return processor; - } else if (Request.CANCEL.equals(method)) { - CancelRequestProcessor processor = new CancelRequestProcessor(); - processor.setRequestEvent(evt); - return processor; - } else if (Request.MESSAGE.equals(method)) { - MessageRequestProcessor processor = new MessageRequestProcessor(); - processor.setRequestEvent(evt); - processor.setTcpSipProvider(getTcpSipProvider()); - processor.setUdpSipProvider(getUdpSipProvider()); - processor.setPublisher(publisher); - processor.setRedis(redis); - processor.setDeferredResultHolder(deferredResultHolder); - processor.setOffLineDetector(offLineDetector); - processor.setCmder(cmder); - processor.setCmderFroPlatform(cmderFroPlatform); - processor.setStorager(storager); - processor.setRedisCatchStorage(redisCatchStorage); - return processor; - } else if (Request.NOTIFY.equalsIgnoreCase(method)) { - NotifyRequestProcessor processor = new NotifyRequestProcessor(); - processor.setRequestEvent(evt); - processor.setTcpSipProvider(getTcpSipProvider()); - processor.setUdpSipProvider(getUdpSipProvider()); - processor.setPublisher(publisher); - processor.setRedis(redis); - processor.setDeferredResultHolder(deferredResultHolder); - processor.setOffLineDetector(offLineDetector); - processor.setCmder(cmder); - processor.setStorager(storager); - processor.setRedisCatchStorage(redisCatchStorage); - return processor; - } else { - OtherRequestProcessor processor = new OtherRequestProcessor(); - processor.setRequestEvent(evt); - return processor; - } - } - - public ISIPResponseProcessor createResponseProcessor(ResponseEvent evt) { - - Response response = evt.getResponse(); - CSeqHeader cseqHeader = (CSeqHeader) response.getHeader(CSeqHeader.NAME); - String method = cseqHeader.getMethod(); - if(Request.INVITE.equals(method)){ - return inviteResponseProcessor; - } else if (Request.BYE.equals(method)) { - return byeResponseProcessor; - } else if (Request.CANCEL.equals(method)) { - return cancelResponseProcessor; - }else if (Request.REGISTER.equals(method)) { - return registerResponseProcessor; - } else { - return otherResponseProcessor; - } - } - - private SipProvider getTcpSipProvider() { - if (tcpSipProvider == null) { - tcpSipProvider = (SipProvider) SpringBeanFactory.getBean("tcpSipProvider"); - } - return tcpSipProvider; - } - - private SipProvider getUdpSipProvider() { - if (udpSipProvider == null) { - udpSipProvider = (SipProvider) SpringBeanFactory.getBean("udpSipProvider"); - } - return udpSipProvider; - } - + if (Request.INVITE.equals(method)) { + InviteRequestProcessor processor = new InviteRequestProcessor(); + processor.setRequestEvent(evt); + processor.setTcpSipProvider(getTcpSipProvider()); + processor.setUdpSipProvider(getUdpSipProvider()); + + processor.setCmder(cmder); + processor.setCmderFroPlatform(cmderFroPlatform); + processor.setPlayService(playService); + processor.setStorager(storager); + processor.setRedisCatchStorage(redisCatchStorage); + processor.setZlmrtpServerFactory(zlmrtpServerFactory); + return processor; + } else if (Request.REGISTER.equals(method)) { + RegisterRequestProcessor processor = new RegisterRequestProcessor(); + processor.setRequestEvent(evt); + processor.setTcpSipProvider(getTcpSipProvider()); + processor.setUdpSipProvider(getUdpSipProvider()); + processor.setHandler(handler); + processor.setPublisher(publisher); + processor.setSipConfig(sipConfig); + processor.setVideoManagerStorager(storager); + return processor; + } else if (Request.SUBSCRIBE.equals(method)) { + SubscribeRequestProcessor processor = new SubscribeRequestProcessor(); + processor.setRequestEvent(evt); + return processor; + } else if (Request.ACK.equals(method)) { + AckRequestProcessor processor = new AckRequestProcessor(); + processor.setRequestEvent(evt); + processor.setRedisCatchStorage(redisCatchStorage); + processor.setZlmrtpServerFactory(zlmrtpServerFactory); + return processor; + } else if (Request.BYE.equals(method)) { + ByeRequestProcessor processor = new ByeRequestProcessor(); + processor.setRequestEvent(evt); + processor.setRedisCatchStorage(redisCatchStorage); + processor.setZlmrtpServerFactory(zlmrtpServerFactory); + processor.setSIPCommander(cmder); + return processor; + } else if (Request.CANCEL.equals(method)) { + CancelRequestProcessor processor = new CancelRequestProcessor(); + processor.setRequestEvent(evt); + return processor; + } else if (Request.MESSAGE.equals(method)) { + MessageRequestProcessor processor = new MessageRequestProcessor(); + processor.setRequestEvent(evt); + processor.setTcpSipProvider(getTcpSipProvider()); + processor.setUdpSipProvider(getUdpSipProvider()); + processor.setPublisher(publisher); + processor.setRedis(redis); + processor.setDeferredResultHolder(deferredResultHolder); + processor.setOffLineDetector(offLineDetector); + processor.setCmder(cmder); + processor.setCmderFroPlatform(cmderFroPlatform); + processor.setStorager(storager); + processor.setRedisCatchStorage(redisCatchStorage); + return processor; + } else if (Request.NOTIFY.equalsIgnoreCase(method)) { + NotifyRequestProcessor processor = new NotifyRequestProcessor(); + processor.setRequestEvent(evt); + processor.setTcpSipProvider(getTcpSipProvider()); + processor.setUdpSipProvider(getUdpSipProvider()); + processor.setPublisher(publisher); + processor.setRedis(redis); + processor.setDeferredResultHolder(deferredResultHolder); + processor.setOffLineDetector(offLineDetector); + processor.setCmder(cmder); + processor.setStorager(storager); + processor.setRedisCatchStorage(redisCatchStorage); + return processor; + } else { + OtherRequestProcessor processor = new OtherRequestProcessor(); + processor.setRequestEvent(evt); + return processor; + } + } + + public ISIPResponseProcessor createResponseProcessor(ResponseEvent evt) { + + Response response = evt.getResponse(); + CSeqHeader cseqHeader = (CSeqHeader) response.getHeader(CSeqHeader.NAME); + String method = cseqHeader.getMethod(); + if (Request.INVITE.equals(method)) { + return inviteResponseProcessor; + } else if (Request.BYE.equals(method)) { + return byeResponseProcessor; + } else if (Request.CANCEL.equals(method)) { + return cancelResponseProcessor; + } else if (Request.REGISTER.equals(method)) { + return registerResponseProcessor; + } else { + return otherResponseProcessor; + } + } + + private SipProvider getTcpSipProvider() { + if (tcpSipProvider == null) { + tcpSipProvider = (SipProvider) SpringBeanFactory.getBean("tcpSipProvider"); + } + return tcpSipProvider; + } + + private SipProvider getUdpSipProvider() { + if (udpSipProvider == null) { + udpSipProvider = (SipProvider) SpringBeanFactory.getBean("udpSipProvider"); + } + return udpSipProvider; + } + } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/DeferredResultHolder.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/DeferredResultHolder.java index 8a0c8ca0..4e45778f 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/DeferredResultHolder.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/DeferredResultHolder.java @@ -1,60 +1,60 @@ package com.genersoft.iot.vmp.gb28181.transmit.callback; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Component; import org.springframework.web.context.request.async.DeferredResult; -/** +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** * @Description: 异步请求处理 * @author: swwheihei - * @date: 2020年5月8日 下午7:59:05 + * @date: 2020年5月8日 下午7:59:05 */ @Component public class DeferredResultHolder { - - public static final String CALLBACK_CMD_DEVICESTATUS = "CALLBACK_DEVICESTATUS"; - - public static final String CALLBACK_CMD_DEVICEINFO = "CALLBACK_DEVICEINFO"; - - public static final String CALLBACK_CMD_DEVICECONTROL = "CALLBACK_DEVICECONTROL"; - - public static final String CALLBACK_CMD_DEVICECONFIG = "CALLBACK_DEVICECONFIG"; - public static final String CALLBACK_CMD_CONFIGDOWNLOAD = "CALLBACK_CONFIGDOWNLOAD"; - - public static final String CALLBACK_CMD_CATALOG = "CALLBACK_CATALOG"; - - public static final String CALLBACK_CMD_RECORDINFO = "CALLBACK_RECORDINFO"; + public static final String CALLBACK_CMD_DEVICESTATUS = "CALLBACK_DEVICESTATUS"; + + public static final String CALLBACK_CMD_DEVICEINFO = "CALLBACK_DEVICEINFO"; + + public static final String CALLBACK_CMD_DEVICECONTROL = "CALLBACK_DEVICECONTROL"; + + public static final String CALLBACK_CMD_DEVICECONFIG = "CALLBACK_DEVICECONFIG"; + + public static final String CALLBACK_CMD_CONFIGDOWNLOAD = "CALLBACK_CONFIGDOWNLOAD"; + + public static final String CALLBACK_CMD_CATALOG = "CALLBACK_CATALOG"; + + public static final String CALLBACK_CMD_RECORDINFO = "CALLBACK_RECORDINFO"; - public static final String CALLBACK_CMD_PlAY = "CALLBACK_PLAY"; + public static final String CALLBACK_CMD_PlAY = "CALLBACK_PLAY"; - public static final String CALLBACK_CMD_STOP = "CALLBACK_STOP"; + public static final String CALLBACK_CMD_STOP = "CALLBACK_STOP"; - public static final String CALLBACK_CMD_MOBILEPOSITION = "CALLBACK_MOBILEPOSITION"; + public static final String CALLBACK_CMD_MOBILEPOSITION = "CALLBACK_MOBILEPOSITION"; - public static final String CALLBACK_CMD_PRESETQUERY = "CALLBACK_PRESETQUERY"; + public static final String CALLBACK_CMD_PRESETQUERY = "CALLBACK_PRESETQUERY"; - public static final String CALLBACK_CMD_ALARM = "CALLBACK_ALARM"; + public static final String CALLBACK_CMD_ALARM = "CALLBACK_ALARM"; - public static final String CALLBACK_CMD_BROADCAST = "CALLBACK_BROADCAST"; + public static final String CALLBACK_CMD_BROADCAST = "CALLBACK_BROADCAST"; - private Map map = new ConcurrentHashMap(); + private Map map = new ConcurrentHashMap(); - public void put(String key, DeferredResult result) { - map.put(key, result); - } + public void put(String key, DeferredResult result) { + map.put(key, result); + } - public void invokeResult(RequestMessage msg) { + public void invokeResult(RequestMessage msg) { // DeferredResult result = map.get(msg.getId()); - // 获取并移除 - DeferredResult result = map.remove(msg.getId()); - if (result == null) { - return; - } - result.setResult(new ResponseEntity<>(msg.getData(),HttpStatus.OK)); - } + // 获取并移除 + DeferredResult result = map.remove(msg.getId()); + if (result == null) { + return; + } + result.setResult(new ResponseEntity<>(msg.getData(), HttpStatus.OK)); + } } 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 a585a131..5eee2586 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 @@ -5,297 +5,300 @@ import com.genersoft.iot.vmp.gb28181.bean.Device; import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe; -/** - * @Description:设备能力接口,用于定义设备的控制、查询能力 +/** + * @Description:设备能力接口,用于定义设备的控制、查询能力 * @author: swwheihei - * @date: 2020年5月3日 下午9:16:34 + * @date: 2020年5月3日 下午9:16:34 */ public interface ISIPCommander { - /** - * 云台方向放控制,使用配置文件中的默认镜头移动速度 - * - * @param device 控制设备 - * @param channelId 预览通道 - * @param leftRight 镜头左移右移 0:停止 1:左移 2:右移 - * @param upDown 镜头上移下移 0:停止 1:上移 2:下移 - * @param moveSpeed 镜头移动速度 - */ - boolean ptzdirectCmd(Device device,String channelId,int leftRight, int upDown); - - /** - * 云台方向放控制 - * - * @param device 控制设备 - * @param channelId 预览通道 - * @param leftRight 镜头左移右移 0:停止 1:左移 2:右移 - * @param upDown 镜头上移下移 0:停止 1:上移 2:下移 - * @param moveSpeed 镜头移动速度 - */ - boolean ptzdirectCmd(Device device,String channelId,int leftRight, int upDown, int moveSpeed); - - /** - * 云台缩放控制,使用配置文件中的默认镜头缩放速度 - * - * @param device 控制设备 - * @param channelId 预览通道 - * @param inOut 镜头放大缩小 0:停止 1:缩小 2:放大 - */ - boolean ptzZoomCmd(Device device,String channelId,int inOut); - - /** - * 云台缩放控制 - * - * @param device 控制设备 - * @param channelId 预览通道 - * @param inOut 镜头放大缩小 0:停止 1:缩小 2:放大 - * @param zoomSpeed 镜头缩放速度 - */ - boolean ptzZoomCmd(Device device,String channelId,int inOut, int moveSpeed); - - /** - * 云台控制,支持方向与缩放控制 - * - * @param device 控制设备 - * @param channelId 预览通道 - * @param leftRight 镜头左移右移 0:停止 1:左移 2:右移 - * @param upDown 镜头上移下移 0:停止 1:上移 2:下移 - * @param inOut 镜头放大缩小 0:停止 1:缩小 2:放大 - * @param moveSpeed 镜头移动速度 - * @param zoomSpeed 镜头缩放速度 - */ - boolean ptzCmd(Device device,String channelId,int leftRight, int upDown, int inOut, int moveSpeed, int zoomSpeed); - - /** - * 前端控制,包括PTZ指令、FI指令、预置位指令、巡航指令、扫描指令和辅助开关指令 - * - * @param device 控制设备 - * @param channelId 预览通道 - * @param cmdCode 指令码 - * @param parameter1 数据1 - * @param parameter2 数据2 - * @param combineCode2 组合码2 - */ - boolean frontEndCmd(Device device, String channelId, int cmdCode, int parameter1, int parameter2, int combineCode2); - - /** - * 前端控制指令(用于转发上级指令) - * @param device 控制设备 - * @param channelId 预览通道 - * @param cmdString 前端控制指令串 - */ - boolean fronEndCmd(Device device, String channelId, String cmdString); - - /** - * 请求预览视频流 - * - * @param device 视频设备 - * @param channelId 预览通道 - */ - void playStreamCmd(Device device, String channelId, ZLMHttpHookSubscribe.Event event, SipSubscribe.Event errorEvent); - - /** - * 请求回放视频流 - * - * @param device 视频设备 - * @param channelId 预览通道 - * @param startTime 开始时间,格式要求:yyyy-MM-dd HH:mm:ss - * @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss - */ - void playbackStreamCmd(Device device, String channelId, String startTime, String endTime, ZLMHttpHookSubscribe.Event event, SipSubscribe.Event errorEvent); - - /** - * 视频流停止 - * - * @param streamInfo streamInfo - * @param okEvent okEvent - */ - void stopStreamByeCmd(StreamInfo streamInfo, SipSubscribe.Event okEvent); - - /** - * 语音广播 - * - * @param device 视频设备 - * @param channelId 预览通道 - */ - boolean audioBroadcastCmd(Device device,String channelId); - - /** - * 语音广播 - * - * @param device 视频设备 - */ - void audioBroadcastCmd(Device device, SipSubscribe.Event okEvent); - boolean audioBroadcastCmd(Device device); - - /** - * 音视频录像控制 - * - * @param device 视频设备 - * @param channelId 预览通道 - * @param recordCmdStr 录像命令:Record / StopRecord - */ - boolean recordCmd(Device device, String channelId, String recordCmdStr, SipSubscribe.Event errorEvent); - - /** - * 远程启动控制命令 - * - * @param device 视频设备 - */ - boolean teleBootCmd(Device device); - - /** - * 报警布防/撤防命令 - * - * @param device 视频设备 - * @param setGuard true: SetGuard, false: ResetGuard - */ - boolean guardCmd(Device device, String guardCmdStr, SipSubscribe.Event errorEvent); - - /** - * 报警复位命令 - * - * @param device 视频设备 - * @param alarmMethod 报警方式(可选) - * @param alarmType 报警类型(可选) - */ - boolean alarmCmd(Device device, String alarmMethod, String alarmType, SipSubscribe.Event errorEvent); - - /** - * 强制关键帧命令,设备收到此命令应立刻发送一个IDR帧 - * - * @param device 视频设备 - * @param channelId 预览通道 - */ - boolean iFrameCmd(Device device, String channelId); - - /** - * 看守位控制命令 - * - * @param device 视频设备 - * @param enabled 看守位使能:1 = 开启,0 = 关闭 - * @param resetTime 自动归位时间间隔,开启看守位时使用,单位:秒(s) - * @param presetIndex 调用预置位编号,开启看守位时使用,取值范围0~255 - */ - boolean homePositionCmd(Device device, String channelId, String enabled, String resetTime, String presetIndex, SipSubscribe.Event errorEvent); - - /** - * 设备配置命令 - * - * @param device 视频设备 - */ - boolean deviceConfigCmd(Device device); - - /** - * 设备配置命令:basicParam - * - * @param device 视频设备 - * @param channelId 通道编码(可选) - * @param name 设备/通道名称(可选) - * @param expiration 注册过期时间(可选) - * @param heartBeatInterval 心跳间隔时间(可选) - * @param heartBeatCount 心跳超时次数(可选) - */ - boolean deviceBasicConfigCmd(Device device, String channelId, String name, String expiration, String heartBeatInterval, String heartBeatCount, SipSubscribe.Event errorEvent); - - /** - * 查询设备状态 - * - * @param device 视频设备 - */ - boolean deviceStatusQuery(Device device, SipSubscribe.Event errorEvent); - - /** - * 查询设备信息 - * - * @param device 视频设备 - * @return - */ - boolean deviceInfoQuery(Device device); - - /** - * 查询目录列表 - * - * @param device 视频设备 - */ - boolean catalogQuery(Device device, SipSubscribe.Event errorEvent); - - /** - * 查询录像信息 - * - * @param device 视频设备 - * @param startTime 开始时间,格式要求:yyyy-MM-dd HH:mm:ss - * @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss - */ - boolean recordInfoQuery(Device device, String channelId, String startTime, String endTime); - - /** - * 查询报警信息 - * - * @param device 视频设备 - * @param startPriority 报警起始级别(可选) - * @param endPriority 报警终止级别(可选) - * @param alarmMethod 报警方式条件(可选) - * @param alarmType 报警类型 - * @param startTime 报警发生起始时间(可选) - * @param endTime 报警发生终止时间(可选) - * @return true = 命令发送成功 - */ - boolean alarmInfoQuery(Device device, String startPriority, String endPriority, String alarmMethod, - String alarmType, String startTime, String endTime, SipSubscribe.Event errorEvent); - - /** - * 查询设备配置 - * - * @param device 视频设备 - * @param channelId 通道编码(可选) - * @param configType 配置类型: - */ - boolean deviceConfigQuery(Device device, String channelId, String configType, SipSubscribe.Event errorEvent); - - /** - * 查询设备预置位置 - * - * @param device 视频设备 - */ - boolean presetQuery(Device device, String channelId, SipSubscribe.Event errorEvent); - - /** - * 查询移动设备位置数据 - * - * @param device 视频设备 - */ - boolean mobilePostitionQuery(Device device, SipSubscribe.Event errorEvent); - - /** - * 订阅、取消订阅移动位置 - * - * @param device 视频设备 - * @param expires 订阅超时时间(值=0时为取消订阅) - * @param interval 上报时间间隔 - * @return true = 命令发送成功 - */ - boolean mobilePositionSubscribe(Device device, int expires, int interval); - - /** - * 订阅、取消订阅报警信息 - * @param device 视频设备 - * @param expires 订阅过期时间(0 = 取消订阅) - * @param startPriority 报警起始级别(可选) - * @param endPriority 报警终止级别(可选) - * @param alarmMethods 报警方式条件(可选) - * @param alarmType 报警类型 - * @param startTime 报警发生起始时间(可选) - * @param endTime 报警发生终止时间(可选) - * @return true = 命令发送成功 - */ - boolean alarmSubscribe(Device device, int expires, String startPriority, String endPriority, String alarmMethod, String alarmType, String startTime, String endTime); - - - /** - * 释放rtpserver - * @param device - * @param channelId - */ + /** + * 云台方向放控制,使用配置文件中的默认镜头移动速度 + * + * @param device 控制设备 + * @param channelId 预览通道 + * @param leftRight 镜头左移右移 0:停止 1:左移 2:右移 + * @param upDown 镜头上移下移 0:停止 1:上移 2:下移 + */ + boolean ptzdirectCmd(Device device, String channelId, int leftRight, int upDown); + + /** + * 云台方向放控制 + * + * @param device 控制设备 + * @param channelId 预览通道 + * @param leftRight 镜头左移右移 0:停止 1:左移 2:右移 + * @param upDown 镜头上移下移 0:停止 1:上移 2:下移 + * @param moveSpeed 镜头移动速度 + */ + boolean ptzdirectCmd(Device device, String channelId, int leftRight, int upDown, int moveSpeed); + + /** + * 云台缩放控制,使用配置文件中的默认镜头缩放速度 + * + * @param device 控制设备 + * @param channelId 预览通道 + * @param inOut 镜头放大缩小 0:停止 1:缩小 2:放大 + */ + boolean ptzZoomCmd(Device device, String channelId, int inOut); + + /** + * 云台缩放控制 + * + * @param device 控制设备 + * @param channelId 预览通道 + * @param inOut 镜头放大缩小 0:停止 1:缩小 2:放大 + * @param moveSpeed 镜头缩放速度 + */ + boolean ptzZoomCmd(Device device, String channelId, int inOut, int moveSpeed); + + /** + * 云台控制,支持方向与缩放控制 + * + * @param device 控制设备 + * @param channelId 预览通道 + * @param leftRight 镜头左移右移 0:停止 1:左移 2:右移 + * @param upDown 镜头上移下移 0:停止 1:上移 2:下移 + * @param inOut 镜头放大缩小 0:停止 1:缩小 2:放大 + * @param moveSpeed 镜头移动速度 + * @param zoomSpeed 镜头缩放速度 + */ + boolean ptzCmd(Device device, String channelId, int leftRight, int upDown, int inOut, int moveSpeed, int zoomSpeed); + + /** + * 前端控制,包括PTZ指令、FI指令、预置位指令、巡航指令、扫描指令和辅助开关指令 + * + * @param device 控制设备 + * @param channelId 预览通道 + * @param cmdCode 指令码 + * @param parameter1 数据1 + * @param parameter2 数据2 + * @param combineCode2 组合码2 + */ + boolean frontEndCmd(Device device, String channelId, int cmdCode, int parameter1, int parameter2, int combineCode2); + + /** + * 前端控制指令(用于转发上级指令) + * + * @param device 控制设备 + * @param channelId 预览通道 + * @param cmdString 前端控制指令串 + */ + boolean fronEndCmd(Device device, String channelId, String cmdString); + + /** + * 请求预览视频流 + * + * @param device 视频设备 + * @param channelId 预览通道 + */ + void playStreamCmd(Device device, String channelId, ZLMHttpHookSubscribe.Event event, SipSubscribe.Event errorEvent); + + /** + * 请求回放视频流 + * + * @param device 视频设备 + * @param channelId 预览通道 + * @param startTime 开始时间,格式要求:yyyy-MM-dd HH:mm:ss + * @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss + */ + void playbackStreamCmd(Device device, String channelId, String startTime, String endTime, ZLMHttpHookSubscribe.Event event, SipSubscribe.Event errorEvent); + + /** + * 视频流停止 + * + * @param streamInfo streamInfo + * @param okEvent okEvent + */ + void stopStreamByeCmd(StreamInfo streamInfo, SipSubscribe.Event okEvent); + + /** + * 语音广播 + * + * @param device 视频设备 + * @param channelId 预览通道 + */ + boolean audioBroadcastCmd(Device device, String channelId); + + /** + * 语音广播 + * + * @param device 视频设备 + */ + void audioBroadcastCmd(Device device, SipSubscribe.Event okEvent); + + boolean audioBroadcastCmd(Device device); + + /** + * 音视频录像控制 + * + * @param device 视频设备 + * @param channelId 预览通道 + * @param recordCmdStr 录像命令:Record / StopRecord + */ + boolean recordCmd(Device device, String channelId, String recordCmdStr, SipSubscribe.Event errorEvent); + + /** + * 远程启动控制命令 + * + * @param device 视频设备 + */ + boolean teleBootCmd(Device device); + + /** + * 报警布防/撤防命令 + * + * @param device 视频设备 + * @param guardCmdStr true: SetGuard, false: ResetGuard + */ + boolean guardCmd(Device device, String guardCmdStr, SipSubscribe.Event errorEvent); + + /** + * 报警复位命令 + * + * @param device 视频设备 + * @param alarmMethod 报警方式(可选) + * @param alarmType 报警类型(可选) + */ + boolean alarmCmd(Device device, String alarmMethod, String alarmType, SipSubscribe.Event errorEvent); + + /** + * 强制关键帧命令,设备收到此命令应立刻发送一个IDR帧 + * + * @param device 视频设备 + * @param channelId 预览通道 + */ + boolean iFrameCmd(Device device, String channelId); + + /** + * 看守位控制命令 + * + * @param device 视频设备 + * @param enabled 看守位使能:1 = 开启,0 = 关闭 + * @param resetTime 自动归位时间间隔,开启看守位时使用,单位:秒(s) + * @param presetIndex 调用预置位编号,开启看守位时使用,取值范围0~255 + */ + boolean homePositionCmd(Device device, String channelId, String enabled, String resetTime, String presetIndex, SipSubscribe.Event errorEvent); + + /** + * 设备配置命令 + * + * @param device 视频设备 + */ + boolean deviceConfigCmd(Device device); + + /** + * 设备配置命令:basicParam + * + * @param device 视频设备 + * @param channelId 通道编码(可选) + * @param name 设备/通道名称(可选) + * @param expiration 注册过期时间(可选) + * @param heartBeatInterval 心跳间隔时间(可选) + * @param heartBeatCount 心跳超时次数(可选) + */ + boolean deviceBasicConfigCmd(Device device, String channelId, String name, String expiration, String heartBeatInterval, String heartBeatCount, SipSubscribe.Event errorEvent); + + /** + * 查询设备状态 + * + * @param device 视频设备 + */ + boolean deviceStatusQuery(Device device, SipSubscribe.Event errorEvent); + + /** + * 查询设备信息 + * + * @param device 视频设备 + * @return + */ + boolean deviceInfoQuery(Device device); + + /** + * 查询目录列表 + * + * @param device 视频设备 + */ + boolean catalogQuery(Device device, SipSubscribe.Event errorEvent); + + /** + * 查询录像信息 + * + * @param device 视频设备 + * @param startTime 开始时间,格式要求:yyyy-MM-dd HH:mm:ss + * @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss + */ + boolean recordInfoQuery(Device device, String channelId, String startTime, String endTime); + + /** + * 查询报警信息 + * + * @param device 视频设备 + * @param startPriority 报警起始级别(可选) + * @param endPriority 报警终止级别(可选) + * @param alarmMethod 报警方式条件(可选) + * @param alarmType 报警类型 + * @param startTime 报警发生起始时间(可选) + * @param endTime 报警发生终止时间(可选) + * @return true = 命令发送成功 + */ + boolean alarmInfoQuery(Device device, String startPriority, String endPriority, String alarmMethod, + String alarmType, String startTime, String endTime, SipSubscribe.Event errorEvent); + + /** + * 查询设备配置 + * + * @param device 视频设备 + * @param channelId 通道编码(可选) + * @param configType 配置类型: + */ + boolean deviceConfigQuery(Device device, String channelId, String configType, SipSubscribe.Event errorEvent); + + /** + * 查询设备预置位置 + * + * @param device 视频设备 + */ + boolean presetQuery(Device device, String channelId, SipSubscribe.Event errorEvent); + + /** + * 查询移动设备位置数据 + * + * @param device 视频设备 + */ + boolean mobilePostitionQuery(Device device, SipSubscribe.Event errorEvent); + + /** + * 订阅、取消订阅移动位置 + * + * @param device 视频设备 + * @param expires 订阅超时时间(值=0时为取消订阅) + * @param interval 上报时间间隔 + * @return true = 命令发送成功 + */ + boolean mobilePositionSubscribe(Device device, int expires, int interval); + + /** + * 订阅、取消订阅报警信息 + * + * @param device 视频设备 + * @param expires 订阅过期时间(0 = 取消订阅) + * @param startPriority 报警起始级别(可选) + * @param endPriority 报警终止级别(可选) + * @param alarmMethod 报警方式条件(可选) + * @param alarmType 报警类型 + * @param startTime 报警发生起始时间(可选) + * @param endTime 报警发生终止时间(可选) + * @return true = 命令发送成功 + */ + boolean alarmSubscribe(Device device, int expires, String startPriority, String endPriority, String alarmMethod, String alarmType, String startTime, String endTime); + + + /** + * 释放rtpserver + * + * @param device + * @param channelId + */ void closeRTPServer(Device device, String channelId); } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java index cc992f68..73015c44 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java @@ -1,23 +1,19 @@ package com.genersoft.iot.vmp.gb28181.transmit.cmd; -import java.text.ParseException; -import java.util.ArrayList; +import com.genersoft.iot.vmp.conf.SipConfig; +import com.genersoft.iot.vmp.gb28181.bean.Device; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; import javax.sip.InvalidArgumentException; import javax.sip.PeerUnavailableException; import javax.sip.SipFactory; -// import javax.sip.SipProvider; import javax.sip.address.Address; import javax.sip.address.SipURI; import javax.sip.header.*; import javax.sip.message.Request; - -import org.springframework.beans.factory.annotation.Autowired; -// import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.stereotype.Component; - -import com.genersoft.iot.vmp.conf.SipConfig; -import com.genersoft.iot.vmp.gb28181.bean.Device; +import java.text.ParseException; +import java.util.ArrayList; /** * @Description:摄像头命令request创造器 TODO 冗余代码太多待优化 @@ -27,157 +23,165 @@ import com.genersoft.iot.vmp.gb28181.bean.Device; @Component public class SIPRequestHeaderProvider { - @Autowired - private SipConfig sipConfig; - - @Autowired - private SipFactory sipFactory; - - public Request createMessageRequest(Device device, String content, String viaTag, String fromTag, String toTag, CallIdHeader callIdHeader) throws ParseException, InvalidArgumentException, PeerUnavailableException { - Request request = null; - // sipuri - SipURI requestURI = sipFactory.createAddressFactory().createSipURI(device.getDeviceId(), device.getHostAddress()); - // via - ArrayList viaHeaders = new ArrayList(); - ViaHeader viaHeader = sipFactory.createHeaderFactory().createViaHeader(sipConfig.getSipIp(), sipConfig.getSipPort(), - device.getTransport(), viaTag); - viaHeader.setRPort(); - viaHeaders.add(viaHeader); - // from - SipURI fromSipURI = sipFactory.createAddressFactory().createSipURI(sipConfig.getSipId(), - sipConfig.getSipIp() + ":" + sipConfig.getSipPort()); - Address fromAddress = sipFactory.createAddressFactory().createAddress(fromSipURI); - FromHeader fromHeader = sipFactory.createHeaderFactory().createFromHeader(fromAddress, fromTag); - // to - SipURI toSipURI = sipFactory.createAddressFactory().createSipURI(device.getDeviceId(), sipConfig.getSipDomain()); - Address toAddress = sipFactory.createAddressFactory().createAddress(toSipURI); - ToHeader toHeader = sipFactory.createHeaderFactory().createToHeader(toAddress, toTag); - - // Forwards - MaxForwardsHeader maxForwards = sipFactory.createHeaderFactory().createMaxForwardsHeader(70); - // ceq - CSeqHeader cSeqHeader = sipFactory.createHeaderFactory().createCSeqHeader(1L, Request.MESSAGE); - - request = sipFactory.createMessageFactory().createRequest(requestURI, Request.MESSAGE, callIdHeader, cSeqHeader, fromHeader, - toHeader, viaHeaders, maxForwards); - ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("APPLICATION", "MANSCDP+xml"); - request.setContent(content, contentTypeHeader); - return request; - } - - public Request createInviteRequest(Device device, String channelId, String content, String viaTag, String fromTag, String toTag, String ssrc, CallIdHeader callIdHeader) throws ParseException, InvalidArgumentException, PeerUnavailableException { - Request request = null; - //请求行 - SipURI requestLine = sipFactory.createAddressFactory().createSipURI(channelId, device.getHostAddress()); - //via - ArrayList viaHeaders = new ArrayList(); - ViaHeader viaHeader = sipFactory.createHeaderFactory().createViaHeader(device.getIp(), device.getPort(), device.getTransport(), viaTag); - viaHeader.setRPort(); - viaHeaders.add(viaHeader); - - //from - SipURI fromSipURI = sipFactory.createAddressFactory().createSipURI(sipConfig.getSipId(),sipConfig.getSipDomain()); - Address fromAddress = sipFactory.createAddressFactory().createAddress(fromSipURI); - FromHeader fromHeader = sipFactory.createHeaderFactory().createFromHeader(fromAddress, fromTag); //必须要有标记,否则无法创建会话,无法回应ack - //to - SipURI toSipURI = sipFactory.createAddressFactory().createSipURI(channelId,sipConfig.getSipDomain()); - Address toAddress = sipFactory.createAddressFactory().createAddress(toSipURI); - ToHeader toHeader = sipFactory.createHeaderFactory().createToHeader(toAddress,null); - - //Forwards - MaxForwardsHeader maxForwards = sipFactory.createHeaderFactory().createMaxForwardsHeader(70); - - //ceq - CSeqHeader cSeqHeader = sipFactory.createHeaderFactory().createCSeqHeader(1L, Request.INVITE); - request = sipFactory.createMessageFactory().createRequest(requestLine, Request.INVITE, callIdHeader, cSeqHeader,fromHeader, toHeader, viaHeaders, maxForwards); - - Address concatAddress = sipFactory.createAddressFactory().createAddress(sipFactory.createAddressFactory().createSipURI(sipConfig.getSipId(), sipConfig.getSipIp()+":"+sipConfig.getSipPort())); - // Address concatAddress = sipFactory.createAddressFactory().createAddress(sipFactory.createAddressFactory().createSipURI(sipConfig.getSipId(), device.getHost().getIp()+":"+device.getHost().getPort())); - request.addHeader(sipFactory.createHeaderFactory().createContactHeader(concatAddress)); - // Subject - SubjectHeader subjectHeader = sipFactory.createHeaderFactory().createSubjectHeader(String.format("%s:%s,%s:%s", channelId, ssrc, sipConfig.getSipId(), 0)); - request.addHeader(subjectHeader); - ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("APPLICATION", "SDP"); - request.setContent(content, contentTypeHeader); - return request; - } - - public Request createPlaybackInviteRequest(Device device, String channelId, String content, String viaTag, String fromTag, String toTag, CallIdHeader callIdHeader) throws ParseException, InvalidArgumentException, PeerUnavailableException { - Request request = null; - //请求行 - SipURI requestLine = sipFactory.createAddressFactory().createSipURI(device.getDeviceId(), device.getHostAddress()); - // via - ArrayList viaHeaders = new ArrayList(); - ViaHeader viaHeader = sipFactory.createHeaderFactory().createViaHeader(device.getIp(), device.getPort(), device.getTransport(), viaTag); - viaHeader.setRPort(); - viaHeaders.add(viaHeader); - //from - SipURI fromSipURI = sipFactory.createAddressFactory().createSipURI(sipConfig.getSipId(),sipConfig.getSipDomain()); - Address fromAddress = sipFactory.createAddressFactory().createAddress(fromSipURI); - FromHeader fromHeader = sipFactory.createHeaderFactory().createFromHeader(fromAddress, fromTag); //必须要有标记,否则无法创建会话,无法回应ack - //to - SipURI toSipURI = sipFactory.createAddressFactory().createSipURI(channelId,sipConfig.getSipDomain()); - Address toAddress = sipFactory.createAddressFactory().createAddress(toSipURI); - ToHeader toHeader = sipFactory.createHeaderFactory().createToHeader(toAddress,null); - - //Forwards - MaxForwardsHeader maxForwards = sipFactory.createHeaderFactory().createMaxForwardsHeader(70); - - //ceq - CSeqHeader cSeqHeader = sipFactory.createHeaderFactory().createCSeqHeader(1L, Request.INVITE); - request = sipFactory.createMessageFactory().createRequest(requestLine, Request.INVITE, callIdHeader, cSeqHeader,fromHeader, toHeader, viaHeaders, maxForwards); - - Address concatAddress = sipFactory.createAddressFactory().createAddress(sipFactory.createAddressFactory().createSipURI(sipConfig.getSipId(), sipConfig.getSipIp()+":"+sipConfig.getSipPort())); - // Address concatAddress = sipFactory.createAddressFactory().createAddress(sipFactory.createAddressFactory().createSipURI(sipConfig.getSipId(), device.getHost().getIp()+":"+device.getHost().getPort())); - request.addHeader(sipFactory.createHeaderFactory().createContactHeader(concatAddress)); - - ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("APPLICATION", "SDP"); - request.setContent(content, contentTypeHeader); - return request; - } - - public Request createSubscribeRequest(Device device, String content, String viaTag, String fromTag, String toTag, Integer expires, String event, CallIdHeader callIdHeader) throws ParseException, InvalidArgumentException, PeerUnavailableException { - Request request = null; - // sipuri - SipURI requestURI = sipFactory.createAddressFactory().createSipURI(device.getDeviceId(), device.getHostAddress()); - // via - ArrayList viaHeaders = new ArrayList(); - ViaHeader viaHeader = sipFactory.createHeaderFactory().createViaHeader(sipConfig.getSipIp(), sipConfig.getSipPort(), - device.getTransport(), viaTag); - viaHeader.setRPort(); - viaHeaders.add(viaHeader); - // from - SipURI fromSipURI = sipFactory.createAddressFactory().createSipURI(sipConfig.getSipId(), - sipConfig.getSipIp() + ":" + sipConfig.getSipPort()); - Address fromAddress = sipFactory.createAddressFactory().createAddress(fromSipURI); - FromHeader fromHeader = sipFactory.createHeaderFactory().createFromHeader(fromAddress, fromTag); - // to - SipURI toSipURI = sipFactory.createAddressFactory().createSipURI(device.getDeviceId(), sipConfig.getSipDomain()); - Address toAddress = sipFactory.createAddressFactory().createAddress(toSipURI); - ToHeader toHeader = sipFactory.createHeaderFactory().createToHeader(toAddress, toTag); - - // Forwards - MaxForwardsHeader maxForwards = sipFactory.createHeaderFactory().createMaxForwardsHeader(70); - // ceq - CSeqHeader cSeqHeader = sipFactory.createHeaderFactory().createCSeqHeader(1L, Request.SUBSCRIBE); - - request = sipFactory.createMessageFactory().createRequest(requestURI, Request.SUBSCRIBE, callIdHeader, cSeqHeader, fromHeader, - toHeader, viaHeaders, maxForwards); - - - Address concatAddress = sipFactory.createAddressFactory().createAddress(sipFactory.createAddressFactory().createSipURI(sipConfig.getSipId(), sipConfig.getSipIp()+":"+sipConfig.getSipPort())); - request.addHeader(sipFactory.createHeaderFactory().createContactHeader(concatAddress)); - - // Expires - ExpiresHeader expireHeader = sipFactory.createHeaderFactory().createExpiresHeader(expires); - request.addHeader(expireHeader); - - // Event - EventHeader eventHeader = sipFactory.createHeaderFactory().createEventHeader(event); - request.addHeader(eventHeader); - - ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("APPLICATION", "MANSCDP+xml"); - request.setContent(content, contentTypeHeader); - return request; - } + @Autowired + private SipConfig sipConfig; + + @Autowired + private SipFactory sipFactory; + + public Request createMessageRequest(Device device, String content, String viaTag, String fromTag, String toTag, CallIdHeader callIdHeader) throws ParseException, InvalidArgumentException, PeerUnavailableException { + Request request = null; + // sipuri + SipURI requestURI = sipFactory.createAddressFactory().createSipURI(device.getDeviceId(), device.getHostAddress()); + // via + ArrayList viaHeaders = new ArrayList(); + ViaHeader viaHeader = sipFactory.createHeaderFactory().createViaHeader(sipConfig.getSipIp(), sipConfig.getSipPort(), + device.getTransport(), viaTag); + viaHeader.setRPort(); + viaHeaders.add(viaHeader); + // from + SipURI fromSipURI = sipFactory.createAddressFactory().createSipURI(sipConfig.getSipId(), + sipConfig.getSipIp() + ":" + sipConfig.getSipPort()); + Address fromAddress = sipFactory.createAddressFactory().createAddress(fromSipURI); + FromHeader fromHeader = sipFactory.createHeaderFactory().createFromHeader(fromAddress, fromTag); + // to + SipURI toSipURI = sipFactory.createAddressFactory().createSipURI(device.getDeviceId(), sipConfig.getSipDomain()); + Address toAddress = sipFactory.createAddressFactory().createAddress(toSipURI); + ToHeader toHeader = sipFactory.createHeaderFactory().createToHeader(toAddress, toTag); + + // Forwards + MaxForwardsHeader maxForwards = sipFactory.createHeaderFactory().createMaxForwardsHeader(70); + // ceq + CSeqHeader cSeqHeader = sipFactory.createHeaderFactory().createCSeqHeader(1L, Request.MESSAGE); + + request = sipFactory.createMessageFactory().createRequest(requestURI, Request.MESSAGE, callIdHeader, cSeqHeader, fromHeader, + toHeader, viaHeaders, maxForwards); + ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("APPLICATION", "MANSCDP+xml"); + request.setContent(content, contentTypeHeader); + return request; + } + + public Request createInviteRequest(Device device, String channelId, String content, String viaTag, String fromTag, String toTag, String ssrc, CallIdHeader callIdHeader) throws ParseException, InvalidArgumentException, PeerUnavailableException { + Request request = null; + //请求行 + SipURI requestLine = sipFactory.createAddressFactory().createSipURI(channelId, device.getHostAddress()); + //via + ArrayList viaHeaders = new ArrayList(); + ViaHeader viaHeader = sipFactory.createHeaderFactory().createViaHeader(device.getIp(), device.getPort(), device.getTransport(), viaTag); + viaHeader.setRPort(); + viaHeaders.add(viaHeader); + + //from + SipURI fromSipURI = sipFactory.createAddressFactory().createSipURI(sipConfig.getSipId(), sipConfig.getSipDomain()); + Address fromAddress = sipFactory.createAddressFactory().createAddress(fromSipURI); + FromHeader fromHeader = sipFactory.createHeaderFactory().createFromHeader(fromAddress, fromTag); //必须要有标记,否则无法创建会话,无法回应ack + //to + SipURI toSipURI = sipFactory.createAddressFactory().createSipURI(channelId, sipConfig.getSipDomain()); + Address toAddress = sipFactory.createAddressFactory().createAddress(toSipURI); + ToHeader toHeader = sipFactory.createHeaderFactory().createToHeader(toAddress, null); + + //Forwards + MaxForwardsHeader maxForwards = sipFactory.createHeaderFactory().createMaxForwardsHeader(70); + + //ceq + CSeqHeader cSeqHeader = sipFactory.createHeaderFactory().createCSeqHeader(1L, Request.INVITE); + request = sipFactory.createMessageFactory().createRequest(requestLine, Request.INVITE, callIdHeader, cSeqHeader, fromHeader, toHeader, viaHeaders, maxForwards); + + Address concatAddress = sipFactory.createAddressFactory().createAddress(sipFactory.createAddressFactory().createSipURI(sipConfig.getSipId(), sipConfig.getSipIp() + ":" + sipConfig.getSipPort())); + // Address concatAddress = sipFactory.createAddressFactory().createAddress(sipFactory.createAddressFactory().createSipURI(sipConfig.getSipId(), device.getHost().getIp()+":"+device.getHost().getPort())); + request.addHeader(sipFactory.createHeaderFactory().createContactHeader(concatAddress)); + // Subject + SubjectHeader subjectHeader = sipFactory.createHeaderFactory().createSubjectHeader(String.format("%s:%s,%s:%s", channelId, ssrc, sipConfig.getSipId(), 0)); + request.addHeader(subjectHeader); + ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("APPLICATION", "SDP"); + request.setContent(content, contentTypeHeader); + return request; + } + + public Request createPlaybackInviteRequest(Device device, String channelId, String content, String viaTag, String fromTag, String toTag, CallIdHeader callIdHeader) throws ParseException, InvalidArgumentException, PeerUnavailableException { + Request request = null; + //请求行 + SipURI requestLine = sipFactory.createAddressFactory().createSipURI(device.getDeviceId(), device.getHostAddress()); + // via + ArrayList viaHeaders = new ArrayList(); + ViaHeader viaHeader = sipFactory.createHeaderFactory().createViaHeader(device.getIp(), device.getPort(), device.getTransport(), viaTag); + viaHeader.setRPort(); + viaHeaders.add(viaHeader); + //from + SipURI fromSipURI = sipFactory.createAddressFactory().createSipURI(sipConfig.getSipId(), sipConfig.getSipDomain()); + Address fromAddress = sipFactory.createAddressFactory().createAddress(fromSipURI); + FromHeader fromHeader = sipFactory.createHeaderFactory().createFromHeader(fromAddress, fromTag); //必须要有标记,否则无法创建会话,无法回应ack + //to + SipURI toSipURI = sipFactory.createAddressFactory().createSipURI(channelId, sipConfig.getSipDomain()); + Address toAddress = sipFactory.createAddressFactory().createAddress(toSipURI); + ToHeader toHeader = sipFactory.createHeaderFactory().createToHeader(toAddress, null); + + //Forwards + MaxForwardsHeader maxForwards = sipFactory.createHeaderFactory().createMaxForwardsHeader(70); + + //ceq + CSeqHeader cSeqHeader = sipFactory.createHeaderFactory().createCSeqHeader(1L, Request.INVITE); + request = sipFactory.createMessageFactory().createRequest(requestLine, Request.INVITE, callIdHeader, cSeqHeader, fromHeader, toHeader, viaHeaders, maxForwards); + + Address concatAddress = sipFactory.createAddressFactory().createAddress(sipFactory.createAddressFactory().createSipURI(sipConfig.getSipId(), sipConfig.getSipIp() + ":" + sipConfig.getSipPort())); + // Address concatAddress = sipFactory.createAddressFactory().createAddress(sipFactory.createAddressFactory().createSipURI(sipConfig.getSipId(), device.getHost().getIp()+":"+device.getHost().getPort())); + request.addHeader(sipFactory.createHeaderFactory().createContactHeader(concatAddress)); + + ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("APPLICATION", "SDP"); + request.setContent(content, contentTypeHeader); + return request; + } + + public Request createSubscribeRequest(Device device, + String content, + String viaTag, + String fromTag, + String toTag, + Integer expires, + String event, + CallIdHeader callIdHeader + ) throws ParseException, InvalidArgumentException, PeerUnavailableException { + Request request = null; + // sipuri + SipURI requestURI = sipFactory.createAddressFactory().createSipURI(device.getDeviceId(), device.getHostAddress()); + // via + ArrayList viaHeaders = new ArrayList(); + ViaHeader viaHeader = sipFactory.createHeaderFactory().createViaHeader(sipConfig.getSipIp(), sipConfig.getSipPort(), + device.getTransport(), viaTag); + viaHeader.setRPort(); + viaHeaders.add(viaHeader); + // from + SipURI fromSipURI = sipFactory.createAddressFactory().createSipURI(sipConfig.getSipId(), + sipConfig.getSipIp() + ":" + sipConfig.getSipPort()); + Address fromAddress = sipFactory.createAddressFactory().createAddress(fromSipURI); + FromHeader fromHeader = sipFactory.createHeaderFactory().createFromHeader(fromAddress, fromTag); + // to + SipURI toSipURI = sipFactory.createAddressFactory().createSipURI(device.getDeviceId(), sipConfig.getSipDomain()); + Address toAddress = sipFactory.createAddressFactory().createAddress(toSipURI); + ToHeader toHeader = sipFactory.createHeaderFactory().createToHeader(toAddress, toTag); + + // Forwards + MaxForwardsHeader maxForwards = sipFactory.createHeaderFactory().createMaxForwardsHeader(70); + // ceq + CSeqHeader cSeqHeader = sipFactory.createHeaderFactory().createCSeqHeader(1L, Request.SUBSCRIBE); + + request = sipFactory.createMessageFactory().createRequest(requestURI, Request.SUBSCRIBE, callIdHeader, cSeqHeader, fromHeader, + toHeader, viaHeaders, maxForwards); + + + Address concatAddress = sipFactory.createAddressFactory().createAddress(sipFactory.createAddressFactory().createSipURI(sipConfig.getSipId(), sipConfig.getSipIp() + ":" + sipConfig.getSipPort())); + request.addHeader(sipFactory.createHeaderFactory().createContactHeader(concatAddress)); + + // Expires + ExpiresHeader expireHeader = sipFactory.createHeaderFactory().createExpiresHeader(expires); + request.addHeader(expireHeader); + + // Event + EventHeader eventHeader = sipFactory.createHeaderFactory().createEventHeader(event); + request.addHeader(eventHeader); + + ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("APPLICATION", "MANSCDP+xml"); + request.setContent(content, contentTypeHeader); + return request; + } } 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 f7a54974..cfccb56c 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 @@ -17,13 +17,10 @@ import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe; import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.storager.IVideoManagerStorager; -import lombok.extern.slf4j.Slf4j; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.beans.factory.annotation.Value; -// import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.DependsOn; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Component; @@ -46,32 +43,32 @@ import java.util.regex.Pattern; @DependsOn("sipLayer") public class SIPCommander implements ISIPCommander { - private final Logger logger = LoggerFactory.getLogger(SIPCommander.class); - - @Autowired - private SipConfig sipConfig; + private final Logger logger = LoggerFactory.getLogger(SIPCommander.class); - @Lazy - @Autowired - @Qualifier(value="tcpSipProvider") - private SipProvider tcpSipProvider; + @Autowired + private SipConfig sipConfig; + + @Lazy + @Autowired + @Qualifier(value = "tcpSipProvider") + private SipProvider tcpSipProvider; + + @Lazy + @Autowired + @Qualifier(value = "udpSipProvider") + private SipProvider udpSipProvider; - @Lazy - @Autowired - @Qualifier(value="udpSipProvider") - private SipProvider udpSipProvider; + @Autowired + private SIPRequestHeaderProvider headerProvider; - @Autowired - private SIPRequestHeaderProvider headerProvider; - - @Autowired - private VideoStreamSessionManager streamSession; + @Autowired + private VideoStreamSessionManager streamSession; @Autowired private IVideoManagerStorager storager; - @Autowired - private IRedisCatchStorage redisCatchStorage; + @Autowired + private IRedisCatchStorage redisCatchStorage; @Autowired private ZLMRTPServerFactory zlmrtpServerFactory; @@ -206,68 +203,68 @@ public class SIPCommander implements ISIPCommander { return builder.toString(); } - /** - * 云台控制,支持方向与缩放控制 - * - * @param device 控制设备 - * @param channelId 预览通道 - * @param leftRight 镜头左移右移 0:停止 1:左移 2:右移 - * @param upDown 镜头上移下移 0:停止 1:上移 2:下移 - * @param inOut 镜头放大缩小 0:停止 1:缩小 2:放大 - * @param moveSpeed 镜头移动速度 - * @param zoomSpeed 镜头缩放速度 - */ - @Override - public boolean ptzCmd(Device device, String channelId, int leftRight, int upDown, int inOut, int moveSpeed, - int zoomSpeed) { - try { - String cmdStr= cmdString(leftRight, upDown, inOut, moveSpeed, zoomSpeed); - StringBuffer ptzXml = new StringBuffer(200); - ptzXml.append("\r\n"); - ptzXml.append("\r\n"); - ptzXml.append("DeviceControl\r\n"); - ptzXml.append("" + (int)((Math.random()*9+1)*100000) + "\r\n"); - ptzXml.append("" + channelId + "\r\n"); - ptzXml.append("" + cmdStr + "\r\n"); - ptzXml.append("\r\n"); - ptzXml.append("\r\n"); - ptzXml.append("\r\n"); - - String tm = Long.toString(System.currentTimeMillis()); - - CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId() - : udpSipProvider.getNewCallId(); - - Request request = headerProvider.createMessageRequest(device, ptzXml.toString(), "z9hG4bK-ViaPtz-" + tm, "FromPtz" + tm, null, callIdHeader); - - transmitRequest(device, request); - return true; - } catch (SipException | ParseException | InvalidArgumentException e) { - e.printStackTrace(); - } - return false; - } + /** + * 云台控制,支持方向与缩放控制 + * + * @param device 控制设备 + * @param channelId 预览通道 + * @param leftRight 镜头左移右移 0:停止 1:左移 2:右移 + * @param upDown 镜头上移下移 0:停止 1:上移 2:下移 + * @param inOut 镜头放大缩小 0:停止 1:缩小 2:放大 + * @param moveSpeed 镜头移动速度 + * @param zoomSpeed 镜头缩放速度 + */ + @Override + public boolean ptzCmd(Device device, String channelId, int leftRight, int upDown, int inOut, int moveSpeed, + int zoomSpeed) { + try { + String cmdStr = cmdString(leftRight, upDown, inOut, moveSpeed, zoomSpeed); + StringBuffer ptzXml = new StringBuffer(200); + ptzXml.append("\r\n"); + ptzXml.append("\r\n"); + ptzXml.append("DeviceControl\r\n"); + ptzXml.append("" + (int) ((Math.random() * 9 + 1) * 100000) + "\r\n"); + ptzXml.append("" + channelId + "\r\n"); + ptzXml.append("" + cmdStr + "\r\n"); + ptzXml.append("\r\n"); + ptzXml.append("\r\n"); + ptzXml.append("\r\n"); + + String tm = Long.toString(System.currentTimeMillis()); + + CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId() + : udpSipProvider.getNewCallId(); + + Request request = headerProvider.createMessageRequest(device, ptzXml.toString(), "z9hG4bK-ViaPtz-" + tm, "FromPtz" + tm, null, callIdHeader); + + transmitRequest(device, request); + return true; + } catch (SipException | ParseException | InvalidArgumentException e) { + e.printStackTrace(); + } + return false; + } /** * 前端控制,包括PTZ指令、FI指令、预置位指令、巡航指令、扫描指令和辅助开关指令 * - * @param device 控制设备 - * @param channelId 预览通道 - * @param cmdCode 指令码 - * @param parameter1 数据1 - * @param parameter2 数据2 - * @param combineCode2 组合码2 + * @param device 控制设备 + * @param channelId 预览通道 + * @param cmdCode 指令码 + * @param parameter1 数据1 + * @param parameter2 数据2 + * @param combineCode2 组合码2 */ @Override public boolean frontEndCmd(Device device, String channelId, int cmdCode, int parameter1, int parameter2, int combineCode2) { try { - String cmdStr= frontEndCmdString(cmdCode, parameter1, parameter2, combineCode2); + String cmdStr = frontEndCmdString(cmdCode, parameter1, parameter2, combineCode2); System.out.println("控制字符串:" + cmdStr); StringBuffer ptzXml = new StringBuffer(200); ptzXml.append("\r\n"); ptzXml.append("\r\n"); ptzXml.append("DeviceControl\r\n"); - ptzXml.append("" + (int)((Math.random()*9+1)*100000) + "\r\n"); + ptzXml.append("" + (int) ((Math.random() * 9 + 1) * 100000) + "\r\n"); ptzXml.append("" + channelId + "\r\n"); ptzXml.append("" + cmdStr + "\r\n"); ptzXml.append("\r\n"); @@ -290,9 +287,10 @@ public class SIPCommander implements ISIPCommander { /** * 前端控制指令(用于转发上级指令) - * @param device 控制设备 - * @param channelId 预览通道 - * @param cmdString 前端控制指令串 + * + * @param device 控制设备 + * @param channelId 预览通道 + * @param cmdString 前端控制指令串 */ @Override public boolean fronEndCmd(Device device, String channelId, String cmdString) { @@ -301,7 +299,7 @@ public class SIPCommander implements ISIPCommander { ptzXml.append("\r\n"); ptzXml.append("\r\n"); ptzXml.append("DeviceControl\r\n"); - ptzXml.append("" + (int)((Math.random()*9+1)*100000) + "\r\n"); + ptzXml.append("" + (int) ((Math.random() * 9 + 1) * 100000) + "\r\n"); ptzXml.append("" + channelId + "\r\n"); ptzXml.append("" + cmdString + "\r\n"); ptzXml.append("\r\n"); @@ -359,58 +357,58 @@ public class SIPCommander implements ISIPCommander { content.append("c=IN IP4 " + mediaServerIp + "\r\n"); content.append("t=0 0\r\n"); - if (mediaConfig.getSeniorSdp()) { - if("TCP-PASSIVE".equals(streamMode)) { - content.append("m=video "+ mediaPort +" TCP/RTP/AVP 96 126 125 99 34 98 97\r\n"); - }else if ("TCP-ACTIVE".equals(streamMode)) { - content.append("m=video "+ mediaPort +" TCP/RTP/AVP 96 126 125 99 34 98 97\r\n"); - }else if("UDP".equals(streamMode)) { - content.append("m=video "+ mediaPort +" RTP/AVP 96 126 125 99 34 98 97\r\n"); - } - content.append("a=recvonly\r\n"); - content.append("a=rtpmap:96 PS/90000\r\n"); - content.append("a=fmtp:126 profile-level-id=42e01e\r\n"); - content.append("a=rtpmap:126 H264/90000\r\n"); - content.append("a=rtpmap:125 H264S/90000\r\n"); - content.append("a=fmtp:125 profile-level-id=42e01e\r\n"); - content.append("a=rtpmap:99 MP4V-ES/90000\r\n"); - content.append("a=fmtp:99 profile-level-id=3\r\n"); - content.append("a=rtpmap:98 H264/90000\r\n"); - content.append("a=rtpmap:97 MPEG4/90000\r\n"); - if("TCP-PASSIVE".equals(streamMode)){ // tcp被动模式 - content.append("a=setup:passive\r\n"); - content.append("a=connection:new\r\n"); - }else if ("TCP-ACTIVE".equals(streamMode)) { // tcp主动模式 - content.append("a=setup:active\r\n"); - content.append("a=connection:new\r\n"); - } - }else { - if("TCP-PASSIVE".equals(streamMode)) { - content.append("m=video "+ mediaPort +" TCP/RTP/AVP 96 98 97\r\n"); - }else if ("TCP-ACTIVE".equals(streamMode)) { - content.append("m=video "+ mediaPort +" TCP/RTP/AVP 96 98 97\r\n"); - }else if("UDP".equals(streamMode)) { - content.append("m=video "+ mediaPort +" RTP/AVP 96 98 97\r\n"); - } - content.append("a=recvonly\r\n"); - content.append("a=rtpmap:96 PS/90000\r\n"); - content.append("a=rtpmap:98 H264/90000\r\n"); - content.append("a=rtpmap:97 MPEG4/90000\r\n"); - if("TCP-PASSIVE".equals(streamMode)) { // tcp被动模式 - content.append("a=setup:passive\r\n"); - content.append("a=recvonly\r\n"); - content.append("a=rtpmap:96 PS/90000\r\n"); - content.append("a=rtpmap:98 H264/90000\r\n"); - content.append("a=rtpmap:97 MPEG4/90000\r\n"); - if ("TCP-PASSIVE".equals(streamMode)) { // tcp被动模式 - content.append("a=setup:passive\r\n"); - content.append("a=connection:new\r\n"); - } else if ("TCP-ACTIVE".equals(streamMode)) { // tcp主动模式 - content.append("a=setup:active\r\n"); - content.append("a=connection:new\r\n"); - } - } - } + if (mediaConfig.getSeniorSdp()) { + if ("TCP-PASSIVE".equals(streamMode)) { + content.append("m=video " + mediaPort + " TCP/RTP/AVP 96 126 125 99 34 98 97\r\n"); + } else if ("TCP-ACTIVE".equals(streamMode)) { + content.append("m=video " + mediaPort + " TCP/RTP/AVP 96 126 125 99 34 98 97\r\n"); + } else if ("UDP".equals(streamMode)) { + content.append("m=video " + mediaPort + " RTP/AVP 96 126 125 99 34 98 97\r\n"); + } + content.append("a=recvonly\r\n"); + content.append("a=rtpmap:96 PS/90000\r\n"); + content.append("a=fmtp:126 profile-level-id=42e01e\r\n"); + content.append("a=rtpmap:126 H264/90000\r\n"); + content.append("a=rtpmap:125 H264S/90000\r\n"); + content.append("a=fmtp:125 profile-level-id=42e01e\r\n"); + content.append("a=rtpmap:99 MP4V-ES/90000\r\n"); + content.append("a=fmtp:99 profile-level-id=3\r\n"); + content.append("a=rtpmap:98 H264/90000\r\n"); + content.append("a=rtpmap:97 MPEG4/90000\r\n"); + if ("TCP-PASSIVE".equals(streamMode)) { // tcp被动模式 + content.append("a=setup:passive\r\n"); + content.append("a=connection:new\r\n"); + } else if ("TCP-ACTIVE".equals(streamMode)) { // tcp主动模式 + content.append("a=setup:active\r\n"); + content.append("a=connection:new\r\n"); + } + } else { + if ("TCP-PASSIVE".equals(streamMode)) { + content.append("m=video " + mediaPort + " TCP/RTP/AVP 96 98 97\r\n"); + } else if ("TCP-ACTIVE".equals(streamMode)) { + content.append("m=video " + mediaPort + " TCP/RTP/AVP 96 98 97\r\n"); + } else if ("UDP".equals(streamMode)) { + content.append("m=video " + mediaPort + " RTP/AVP 96 98 97\r\n"); + } + content.append("a=recvonly\r\n"); + content.append("a=rtpmap:96 PS/90000\r\n"); + content.append("a=rtpmap:98 H264/90000\r\n"); + content.append("a=rtpmap:97 MPEG4/90000\r\n"); + if ("TCP-PASSIVE".equals(streamMode)) { // tcp被动模式 + content.append("a=setup:passive\r\n"); + content.append("a=recvonly\r\n"); + content.append("a=rtpmap:96 PS/90000\r\n"); + content.append("a=rtpmap:98 H264/90000\r\n"); + content.append("a=rtpmap:97 MPEG4/90000\r\n"); + if ("TCP-PASSIVE".equals(streamMode)) { // tcp被动模式 + content.append("a=setup:passive\r\n"); + content.append("a=connection:new\r\n"); + } else if ("TCP-ACTIVE".equals(streamMode)) { // tcp主动模式 + content.append("a=setup:active\r\n"); + content.append("a=connection:new\r\n"); + } + } + } content.append("y=" + ssrc + "\r\n");//ssrc try { @@ -592,306 +590,307 @@ public class SIPCommander implements ISIPCommander { } } - /** - * 语音广播 - * - * @param device 视频设备 - * @param channelId 预览通道 - */ - @Override - public boolean audioBroadcastCmd(Device device, String channelId) { - // 改为新的实现 - return false; - } - - /** - * 语音广播 - * - * @param device 视频设备 - * @param channelId 预览通道 - */ - @Override - public boolean audioBroadcastCmd(Device device) { - try { - StringBuffer broadcastXml = new StringBuffer(200); - broadcastXml.append("\r\n"); - broadcastXml.append("\r\n"); - broadcastXml.append("Broadcast\r\n"); - broadcastXml.append("" + (int)((Math.random()*9+1)*100000) + "\r\n"); - broadcastXml.append("" + sipConfig.getSipId() + "\r\n"); - broadcastXml.append("" + device.getDeviceId() + "\r\n"); - broadcastXml.append("\r\n"); - - String tm = Long.toString(System.currentTimeMillis()); - - CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId() - : udpSipProvider.getNewCallId(); - - Request request = headerProvider.createMessageRequest(device, broadcastXml.toString(), "z9hG4bK-ViaBcst-" + tm, "FromBcst" + tm, null, callIdHeader); - transmitRequest(device, request); - return true; - } catch (SipException | ParseException | InvalidArgumentException e) { - e.printStackTrace(); - } - return false; - } - @Override - public void audioBroadcastCmd(Device device, SipSubscribe.Event errorEvent) { - try { - StringBuffer broadcastXml = new StringBuffer(200); - broadcastXml.append("\r\n"); - broadcastXml.append("\r\n"); - broadcastXml.append("Broadcast\r\n"); - broadcastXml.append("" + (int)((Math.random()*9+1)*100000) + "\r\n"); - broadcastXml.append("" + sipConfig.getSipId() + "\r\n"); - broadcastXml.append("" + device.getDeviceId() + "\r\n"); - broadcastXml.append("\r\n"); - - String tm = Long.toString(System.currentTimeMillis()); - - CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId() - : udpSipProvider.getNewCallId(); - - Request request = headerProvider.createMessageRequest(device, broadcastXml.toString(), "z9hG4bK-ViaBcst-" + tm, "FromBcst" + tm, null, callIdHeader); - transmitRequest(device, request, errorEvent); - } catch (SipException | ParseException | InvalidArgumentException e) { - e.printStackTrace(); - } - } - - - /** - * 音视频录像控制 - * - * @param device 视频设备 - * @param channelId 预览通道 - * @param recordCmdStr 录像命令:Record / StopRecord - */ - @Override - public boolean recordCmd(Device device, String channelId, String recordCmdStr, SipSubscribe.Event errorEvent) { - try { - StringBuffer cmdXml = new StringBuffer(200); - cmdXml.append("\r\n"); - cmdXml.append("\r\n"); - cmdXml.append("DeviceControl\r\n"); - cmdXml.append("" + (int)((Math.random()*9+1)*100000) + "\r\n"); - if (XmlUtil.isEmpty(channelId)) { - cmdXml.append("" + device.getDeviceId() + "\r\n"); - } else { - cmdXml.append("" + channelId + "\r\n"); - } - cmdXml.append("" + recordCmdStr + "\r\n"); - cmdXml.append("\r\n"); - - String tm = Long.toString(System.currentTimeMillis()); - - CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId() - : udpSipProvider.getNewCallId(); - - Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, "FromRecord" + tm, null, callIdHeader); - transmitRequest(device, request, errorEvent); - return true; - } catch (SipException | ParseException | InvalidArgumentException e) { - e.printStackTrace(); - return false; - } - } - - /** - * 远程启动控制命令 - * - * @param device 视频设备 - */ - @Override - public boolean teleBootCmd(Device device) { - try { - StringBuffer cmdXml = new StringBuffer(200); - cmdXml.append("\r\n"); - cmdXml.append("\r\n"); - cmdXml.append("DeviceControl\r\n"); - cmdXml.append("" + (int)((Math.random()*9+1)*100000) + "\r\n"); - cmdXml.append("" + device.getDeviceId() + "\r\n"); - cmdXml.append("Boot\r\n"); - cmdXml.append("\r\n"); - - String tm = Long.toString(System.currentTimeMillis()); - - CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId() - : udpSipProvider.getNewCallId(); - - Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, "FromBoot" + tm, null, callIdHeader); - transmitRequest(device, request); - return true; - } catch (SipException | ParseException | InvalidArgumentException e) { - e.printStackTrace(); - return false; - } - } - - /** - * 报警布防/撤防命令 - * - * @param device 视频设备 - * @param guardCmdStr "SetGuard"/"ResetGuard" - */ - @Override - public boolean guardCmd(Device device, String guardCmdStr, SipSubscribe.Event errorEvent) { - try { - StringBuffer cmdXml = new StringBuffer(200); - cmdXml.append("\r\n"); - cmdXml.append("\r\n"); - cmdXml.append("DeviceControl\r\n"); - cmdXml.append("" + (int)((Math.random()*9+1)*100000) + "\r\n"); - cmdXml.append("" + device.getDeviceId() + "\r\n"); - cmdXml.append("" + guardCmdStr + "\r\n"); - cmdXml.append("\r\n"); - - String tm = Long.toString(System.currentTimeMillis()); - - CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId() - : udpSipProvider.getNewCallId(); - - Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, "FromGuard" + tm, null, callIdHeader); - transmitRequest(device, request, errorEvent); - return true; - } catch (SipException | ParseException | InvalidArgumentException e) { - e.printStackTrace(); - return false; - } - } - - /** - * 报警复位命令 - * - * @param device 视频设备 - */ - @Override - public boolean alarmCmd(Device device, String alarmMethod, String alarmType, SipSubscribe.Event errorEvent) { - try { - StringBuffer cmdXml = new StringBuffer(200); - cmdXml.append("\r\n"); - cmdXml.append("\r\n"); - cmdXml.append("DeviceControl\r\n"); - cmdXml.append("" + (int)((Math.random()*9+1)*100000) + "\r\n"); - cmdXml.append("" + device.getDeviceId() + "\r\n"); - cmdXml.append("ResetAlarm\r\n"); - if (!XmlUtil.isEmpty(alarmMethod) || !XmlUtil.isEmpty(alarmType)) { - cmdXml.append("\r\n"); - } - if (!XmlUtil.isEmpty(alarmMethod)) { - cmdXml.append("" + alarmMethod + "\r\n"); - } - if (!XmlUtil.isEmpty(alarmType)) { - cmdXml.append("" + alarmType + "\r\n"); - } - if (!XmlUtil.isEmpty(alarmMethod) || !XmlUtil.isEmpty(alarmType)) { - cmdXml.append("\r\n"); - } - cmdXml.append("\r\n"); - - String tm = Long.toString(System.currentTimeMillis()); - - CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId() - : udpSipProvider.getNewCallId(); - - Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, "FromAlarm" + tm, null, callIdHeader); - transmitRequest(device, request, errorEvent); - return true; - } catch (SipException | ParseException | InvalidArgumentException e) { - e.printStackTrace(); - return false; - } - } - - /** - * 强制关键帧命令,设备收到此命令应立刻发送一个IDR帧 - * - * @param device 视频设备 - * @param channelId 预览通道 - */ - @Override - public boolean iFrameCmd(Device device, String channelId) { - try { - StringBuffer cmdXml = new StringBuffer(200); - cmdXml.append("\r\n"); - cmdXml.append("\r\n"); - cmdXml.append("DeviceControl\r\n"); - cmdXml.append("" + (int)((Math.random()*9+1)*100000) + "\r\n"); - if (XmlUtil.isEmpty(channelId)) { - cmdXml.append("" + device.getDeviceId() + "\r\n"); - } else { - cmdXml.append("" + channelId + "\r\n"); - } - cmdXml.append("Send\r\n"); - cmdXml.append("\r\n"); - - String tm = Long.toString(System.currentTimeMillis()); - - CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId() - : udpSipProvider.getNewCallId(); - - Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, "FromBoot" + tm, null, callIdHeader); - transmitRequest(device, request); - return true; - } catch (SipException | ParseException | InvalidArgumentException e) { - e.printStackTrace(); - return false; - } - } - - /** - * 看守位控制命令 - * - * @param device 视频设备 - * @param enabled 看守位使能:1 = 开启,0 = 关闭 - * @param resetTime 自动归位时间间隔,开启看守位时使用,单位:秒(s) - * @param presetIndex 调用预置位编号,开启看守位时使用,取值范围0~255 - */ - @Override - public boolean homePositionCmd(Device device, String channelId, String enabled, String resetTime, String presetIndex, SipSubscribe.Event errorEvent) { - try { - StringBuffer cmdXml = new StringBuffer(200); - cmdXml.append("\r\n"); - cmdXml.append("\r\n"); - cmdXml.append("DeviceControl\r\n"); - cmdXml.append("" + (int)((Math.random()*9+1)*100000) + "\r\n"); - if (XmlUtil.isEmpty(channelId)) { - cmdXml.append("" + device.getDeviceId() + "\r\n"); - } else { - cmdXml.append("" + channelId + "\r\n"); - } - cmdXml.append("\r\n"); - if (NumericUtil.isInteger(enabled) && (!enabled.equals("0"))) { - cmdXml.append("1\r\n"); - if (NumericUtil.isInteger(resetTime)) { - cmdXml.append("" + resetTime + "\r\n"); - } else { - cmdXml.append("0\r\n"); - } - if (NumericUtil.isInteger(presetIndex)) { - cmdXml.append("" + presetIndex + "\r\n"); - } else { - cmdXml.append("0\r\n"); - } - } else { - cmdXml.append("0\r\n"); - } - cmdXml.append("\r\n"); - cmdXml.append("\r\n"); - - String tm = Long.toString(System.currentTimeMillis()); - - CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId() - : udpSipProvider.getNewCallId(); - - Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, "FromGuard" + tm, null, callIdHeader); - transmitRequest(device, request, errorEvent); - return true; - } catch (SipException | ParseException | InvalidArgumentException e) { - e.printStackTrace(); - return false; - } - } + /** + * 语音广播 + * + * @param device 视频设备 + * @param channelId 预览通道 + */ + @Override + public boolean audioBroadcastCmd(Device device, String channelId) { + // 改为新的实现 + return false; + } + + /** + * 语音广播 + * + * @param device 视频设备 + * @param channelId 预览通道 + */ + @Override + public boolean audioBroadcastCmd(Device device) { + try { + StringBuffer broadcastXml = new StringBuffer(200); + broadcastXml.append("\r\n"); + broadcastXml.append("\r\n"); + broadcastXml.append("Broadcast\r\n"); + broadcastXml.append("" + (int) ((Math.random() * 9 + 1) * 100000) + "\r\n"); + broadcastXml.append("" + sipConfig.getSipId() + "\r\n"); + broadcastXml.append("" + device.getDeviceId() + "\r\n"); + broadcastXml.append("\r\n"); + + String tm = Long.toString(System.currentTimeMillis()); + + CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId() + : udpSipProvider.getNewCallId(); + + Request request = headerProvider.createMessageRequest(device, broadcastXml.toString(), "z9hG4bK-ViaBcst-" + tm, "FromBcst" + tm, null, callIdHeader); + transmitRequest(device, request); + return true; + } catch (SipException | ParseException | InvalidArgumentException e) { + e.printStackTrace(); + } + return false; + } + + @Override + public void audioBroadcastCmd(Device device, SipSubscribe.Event errorEvent) { + try { + StringBuffer broadcastXml = new StringBuffer(200); + broadcastXml.append("\r\n"); + broadcastXml.append("\r\n"); + broadcastXml.append("Broadcast\r\n"); + broadcastXml.append("" + (int) ((Math.random() * 9 + 1) * 100000) + "\r\n"); + broadcastXml.append("" + sipConfig.getSipId() + "\r\n"); + broadcastXml.append("" + device.getDeviceId() + "\r\n"); + broadcastXml.append("\r\n"); + + String tm = Long.toString(System.currentTimeMillis()); + + CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId() + : udpSipProvider.getNewCallId(); + + Request request = headerProvider.createMessageRequest(device, broadcastXml.toString(), "z9hG4bK-ViaBcst-" + tm, "FromBcst" + tm, null, callIdHeader); + transmitRequest(device, request, errorEvent); + } catch (SipException | ParseException | InvalidArgumentException e) { + e.printStackTrace(); + } + } + + + /** + * 音视频录像控制 + * + * @param device 视频设备 + * @param channelId 预览通道 + * @param recordCmdStr 录像命令:Record / StopRecord + */ + @Override + public boolean recordCmd(Device device, String channelId, String recordCmdStr, SipSubscribe.Event errorEvent) { + try { + StringBuffer cmdXml = new StringBuffer(200); + cmdXml.append("\r\n"); + cmdXml.append("\r\n"); + cmdXml.append("DeviceControl\r\n"); + cmdXml.append("" + (int) ((Math.random() * 9 + 1) * 100000) + "\r\n"); + if (XmlUtil.isEmpty(channelId)) { + cmdXml.append("" + device.getDeviceId() + "\r\n"); + } else { + cmdXml.append("" + channelId + "\r\n"); + } + cmdXml.append("" + recordCmdStr + "\r\n"); + cmdXml.append("\r\n"); + + String tm = Long.toString(System.currentTimeMillis()); + + CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId() + : udpSipProvider.getNewCallId(); + + Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, "FromRecord" + tm, null, callIdHeader); + transmitRequest(device, request, errorEvent); + return true; + } catch (SipException | ParseException | InvalidArgumentException e) { + e.printStackTrace(); + return false; + } + } + + /** + * 远程启动控制命令 + * + * @param device 视频设备 + */ + @Override + public boolean teleBootCmd(Device device) { + try { + StringBuffer cmdXml = new StringBuffer(200); + cmdXml.append("\r\n"); + cmdXml.append("\r\n"); + cmdXml.append("DeviceControl\r\n"); + cmdXml.append("" + (int) ((Math.random() * 9 + 1) * 100000) + "\r\n"); + cmdXml.append("" + device.getDeviceId() + "\r\n"); + cmdXml.append("Boot\r\n"); + cmdXml.append("\r\n"); + + String tm = Long.toString(System.currentTimeMillis()); + + CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId() + : udpSipProvider.getNewCallId(); + + Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, "FromBoot" + tm, null, callIdHeader); + transmitRequest(device, request); + return true; + } catch (SipException | ParseException | InvalidArgumentException e) { + e.printStackTrace(); + return false; + } + } + + /** + * 报警布防/撤防命令 + * + * @param device 视频设备 + * @param guardCmdStr "SetGuard"/"ResetGuard" + */ + @Override + public boolean guardCmd(Device device, String guardCmdStr, SipSubscribe.Event errorEvent) { + try { + StringBuffer cmdXml = new StringBuffer(200); + cmdXml.append("\r\n"); + cmdXml.append("\r\n"); + cmdXml.append("DeviceControl\r\n"); + cmdXml.append("" + (int) ((Math.random() * 9 + 1) * 100000) + "\r\n"); + cmdXml.append("" + device.getDeviceId() + "\r\n"); + cmdXml.append("" + guardCmdStr + "\r\n"); + cmdXml.append("\r\n"); + + String tm = Long.toString(System.currentTimeMillis()); + + CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId() + : udpSipProvider.getNewCallId(); + + Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, "FromGuard" + tm, null, callIdHeader); + transmitRequest(device, request, errorEvent); + return true; + } catch (SipException | ParseException | InvalidArgumentException e) { + e.printStackTrace(); + return false; + } + } + + /** + * 报警复位命令 + * + * @param device 视频设备 + */ + @Override + public boolean alarmCmd(Device device, String alarmMethod, String alarmType, SipSubscribe.Event errorEvent) { + try { + StringBuffer cmdXml = new StringBuffer(200); + cmdXml.append("\r\n"); + cmdXml.append("\r\n"); + cmdXml.append("DeviceControl\r\n"); + cmdXml.append("" + (int) ((Math.random() * 9 + 1) * 100000) + "\r\n"); + cmdXml.append("" + device.getDeviceId() + "\r\n"); + cmdXml.append("ResetAlarm\r\n"); + if (!XmlUtil.isEmpty(alarmMethod) || !XmlUtil.isEmpty(alarmType)) { + cmdXml.append("\r\n"); + } + if (!XmlUtil.isEmpty(alarmMethod)) { + cmdXml.append("" + alarmMethod + "\r\n"); + } + if (!XmlUtil.isEmpty(alarmType)) { + cmdXml.append("" + alarmType + "\r\n"); + } + if (!XmlUtil.isEmpty(alarmMethod) || !XmlUtil.isEmpty(alarmType)) { + cmdXml.append("\r\n"); + } + cmdXml.append("\r\n"); + + String tm = Long.toString(System.currentTimeMillis()); + + CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId() + : udpSipProvider.getNewCallId(); + + Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, "FromAlarm" + tm, null, callIdHeader); + transmitRequest(device, request, errorEvent); + return true; + } catch (SipException | ParseException | InvalidArgumentException e) { + e.printStackTrace(); + return false; + } + } + + /** + * 强制关键帧命令,设备收到此命令应立刻发送一个IDR帧 + * + * @param device 视频设备 + * @param channelId 预览通道 + */ + @Override + public boolean iFrameCmd(Device device, String channelId) { + try { + StringBuffer cmdXml = new StringBuffer(200); + cmdXml.append("\r\n"); + cmdXml.append("\r\n"); + cmdXml.append("DeviceControl\r\n"); + cmdXml.append("" + (int) ((Math.random() * 9 + 1) * 100000) + "\r\n"); + if (XmlUtil.isEmpty(channelId)) { + cmdXml.append("" + device.getDeviceId() + "\r\n"); + } else { + cmdXml.append("" + channelId + "\r\n"); + } + cmdXml.append("Send\r\n"); + cmdXml.append("\r\n"); + + String tm = Long.toString(System.currentTimeMillis()); + + CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId() + : udpSipProvider.getNewCallId(); + + Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, "FromBoot" + tm, null, callIdHeader); + transmitRequest(device, request); + return true; + } catch (SipException | ParseException | InvalidArgumentException e) { + e.printStackTrace(); + return false; + } + } + + /** + * 看守位控制命令 + * + * @param device 视频设备 + * @param enabled 看守位使能:1 = 开启,0 = 关闭 + * @param resetTime 自动归位时间间隔,开启看守位时使用,单位:秒(s) + * @param presetIndex 调用预置位编号,开启看守位时使用,取值范围0~255 + */ + @Override + public boolean homePositionCmd(Device device, String channelId, String enabled, String resetTime, String presetIndex, SipSubscribe.Event errorEvent) { + try { + StringBuffer cmdXml = new StringBuffer(200); + cmdXml.append("\r\n"); + cmdXml.append("\r\n"); + cmdXml.append("DeviceControl\r\n"); + cmdXml.append("" + (int) ((Math.random() * 9 + 1) * 100000) + "\r\n"); + if (XmlUtil.isEmpty(channelId)) { + cmdXml.append("" + device.getDeviceId() + "\r\n"); + } else { + cmdXml.append("" + channelId + "\r\n"); + } + cmdXml.append("\r\n"); + if (NumericUtil.isInteger(enabled) && (!enabled.equals("0"))) { + cmdXml.append("1\r\n"); + if (NumericUtil.isInteger(resetTime)) { + cmdXml.append("" + resetTime + "\r\n"); + } else { + cmdXml.append("0\r\n"); + } + if (NumericUtil.isInteger(presetIndex)) { + cmdXml.append("" + presetIndex + "\r\n"); + } else { + cmdXml.append("0\r\n"); + } + } else { + cmdXml.append("0\r\n"); + } + cmdXml.append("\r\n"); + cmdXml.append("\r\n"); + + String tm = Long.toString(System.currentTimeMillis()); + + CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId() + : udpSipProvider.getNewCallId(); + + Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, "FromGuard" + tm, null, callIdHeader); + transmitRequest(device, request, errorEvent); + return true; + } catch (SipException | ParseException | InvalidArgumentException e) { + e.printStackTrace(); + return false; + } + } /** * 设备配置命令 @@ -904,88 +903,88 @@ public class SIPCommander implements ISIPCommander { return false; } - /** - * 设备配置命令:basicParam - * - * @param device 视频设备 - * @param channelId 通道编码(可选) - * @param name 设备/通道名称(可选) - * @param expiration 注册过期时间(可选) - * @param heartBeatInterval 心跳间隔时间(可选) - * @param heartBeatCount 心跳超时次数(可选) - */ - @Override - public boolean deviceBasicConfigCmd(Device device, String channelId, String name, String expiration, - String heartBeatInterval, String heartBeatCount, SipSubscribe.Event errorEvent) { - try { - StringBuffer cmdXml = new StringBuffer(200); - cmdXml.append("\r\n"); - cmdXml.append("\r\n"); - cmdXml.append("DeviceConfig\r\n"); - cmdXml.append("" + (int)((Math.random()*9+1)*100000) + "\r\n"); - if (XmlUtil.isEmpty(channelId)) { - cmdXml.append("" + device.getDeviceId() + "\r\n"); - } else { - cmdXml.append("" + channelId + "\r\n"); - } - cmdXml.append("\r\n"); - if (!XmlUtil.isEmpty(name)) { - cmdXml.append("" + name + "\r\n"); - } - if (NumericUtil.isInteger(expiration)) { - if (Integer.valueOf(expiration) > 0) { - cmdXml.append("" + expiration + "\r\n"); - } - } - if (NumericUtil.isInteger(heartBeatInterval)) { - if (Integer.valueOf(heartBeatInterval) > 0) { - cmdXml.append("" + heartBeatInterval + "\r\n"); - } - } - if (NumericUtil.isInteger(heartBeatCount)) { - if (Integer.valueOf(heartBeatCount) > 0) { - cmdXml.append("" + heartBeatCount + "\r\n"); - } - } - cmdXml.append("\r\n"); - cmdXml.append("\r\n"); - - String tm = Long.toString(System.currentTimeMillis()); - - CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId() - : udpSipProvider.getNewCallId(); - - Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, "FromConfig" + tm, null, callIdHeader); - transmitRequest(device, request, errorEvent); - return true; - } catch (SipException | ParseException | InvalidArgumentException e) { - e.printStackTrace(); - return false; - } - } - - /** - * 查询设备状态 - * - * @param device 视频设备 - */ - @Override - public boolean deviceStatusQuery(Device device, SipSubscribe.Event errorEvent) { - try { - StringBuffer catalogXml = new StringBuffer(200); - catalogXml.append("\r\n"); - catalogXml.append("\r\n"); - catalogXml.append("DeviceStatus\r\n"); - catalogXml.append("" + (int)((Math.random()*9+1)*100000) + "\r\n"); - catalogXml.append("" + device.getDeviceId() + "\r\n"); - catalogXml.append("\r\n"); - - String tm = Long.toString(System.currentTimeMillis()); - - CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId() - : udpSipProvider.getNewCallId(); - - Request request = headerProvider.createMessageRequest(device, catalogXml.toString(), null, "FromStatus" + tm, null, callIdHeader); + /** + * 设备配置命令:basicParam + * + * @param device 视频设备 + * @param channelId 通道编码(可选) + * @param name 设备/通道名称(可选) + * @param expiration 注册过期时间(可选) + * @param heartBeatInterval 心跳间隔时间(可选) + * @param heartBeatCount 心跳超时次数(可选) + */ + @Override + public boolean deviceBasicConfigCmd(Device device, String channelId, String name, String expiration, + String heartBeatInterval, String heartBeatCount, SipSubscribe.Event errorEvent) { + try { + StringBuffer cmdXml = new StringBuffer(200); + cmdXml.append("\r\n"); + cmdXml.append("\r\n"); + cmdXml.append("DeviceConfig\r\n"); + cmdXml.append("" + (int) ((Math.random() * 9 + 1) * 100000) + "\r\n"); + if (XmlUtil.isEmpty(channelId)) { + cmdXml.append("" + device.getDeviceId() + "\r\n"); + } else { + cmdXml.append("" + channelId + "\r\n"); + } + cmdXml.append("\r\n"); + if (!XmlUtil.isEmpty(name)) { + cmdXml.append("" + name + "\r\n"); + } + if (NumericUtil.isInteger(expiration)) { + if (Integer.valueOf(expiration) > 0) { + cmdXml.append("" + expiration + "\r\n"); + } + } + if (NumericUtil.isInteger(heartBeatInterval)) { + if (Integer.valueOf(heartBeatInterval) > 0) { + cmdXml.append("" + heartBeatInterval + "\r\n"); + } + } + if (NumericUtil.isInteger(heartBeatCount)) { + if (Integer.valueOf(heartBeatCount) > 0) { + cmdXml.append("" + heartBeatCount + "\r\n"); + } + } + cmdXml.append("\r\n"); + cmdXml.append("\r\n"); + + String tm = Long.toString(System.currentTimeMillis()); + + CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId() + : udpSipProvider.getNewCallId(); + + Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, "FromConfig" + tm, null, callIdHeader); + transmitRequest(device, request, errorEvent); + return true; + } catch (SipException | ParseException | InvalidArgumentException e) { + e.printStackTrace(); + return false; + } + } + + /** + * 查询设备状态 + * + * @param device 视频设备 + */ + @Override + public boolean deviceStatusQuery(Device device, SipSubscribe.Event errorEvent) { + try { + StringBuffer catalogXml = new StringBuffer(200); + catalogXml.append("\r\n"); + catalogXml.append("\r\n"); + catalogXml.append("DeviceStatus\r\n"); + catalogXml.append("" + (int) ((Math.random() * 9 + 1) * 100000) + "\r\n"); + catalogXml.append("" + device.getDeviceId() + "\r\n"); + catalogXml.append("\r\n"); + + String tm = Long.toString(System.currentTimeMillis()); + + CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId() + : udpSipProvider.getNewCallId(); + + Request request = headerProvider.createMessageRequest(device, catalogXml.toString(), null, "FromStatus" + tm, null, callIdHeader); transmitRequest(device, request, errorEvent); return true; @@ -996,28 +995,28 @@ public class SIPCommander implements ISIPCommander { } } - /** - * 查询设备信息 - * - * @param device 视频设备 - */ - @Override - public boolean deviceInfoQuery(Device device) { - try { - StringBuffer catalogXml = new StringBuffer(200); - catalogXml.append("\r\n"); - catalogXml.append("\r\n"); - catalogXml.append("DeviceInfo\r\n"); - catalogXml.append("" + (int)((Math.random()*9+1)*100000) + "\r\n"); - catalogXml.append("" + device.getDeviceId() + "\r\n"); - catalogXml.append("\r\n"); - - String tm = Long.toString(System.currentTimeMillis()); - - CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId() - : udpSipProvider.getNewCallId(); - - Request request = headerProvider.createMessageRequest(device, catalogXml.toString(), "z9hG4bK-ViaDeviceInfo-" + tm, "FromDev" + tm, null, callIdHeader); + /** + * 查询设备信息 + * + * @param device 视频设备 + */ + @Override + public boolean deviceInfoQuery(Device device) { + try { + StringBuffer catalogXml = new StringBuffer(200); + catalogXml.append("\r\n"); + catalogXml.append("\r\n"); + catalogXml.append("DeviceInfo\r\n"); + catalogXml.append("" + (int) ((Math.random() * 9 + 1) * 100000) + "\r\n"); + catalogXml.append("" + device.getDeviceId() + "\r\n"); + catalogXml.append("\r\n"); + + String tm = Long.toString(System.currentTimeMillis()); + + CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId() + : udpSipProvider.getNewCallId(); + + Request request = headerProvider.createMessageRequest(device, catalogXml.toString(), "z9hG4bK-ViaDeviceInfo-" + tm, "FromDev" + tm, null, callIdHeader); transmitRequest(device, request); @@ -1028,30 +1027,30 @@ public class SIPCommander implements ISIPCommander { return true; } - /** - * 查询目录列表 - * - * @param device 视频设备 - */ - @Override - public boolean catalogQuery(Device device, SipSubscribe.Event errorEvent) { - // 清空通道 - storager.cleanChannelsForDevice(device.getDeviceId()); - try { - StringBuffer catalogXml = new StringBuffer(200); - catalogXml.append("\r\n"); - catalogXml.append("\r\n"); - catalogXml.append("Catalog\r\n"); - catalogXml.append("" + (int)((Math.random()*9+1)*100000) + "\r\n"); - catalogXml.append("" + device.getDeviceId() + "\r\n"); - catalogXml.append("\r\n"); - - String tm = Long.toString(System.currentTimeMillis()); - - CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId() - : udpSipProvider.getNewCallId(); - - Request request = headerProvider.createMessageRequest(device, catalogXml.toString(), "z9hG4bK-ViaCatalog-" + tm, "FromCat" + tm, null, callIdHeader); + /** + * 查询目录列表 + * + * @param device 视频设备 + */ + @Override + public boolean catalogQuery(Device device, SipSubscribe.Event errorEvent) { + // 清空通道 + storager.cleanChannelsForDevice(device.getDeviceId()); + try { + StringBuffer catalogXml = new StringBuffer(200); + catalogXml.append("\r\n"); + catalogXml.append("\r\n"); + catalogXml.append("Catalog\r\n"); + catalogXml.append("" + (int) ((Math.random() * 9 + 1) * 100000) + "\r\n"); + catalogXml.append("" + device.getDeviceId() + "\r\n"); + catalogXml.append("\r\n"); + + String tm = Long.toString(System.currentTimeMillis()); + + CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId() + : udpSipProvider.getNewCallId(); + + Request request = headerProvider.createMessageRequest(device, catalogXml.toString(), "z9hG4bK-ViaCatalog-" + tm, "FromCat" + tm, null, callIdHeader); transmitRequest(device, request, errorEvent); } catch (SipException | ParseException | InvalidArgumentException e) { @@ -1061,37 +1060,37 @@ public class SIPCommander implements ISIPCommander { return true; } - /** - * 查询录像信息 - * - * @param device 视频设备 - * @param startTime 开始时间,格式要求:yyyy-MM-dd HH:mm:ss - * @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss - */ - @Override - public boolean recordInfoQuery(Device device, String channelId, String startTime, String endTime) { - - try { - StringBuffer recordInfoXml = new StringBuffer(200); - recordInfoXml.append("\r\n"); - recordInfoXml.append("\r\n"); - recordInfoXml.append("RecordInfo\r\n"); - recordInfoXml.append("" + (int)((Math.random()*9+1)*100000) + "\r\n"); - recordInfoXml.append("" + channelId + "\r\n"); - recordInfoXml.append("" + DateUtil.yyyy_MM_dd_HH_mm_ssToISO8601(startTime) + "\r\n"); - recordInfoXml.append("" + DateUtil.yyyy_MM_dd_HH_mm_ssToISO8601(endTime) + "\r\n"); - recordInfoXml.append("0\r\n"); - // 大华NVR要求必须增加一个值为all的文本元素节点Type - recordInfoXml.append("all\r\n"); - recordInfoXml.append("\r\n"); - - String tm = Long.toString(System.currentTimeMillis()); - - CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId() - : udpSipProvider.getNewCallId(); - - Request request = headerProvider.createMessageRequest(device, recordInfoXml.toString(), - "z9hG4bK-ViaRecordInfo-" + tm, "fromRec" + tm, null, callIdHeader); + /** + * 查询录像信息 + * + * @param device 视频设备 + * @param startTime 开始时间,格式要求:yyyy-MM-dd HH:mm:ss + * @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss + */ + @Override + public boolean recordInfoQuery(Device device, String channelId, String startTime, String endTime) { + + try { + StringBuffer recordInfoXml = new StringBuffer(200); + recordInfoXml.append("\r\n"); + recordInfoXml.append("\r\n"); + recordInfoXml.append("RecordInfo\r\n"); + recordInfoXml.append("" + (int) ((Math.random() * 9 + 1) * 100000) + "\r\n"); + recordInfoXml.append("" + channelId + "\r\n"); + recordInfoXml.append("" + DateUtil.yyyy_MM_dd_HH_mm_ssToISO8601(startTime) + "\r\n"); + recordInfoXml.append("" + DateUtil.yyyy_MM_dd_HH_mm_ssToISO8601(endTime) + "\r\n"); + recordInfoXml.append("0\r\n"); + // 大华NVR要求必须增加一个值为all的文本元素节点Type + recordInfoXml.append("all\r\n"); + recordInfoXml.append("\r\n"); + + String tm = Long.toString(System.currentTimeMillis()); + + CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId() + : udpSipProvider.getNewCallId(); + + Request request = headerProvider.createMessageRequest(device, recordInfoXml.toString(), + "z9hG4bK-ViaRecordInfo-" + tm, "fromRec" + tm, null, callIdHeader); transmitRequest(device, request); } catch (SipException | ParseException | InvalidArgumentException e) { @@ -1101,156 +1100,156 @@ public class SIPCommander implements ISIPCommander { return true; } - /** - * 查询报警信息 - * - * @param device 视频设备 - * @param startPriority 报警起始级别(可选) - * @param endPriority 报警终止级别(可选) - * @param alarmMethods 报警方式条件(可选) - * @param alarmType 报警类型 - * @param startTime 报警发生起始时间(可选) - * @param endTime 报警发生终止时间(可选) - * @return true = 命令发送成功 - */ - @Override - public boolean alarmInfoQuery(Device device, String startPriority, String endPriority, String alarmMethod, String alarmType, - String startTime, String endTime, SipSubscribe.Event errorEvent) { - try { - StringBuffer cmdXml = new StringBuffer(200); - cmdXml.append("\r\n"); - cmdXml.append("\r\n"); - cmdXml.append("Alarm\r\n"); - cmdXml.append("" + (int)((Math.random()*9+1)*100000) + "\r\n"); - cmdXml.append("" + device.getDeviceId() + "\r\n"); - if (!XmlUtil.isEmpty(startPriority)) { - cmdXml.append("" + startPriority + "\r\n"); - } - if (!XmlUtil.isEmpty(endPriority)) { - cmdXml.append("" + endPriority + "\r\n"); - } - if (!XmlUtil.isEmpty(alarmMethod)) { - cmdXml.append("" + alarmMethod + "\r\n"); - } - if (!XmlUtil.isEmpty(alarmType)) { - cmdXml.append("" + alarmType + "\r\n"); - } - if (!XmlUtil.isEmpty(startTime)) { - cmdXml.append("" + startTime + "\r\n"); - } - if (!XmlUtil.isEmpty(endTime)) { - cmdXml.append("" + endTime + "\r\n"); - } - cmdXml.append("\r\n"); - - String tm = Long.toString(System.currentTimeMillis()); - - CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId() - : udpSipProvider.getNewCallId(); - - Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, "FromAlarm" + tm, null, callIdHeader); - transmitRequest(device, request, errorEvent); - return true; - } catch (SipException | ParseException | InvalidArgumentException e) { - e.printStackTrace(); - return false; - } - } - - /** - * 查询设备配置 - * - * @param device 视频设备 - * @param channelId 通道编码(可选) - * @param configType 配置类型: - */ - @Override - public boolean deviceConfigQuery(Device device, String channelId, String configType, SipSubscribe.Event errorEvent) { - try { - StringBuffer cmdXml = new StringBuffer(200); - cmdXml.append("\r\n"); - cmdXml.append("\r\n"); - cmdXml.append("ConfigDownload\r\n"); - cmdXml.append("" + (int)((Math.random()*9+1)*100000) + "\r\n"); - if (XmlUtil.isEmpty(channelId)) { - cmdXml.append("" + device.getDeviceId() + "\r\n"); - } else { - cmdXml.append("" + channelId + "\r\n"); - } - cmdXml.append("" + configType + "\r\n"); - cmdXml.append("\r\n"); - - String tm = Long.toString(System.currentTimeMillis()); - - CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId() - : udpSipProvider.getNewCallId(); - - Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, "FromConfig" + tm, null, callIdHeader); - transmitRequest(device, request, errorEvent); - return true; - } catch (SipException | ParseException | InvalidArgumentException e) { - e.printStackTrace(); - return false; - } - } - - /** - * 查询设备预置位置 - * - * @param device 视频设备 - */ - @Override - public boolean presetQuery(Device device, String channelId, SipSubscribe.Event errorEvent) { - try { - StringBuffer cmdXml = new StringBuffer(200); - cmdXml.append("\r\n"); - cmdXml.append("\r\n"); - cmdXml.append("PresetQuery\r\n"); - cmdXml.append("" + (int)((Math.random()*9+1)*100000) + "\r\n"); - if (XmlUtil.isEmpty(channelId)) { - cmdXml.append("" + device.getDeviceId() + "\r\n"); - } else { - cmdXml.append("" + channelId + "\r\n"); - } - cmdXml.append("\r\n"); - - String tm = Long.toString(System.currentTimeMillis()); - - CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId() - : udpSipProvider.getNewCallId(); - - Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, "FromConfig" + tm, null, callIdHeader); - transmitRequest(device, request, errorEvent); - return true; - } catch (SipException | ParseException | InvalidArgumentException e) { - e.printStackTrace(); - return false; - } - } - - /** - * 查询移动设备位置数据 - * - * @param device 视频设备 - */ - @Override - public boolean mobilePostitionQuery(Device device, SipSubscribe.Event errorEvent) { - try { - StringBuffer mobilePostitionXml = new StringBuffer(200); - mobilePostitionXml.append("\r\n"); - mobilePostitionXml.append("\r\n"); - mobilePostitionXml.append("MobilePosition\r\n"); - mobilePostitionXml.append("" + (int)((Math.random()*9+1)*100000) + "\r\n"); - mobilePostitionXml.append("" + device.getDeviceId() + "\r\n"); - mobilePostitionXml.append("60\r\n"); - mobilePostitionXml.append("\r\n"); - - String tm = Long.toString(System.currentTimeMillis()); - - CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId() - : udpSipProvider.getNewCallId(); - - Request request = headerProvider.createMessageRequest(device, mobilePostitionXml.toString(), "z9hG4bK-viaPos-" + tm, "fromTagPos" + tm, null, callIdHeader); + /** + * 查询报警信息 + * + * @param device 视频设备 + * @param startPriority 报警起始级别(可选) + * @param endPriority 报警终止级别(可选) + * @param alarmMethod 报警方式条件(可选) + * @param alarmType 报警类型 + * @param startTime 报警发生起始时间(可选) + * @param endTime 报警发生终止时间(可选) + * @return true = 命令发送成功 + */ + @Override + public boolean alarmInfoQuery(Device device, String startPriority, String endPriority, String alarmMethod, String alarmType, + String startTime, String endTime, SipSubscribe.Event errorEvent) { + try { + StringBuffer cmdXml = new StringBuffer(200); + cmdXml.append("\r\n"); + cmdXml.append("\r\n"); + cmdXml.append("Alarm\r\n"); + cmdXml.append("" + (int) ((Math.random() * 9 + 1) * 100000) + "\r\n"); + cmdXml.append("" + device.getDeviceId() + "\r\n"); + if (!XmlUtil.isEmpty(startPriority)) { + cmdXml.append("" + startPriority + "\r\n"); + } + if (!XmlUtil.isEmpty(endPriority)) { + cmdXml.append("" + endPriority + "\r\n"); + } + if (!XmlUtil.isEmpty(alarmMethod)) { + cmdXml.append("" + alarmMethod + "\r\n"); + } + if (!XmlUtil.isEmpty(alarmType)) { + cmdXml.append("" + alarmType + "\r\n"); + } + if (!XmlUtil.isEmpty(startTime)) { + cmdXml.append("" + startTime + "\r\n"); + } + if (!XmlUtil.isEmpty(endTime)) { + cmdXml.append("" + endTime + "\r\n"); + } + cmdXml.append("\r\n"); + + String tm = Long.toString(System.currentTimeMillis()); + + CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId() + : udpSipProvider.getNewCallId(); + + Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, "FromAlarm" + tm, null, callIdHeader); + transmitRequest(device, request, errorEvent); + return true; + } catch (SipException | ParseException | InvalidArgumentException e) { + e.printStackTrace(); + return false; + } + } + + /** + * 查询设备配置 + * + * @param device 视频设备 + * @param channelId 通道编码(可选) + * @param configType 配置类型: + */ + @Override + public boolean deviceConfigQuery(Device device, String channelId, String configType, SipSubscribe.Event errorEvent) { + try { + StringBuffer cmdXml = new StringBuffer(200); + cmdXml.append("\r\n"); + cmdXml.append("\r\n"); + cmdXml.append("ConfigDownload\r\n"); + cmdXml.append("" + (int) ((Math.random() * 9 + 1) * 100000) + "\r\n"); + if (XmlUtil.isEmpty(channelId)) { + cmdXml.append("" + device.getDeviceId() + "\r\n"); + } else { + cmdXml.append("" + channelId + "\r\n"); + } + cmdXml.append("" + configType + "\r\n"); + cmdXml.append("\r\n"); + + String tm = Long.toString(System.currentTimeMillis()); + + CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId() + : udpSipProvider.getNewCallId(); + + Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, "FromConfig" + tm, null, callIdHeader); + transmitRequest(device, request, errorEvent); + return true; + } catch (SipException | ParseException | InvalidArgumentException e) { + e.printStackTrace(); + return false; + } + } + + /** + * 查询设备预置位置 + * + * @param device 视频设备 + */ + @Override + public boolean presetQuery(Device device, String channelId, SipSubscribe.Event errorEvent) { + try { + StringBuffer cmdXml = new StringBuffer(200); + cmdXml.append("\r\n"); + cmdXml.append("\r\n"); + cmdXml.append("PresetQuery\r\n"); + cmdXml.append("" + (int) ((Math.random() * 9 + 1) * 100000) + "\r\n"); + if (XmlUtil.isEmpty(channelId)) { + cmdXml.append("" + device.getDeviceId() + "\r\n"); + } else { + cmdXml.append("" + channelId + "\r\n"); + } + cmdXml.append("\r\n"); + + String tm = Long.toString(System.currentTimeMillis()); + + CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId() + : udpSipProvider.getNewCallId(); + + Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, "FromConfig" + tm, null, callIdHeader); + transmitRequest(device, request, errorEvent); + return true; + } catch (SipException | ParseException | InvalidArgumentException e) { + e.printStackTrace(); + return false; + } + } + + /** + * 查询移动设备位置数据 + * + * @param device 视频设备 + */ + @Override + public boolean mobilePostitionQuery(Device device, SipSubscribe.Event errorEvent) { + try { + StringBuffer mobilePostitionXml = new StringBuffer(200); + mobilePostitionXml.append("\r\n"); + mobilePostitionXml.append("\r\n"); + mobilePostitionXml.append("MobilePosition\r\n"); + mobilePostitionXml.append("" + (int) ((Math.random() * 9 + 1) * 100000) + "\r\n"); + mobilePostitionXml.append("" + device.getDeviceId() + "\r\n"); + mobilePostitionXml.append("60\r\n"); + mobilePostitionXml.append("\r\n"); + + String tm = Long.toString(System.currentTimeMillis()); + + CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId() + : udpSipProvider.getNewCallId(); + + Request request = headerProvider.createMessageRequest(device, mobilePostitionXml.toString(), "z9hG4bK-viaPos-" + tm, "fromTagPos" + tm, null, callIdHeader); transmitRequest(device, request, errorEvent); @@ -1269,6 +1268,7 @@ public class SIPCommander implements ISIPCommander { * @param interval 上报时间间隔 * @return true = 命令发送成功 */ + @Override public boolean mobilePositionSubscribe(Device device, int expires, int interval) { try { StringBuffer subscribePostitionXml = new StringBuffer(200); @@ -1282,13 +1282,13 @@ public class SIPCommander implements ISIPCommander { } subscribePostitionXml.append("\r\n"); - String tm = Long.toString(System.currentTimeMillis()); + String tm = Long.toString(System.currentTimeMillis()); - CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId() - : udpSipProvider.getNewCallId(); + CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId() + : udpSipProvider.getNewCallId(); - Request request = headerProvider.createSubscribeRequest(device, subscribePostitionXml.toString(), "z9hG4bK-viaPos-" + tm, "fromTagPos" + tm, null, expires, "presence" ,callIdHeader); //Position;id=" + tm.substring(tm.length() - 4)); - transmitRequest(device, request); + Request request = headerProvider.createSubscribeRequest(device, subscribePostitionXml.toString(), "z9hG4bK-viaPos-" + tm, "fromTagPos" + tm, null, expires, "presence", callIdHeader); //Position;id=" + tm.substring(tm.length() - 4)); + transmitRequest(device, request); return true; @@ -1339,9 +1339,21 @@ public class SIPCommander implements ISIPCommander { } cmdXml.append("\r\n"); - String tm = Long.toString(System.currentTimeMillis()); - Request request = headerProvider.createSubscribeRequest(device, cmdXml.toString(), "viaTagPos" + tm, "fromTagPos" + tm, null, expires, "presence" ); - transmitRequest(device, request); + String tm = Long.toString(System.currentTimeMillis()); + + CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId() + : udpSipProvider.getNewCallId(); + + Request request = headerProvider.createSubscribeRequest( + device, + cmdXml.toString(), + "viaTagPos" + tm, + "fromTagPos" + tm, + null, + expires, + "presence", + callIdHeader); + transmitRequest(device, request); return true; diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/AckRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/AckRequestProcessor.java index 20e1c800..e4e73995 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/AckRequestProcessor.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/AckRequestProcessor.java @@ -1,113 +1,120 @@ -package com.genersoft.iot.vmp.gb28181.transmit.request.impl; - -import java.util.HashMap; -import java.util.Map; - -import javax.sip.*; -import javax.sip.address.SipURI; -import javax.sip.header.FromHeader; -import javax.sip.header.HeaderAddress; -import javax.sip.header.ToHeader; - -import com.genersoft.iot.vmp.common.StreamInfo; -import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem; -import com.genersoft.iot.vmp.gb28181.transmit.request.SIPRequestAbstractProcessor; -import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; -import com.genersoft.iot.vmp.storager.IRedisCatchStorage; - -/** - * @Description:ACK请求处理器 - * @author: swwheihei - * @date: 2020年5月3日 下午5:31:45 - */ -public class AckRequestProcessor extends SIPRequestAbstractProcessor { - - private IRedisCatchStorage redisCatchStorage; - - private ZLMRTPServerFactory zlmrtpServerFactory; - - /** - * 处理 ACK请求 - * - * @param evt - */ - @Override - public void process(RequestEvent evt) { - //Request request = evt.getRequest(); - Dialog dialog = evt.getDialog(); - if (dialog == null) return; - //DialogState state = dialog.getState(); - if (/*request.getMecodewwthod().equals(Request.INVITE) &&*/ dialog.getState()== DialogState.CONFIRMED) { - String platformGbId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(FromHeader.NAME)).getAddress().getURI()).getUser(); - String channelId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(ToHeader.NAME)).getAddress().getURI()).getUser(); - SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(platformGbId, channelId); - String is_Udp = sendRtpItem.isTcp() ? "0" : "1"; - String deviceId = sendRtpItem.getDeviceId(); - StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channelId); - sendRtpItem.setStreamId(streamInfo.getStreamId()); - redisCatchStorage.updateSendRTPSever(sendRtpItem); - System.out.println(platformGbId); - System.out.println(channelId); - Map param = new HashMap<>(); - param.put("vhost","__defaultVhost__"); - param.put("app","rtp"); - param.put("stream",streamInfo.getStreamId()); - param.put("ssrc", sendRtpItem.getSsrc()); - param.put("dst_url",sendRtpItem.getIp()); - param.put("dst_port", sendRtpItem.getPort()); - param.put("is_udp", is_Udp); - //param.put ("src_port", sendRtpItem.getLocalPort()); - // 设备推流查询,成功后才能转推 - boolean rtpPushed = false; - long startTime = System.currentTimeMillis(); - while (!rtpPushed) { - try { - if (System.currentTimeMillis() - startTime < 30 * 1000) { - if (zlmrtpServerFactory.isRtpReady(streamInfo.getStreamId())) { - rtpPushed = true; - System.out.println("已获取设备推流,开始向上级推流"); - zlmrtpServerFactory.startSendRtpStream(param); - } else { - System.out.println("等待设备推流......."); - Thread.sleep(2000); - continue; - } - } else { - rtpPushed = true; - System.out.println("设备推流超时,终止向上级推流"); - } - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - } - // try { - // Request ackRequest = null; - // CSeq csReq = (CSeq) request.getHeader(CSeq.NAME); - // ackRequest = dialog.createAck(csReq.getSeqNumber()); - // dialog.sendAck(ackRequest); - // System.out.println("send ack to callee:" + ackRequest.toString()); - // } catch (SipException e) { - // e.printStackTrace(); - // } catch (InvalidArgumentException e) { - // e.printStackTrace(); - // } - - } - - public IRedisCatchStorage getRedisCatchStorage() { - return redisCatchStorage; - } - - public void setRedisCatchStorage(IRedisCatchStorage redisCatchStorage) { - this.redisCatchStorage = redisCatchStorage; - } - - public ZLMRTPServerFactory getZlmrtpServerFactory() { - return zlmrtpServerFactory; - } - - public void setZlmrtpServerFactory(ZLMRTPServerFactory zlmrtpServerFactory) { - this.zlmrtpServerFactory = zlmrtpServerFactory; - } -} +package com.genersoft.iot.vmp.gb28181.transmit.request.impl; + +import java.util.HashMap; +import java.util.Map; + +import javax.sip.*; +import javax.sip.address.SipURI; +import javax.sip.header.FromHeader; +import javax.sip.header.HeaderAddress; +import javax.sip.header.ToHeader; + +import com.genersoft.iot.vmp.common.StreamInfo; +import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem; +import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; +import com.genersoft.iot.vmp.gb28181.transmit.request.SIPRequestAbstractProcessor; +import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; +import com.genersoft.iot.vmp.storager.IRedisCatchStorage; +import org.springframework.beans.factory.annotation.Autowired; + +/** + * @Description:ACK请求处理器 + * @author: swwheihei + * @date: 2020年5月3日 下午5:31:45 + */ +public class AckRequestProcessor extends SIPRequestAbstractProcessor { + + private IRedisCatchStorage redisCatchStorage; + + private ZLMRTPServerFactory zlmrtpServerFactory; + + @Autowired + private VideoStreamSessionManager streamSession; + + /** + * 处理 ACK请求 + * + * @param evt + */ + @Override + public void process(RequestEvent evt) { + //Request request = evt.getRequest(); + Dialog dialog = evt.getDialog(); + if (dialog == null) { + return; + } + //DialogState state = dialog.getState(); + if (/*request.getMecodewwthod().equals(Request.INVITE) &&*/ dialog.getState()== DialogState.CONFIRMED) { + String platformGbId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(FromHeader.NAME)).getAddress().getURI()).getUser(); + String channelId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(ToHeader.NAME)).getAddress().getURI()).getUser(); + SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(platformGbId, channelId); + String is_Udp = sendRtpItem.isTcp() ? "0" : "1"; + String deviceId = sendRtpItem.getDeviceId(); + StreamInfo streamInfo = redisCatchStorage.queryPlayByChannel(channelId); + sendRtpItem.setStreamId(streamInfo.getStreamId()); + redisCatchStorage.updateSendRTPSever(sendRtpItem); + System.out.println(platformGbId); + System.out.println(channelId); + Map param = new HashMap<>(); + param.put("vhost","__defaultVhost__"); + param.put("app","rtp"); + param.put("stream",streamInfo.getStreamId()); + param.put("ssrc", sendRtpItem.getSsrc()); + param.put("dst_url",sendRtpItem.getIp()); + param.put("dst_port", sendRtpItem.getPort()); + param.put("is_udp", is_Udp); + //param.put ("src_port", sendRtpItem.getLocalPort()); + // 设备推流查询,成功后才能转推 + boolean rtpPushed = false; + long startTime = System.currentTimeMillis(); + while (!rtpPushed) { + try { + if (System.currentTimeMillis() - startTime < 30 * 1000) { + if (zlmrtpServerFactory.isRtpReady(streamInfo.getStreamId())) { + rtpPushed = true; + System.out.println("已获取设备推流,开始向上级推流"); + zlmrtpServerFactory.startSendRtpStream(param); + } else { + System.out.println("等待设备推流......."); + Thread.sleep(2000); + continue; + } + } else { + rtpPushed = true; + System.out.println("设备推流超时,终止向上级推流"); + } + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + // try { + // Request ackRequest = null; + // CSeq csReq = (CSeq) request.getHeader(CSeq.NAME); + // ackRequest = dialog.createAck(csReq.getSeqNumber()); + // dialog.sendAck(ackRequest); + // System.out.println("send ack to callee:" + ackRequest.toString()); + // } catch (SipException e) { + // e.printStackTrace(); + // } catch (InvalidArgumentException e) { + // e.printStackTrace(); + // } + + } + + public IRedisCatchStorage getRedisCatchStorage() { + return redisCatchStorage; + } + + public void setRedisCatchStorage(IRedisCatchStorage redisCatchStorage) { + this.redisCatchStorage = redisCatchStorage; + } + + public ZLMRTPServerFactory getZlmrtpServerFactory() { + return zlmrtpServerFactory; + } + + public void setZlmrtpServerFactory(ZLMRTPServerFactory zlmrtpServerFactory) { + this.zlmrtpServerFactory = zlmrtpServerFactory; + } +} diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/ByeRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/ByeRequestProcessor.java index c96501d5..6c3b6269 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/ByeRequestProcessor.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/ByeRequestProcessor.java @@ -1,109 +1,116 @@ -package com.genersoft.iot.vmp.gb28181.transmit.request.impl; - -import javax.sip.address.SipURI; -import javax.sip.Dialog; -import javax.sip.DialogState; -import javax.sip.InvalidArgumentException; -import javax.sip.RequestEvent; -import javax.sip.SipException; -import javax.sip.header.FromHeader; -import javax.sip.header.HeaderAddress; -import javax.sip.header.ToHeader; -import javax.sip.message.Response; - -import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem; -import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander; -import com.genersoft.iot.vmp.gb28181.transmit.request.SIPRequestAbstractProcessor; -import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; -import com.genersoft.iot.vmp.storager.IRedisCatchStorage; - -import java.text.ParseException; -import java.util.HashMap; -import java.util.Map; - -/** - * @Description: BYE请求处理器 - * @author: lawrencehj - * @date: 2021年3月9日 - */ -public class ByeRequestProcessor extends SIPRequestAbstractProcessor { - - private ISIPCommander cmder; - - private IRedisCatchStorage redisCatchStorage; - - private ZLMRTPServerFactory zlmrtpServerFactory; - - /** - * 处理BYE请求 - * @param evt - */ - @Override - public void process(RequestEvent evt) { - try { - responseAck(evt); - Dialog dialog = evt.getDialog(); - if (dialog == null) return; - if (dialog.getState().equals(DialogState.TERMINATED)) { - String platformGbId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(FromHeader.NAME)).getAddress().getURI()).getUser(); - String channelId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(ToHeader.NAME)).getAddress().getURI()).getUser(); - SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(platformGbId, channelId); - String streamId = sendRtpItem.getStreamId(); - Map param = new HashMap<>(); - param.put("vhost","__defaultVhost__"); - param.put("app","rtp"); - param.put("stream",streamId); - System.out.println("停止向上级推流:" + streamId); - zlmrtpServerFactory.stopSendRtpStream(param); - redisCatchStorage.deleteSendRTPServer(platformGbId, channelId); - if (zlmrtpServerFactory.totalReaderCount(streamId) == 0) { - System.out.println(streamId + "无其它观看者,通知设备停止推流"); - cmder.streamByeCmd(streamId); - } - } - } catch (SipException e) { - e.printStackTrace(); - } catch (InvalidArgumentException e) { - e.printStackTrace(); - } catch (ParseException e) { - e.printStackTrace(); - } - } - - /*** - * 回复200 OK - * @param evt - * @throws SipException - * @throws InvalidArgumentException - * @throws ParseException - */ - private void responseAck(RequestEvent evt) throws SipException, InvalidArgumentException, ParseException { - Response response = getMessageFactory().createResponse(Response.OK, evt.getRequest()); - getServerTransaction(evt).sendResponse(response); - } - - public IRedisCatchStorage getRedisCatchStorage() { - return redisCatchStorage; - } - - public void setRedisCatchStorage(IRedisCatchStorage redisCatchStorage) { - this.redisCatchStorage = redisCatchStorage; - } - - public ZLMRTPServerFactory getZlmrtpServerFactory() { - return zlmrtpServerFactory; - } - - public void setZlmrtpServerFactory(ZLMRTPServerFactory zlmrtpServerFactory) { - this.zlmrtpServerFactory = zlmrtpServerFactory; - } - - public ISIPCommander getSIPCommander() { - return cmder; - } - - public void setSIPCommander(ISIPCommander cmder) { - this.cmder = cmder; - } - -} +package com.genersoft.iot.vmp.gb28181.transmit.request.impl; + +import javax.sip.address.SipURI; +import javax.sip.Dialog; +import javax.sip.DialogState; +import javax.sip.InvalidArgumentException; +import javax.sip.RequestEvent; +import javax.sip.SipException; +import javax.sip.header.FromHeader; +import javax.sip.header.HeaderAddress; +import javax.sip.header.ToHeader; +import javax.sip.message.Response; + +import com.genersoft.iot.vmp.common.StreamInfo; +import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem; +import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; +import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander; +import com.genersoft.iot.vmp.gb28181.transmit.request.SIPRequestAbstractProcessor; +import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; +import com.genersoft.iot.vmp.storager.IRedisCatchStorage; +import org.springframework.beans.factory.annotation.Autowired; + +import java.text.ParseException; +import java.util.HashMap; +import java.util.Map; + +/** + * @Description: BYE请求处理器 + * @author: lawrencehj + * @date: 2021年3月9日 + */ +public class ByeRequestProcessor extends SIPRequestAbstractProcessor { + + private ISIPCommander cmder; + + private IRedisCatchStorage redisCatchStorage; + + private ZLMRTPServerFactory zlmrtpServerFactory; + + @Autowired + private VideoStreamSessionManager streamSession; + + /** + * 处理BYE请求 + * @param evt + */ + @Override + public void process(RequestEvent evt) { + try { + responseAck(evt); + Dialog dialog = evt.getDialog(); + if (dialog == null) return; + if (dialog.getState().equals(DialogState.TERMINATED)) { + String platformGbId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(FromHeader.NAME)).getAddress().getURI()).getUser(); + String channelId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(ToHeader.NAME)).getAddress().getURI()).getUser(); + SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(platformGbId, channelId); + String streamId = sendRtpItem.getStreamId(); + Map param = new HashMap<>(); + param.put("vhost","__defaultVhost__"); + param.put("app","rtp"); + param.put("stream",streamId); + System.out.println("停止向上级推流:" + streamId); + StreamInfo streamInfo = streamSession.getStreamInfo(channelId, streamId); + zlmrtpServerFactory.stopSendRtpStream(param); + redisCatchStorage.deleteSendRTPServer(platformGbId, channelId); + if (zlmrtpServerFactory.totalReaderCount(streamId) == 0) { + System.out.println(streamId + "无其它观看者,通知设备停止推流"); + cmder.stopStreamByeCmd(streamInfo, null); + } + } + } catch (SipException e) { + e.printStackTrace(); + } catch (InvalidArgumentException e) { + e.printStackTrace(); + } catch (ParseException e) { + e.printStackTrace(); + } + } + + /*** + * 回复200 OK + * @param evt + * @throws SipException + * @throws InvalidArgumentException + * @throws ParseException + */ + private void responseAck(RequestEvent evt) throws SipException, InvalidArgumentException, ParseException { + Response response = getMessageFactory().createResponse(Response.OK, evt.getRequest()); + getServerTransaction(evt).sendResponse(response); + } + + public IRedisCatchStorage getRedisCatchStorage() { + return redisCatchStorage; + } + + public void setRedisCatchStorage(IRedisCatchStorage redisCatchStorage) { + this.redisCatchStorage = redisCatchStorage; + } + + public ZLMRTPServerFactory getZlmrtpServerFactory() { + return zlmrtpServerFactory; + } + + public void setZlmrtpServerFactory(ZLMRTPServerFactory zlmrtpServerFactory) { + this.zlmrtpServerFactory = zlmrtpServerFactory; + } + + public ISIPCommander getSIPCommander() { + return cmder; + } + + public void setSIPCommander(ISIPCommander cmder) { + this.cmder = cmder; + } + +} diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/InviteRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/InviteRequestProcessor.java index a7b3d94e..4a1e4879 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/InviteRequestProcessor.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/InviteRequestProcessor.java @@ -1,384 +1,377 @@ -package com.genersoft.iot.vmp.gb28181.transmit.request.impl; - -import javax.sdp.*; -import javax.sip.InvalidArgumentException; -import javax.sip.RequestEvent; -import javax.sip.SipException; -import javax.sip.SipFactory; -import javax.sip.address.Address; -import javax.sip.address.SipURI; -import javax.sip.header.*; -import javax.sip.message.Request; -import javax.sip.message.Response; - -import com.genersoft.iot.vmp.conf.MediaServerConfig; -import com.genersoft.iot.vmp.gb28181.bean.Device; -import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; -import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; -import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem; -import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; -import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform; -import com.genersoft.iot.vmp.gb28181.transmit.request.SIPRequestAbstractProcessor; -import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; -import com.genersoft.iot.vmp.storager.IRedisCatchStorage; -import com.genersoft.iot.vmp.storager.IVideoManagerStorager; -import com.genersoft.iot.vmp.vmanager.play.bean.PlayResult; -import com.genersoft.iot.vmp.vmanager.service.IPlayService; -import gov.nist.javax.sip.address.AddressImpl; -import gov.nist.javax.sip.address.SipUri; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.text.ParseException; -import java.util.Vector; - -/** - * @Description:处理INVITE请求 - * @author: panll - * @date: 2021年1月14日 - */ -@SuppressWarnings("rawtypes") -public class InviteRequestProcessor extends SIPRequestAbstractProcessor { - - private final static Logger logger = LoggerFactory.getLogger(MessageRequestProcessor.class); - - private SIPCommanderFroPlatform cmderFroPlatform; - - private IVideoManagerStorager storager; - - private IRedisCatchStorage redisCatchStorage; - - private SIPCommander cmder; - - private IPlayService playService; - - private ZLMRTPServerFactory zlmrtpServerFactory; - - public ZLMRTPServerFactory getZlmrtpServerFactory() { - return zlmrtpServerFactory; - } - - public void setZlmrtpServerFactory(ZLMRTPServerFactory zlmrtpServerFactory) { - this.zlmrtpServerFactory = zlmrtpServerFactory; - } - - /** - * 处理invite请求 - * - * @param evt - * 请求消息 - */ - @Override - public void process(RequestEvent evt) { - // Invite Request消息实现,此消息一般为级联消息,上级给下级发送请求视频指令 - try { - Request request = evt.getRequest(); - SipURI sipURI = (SipURI) request.getRequestURI(); - String channelId = sipURI.getUser(); - String requesterId = null; - - FromHeader fromHeader = (FromHeader)request.getHeader(FromHeader.NAME); - AddressImpl address = (AddressImpl) fromHeader.getAddress(); - SipUri uri = (SipUri) address.getURI(); - requesterId = uri.getUser(); - - if (requesterId == null || channelId == null) { - logger.info("无法从FromHeader的Address中获取到平台id,返回400"); - responseAck(evt, Response.BAD_REQUEST); // 参数不全, 发400,请求错误 - return; - } - - // 查询请求方是否上级平台 - ParentPlatform platform = storager.queryParentPlatById(requesterId); - if (platform != null) { - // 查询平台下是否有该通道 - DeviceChannel channel = storager.queryChannelInParentPlatform(requesterId, channelId); - if (channel == null) { - logger.info("通道不存在,返回404"); - responseAck(evt, Response.NOT_FOUND); // 通道不存在,发404,资源不存在 - return; - }else { - responseAck(evt, Response.CALL_IS_BEING_FORWARDED); // 通道存在,发181,呼叫转接中 - } - // 解析sdp消息, 使用jainsip 自带的sdp解析方式 - String contentString = new String(request.getRawContent()); - - // jainSip不支持y=字段, 移除移除以解析。 - int ssrcIndex = contentString.indexOf("y="); - //ssrc规定长度为10字节,不取余下长度以避免后续还有“f=”字段 - String ssrc = contentString.substring(ssrcIndex + 2, ssrcIndex + 12); - String substring = contentString.substring(0, contentString.indexOf("y=")); - SessionDescription sdp = SdpFactory.getInstance().createSessionDescription(substring); - - // 获取支持的格式 - Vector mediaDescriptions = sdp.getMediaDescriptions(true); - // 查看是否支持PS 负载96 - //String ip = null; - int port = -1; - //boolean recvonly = false; - boolean mediaTransmissionTCP = false; - Boolean tcpActive = null; - for (int i = 0; i < mediaDescriptions.size(); i++) { - MediaDescription mediaDescription = (MediaDescription)mediaDescriptions.get(i); - Media media = mediaDescription.getMedia(); - - Vector mediaFormats = media.getMediaFormats(false); - if (mediaFormats.contains("96")) { - port = media.getMediaPort(); - //String mediaType = media.getMediaType(); - String protocol = media.getProtocol(); - - // 区分TCP发流还是udp, 当前默认udp - if ("TCP/RTP/AVP".equals(protocol)) { - String setup = mediaDescription.getAttribute("setup"); - if (setup != null) { - mediaTransmissionTCP = true; - if ("active".equals(setup)) { - tcpActive = true; - }else if ("passive".equals(setup)) { - tcpActive = false; - } - } - } - break; - } - } - if (port == -1) { - logger.info("不支持的媒体格式,返回415"); - // 回复不支持的格式 - responseAck(evt, Response.UNSUPPORTED_MEDIA_TYPE); // 不支持的格式,发415 - return; - } - String username = sdp.getOrigin().getUsername(); - String addressStr = sdp.getOrigin().getAddress(); - //String sessionName = sdp.getSessionName().getValue(); - logger.info("[上级点播]用户:{}, 地址:{}:{}, ssrc:{}", username, addressStr, port, ssrc); - - Device device = storager.queryVideoDeviceByPlatformIdAndChannelId(requesterId, channelId); - if (device == null) { - logger.warn("点播平台{}的通道{}时未找到设备信息", requesterId, channel); - responseAck(evt, Response.SERVER_INTERNAL_ERROR); - return; - } - SendRtpItem sendRtpItem = zlmrtpServerFactory.createSendRtpItem(addressStr, port, ssrc, requesterId, device.getDeviceId(), channelId, - mediaTransmissionTCP); - if (tcpActive != null) { - sendRtpItem.setTcpActive(tcpActive); - } - if (sendRtpItem == null) { - logger.warn("服务器端口资源不足"); - responseAck(evt, Response.BUSY_HERE); - return; - } - - // 写入redis, 超时时回复 - redisCatchStorage.updateSendRTPSever(sendRtpItem); - // 通知下级推流, - PlayResult playResult = playService.play(device.getDeviceId(), channelId, (responseJSON)->{ - // 收到推流, 回复200OK, 等待ack - sendRtpItem.setStatus(1); - redisCatchStorage.updateSendRTPSever(sendRtpItem); - // TODO 添加对tcp的支持 - MediaServerConfig mediaInfo = redisCatchStorage.getMediaInfo(); - StringBuffer content = new StringBuffer(200); - content.append("v=0\r\n"); - content.append("o="+"00000"+" 0 0 IN IP4 "+mediaInfo.getWanIp()+"\r\n"); - content.append("s=Play\r\n"); - content.append("c=IN IP4 "+mediaInfo.getWanIp()+"\r\n"); - content.append("t=0 0\r\n"); - content.append("m=video "+ sendRtpItem.getLocalPort()+" RTP/AVP 96\r\n"); - content.append("a=sendonly\r\n"); - content.append("a=rtpmap:96 PS/90000\r\n"); - content.append("y="+ ssrc + "\r\n"); - content.append("f=\r\n"); - - try { - responseAck(evt, content.toString()); - } catch (SipException e) { - e.printStackTrace(); - } catch (InvalidArgumentException e) { - e.printStackTrace(); - } catch (ParseException e) { - e.printStackTrace(); - } - },(event -> { - // 未知错误。直接转发设备点播的错误 - Response response = null; - try { - response = getMessageFactory().createResponse(event.getResponse().getStatusCode(), evt.getRequest()); - getServerTransaction(evt).sendResponse(response); - } catch (ParseException | SipException | InvalidArgumentException e) { - e.printStackTrace(); - } - })); - if (logger.isDebugEnabled()) { - logger.debug(playResult.getResult().toString()); - } - } else { - // 非上级平台请求,查询是否设备请求(通常为接收语音广播的设备) - Device device = storager.queryVideoDevice(requesterId); - if (device != null) { - logger.info("收到设备" + requesterId + "的语音广播Invite请求"); - responseAck(evt, Response.TRYING); - - String contentString = new String(request.getRawContent()); - // jainSip不支持y=字段, 移除移除以解析。 - String substring = contentString; - String ssrc = "0000000404"; - int ssrcIndex = contentString.indexOf("y="); - if (ssrcIndex > 0) { - substring = contentString.substring(0, ssrcIndex); - ssrc = contentString.substring(ssrcIndex + 2, ssrcIndex + 12); - } - ssrcIndex = substring.indexOf("f="); - if (ssrcIndex > 0) { - substring = contentString.substring(0, ssrcIndex); - } - SessionDescription sdp = SdpFactory.getInstance().createSessionDescription(substring); - - // 获取支持的格式 - Vector mediaDescriptions = sdp.getMediaDescriptions(true); - // 查看是否支持PS 负载96 - int port = -1; - //boolean recvonly = false; - boolean mediaTransmissionTCP = false; - Boolean tcpActive = null; - for (int i = 0; i < mediaDescriptions.size(); i++) { - MediaDescription mediaDescription = (MediaDescription)mediaDescriptions.get(i); - Media media = mediaDescription.getMedia(); - - Vector mediaFormats = media.getMediaFormats(false); - if (mediaFormats.contains("8")) { - port = media.getMediaPort(); - String protocol = media.getProtocol(); - // 区分TCP发流还是udp, 当前默认udp - if ("TCP/RTP/AVP".equals(protocol)) { - String setup = mediaDescription.getAttribute("setup"); - if (setup != null) { - mediaTransmissionTCP = true; - if ("active".equals(setup)) { - tcpActive = true; - } else if ("passive".equals(setup)) { - tcpActive = false; - } - } - } - break; - } - } - if (port == -1) { - logger.info("不支持的媒体格式,返回415"); - // 回复不支持的格式 - responseAck(evt, Response.UNSUPPORTED_MEDIA_TYPE); // 不支持的格式,发415 - return; - } - String username = sdp.getOrigin().getUsername(); - String addressStr = sdp.getOrigin().getAddress(); - logger.info("设备{}请求语音流,地址:{}:{},ssrc:{}", username, addressStr, port, ssrc); - - - - - - - } else { - logger.warn("来自无效设备/平台的请求"); - responseAck(evt, Response.BAD_REQUEST); - } - } - - } catch (SipException | InvalidArgumentException | ParseException e) { - e.printStackTrace(); - logger.warn("sdp解析错误"); - e.printStackTrace(); - } catch (SdpParseException e) { - e.printStackTrace(); - } catch (SdpException e) { - e.printStackTrace(); - } - } - - /*** - * 回复状态码 - * 100 trying - * 200 OK - * 400 - * 404 - * @param evt - * @throws SipException - * @throws InvalidArgumentException - * @throws ParseException - */ - private void responseAck(RequestEvent evt, int statusCode) throws SipException, InvalidArgumentException, ParseException { - Response response = getMessageFactory().createResponse(statusCode, evt.getRequest()); - getServerTransaction(evt).sendResponse(response); - } - - /** - * 回复带sdp的200 - * @param evt - * @param sdp - * @throws SipException - * @throws InvalidArgumentException - * @throws ParseException - */ - private void responseAck(RequestEvent evt, String sdp) throws SipException, InvalidArgumentException, ParseException { - Response response = getMessageFactory().createResponse(Response.OK, evt.getRequest()); - SipFactory sipFactory = SipFactory.getInstance(); - ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("APPLICATION", "SDP"); - response.setContent(sdp, contentTypeHeader); - - SipURI sipURI = (SipURI)evt.getRequest().getRequestURI(); - - Address concatAddress = sipFactory.createAddressFactory().createAddress( - sipFactory.createAddressFactory().createSipURI(sipURI.getUser(), sipURI.getHost()+":"+sipURI.getPort() - )); - response.addHeader(sipFactory.createHeaderFactory().createContactHeader(concatAddress)); - getServerTransaction(evt).sendResponse(response); - } - - - - - - - public SIPCommanderFroPlatform getCmderFroPlatform() { - return cmderFroPlatform; - } - - public void setCmderFroPlatform(SIPCommanderFroPlatform cmderFroPlatform) { - this.cmderFroPlatform = cmderFroPlatform; - } - - public IVideoManagerStorager getStorager() { - return storager; - } - - public void setStorager(IVideoManagerStorager storager) { - this.storager = storager; - } - - public SIPCommander getCmder() { - return cmder; - } - - public void setCmder(SIPCommander cmder) { - this.cmder = cmder; - } - - public IPlayService getPlayService() { - return playService; - } - - public void setPlayService(IPlayService playService) { - this.playService = playService; - } - - public IRedisCatchStorage getRedisCatchStorage() { - return redisCatchStorage; - } - - public void setRedisCatchStorage(IRedisCatchStorage redisCatchStorage) { - this.redisCatchStorage = redisCatchStorage; - } -} +package com.genersoft.iot.vmp.gb28181.transmit.request.impl; + +import com.genersoft.iot.vmp.conf.MediaServerConfig; +import com.genersoft.iot.vmp.gb28181.bean.Device; +import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; +import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; +import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem; +import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; +import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform; +import com.genersoft.iot.vmp.gb28181.transmit.request.SIPRequestAbstractProcessor; +import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; +import com.genersoft.iot.vmp.storager.IRedisCatchStorage; +import com.genersoft.iot.vmp.storager.IVideoManagerStorager; +import com.genersoft.iot.vmp.vmanager.service.IPlayService; +import gov.nist.javax.sip.address.AddressImpl; +import gov.nist.javax.sip.address.SipUri; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.ResponseEntity; +import org.springframework.web.context.request.async.DeferredResult; + +import javax.sdp.*; +import javax.sip.InvalidArgumentException; +import javax.sip.RequestEvent; +import javax.sip.SipException; +import javax.sip.SipFactory; +import javax.sip.address.Address; +import javax.sip.address.SipURI; +import javax.sip.header.ContentTypeHeader; +import javax.sip.header.FromHeader; +import javax.sip.message.Request; +import javax.sip.message.Response; +import java.text.ParseException; +import java.util.Vector; + +/** + * @Description:处理INVITE请求 + * @author: panll + * @date: 2021年1月14日 + */ +@SuppressWarnings("rawtypes") +public class InviteRequestProcessor extends SIPRequestAbstractProcessor { + + private final static Logger logger = LoggerFactory.getLogger(MessageRequestProcessor.class); + + private SIPCommanderFroPlatform cmderFroPlatform; + + private IVideoManagerStorager storager; + + private IRedisCatchStorage redisCatchStorage; + + private SIPCommander cmder; + + private IPlayService playService; + + private ZLMRTPServerFactory zlmrtpServerFactory; + + public ZLMRTPServerFactory getZlmrtpServerFactory() { + return zlmrtpServerFactory; + } + + public void setZlmrtpServerFactory(ZLMRTPServerFactory zlmrtpServerFactory) { + this.zlmrtpServerFactory = zlmrtpServerFactory; + } + + /** + * 处理invite请求 + * + * @param evt 请求消息 + */ + @Override + public void process(RequestEvent evt) { + // Invite Request消息实现,此消息一般为级联消息,上级给下级发送请求视频指令 + try { + Request request = evt.getRequest(); + SipURI sipURI = (SipURI) request.getRequestURI(); + String channelId = sipURI.getUser(); + String requesterId = null; + + FromHeader fromHeader = (FromHeader) request.getHeader(FromHeader.NAME); + AddressImpl address = (AddressImpl) fromHeader.getAddress(); + SipUri uri = (SipUri) address.getURI(); + requesterId = uri.getUser(); + + if (requesterId == null || channelId == null) { + logger.info("无法从FromHeader的Address中获取到平台id,返回400"); + responseAck(evt, Response.BAD_REQUEST); // 参数不全, 发400,请求错误 + return; + } + + // 查询请求方是否上级平台 + ParentPlatform platform = storager.queryParentPlatById(requesterId); + if (platform != null) { + // 查询平台下是否有该通道 + DeviceChannel channel = storager.queryChannelInParentPlatform(requesterId, channelId); + if (channel == null) { + logger.info("通道不存在,返回404"); + responseAck(evt, Response.NOT_FOUND); // 通道不存在,发404,资源不存在 + return; + } else { + responseAck(evt, Response.CALL_IS_BEING_FORWARDED); // 通道存在,发181,呼叫转接中 + } + // 解析sdp消息, 使用jainsip 自带的sdp解析方式 + String contentString = new String(request.getRawContent()); + + // jainSip不支持y=字段, 移除移除以解析。 + int ssrcIndex = contentString.indexOf("y="); + //ssrc规定长度为10字节,不取余下长度以避免后续还有“f=”字段 + String ssrc = contentString.substring(ssrcIndex + 2, ssrcIndex + 12); + String substring = contentString.substring(0, contentString.indexOf("y=")); + SessionDescription sdp = SdpFactory.getInstance().createSessionDescription(substring); + + // 获取支持的格式 + Vector mediaDescriptions = sdp.getMediaDescriptions(true); + // 查看是否支持PS 负载96 + //String ip = null; + int port = -1; + //boolean recvonly = false; + boolean mediaTransmissionTCP = false; + Boolean tcpActive = null; + for (int i = 0; i < mediaDescriptions.size(); i++) { + MediaDescription mediaDescription = (MediaDescription) mediaDescriptions.get(i); + Media media = mediaDescription.getMedia(); + + Vector mediaFormats = media.getMediaFormats(false); + if (mediaFormats.contains("96")) { + port = media.getMediaPort(); + //String mediaType = media.getMediaType(); + String protocol = media.getProtocol(); + + // 区分TCP发流还是udp, 当前默认udp + if ("TCP/RTP/AVP".equals(protocol)) { + String setup = mediaDescription.getAttribute("setup"); + if (setup != null) { + mediaTransmissionTCP = true; + if ("active".equals(setup)) { + tcpActive = true; + } else if ("passive".equals(setup)) { + tcpActive = false; + } + } + } + break; + } + } + if (port == -1) { + logger.info("不支持的媒体格式,返回415"); + // 回复不支持的格式 + responseAck(evt, Response.UNSUPPORTED_MEDIA_TYPE); // 不支持的格式,发415 + return; + } + String username = sdp.getOrigin().getUsername(); + String addressStr = sdp.getOrigin().getAddress(); + //String sessionName = sdp.getSessionName().getValue(); + logger.info("[上级点播]用户:{}, 地址:{}:{}, ssrc:{}", username, addressStr, port, ssrc); + + Device device = storager.queryVideoDeviceByPlatformIdAndChannelId(requesterId, channelId); + if (device == null) { + logger.warn("点播平台{}的通道{}时未找到设备信息", requesterId, channel); + responseAck(evt, Response.SERVER_INTERNAL_ERROR); + return; + } + SendRtpItem sendRtpItem = zlmrtpServerFactory.createSendRtpItem(addressStr, port, ssrc, requesterId, device, channelId, + mediaTransmissionTCP); + if (tcpActive != null) { + sendRtpItem.setTcpActive(tcpActive); + } + if (sendRtpItem == null) { + logger.warn("服务器端口资源不足"); + responseAck(evt, Response.BUSY_HERE); + return; + } + + // 写入redis, 超时时回复 + redisCatchStorage.updateSendRTPSever(sendRtpItem); + // 通知下级推流, + DeferredResult> playResult = playService.play(device.getDeviceId(), channelId, (responseJSON) -> { + // 收到推流, 回复200OK, 等待ack + sendRtpItem.setStatus(1); + redisCatchStorage.updateSendRTPSever(sendRtpItem); + // TODO 添加对tcp的支持 + MediaServerConfig mediaInfo = redisCatchStorage.getMediaInfo(); + StringBuffer content = new StringBuffer(200); + content.append("v=0\r\n"); + content.append("o=" + "00000" + " 0 0 IN IP4 " + mediaInfo.getWanIp() + "\r\n"); + content.append("s=Play\r\n"); + content.append("c=IN IP4 " + mediaInfo.getWanIp() + "\r\n"); + content.append("t=0 0\r\n"); + content.append("m=video " + sendRtpItem.getLocalPort() + " RTP/AVP 96\r\n"); + content.append("a=sendonly\r\n"); + content.append("a=rtpmap:96 PS/90000\r\n"); + content.append("y=" + ssrc + "\r\n"); + content.append("f=\r\n"); + + try { + responseAck(evt, content.toString()); + } catch (SipException e) { + e.printStackTrace(); + } catch (InvalidArgumentException e) { + e.printStackTrace(); + } catch (ParseException e) { + e.printStackTrace(); + } + }, (event -> { + // 未知错误。直接转发设备点播的错误 + Response response = null; + try { + response = getMessageFactory().createResponse(event.getResponse().getStatusCode(), evt.getRequest()); + getServerTransaction(evt).sendResponse(response); + } catch (ParseException | SipException | InvalidArgumentException e) { + e.printStackTrace(); + } + })); + if (logger.isDebugEnabled()) { + logger.debug(playResult.getResult().toString()); + } + } else { + // 非上级平台请求,查询是否设备请求(通常为接收语音广播的设备) + Device device = storager.queryVideoDevice(requesterId); + if (device != null) { + logger.info("收到设备" + requesterId + "的语音广播Invite请求"); + responseAck(evt, Response.TRYING); + + String contentString = new String(request.getRawContent()); + // jainSip不支持y=字段, 移除移除以解析。 + String substring = contentString; + String ssrc = "0000000404"; + int ssrcIndex = contentString.indexOf("y="); + if (ssrcIndex > 0) { + substring = contentString.substring(0, ssrcIndex); + ssrc = contentString.substring(ssrcIndex + 2, ssrcIndex + 12); + } + ssrcIndex = substring.indexOf("f="); + if (ssrcIndex > 0) { + substring = contentString.substring(0, ssrcIndex); + } + SessionDescription sdp = SdpFactory.getInstance().createSessionDescription(substring); + + // 获取支持的格式 + Vector mediaDescriptions = sdp.getMediaDescriptions(true); + // 查看是否支持PS 负载96 + int port = -1; + //boolean recvonly = false; + boolean mediaTransmissionTCP = false; + Boolean tcpActive = null; + for (int i = 0; i < mediaDescriptions.size(); i++) { + MediaDescription mediaDescription = (MediaDescription) mediaDescriptions.get(i); + Media media = mediaDescription.getMedia(); + + Vector mediaFormats = media.getMediaFormats(false); + if (mediaFormats.contains("8")) { + port = media.getMediaPort(); + String protocol = media.getProtocol(); + // 区分TCP发流还是udp, 当前默认udp + if ("TCP/RTP/AVP".equals(protocol)) { + String setup = mediaDescription.getAttribute("setup"); + if (setup != null) { + mediaTransmissionTCP = true; + if ("active".equals(setup)) { + tcpActive = true; + } else if ("passive".equals(setup)) { + tcpActive = false; + } + } + } + break; + } + } + if (port == -1) { + logger.info("不支持的媒体格式,返回415"); + // 回复不支持的格式 + responseAck(evt, Response.UNSUPPORTED_MEDIA_TYPE); // 不支持的格式,发415 + return; + } + String username = sdp.getOrigin().getUsername(); + String addressStr = sdp.getOrigin().getAddress(); + logger.info("设备{}请求语音流,地址:{}:{},ssrc:{}", username, addressStr, port, ssrc); + + + } else { + logger.warn("来自无效设备/平台的请求"); + responseAck(evt, Response.BAD_REQUEST); + } + } + + } catch (SipException | InvalidArgumentException | ParseException e) { + e.printStackTrace(); + logger.warn("sdp解析错误"); + e.printStackTrace(); + } catch (SdpParseException e) { + e.printStackTrace(); + } catch (SdpException e) { + e.printStackTrace(); + } + } + + /*** + * 回复状态码 + * 100 trying + * 200 OK + * 400 + * 404 + * @param evt + * @throws SipException + * @throws InvalidArgumentException + * @throws ParseException + */ + private void responseAck(RequestEvent evt, int statusCode) throws SipException, InvalidArgumentException, ParseException { + Response response = getMessageFactory().createResponse(statusCode, evt.getRequest()); + getServerTransaction(evt).sendResponse(response); + } + + /** + * 回复带sdp的200 + * + * @param evt + * @param sdp + * @throws SipException + * @throws InvalidArgumentException + * @throws ParseException + */ + private void responseAck(RequestEvent evt, String sdp) throws SipException, InvalidArgumentException, ParseException { + Response response = getMessageFactory().createResponse(Response.OK, evt.getRequest()); + SipFactory sipFactory = SipFactory.getInstance(); + ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("APPLICATION", "SDP"); + response.setContent(sdp, contentTypeHeader); + + SipURI sipURI = (SipURI) evt.getRequest().getRequestURI(); + + Address concatAddress = sipFactory.createAddressFactory().createAddress( + sipFactory.createAddressFactory().createSipURI(sipURI.getUser(), sipURI.getHost() + ":" + sipURI.getPort() + )); + response.addHeader(sipFactory.createHeaderFactory().createContactHeader(concatAddress)); + getServerTransaction(evt).sendResponse(response); + } + + + public SIPCommanderFroPlatform getCmderFroPlatform() { + return cmderFroPlatform; + } + + public void setCmderFroPlatform(SIPCommanderFroPlatform cmderFroPlatform) { + this.cmderFroPlatform = cmderFroPlatform; + } + + public IVideoManagerStorager getStorager() { + return storager; + } + + public void setStorager(IVideoManagerStorager storager) { + this.storager = storager; + } + + public SIPCommander getCmder() { + return cmder; + } + + public void setCmder(SIPCommander cmder) { + this.cmder = cmder; + } + + public IPlayService getPlayService() { + return playService; + } + + public void setPlayService(IPlayService playService) { + this.playService = playService; + } + + public IRedisCatchStorage getRedisCatchStorage() { + return redisCatchStorage; + } + + public void setRedisCatchStorage(IRedisCatchStorage redisCatchStorage) { + this.redisCatchStorage = redisCatchStorage; + } +} 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 618f08ef..f05c7939 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 @@ -1,23 +1,5 @@ package com.genersoft.iot.vmp.gb28181.transmit.request.impl; -import java.io.ByteArrayInputStream; -import java.text.ParseException; -import java.util.*; - -import javax.sip.address.SipURI; - -import javax.sip.header.FromHeader; -import javax.sip.header.HeaderAddress; -import javax.sip.header.ToHeader; -import javax.sip.InvalidArgumentException; -import javax.sip.ListeningPoint; -import javax.sip.ObjectInUseException; -import javax.sip.RequestEvent; -import javax.sip.SipException; -import javax.sip.SipProvider; -import javax.sip.message.Request; -import javax.sip.message.Response; - import com.alibaba.fastjson.JSONObject; import com.genersoft.iot.vmp.VManageBootstrap; import com.genersoft.iot.vmp.common.StreamInfo; @@ -26,7 +8,6 @@ import com.genersoft.iot.vmp.conf.UserSetup; import com.genersoft.iot.vmp.gb28181.bean.*; import com.genersoft.iot.vmp.gb28181.event.DeviceOffLineDetector; import com.genersoft.iot.vmp.gb28181.event.EventPublisher; -import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; import com.genersoft.iot.vmp.gb28181.transmit.callback.CheckForAllRecordsThread; import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; @@ -42,11 +23,9 @@ import com.genersoft.iot.vmp.utils.GpsUtil; import com.genersoft.iot.vmp.utils.SpringBeanFactory; import com.genersoft.iot.vmp.utils.redis.RedisUtil; import com.genersoft.iot.vmp.vmanager.platform.bean.ChannelReduce; - import gov.nist.javax.sip.SipStackImpl; import gov.nist.javax.sip.address.AddressImpl; import gov.nist.javax.sip.address.SipUri; - import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.Element; @@ -55,9 +34,11 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.util.StringUtils; -import javax.sip.InvalidArgumentException; -import javax.sip.RequestEvent; -import javax.sip.SipException; +import javax.sip.*; +import javax.sip.address.SipURI; +import javax.sip.header.FromHeader; +import javax.sip.header.HeaderAddress; +import javax.sip.header.ToHeader; import javax.sip.message.Request; import javax.sip.message.Response; import java.io.ByteArrayInputStream; @@ -84,14 +65,10 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor { private SIPCommander cmder; private IVideoManagerStorager storager; - private SIPCommanderFroPlatform cmderFroPlatform; - - private IVideoManagerStorager storager; + private SIPCommanderFroPlatform cmderFroPlatform; private IRedisCatchStorage redisCatchStorage; - private VideoStreamSessionManager streamSession; - private EventPublisher publisher; private RedisUtil redis; @@ -167,7 +144,7 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor { responseAck(evt); } } catch (DocumentException | SipException | InvalidArgumentException | ParseException e) { - log.error("MessageRequestProcessor.process error!", e); + logger.error("MessageRequestProcessor.process error!", e); } } @@ -279,83 +256,83 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor { } } - /** - * 处理DeviceControl设备状态Message - * - * @param evt - */ - private void processMessageDeviceControl(RequestEvent evt) { - try { - Element rootElement = getRootElement(evt); - String deviceId = XmlUtil.getText(rootElement, "DeviceID"); - //String result = XmlUtil.getText(rootElement, "Result"); - // 回复200 OK - responseAck(evt); - if (rootElement.getName().equals("Response")) {//} !XmlUtil.isEmpty(result)) { - // 此处是对本平台发出DeviceControl指令的应答 - JSONObject json = new JSONObject(); - XmlUtil.node2Json(rootElement, json); - if (logger.isDebugEnabled()) { - logger.debug(json.toJSONString()); - } - RequestMessage msg = new RequestMessage(); - msg.setDeviceId(deviceId); - msg.setType(DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL); - msg.setData(json); - deferredResultHolder.invokeResult(msg); - } else { - // 此处是上级发出的DeviceControl指令 - String platformId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(FromHeader.NAME)).getAddress().getURI()).getUser(); - String targetGBId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(ToHeader.NAME)).getAddress().getURI()).getUser(); - // 远程启动功能 - if (!XmlUtil.isEmpty(XmlUtil.getText(rootElement, "TeleBoot"))) { - if (deviceId.equals(targetGBId)) { - // 远程启动本平台:需要在重新启动程序后先对SipStack解绑 - logger.info("执行远程启动本平台命令"); - ParentPlatform parentPlatform = storager.queryParentPlatById(platformId); - cmderFroPlatform.unregister(parentPlatform, null, null); - - Thread restartThread = new Thread(new Runnable() { - @Override - public void run() { - try { - Thread.sleep(3000); - SipProvider up = (SipProvider) SpringBeanFactory.getBean("udpSipProvider"); - SipStackImpl stack = (SipStackImpl)up.getSipStack(); - stack.stop(); - Iterator listener = stack.getListeningPoints(); - while (listener.hasNext()) { - stack.deleteListeningPoint((ListeningPoint) listener.next()); - } - Iterator providers = stack.getSipProviders(); - while (providers.hasNext()) { - stack.deleteSipProvider((SipProvider) providers.next()); - } - VManageBootstrap.restart(); - } catch (InterruptedException ignored) { - } catch (ObjectInUseException e) { - e.printStackTrace(); - } - } - }); - - restartThread.setDaemon(false); - restartThread.start(); - } else { - // 远程启动指定设备 - } - } - // 云台/前端控制命令 - if (!XmlUtil.isEmpty(XmlUtil.getText(rootElement,"PTZCmd")) && !deviceId.equals(targetGBId)) { - String cmdString = XmlUtil.getText(rootElement,"PTZCmd"); - Device device = storager.queryVideoDeviceByPlatformIdAndChannelId(platformId, deviceId); - cmder.fronEndCmd(device, deviceId, cmdString); - } - } - } catch (ParseException | SipException | InvalidArgumentException | DocumentException e) { - e.printStackTrace(); - } - } + /** + * 处理DeviceControl设备状态Message + * + * @param evt + */ + private void processMessageDeviceControl(RequestEvent evt) { + try { + Element rootElement = getRootElement(evt); + String deviceId = XmlUtil.getText(rootElement, "DeviceID"); + //String result = XmlUtil.getText(rootElement, "Result"); + // 回复200 OK + responseAck(evt); + if (rootElement.getName().equals("Response")) {//} !XmlUtil.isEmpty(result)) { + // 此处是对本平台发出DeviceControl指令的应答 + JSONObject json = new JSONObject(); + XmlUtil.node2Json(rootElement, json); + if (logger.isDebugEnabled()) { + logger.debug(json.toJSONString()); + } + RequestMessage msg = new RequestMessage(); + msg.setDeviceId(deviceId); + msg.setType(DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL); + msg.setData(json); + deferredResultHolder.invokeResult(msg); + } else { + // 此处是上级发出的DeviceControl指令 + String platformId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(FromHeader.NAME)).getAddress().getURI()).getUser(); + String targetGBId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(ToHeader.NAME)).getAddress().getURI()).getUser(); + // 远程启动功能 + if (!XmlUtil.isEmpty(XmlUtil.getText(rootElement, "TeleBoot"))) { + if (deviceId.equals(targetGBId)) { + // 远程启动本平台:需要在重新启动程序后先对SipStack解绑 + logger.info("执行远程启动本平台命令"); + ParentPlatform parentPlatform = storager.queryParentPlatById(platformId); + cmderFroPlatform.unregister(parentPlatform, null, null); + + Thread restartThread = new Thread(new Runnable() { + @Override + public void run() { + try { + Thread.sleep(3000); + SipProvider up = (SipProvider) SpringBeanFactory.getBean("udpSipProvider"); + SipStackImpl stack = (SipStackImpl) up.getSipStack(); + stack.stop(); + Iterator listener = stack.getListeningPoints(); + while (listener.hasNext()) { + stack.deleteListeningPoint((ListeningPoint) listener.next()); + } + Iterator providers = stack.getSipProviders(); + while (providers.hasNext()) { + stack.deleteSipProvider((SipProvider) providers.next()); + } + VManageBootstrap.restart(); + } catch (InterruptedException ignored) { + } catch (ObjectInUseException e) { + e.printStackTrace(); + } + } + }); + + restartThread.setDaemon(false); + restartThread.start(); + } else { + // 远程启动指定设备 + } + } + // 云台/前端控制命令 + if (!XmlUtil.isEmpty(XmlUtil.getText(rootElement, "PTZCmd")) && !deviceId.equals(targetGBId)) { + String cmdString = XmlUtil.getText(rootElement, "PTZCmd"); + Device device = storager.queryVideoDeviceByPlatformIdAndChannelId(platformId, deviceId); + cmder.fronEndCmd(device, deviceId, cmdString); + } + } + } catch (ParseException | SipException | InvalidArgumentException | DocumentException e) { + e.printStackTrace(); + } + } /** * 处理DeviceConfig设备状态Message @@ -450,224 +427,224 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor { } } - /** - * 处理DeviceInfo设备信息Message - * - * @param evt - */ - private void processMessageDeviceInfo(RequestEvent evt) { - try { - Element rootElement = getRootElement(evt); - String requestName = rootElement.getName(); - Element deviceIdElement = rootElement.element("DeviceID"); - String deviceId = deviceIdElement.getTextTrim().toString(); - if (requestName.equals("Query")) { - logger.info("接收到DeviceInfo查询消息"); - FromHeader fromHeader = (FromHeader) evt.getRequest().getHeader(FromHeader.NAME); - String platformId = ((SipUri) fromHeader.getAddress().getURI()).getUser(); - if (platformId == null) { - response404Ack(evt); - return; - } else { - // 回复200 OK - responseAck(evt); - String sn = rootElement.element("SN").getText(); - ParentPlatform parentPlatform = storager.queryParentPlatById(platformId); - cmderFroPlatform.deviceInfoResponse(parentPlatform, sn, fromHeader.getTag()); - } - } else { - logger.info("接收到DeviceInfo应答消息"); - Device device = storager.queryVideoDevice(deviceId); - if (device == null) { - 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")); - if (StringUtils.isEmpty(device.getStreamMode())) { - device.setStreamMode("UDP"); - } - storager.updateDevice(device); - - RequestMessage msg = new RequestMessage(); - msg.setDeviceId(deviceId); - msg.setType(DeferredResultHolder.CALLBACK_CMD_DEVICEINFO); - msg.setData(device); - deferredResultHolder.invokeResult(msg); - // 回复200 OK - responseAck(evt); - if (offLineDetector.isOnline(deviceId)) { - publisher.onlineEventPublish(deviceId, VideoManagerConstants.EVENT_ONLINE_KEEPLIVE); - } - } - } catch (DocumentException | SipException | InvalidArgumentException | ParseException e) { - e.printStackTrace(); - } - } - - /*** - * 收到catalog设备目录列表请求 处理 - * - * @param evt - */ - private void processMessageCatalogList(RequestEvent evt) { - try { - Element rootElement = getRootElement(evt); - String name = rootElement.getName(); - Element deviceIdElement = rootElement.element("DeviceID"); - String deviceId = deviceIdElement.getText(); - Element deviceListElement = rootElement.element("DeviceList"); - - FromHeader fromHeader = (FromHeader) evt.getRequest().getHeader(FromHeader.NAME); - AddressImpl address = (AddressImpl) fromHeader.getAddress(); - SipUri uri = (SipUri) address.getURI(); - String platformId = uri.getUser(); - // if (deviceListElement == null) { // 存在DeviceList则为响应 catalog, 不存在DeviceList则为查询请求 - if (name.equalsIgnoreCase("Query")) { // 区分是Response——查询响应,还是Query——查询请求 - // TODO 后续将代码拆分 - ParentPlatform parentPlatform = storager.queryParentPlatById(platformId); - if (parentPlatform == null) { - response404Ack(evt); - return; - } else { - // 回复200 OK - responseAck(evt); - - Element snElement = rootElement.element("SN"); - String sn = snElement.getText(); - // 准备回复通道信息 - List channelReduces = storager.queryChannelListInParentPlatform(parentPlatform.getServerGBId()); - if (channelReduces.size() > 0) { - for (ChannelReduce channelReduce : channelReduces) { - DeviceChannel deviceChannel = storager.queryChannel(channelReduce.getDeviceId(), channelReduce.getChannelId()); - cmderFroPlatform.catalogQuery(deviceChannel, parentPlatform, sn, fromHeader.getTag(), channelReduces.size()); - } - } - - } - - - } else { - Iterator deviceListIterator = deviceListElement.elementIterator(); - if (deviceListIterator != null) { - Device device = storager.queryVideoDevice(deviceId); - if (device == null) { - return; - } - // 遍历DeviceList - while (deviceListIterator.hasNext()) { - Element itemDevice = deviceListIterator.next(); - Element channelDeviceElement = itemDevice.element("DeviceID"); - if (channelDeviceElement == null) { - continue; - } - String channelDeviceId = channelDeviceElement.getText(); - Element channdelNameElement = itemDevice.element("Name"); - String channelName = channdelNameElement != null ? channdelNameElement.getTextTrim().toString() : ""; - Element statusElement = itemDevice.element("Status"); - String status = statusElement != null ? statusElement.getText().toString() : "ON"; - DeviceChannel deviceChannel = new DeviceChannel(); - deviceChannel.setName(channelName); - deviceChannel.setChannelId(channelDeviceId); - // ONLINE OFFLINE HIKVISION DS-7716N-E4 NVR的兼容性处理 - if (status.equals("ON") || status.equals("On") || status.equals("ONLINE")) { - deviceChannel.setStatus(1); - } - if (status.equals("OFF") || status.equals("Off") || status.equals("OFFLINE")) { - deviceChannel.setStatus(0); - } - - deviceChannel.setManufacture(XmlUtil.getText(itemDevice, "Manufacturer")); - deviceChannel.setModel(XmlUtil.getText(itemDevice, "Model")); - deviceChannel.setOwner(XmlUtil.getText(itemDevice, "Owner")); - deviceChannel.setCivilCode(XmlUtil.getText(itemDevice, "CivilCode")); - deviceChannel.setBlock(XmlUtil.getText(itemDevice, "Block")); - deviceChannel.setAddress(XmlUtil.getText(itemDevice, "Address")); - if (XmlUtil.getText(itemDevice, "Parental") == null || XmlUtil.getText(itemDevice, "Parental") == "") { - deviceChannel.setParental(0); - } else { - deviceChannel.setParental(Integer.parseInt(XmlUtil.getText(itemDevice, "Parental"))); - } - deviceChannel.setParentId(XmlUtil.getText(itemDevice, "ParentID")); - if (XmlUtil.getText(itemDevice, "SafetyWay") == null || XmlUtil.getText(itemDevice, "SafetyWay") == "") { - deviceChannel.setSafetyWay(0); - } else { - deviceChannel.setSafetyWay(Integer.parseInt(XmlUtil.getText(itemDevice, "SafetyWay"))); - } - if (XmlUtil.getText(itemDevice, "RegisterWay") == null || XmlUtil.getText(itemDevice, "RegisterWay") == "") { - deviceChannel.setRegisterWay(1); - } else { - deviceChannel.setRegisterWay(Integer.parseInt(XmlUtil.getText(itemDevice, "RegisterWay"))); - } - deviceChannel.setCertNum(XmlUtil.getText(itemDevice, "CertNum")); - if (XmlUtil.getText(itemDevice, "Certifiable") == null || XmlUtil.getText(itemDevice, "Certifiable") == "") { - deviceChannel.setCertifiable(0); - } else { - deviceChannel.setCertifiable(Integer.parseInt(XmlUtil.getText(itemDevice, "Certifiable"))); - } - if (XmlUtil.getText(itemDevice, "ErrCode") == null || XmlUtil.getText(itemDevice, "ErrCode") == "") { - deviceChannel.setErrCode(0); - } else { - deviceChannel.setErrCode(Integer.parseInt(XmlUtil.getText(itemDevice, "ErrCode"))); - } - deviceChannel.setEndTime(XmlUtil.getText(itemDevice, "EndTime")); - deviceChannel.setSecrecy(XmlUtil.getText(itemDevice, "Secrecy")); - deviceChannel.setIpAddress(XmlUtil.getText(itemDevice, "IPAddress")); - if (XmlUtil.getText(itemDevice, "Port") == null || XmlUtil.getText(itemDevice, "Port") == "") { - deviceChannel.setPort(0); - } else { - deviceChannel.setPort(Integer.parseInt(XmlUtil.getText(itemDevice, "Port"))); - } - deviceChannel.setPassword(XmlUtil.getText(itemDevice, "Password")); - if (NumericUtil.isDouble(XmlUtil.getText(itemDevice, "Longitude"))) { - deviceChannel.setLongitude(Double.parseDouble(XmlUtil.getText(itemDevice, "Longitude"))); - } else { - deviceChannel.setLongitude(0.00); - } - if (NumericUtil.isDouble(XmlUtil.getText(itemDevice, "Latitude"))) { - deviceChannel.setLatitude(Double.parseDouble(XmlUtil.getText(itemDevice, "Latitude"))); - } else { - deviceChannel.setLatitude(0.00); - } - if (XmlUtil.getText(itemDevice, "PTZType") == null || XmlUtil.getText(itemDevice, "PTZType") == "") { - deviceChannel.setPTZType(0); - } else { - deviceChannel.setPTZType(Integer.parseInt(XmlUtil.getText(itemDevice, "PTZType"))); - } - deviceChannel.setHasAudio(true); // 默认含有音频,播放时再检查是否有音频及是否AAC - storager.updateChannel(device.getDeviceId(), deviceChannel); - } - - RequestMessage msg = new RequestMessage(); - msg.setDeviceId(deviceId); - msg.setType(DeferredResultHolder.CALLBACK_CMD_CATALOG); - msg.setData(device); - deferredResultHolder.invokeResult(msg); - // 回复200 OK - responseAck(evt); - if (offLineDetector.isOnline(deviceId)) { - publisher.onlineEventPublish(deviceId, VideoManagerConstants.EVENT_ONLINE_KEEPLIVE); - } - } - } - } catch (DocumentException | SipException | InvalidArgumentException | ParseException e) { - e.printStackTrace(); - } - } - - /*** - * 收到alarm设备报警信息 处理 - * - * @param evt - */ - private void processMessageAlarm(RequestEvent evt) { - try { - Element rootElement = getRootElement(evt); - Element deviceIdElement = rootElement.element("DeviceID"); - String deviceId = deviceIdElement.getText().toString(); - // 回复200 OK - responseAck(evt); + /** + * 处理DeviceInfo设备信息Message + * + * @param evt + */ + private void processMessageDeviceInfo(RequestEvent evt) { + try { + Element rootElement = getRootElement(evt); + String requestName = rootElement.getName(); + Element deviceIdElement = rootElement.element("DeviceID"); + String deviceId = deviceIdElement.getTextTrim().toString(); + if (requestName.equals("Query")) { + logger.info("接收到DeviceInfo查询消息"); + FromHeader fromHeader = (FromHeader) evt.getRequest().getHeader(FromHeader.NAME); + String platformId = ((SipUri) fromHeader.getAddress().getURI()).getUser(); + if (platformId == null) { + response404Ack(evt); + return; + } else { + // 回复200 OK + responseAck(evt); + String sn = rootElement.element("SN").getText(); + ParentPlatform parentPlatform = storager.queryParentPlatById(platformId); + cmderFroPlatform.deviceInfoResponse(parentPlatform, sn, fromHeader.getTag()); + } + } else { + logger.info("接收到DeviceInfo应答消息"); + Device device = storager.queryVideoDevice(deviceId); + if (device == null) { + 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")); + if (StringUtils.isEmpty(device.getStreamMode())) { + device.setStreamMode("UDP"); + } + storager.updateDevice(device); + + RequestMessage msg = new RequestMessage(); + msg.setDeviceId(deviceId); + msg.setType(DeferredResultHolder.CALLBACK_CMD_DEVICEINFO); + msg.setData(device); + deferredResultHolder.invokeResult(msg); + // 回复200 OK + responseAck(evt); + if (offLineDetector.isOnline(deviceId)) { + publisher.onlineEventPublish(deviceId, VideoManagerConstants.EVENT_ONLINE_KEEPLIVE); + } + } + } catch (DocumentException | SipException | InvalidArgumentException | ParseException e) { + e.printStackTrace(); + } + } + + /*** + * 收到catalog设备目录列表请求 处理 + * + * @param evt + */ + private void processMessageCatalogList(RequestEvent evt) { + try { + Element rootElement = getRootElement(evt); + String name = rootElement.getName(); + Element deviceIdElement = rootElement.element("DeviceID"); + String deviceId = deviceIdElement.getText(); + Element deviceListElement = rootElement.element("DeviceList"); + + FromHeader fromHeader = (FromHeader) evt.getRequest().getHeader(FromHeader.NAME); + AddressImpl address = (AddressImpl) fromHeader.getAddress(); + SipUri uri = (SipUri) address.getURI(); + String platformId = uri.getUser(); + // if (deviceListElement == null) { // 存在DeviceList则为响应 catalog, 不存在DeviceList则为查询请求 + if (name.equalsIgnoreCase("Query")) { // 区分是Response——查询响应,还是Query——查询请求 + // TODO 后续将代码拆分 + ParentPlatform parentPlatform = storager.queryParentPlatById(platformId); + if (parentPlatform == null) { + response404Ack(evt); + return; + } else { + // 回复200 OK + responseAck(evt); + + Element snElement = rootElement.element("SN"); + String sn = snElement.getText(); + // 准备回复通道信息 + List channelReduces = storager.queryChannelListInParentPlatform(parentPlatform.getServerGBId()); + if (channelReduces.size() > 0) { + for (ChannelReduce channelReduce : channelReduces) { + DeviceChannel deviceChannel = storager.queryChannel(channelReduce.getDeviceId(), channelReduce.getChannelId()); + cmderFroPlatform.catalogQuery(deviceChannel, parentPlatform, sn, fromHeader.getTag(), channelReduces.size()); + } + } + + } + + + } else { + Iterator deviceListIterator = deviceListElement.elementIterator(); + if (deviceListIterator != null) { + Device device = storager.queryVideoDevice(deviceId); + if (device == null) { + return; + } + // 遍历DeviceList + while (deviceListIterator.hasNext()) { + Element itemDevice = deviceListIterator.next(); + Element channelDeviceElement = itemDevice.element("DeviceID"); + if (channelDeviceElement == null) { + continue; + } + String channelDeviceId = channelDeviceElement.getText(); + Element channdelNameElement = itemDevice.element("Name"); + String channelName = channdelNameElement != null ? channdelNameElement.getTextTrim().toString() : ""; + Element statusElement = itemDevice.element("Status"); + String status = statusElement != null ? statusElement.getText().toString() : "ON"; + DeviceChannel deviceChannel = new DeviceChannel(); + deviceChannel.setName(channelName); + deviceChannel.setChannelId(channelDeviceId); + // ONLINE OFFLINE HIKVISION DS-7716N-E4 NVR的兼容性处理 + if (status.equals("ON") || status.equals("On") || status.equals("ONLINE")) { + deviceChannel.setStatus(1); + } + if (status.equals("OFF") || status.equals("Off") || status.equals("OFFLINE")) { + deviceChannel.setStatus(0); + } + + deviceChannel.setManufacture(XmlUtil.getText(itemDevice, "Manufacturer")); + deviceChannel.setModel(XmlUtil.getText(itemDevice, "Model")); + deviceChannel.setOwner(XmlUtil.getText(itemDevice, "Owner")); + deviceChannel.setCivilCode(XmlUtil.getText(itemDevice, "CivilCode")); + deviceChannel.setBlock(XmlUtil.getText(itemDevice, "Block")); + deviceChannel.setAddress(XmlUtil.getText(itemDevice, "Address")); + if (XmlUtil.getText(itemDevice, "Parental") == null || XmlUtil.getText(itemDevice, "Parental") == "") { + deviceChannel.setParental(0); + } else { + deviceChannel.setParental(Integer.parseInt(XmlUtil.getText(itemDevice, "Parental"))); + } + deviceChannel.setParentId(XmlUtil.getText(itemDevice, "ParentID")); + if (XmlUtil.getText(itemDevice, "SafetyWay") == null || XmlUtil.getText(itemDevice, "SafetyWay") == "") { + deviceChannel.setSafetyWay(0); + } else { + deviceChannel.setSafetyWay(Integer.parseInt(XmlUtil.getText(itemDevice, "SafetyWay"))); + } + if (XmlUtil.getText(itemDevice, "RegisterWay") == null || XmlUtil.getText(itemDevice, "RegisterWay") == "") { + deviceChannel.setRegisterWay(1); + } else { + deviceChannel.setRegisterWay(Integer.parseInt(XmlUtil.getText(itemDevice, "RegisterWay"))); + } + deviceChannel.setCertNum(XmlUtil.getText(itemDevice, "CertNum")); + if (XmlUtil.getText(itemDevice, "Certifiable") == null || XmlUtil.getText(itemDevice, "Certifiable") == "") { + deviceChannel.setCertifiable(0); + } else { + deviceChannel.setCertifiable(Integer.parseInt(XmlUtil.getText(itemDevice, "Certifiable"))); + } + if (XmlUtil.getText(itemDevice, "ErrCode") == null || XmlUtil.getText(itemDevice, "ErrCode") == "") { + deviceChannel.setErrCode(0); + } else { + deviceChannel.setErrCode(Integer.parseInt(XmlUtil.getText(itemDevice, "ErrCode"))); + } + deviceChannel.setEndTime(XmlUtil.getText(itemDevice, "EndTime")); + deviceChannel.setSecrecy(XmlUtil.getText(itemDevice, "Secrecy")); + deviceChannel.setIpAddress(XmlUtil.getText(itemDevice, "IPAddress")); + if (XmlUtil.getText(itemDevice, "Port") == null || XmlUtil.getText(itemDevice, "Port") == "") { + deviceChannel.setPort(0); + } else { + deviceChannel.setPort(Integer.parseInt(XmlUtil.getText(itemDevice, "Port"))); + } + deviceChannel.setPassword(XmlUtil.getText(itemDevice, "Password")); + if (NumericUtil.isDouble(XmlUtil.getText(itemDevice, "Longitude"))) { + deviceChannel.setLongitude(Double.parseDouble(XmlUtil.getText(itemDevice, "Longitude"))); + } else { + deviceChannel.setLongitude(0.00); + } + if (NumericUtil.isDouble(XmlUtil.getText(itemDevice, "Latitude"))) { + deviceChannel.setLatitude(Double.parseDouble(XmlUtil.getText(itemDevice, "Latitude"))); + } else { + deviceChannel.setLatitude(0.00); + } + if (XmlUtil.getText(itemDevice, "PTZType") == null || XmlUtil.getText(itemDevice, "PTZType") == "") { + deviceChannel.setPTZType(0); + } else { + deviceChannel.setPTZType(Integer.parseInt(XmlUtil.getText(itemDevice, "PTZType"))); + } + deviceChannel.setHasAudio(true); // 默认含有音频,播放时再检查是否有音频及是否AAC + storager.updateChannel(device.getDeviceId(), deviceChannel); + } + + RequestMessage msg = new RequestMessage(); + msg.setDeviceId(deviceId); + msg.setType(DeferredResultHolder.CALLBACK_CMD_CATALOG); + msg.setData(device); + deferredResultHolder.invokeResult(msg); + // 回复200 OK + responseAck(evt); + if (offLineDetector.isOnline(deviceId)) { + publisher.onlineEventPublish(deviceId, VideoManagerConstants.EVENT_ONLINE_KEEPLIVE); + } + } + } + } catch (DocumentException | SipException | InvalidArgumentException | ParseException e) { + e.printStackTrace(); + } + } + + /*** + * 收到alarm设备报警信息 处理 + * + * @param evt + */ + private void processMessageAlarm(RequestEvent evt) { + try { + Element rootElement = getRootElement(evt); + Element deviceIdElement = rootElement.element("DeviceID"); + String deviceId = deviceIdElement.getText().toString(); + // 回复200 OK + responseAck(evt); Device device = storager.queryVideoDevice(deviceId); if (device == null) { @@ -735,7 +712,7 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor { } } catch (DocumentException | SipException | InvalidArgumentException | ParseException e) { // } catch (DocumentException e) { - log.error("MessageRequestProcessor.processMessageAlarm error!", e); + logger.error("MessageRequestProcessor.processMessageAlarm error!", e); } } @@ -758,7 +735,7 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor { } } } catch (ParseException | SipException | InvalidArgumentException | DocumentException e) { - log.error("MessageRequestProcessor.processMessageKeepAlive error!", e); + logger.error("MessageRequestProcessor.processMessageKeepAlive error!", e); } } @@ -824,30 +801,30 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor { recordInfo.setRecordList(recordList); } - // 改用单独线程统计已获取录像文件数量,避免多包并行分别统计不完整的问题 - String cacheKey = CACHE_RECORDINFO_KEY + deviceId + sn; - redis.set(cacheKey + "_" + uuid, recordList, 90); - if (!threadNameList.contains(cacheKey)) { - threadNameList.add(cacheKey); - CheckForAllRecordsThread chk = new CheckForAllRecordsThread(cacheKey, recordInfo); - chk.setName(cacheKey); - chk.setDeferredResultHolder(deferredResultHolder); - chk.setRedis(redis); - chk.setLogger(logger); - chk.start(); - if (logger.isDebugEnabled()) { - logger.debug("Start Thread " + cacheKey + "."); - } - } else { - if (logger.isDebugEnabled()) { - logger.debug("Thread " + cacheKey + " already started."); - } - } - - // 存在录像且如果当前录像明细个数小于总条数,说明拆包返回,需要组装,暂不返回 - // if (recordInfo.getSumNum() > 0 && recordList.size() > 0 && recordList.size() < recordInfo.getSumNum()) { - // // 为防止连续请求该设备的录像数据,返回数据错乱,特增加sn进行区分 - // String cacheKey = CACHE_RECORDINFO_KEY + deviceId + sn; + // 改用单独线程统计已获取录像文件数量,避免多包并行分别统计不完整的问题 + String cacheKey = CACHE_RECORDINFO_KEY + deviceId + sn; + redis.set(cacheKey + "_" + uuid, recordList, 90); + if (!threadNameList.contains(cacheKey)) { + threadNameList.add(cacheKey); + CheckForAllRecordsThread chk = new CheckForAllRecordsThread(cacheKey, recordInfo); + chk.setName(cacheKey); + chk.setDeferredResultHolder(deferredResultHolder); + chk.setRedis(redis); + chk.setLogger(logger); + chk.start(); + if (logger.isDebugEnabled()) { + logger.debug("Start Thread " + cacheKey + "."); + } + } else { + if (logger.isDebugEnabled()) { + logger.debug("Thread " + cacheKey + " already started."); + } + } + + // 存在录像且如果当前录像明细个数小于总条数,说明拆包返回,需要组装,暂不返回 + // if (recordInfo.getSumNum() > 0 && recordList.size() > 0 && recordList.size() < recordInfo.getSumNum()) { + // // 为防止连续请求该设备的录像数据,返回数据错乱,特增加sn进行区分 + // String cacheKey = CACHE_RECORDINFO_KEY + deviceId + sn; // redis.set(cacheKey + "_" + uuid, recordList, 90); // List cacheKeys = redis.scan(cacheKey + "_*"); @@ -879,7 +856,7 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor { // deferredResultHolder.invokeResult(msg); // logger.info("处理完成,返回结果"); } catch (DocumentException | SipException | InvalidArgumentException | ParseException e) { - log.error("MessageRequestProcessor.processMessageRecordInfo error!", e); + logger.error("MessageRequestProcessor.processMessageRecordInfo error!", e); } } @@ -905,40 +882,40 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor { } } } catch (ParseException | SipException | InvalidArgumentException | DocumentException e) { - log.error("MessageRequestProcessor.processMessageMediaStatus error!", e); + logger.error("MessageRequestProcessor.processMessageMediaStatus error!", e); } } - /** - * 处理AudioBroadcast语音广播Message - * - * @param evt - */ - private void processMessageBroadcast(RequestEvent evt) { - try { - Element rootElement = getRootElement(evt); - String deviceId = XmlUtil.getText(rootElement, "DeviceID"); - // 回复200 OK - responseAck(evt); - if (rootElement.getName().equals("Response")) { - // 此处是对本平台发出Broadcast指令的应答 - JSONObject json = new JSONObject(); - XmlUtil.node2Json(rootElement, json); - if (logger.isDebugEnabled()) { - logger.debug(json.toJSONString()); - } - RequestMessage msg = new RequestMessage(); - msg.setDeviceId(deviceId); - msg.setType(DeferredResultHolder.CALLBACK_CMD_BROADCAST); - msg.setData(json); - deferredResultHolder.invokeResult(msg); - } else { - // 此处是上级发出的Broadcast指令 - } - } catch (ParseException | SipException | InvalidArgumentException | DocumentException e) { - e.printStackTrace(); - } - } + /** + * 处理AudioBroadcast语音广播Message + * + * @param evt + */ + private void processMessageBroadcast(RequestEvent evt) { + try { + Element rootElement = getRootElement(evt); + String deviceId = XmlUtil.getText(rootElement, "DeviceID"); + // 回复200 OK + responseAck(evt); + if (rootElement.getName().equals("Response")) { + // 此处是对本平台发出Broadcast指令的应答 + JSONObject json = new JSONObject(); + XmlUtil.node2Json(rootElement, json); + if (logger.isDebugEnabled()) { + logger.debug(json.toJSONString()); + } + RequestMessage msg = new RequestMessage(); + msg.setDeviceId(deviceId); + msg.setType(DeferredResultHolder.CALLBACK_CMD_BROADCAST); + msg.setData(json); + deferredResultHolder.invokeResult(msg); + } else { + // 此处是上级发出的Broadcast指令 + } + } catch (ParseException | SipException | InvalidArgumentException | DocumentException e) { + e.printStackTrace(); + } + } /*** @@ -953,25 +930,25 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor { getServerTransaction(evt).sendResponse(response); } - /*** - * 回复404 - * @param evt - * @throws SipException - * @throws InvalidArgumentException - * @throws ParseException - */ - private void response404Ack(RequestEvent evt) throws SipException, InvalidArgumentException, ParseException { - Response response = getMessageFactory().createResponse(Response.NOT_FOUND, evt.getRequest()); - getServerTransaction(evt).sendResponse(response); - } - - private Element getRootElement(RequestEvent evt) throws DocumentException { - Request request = evt.getRequest(); - SAXReader reader = new SAXReader(); - reader.setEncoding("gbk"); - Document xml = reader.read(new ByteArrayInputStream(request.getRawContent())); - return xml.getRootElement(); - } + /*** + * 回复404 + * @param evt + * @throws SipException + * @throws InvalidArgumentException + * @throws ParseException + */ + private void response404Ack(RequestEvent evt) throws SipException, InvalidArgumentException, ParseException { + Response response = getMessageFactory().createResponse(Response.NOT_FOUND, evt.getRequest()); + getServerTransaction(evt).sendResponse(response); + } + + private Element getRootElement(RequestEvent evt) throws DocumentException { + Request request = evt.getRequest(); + SAXReader reader = new SAXReader(); + reader.setEncoding("gbk"); + Document xml = reader.read(new ByteArrayInputStream(request.getRawContent())); + return xml.getRootElement(); + } public void setCmder(SIPCommander cmder) { this.cmder = cmder; @@ -1001,15 +978,15 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor { return redisCatchStorage; } - public void setRedisCatchStorage(IRedisCatchStorage redisCatchStorage) { - this.redisCatchStorage = redisCatchStorage; - } + public void setRedisCatchStorage(IRedisCatchStorage redisCatchStorage) { + this.redisCatchStorage = redisCatchStorage; + } - public SIPCommanderFroPlatform getCmderFroPlatform() { - return cmderFroPlatform; - } + public SIPCommanderFroPlatform getCmderFroPlatform() { + return cmderFroPlatform; + } - public void setCmderFroPlatform(SIPCommanderFroPlatform cmderFroPlatform) { - this.cmderFroPlatform = cmderFroPlatform; - } + public void setCmderFroPlatform(SIPCommanderFroPlatform cmderFroPlatform) { + this.cmderFroPlatform = cmderFroPlatform; + } } 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 2eadab3c..f3c105e6 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 @@ -45,11 +45,9 @@ public class ZLMHttpHookListener { @Autowired private IRedisCatchStorage redisCatchStorage; - @Autowired - private ZLMMediaListManager zlmMediaListManager; + @Autowired + private ZLMMediaListManager zlmMediaListManager; - @Autowired - private ZLMHttpHookSubscribe subscribe; @Autowired private ZLMHttpHookSubscribe subscribe; @@ -59,161 +57,153 @@ public class ZLMHttpHookListener { @Autowired private VideoStreamSessionManager streamSession; - /** - * 流量统计事件,播放器或推流器断开时并且耗用流量超过特定阈值时会触发此事件,阈值通过配置文件general.flowThreshold配置;此事件对回复不敏感。 - * - */ - @ResponseBody - @PostMapping(value = "/on_flow_report", produces = "application/json;charset=UTF-8") - public ResponseEntity onFlowReport(@RequestBody JSONObject json){ - - if (logger.isDebugEnabled()) { - logger.debug("ZLM HOOK on_flow_report API调用,参数:" + json.toString()); - } - JSONObject ret = new JSONObject(); - ret.put("code", 0); - ret.put("msg", "success"); - return new ResponseEntity(ret.toString(),HttpStatus.OK); - } - - /** - * 访问http文件服务器上hls之外的文件时触发。 - * - */ - @ResponseBody - @PostMapping(value = "/on_http_access", produces = "application/json;charset=UTF-8") - public ResponseEntity onHttpAccess(@RequestBody JSONObject json){ - - if (logger.isDebugEnabled()) { - logger.debug("ZLM HOOK on_http_access API 调用,参数:" + json.toString()); - } - JSONObject ret = new JSONObject(); - ret.put("code", 0); - ret.put("err", ""); - ret.put("path", ""); - ret.put("second", 600); - return new ResponseEntity(ret.toString(),HttpStatus.OK); - } - - /** - * 播放器鉴权事件,rtsp/rtmp/http-flv/ws-flv/hls的播放都将触发此鉴权事件。 - * - */ - @ResponseBody - @PostMapping(value = "/on_play", produces = "application/json;charset=UTF-8") - public ResponseEntity onPlay(@RequestBody JSONObject json){ - - if (logger.isDebugEnabled()) { - logger.debug("ZLM HOOK on_play API调用,参数:" + json.toString()); - } - JSONObject ret = new JSONObject(); - ret.put("code", 0); - ret.put("msg", "success"); - return new ResponseEntity(ret.toString(),HttpStatus.OK); - } - - /** - * rtsp/rtmp/rtp推流鉴权事件。 - * - */ - @ResponseBody - @PostMapping(value = "/on_publish", produces = "application/json;charset=UTF-8") - public ResponseEntity onPublish(@RequestBody JSONObject json){ - - if (logger.isDebugEnabled()) { - logger.debug("ZLM HOOK on_publish API调用,参数:" + json.toString()); - } + /** + * 流量统计事件,播放器或推流器断开时并且耗用流量超过特定阈值时会触发此事件,阈值通过配置文件general.flowThreshold配置;此事件对回复不敏感。 + */ + @ResponseBody + @PostMapping(value = "/on_flow_report", produces = "application/json;charset=UTF-8") + public ResponseEntity onFlowReport(@RequestBody JSONObject json) { + + if (logger.isDebugEnabled()) { + logger.debug("ZLM HOOK on_flow_report API调用,参数:" + json.toString()); + } + JSONObject ret = new JSONObject(); + ret.put("code", 0); + ret.put("msg", "success"); + return new ResponseEntity(ret.toString(), HttpStatus.OK); + } + + /** + * 访问http文件服务器上hls之外的文件时触发。 + */ + @ResponseBody + @PostMapping(value = "/on_http_access", produces = "application/json;charset=UTF-8") + public ResponseEntity onHttpAccess(@RequestBody JSONObject json) { + + if (logger.isDebugEnabled()) { + logger.debug("ZLM HOOK on_http_access API 调用,参数:" + json.toString()); + } + JSONObject ret = new JSONObject(); + ret.put("code", 0); + ret.put("err", ""); + ret.put("path", ""); + ret.put("second", 600); + return new ResponseEntity(ret.toString(), HttpStatus.OK); + } + + /** + * 播放器鉴权事件,rtsp/rtmp/http-flv/ws-flv/hls的播放都将触发此鉴权事件。 + */ + @ResponseBody + @PostMapping(value = "/on_play", produces = "application/json;charset=UTF-8") + public ResponseEntity onPlay(@RequestBody JSONObject json) { + + if (logger.isDebugEnabled()) { + logger.debug("ZLM HOOK on_play API调用,参数:" + json.toString()); + } + JSONObject ret = new JSONObject(); + ret.put("code", 0); + ret.put("msg", "success"); + return new ResponseEntity(ret.toString(), HttpStatus.OK); + } + + /** + * rtsp/rtmp/rtp推流鉴权事件。 + */ + @ResponseBody + @PostMapping(value = "/on_publish", produces = "application/json;charset=UTF-8") + public ResponseEntity onPublish(@RequestBody JSONObject json) { + + if (logger.isDebugEnabled()) { + logger.debug("ZLM HOOK on_publish API调用,参数:" + json.toString()); + } ZLMHttpHookSubscribe.Event subscribe = this.subscribe.getSubscribe(ZLMHttpHookSubscribe.HookType.on_publish, json); if (subscribe != null) { subscribe.response(json); } - JSONObject ret = new JSONObject(); - ret.put("code", 0); - ret.put("msg", "success"); - ret.put("enableHls", true); - ret.put("enableMP4", false); - ret.put("enableRtxp", true); - return new ResponseEntity(ret.toString(),HttpStatus.OK); - } - - /** - * 录制mp4完成后通知事件;此事件对回复不敏感。 - * - */ - @ResponseBody - @PostMapping(value = "/on_record_mp4", produces = "application/json;charset=UTF-8") - public ResponseEntity onRecordMp4(@RequestBody JSONObject json){ - - if (logger.isDebugEnabled()) { - logger.debug("ZLM HOOK on_record_mp4 API调用,参数:" + json.toString()); - } - JSONObject ret = new JSONObject(); - ret.put("code", 0); - ret.put("msg", "success"); - return new ResponseEntity(ret.toString(),HttpStatus.OK); - } - - /** - * rtsp专用的鉴权事件,先触发on_rtsp_realm事件然后才会触发on_rtsp_auth事件。 - * - */ - @ResponseBody - @PostMapping(value = "/on_rtsp_realm", produces = "application/json;charset=UTF-8") - public ResponseEntity onRtspRealm(@RequestBody JSONObject json){ - - if (logger.isDebugEnabled()) { - logger.debug("ZLM HOOK on_rtsp_realm API调用,参数:" + json.toString()); - } - JSONObject ret = new JSONObject(); - ret.put("code", 0); - ret.put("realm", ""); - return new ResponseEntity(ret.toString(),HttpStatus.OK); - } - - - /** - * 该rtsp流是否开启rtsp专用方式的鉴权事件,开启后才会触发on_rtsp_auth事件。需要指出的是rtsp也支持url参数鉴权,它支持两种方式鉴权。 - * - */ - @ResponseBody - @PostMapping(value = "/on_rtsp_auth", produces = "application/json;charset=UTF-8") - public ResponseEntity onRtspAuth(@RequestBody JSONObject json){ - - if (logger.isDebugEnabled()) { - logger.debug("ZLM HOOK on_rtsp_auth API调用,参数:" + json.toString()); - } - JSONObject ret = new JSONObject(); - ret.put("code", 0); - ret.put("encrypted", false); - ret.put("passwd", "test"); - return new ResponseEntity(ret.toString(),HttpStatus.OK); - } - - /** - * shell登录鉴权,ZLMediaKit提供简单的telnet调试方式,使用telnet 127.0.0.1 9000能进入MediaServer进程的shell界面。 - * - */ - @ResponseBody - @PostMapping(value = "/on_shell_login", produces = "application/json;charset=UTF-8") - public ResponseEntity onShellLogin(@RequestBody JSONObject json){ - - if (logger.isDebugEnabled()) { - logger.debug("ZLM HOOK on_shell_login API调用,参数:" + json.toString()); - } - // TODO 如果是带有rtpstream则开启按需拉流 - // String app = json.getString("app"); - // String stream = json.getString("stream"); - - ZLMHttpHookSubscribe.Event subscribe = this.subscribe.getSubscribe(ZLMHttpHookSubscribe.HookType.on_publish, json); - if (subscribe != null) subscribe.response(json); - - JSONObject ret = new JSONObject(); - ret.put("code", 0); - ret.put("msg", "success"); - return new ResponseEntity(ret.toString(),HttpStatus.OK); - } + JSONObject ret = new JSONObject(); + ret.put("code", 0); + ret.put("msg", "success"); + ret.put("enableHls", true); + ret.put("enableMP4", false); + ret.put("enableRtxp", true); + return new ResponseEntity(ret.toString(), HttpStatus.OK); + } + + /** + * 录制mp4完成后通知事件;此事件对回复不敏感。 + */ + @ResponseBody + @PostMapping(value = "/on_record_mp4", produces = "application/json;charset=UTF-8") + public ResponseEntity onRecordMp4(@RequestBody JSONObject json) { + + if (logger.isDebugEnabled()) { + logger.debug("ZLM HOOK on_record_mp4 API调用,参数:" + json.toString()); + } + JSONObject ret = new JSONObject(); + ret.put("code", 0); + ret.put("msg", "success"); + return new ResponseEntity(ret.toString(), HttpStatus.OK); + } + + /** + * rtsp专用的鉴权事件,先触发on_rtsp_realm事件然后才会触发on_rtsp_auth事件。 + */ + @ResponseBody + @PostMapping(value = "/on_rtsp_realm", produces = "application/json;charset=UTF-8") + public ResponseEntity onRtspRealm(@RequestBody JSONObject json) { + + if (logger.isDebugEnabled()) { + logger.debug("ZLM HOOK on_rtsp_realm API调用,参数:" + json.toString()); + } + JSONObject ret = new JSONObject(); + ret.put("code", 0); + ret.put("realm", ""); + return new ResponseEntity(ret.toString(), HttpStatus.OK); + } + + + /** + * 该rtsp流是否开启rtsp专用方式的鉴权事件,开启后才会触发on_rtsp_auth事件。需要指出的是rtsp也支持url参数鉴权,它支持两种方式鉴权。 + */ + @ResponseBody + @PostMapping(value = "/on_rtsp_auth", produces = "application/json;charset=UTF-8") + public ResponseEntity onRtspAuth(@RequestBody JSONObject json) { + + if (logger.isDebugEnabled()) { + logger.debug("ZLM HOOK on_rtsp_auth API调用,参数:" + json.toString()); + } + JSONObject ret = new JSONObject(); + ret.put("code", 0); + ret.put("encrypted", false); + ret.put("passwd", "test"); + return new ResponseEntity(ret.toString(), HttpStatus.OK); + } + + /** + * shell登录鉴权,ZLMediaKit提供简单的telnet调试方式,使用telnet 127.0.0.1 9000能进入MediaServer进程的shell界面。 + */ + @ResponseBody + @PostMapping(value = "/on_shell_login", produces = "application/json;charset=UTF-8") + public ResponseEntity onShellLogin(@RequestBody JSONObject json) { + + if (logger.isDebugEnabled()) { + logger.debug("ZLM HOOK on_shell_login API调用,参数:" + json.toString()); + } + // TODO 如果是带有rtpstream则开启按需拉流 + // String app = json.getString("app"); + // String stream = json.getString("stream"); + + ZLMHttpHookSubscribe.Event subscribe = this.subscribe.getSubscribe(ZLMHttpHookSubscribe.HookType.on_publish, json); + if (subscribe != null) subscribe.response(json); + + JSONObject ret = new JSONObject(); + ret.put("code", 0); + ret.put("msg", "success"); + return new ResponseEntity(ret.toString(), HttpStatus.OK); + } /** * rtsp/rtmp流注册或注销时触发此事件;此事件对回复不敏感。 @@ -233,9 +223,10 @@ public class ZLMHttpHookListener { // 流消失移除redis play String app = json.getString("app"); String streamId = json.getString("stream"); + String schema = json.getString("schema"); boolean regist = json.getBoolean("regist"); if (!"rtp".equals(app) || regist) { - if (!"rtp".equals(app) && "rtsp".equals(schema)){ + if (!"rtp".equals(app) && "rtsp".equals(schema)) { zlmMediaListManager.updateMediaList(); } return new ResponseEntity<>(ret.toString(), HttpStatus.OK); @@ -335,18 +326,17 @@ public class ZLMHttpHookListener { } return new ResponseEntity<>(ret.toString(), HttpStatus.OK); } - - /** - * 服务器启动事件,可以用于监听服务器崩溃重启;此事件对回复不敏感。 - * - */ - @ResponseBody - @PostMapping(value = "/on_server_started", produces = "application/json;charset=UTF-8") - public ResponseEntity onServerStarted(HttpServletRequest request, @RequestBody JSONObject json){ - - if (logger.isDebugEnabled()) { - logger.debug("ZLM HOOK on_server_started API调用,参数:" + json.toString()); - } + + /** + * 服务器启动事件,可以用于监听服务器崩溃重启;此事件对回复不敏感。 + */ + @ResponseBody + @PostMapping(value = "/on_server_started", produces = "application/json;charset=UTF-8") + public ResponseEntity onServerStarted(HttpServletRequest request, @RequestBody JSONObject json) { + + if (logger.isDebugEnabled()) { + logger.debug("ZLM HOOK on_server_started API调用,参数:" + json.toString()); + } MediaServerConfig mediaServerConfig = JSON.toJavaObject(json, MediaServerConfig.class); redisCatchStorage.updateMediaInfo(mediaServerConfig); diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMMediaListManager.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMMediaListManager.java index b17151af..1bbee5e6 100644 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMMediaListManager.java +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMMediaListManager.java @@ -1,19 +1,14 @@ package com.genersoft.iot.vmp.media.zlm; import com.alibaba.fastjson.JSON; -import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.TypeReference; import com.genersoft.iot.vmp.common.RealVideo; -import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem; -import com.genersoft.iot.vmp.gb28181.session.SsrcUtil; import com.genersoft.iot.vmp.media.zlm.dto.MediaItem; import com.genersoft.iot.vmp.storager.IRedisCatchStorage; -import com.genersoft.iot.vmp.storager.impl.RedisCatchStorageImpl; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import java.util.*; @@ -36,9 +31,10 @@ public class ZLMMediaListManager { Integer code = mediaList.getInteger("code"); Map result = new HashMap<>(); - if (code == 0 ) { + if (code == 0) { if (dataStr != null) { - List mediaItems = JSON.parseObject(dataStr, new TypeReference>() {}); + List mediaItems = JSON.parseObject(dataStr, new TypeReference>() { + }); for (MediaItem item : mediaItems) { if ("rtp".equals(item.getApp())) { continue; @@ -73,7 +69,7 @@ public class ZLMMediaListManager { } } - }else { + } else { logger.warn("更新视频流失败,错误code: " + code); } @@ -83,5 +79,4 @@ public class ZLMMediaListManager { } - } diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRESTfulUtils.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRESTfulUtils.java index 8a0d8d6f..01130b20 100644 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRESTfulUtils.java +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRESTfulUtils.java @@ -80,17 +80,21 @@ public class ZLMRESTfulUtils { // return sendPost("getMediaInfo", param); // } - public JSONObject getMediaList(){ - return sendPost("getMediaList",null); + public JSONObject getMediaList() { + // TODO mediaServerIp 要作为参数传递进来, + String mediaServerIp = mediaConfig.getMediaIp(); + return sendPost(mediaServerIp, "getMediaList", null); } - public JSONObject getMediaInfo(String app, String schema, String stream){ + public JSONObject getMediaInfo(String app, String schema, String stream) { + // TODO mediaServerIp 要作为参数传递进来, + String mediaServerIp = mediaConfig.getMediaIp(); Map param = new HashMap<>(); - param.put("app",app); - param.put("schema",schema); - param.put("stream",stream); - param.put("vhost","__defaultVhost__"); - return sendPost("getMediaInfo",param); + param.put("app", app); + param.put("schema", schema); + param.put("stream", stream); + param.put("vhost", "__defaultVhost__"); + return sendPost(mediaServerIp, "getMediaInfo", param); } public JSONObject getRtpInfo(String mediaServerIp, String stream_id) { @@ -178,10 +182,15 @@ public class ZLMRESTfulUtils { } public JSONObject startSendRtp(Map param) { - return sendPost("startSendRtp",param); + // TODO mediaServerIp 要作为参数传递进来, + String mediaServerIp = mediaConfig.getMediaIp(); + return sendPost(mediaServerIp, "startSendRtp", param); } public JSONObject stopSendRtp(Map param) { - return sendPost("stopSendRtp",param); + + // TODO mediaServerIp 要作为参数传递进来, + String mediaServerIp = mediaConfig.getMediaIp(); + return sendPost(mediaServerIp, "stopSendRtp", param); } } diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRTPServerFactory.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRTPServerFactory.java index af7d1b4b..059bf8f7 100644 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRTPServerFactory.java +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRTPServerFactory.java @@ -1,9 +1,11 @@ package com.genersoft.iot.vmp.media.zlm; import com.alibaba.fastjson.JSONObject; -import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem; -import com.genersoft.iot.vmp.gb28181.session.SsrcUtil; +import com.genersoft.iot.vmp.common.StreamInfo; import com.genersoft.iot.vmp.conf.MediaConfig; +import com.genersoft.iot.vmp.gb28181.bean.Device; +import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem; +import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -24,6 +26,9 @@ public class ZLMRTPServerFactory { @Autowired private ZLMRESTfulUtils zlmresTfulUtils; + @Autowired + private VideoStreamSessionManager streamSession; + private int[] udpPortRangeArray = new int[2]; private ConcurrentHashMap currentPortMap = new ConcurrentHashMap<>(); @@ -110,20 +115,27 @@ public class ZLMRTPServerFactory { /** * 创建一个推流 - * @param ip 推流ip - * @param port 推流端口 - * @param ssrc 推流唯一标识 + * + * @param ip 推流ip + * @param port 推流端口 + * @param ssrc 推流唯一标识 * @param platformId 平台id - * @param channelId 通道id - * @param tcp 是否为tcp + * @param device 平台id + * @param channelId 通道id + * @param tcp 是否为tcp * @return SendRtpItem */ - public SendRtpItem createSendRtpItem(String ip, int port, String ssrc, String platformId, String deviceId, String channelId, boolean tcp){ - String playSsrc = SsrcUtil.getPlaySsrc(); - int localPort = createRTPServer(SsrcUtil.getPlaySsrc()); + public SendRtpItem createSendRtpItem(String ip, int port, String ssrc, String platformId, Device device, String channelId, boolean tcp) { + StreamInfo playStreamInfo = streamSession.createPlayStreamInfo(device, channelId); + String mediaServerIp = playStreamInfo.getMediaServerIp(); + String streamId = playStreamInfo.getStreamId(); + int localPort = createRTPServer(mediaServerIp, streamId); if (localPort != -1) { - closeRTPServer(playSsrc); - }else { + // TODO 没看懂这块逻辑,-1代表失败吗?分配端口后为什么要再把端口关掉? + closeRTPServer(mediaServerIp, streamId); + streamSession.remove(playStreamInfo); + } else { + streamSession.remove(playStreamInfo); logger.error("没有可用的端口"); return null; } @@ -132,7 +144,7 @@ public class ZLMRTPServerFactory { sendRtpItem.setPort(port); sendRtpItem.setSsrc(ssrc); sendRtpItem.setPlatformId(platformId); - sendRtpItem.setDeviceId(deviceId); + sendRtpItem.setDeviceId(device.getDeviceId()); sendRtpItem.setChannelId(channelId); sendRtpItem.setTcp(tcp); sendRtpItem.setLocalPort(localPort); @@ -142,14 +154,14 @@ public class ZLMRTPServerFactory { /** * 调用zlm RESTful API —— startSendRtp */ - public Boolean startSendRtpStream(Mapparam) { + public Boolean startSendRtpStream(Map param) { Boolean result = false; JSONObject jsonObject = zlmresTfulUtils.startSendRtp(param); System.out.println(jsonObject); if (jsonObject == null) { logger.error("RTP推流失败: 请检查ZLM服务"); } else if (jsonObject.getInteger("code") == 0) { - result= true; + result = true; logger.error("RTP推流请求成功,本地推流端口:" + jsonObject.getString("local_port")); } else { logger.error("RTP推流失败: " + jsonObject.getString("msg")); @@ -167,6 +179,7 @@ public class ZLMRTPServerFactory { /** * 查询转推的流是否有其它观看者 + * * @param streamId * @return */ @@ -178,14 +191,14 @@ public class ZLMRTPServerFactory { /** * 调用zlm RESTful API —— stopSendRtp */ - public Boolean stopSendRtpStream(Mapparam) { + public Boolean stopSendRtpStream(Map param) { Boolean result = false; JSONObject jsonObject = zlmresTfulUtils.stopSendRtp(param); System.out.println(jsonObject); if (jsonObject == null) { logger.error("停止RTP推流失败: 请检查ZLM服务"); } else if (jsonObject.getInteger("code") == 0) { - result= true; + result = true; logger.error("停止RTP推流成功"); } else { logger.error("停止RTP推流失败: " + jsonObject.getString("msg")); diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRunner.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRunner.java index 1b9e1749..f443a7be 100644 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRunner.java +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRunner.java @@ -7,7 +7,8 @@ import com.genersoft.iot.vmp.conf.MediaConfig; import com.genersoft.iot.vmp.conf.MediaServerConfig; import com.genersoft.iot.vmp.conf.SipConfig; import com.genersoft.iot.vmp.storager.IRedisCatchStorage; -import lombok.extern.slf4j.Slf4j; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.CommandLineRunner; @@ -18,10 +19,10 @@ import org.springframework.util.StringUtils; import java.util.HashMap; import java.util.Map; -@Slf4j @Component @Order(value = 1) public class ZLMRunner implements CommandLineRunner { + private final Logger logger = LoggerFactory.getLogger(ZLMRunner.class); @Autowired private IRedisCatchStorage redisCatchStorage; @@ -44,10 +45,10 @@ public class ZLMRunner implements CommandLineRunner { String[] mediaIpArr = mediaConfig.getMediaIpArr(); for (String mediaIp : mediaIpArr) { // 获取zlm信息 - log.info("等待zlm {} 接入...", mediaIp); + logger.info("等待zlm {} 接入...", mediaIp); MediaServerConfig mediaServerConfig = getMediaServerConfig(mediaIp); if (mediaServerConfig != null) { - log.info("zlm {} 接入成功...", mediaIp); + logger.info("zlm {} 接入成功...", mediaIp); if (mediaConfig.getAutoConfig()) { // 自动配置zlm saveZLMConfig(mediaIp); @@ -71,7 +72,7 @@ public class ZLMRunner implements CommandLineRunner { mediaServerConfig = JSON.parseObject(JSON.toJSONString(data.get(0)), MediaServerConfig.class); } } else { - log.error("getMediaServerConfig失败, 1s后重试"); + logger.error("getMediaServerConfig失败, 1s后重试"); try { Thread.sleep(1000); } catch (InterruptedException e) { @@ -83,7 +84,7 @@ public class ZLMRunner implements CommandLineRunner { } private void saveZLMConfig(String mediaIp) { - log.info("设置zlm {} ...", mediaIp); + logger.info("设置zlm {} ...", mediaIp); String mediaHookIp = mediaConfig.getMediaHookIp(); if (StringUtils.isEmpty(mediaHookIp)) { mediaHookIp = sipConfig.getSipIp(); @@ -112,9 +113,9 @@ public class ZLMRunner implements CommandLineRunner { JSONObject responseJSON = zlmresTfulUtils.setServerConfig(mediaIp, param); if (responseJSON != null && responseJSON.getInteger("code") == 0) { - log.info("设置zlm {} 成功", mediaIp); + logger.info("设置zlm {} 成功", mediaIp); } else { - log.info("设置zlm {} 失败: {}", mediaIp, responseJSON); + logger.info("设置zlm {} 失败: {}", mediaIp, responseJSON); } } } diff --git a/src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java b/src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java index e2950f3d..e3db72f2 100644 --- a/src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java @@ -8,7 +8,6 @@ import com.genersoft.iot.vmp.gb28181.bean.ParentPlatformCatch; import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem; import java.util.List; -import java.util.Map; public interface IRedisCatchStorage { @@ -56,7 +55,8 @@ public interface IRedisCatchStorage { StreamInfo queryPlaybackByChannel(String channelId); List queryPlayBackByDeviceId(String deviceId); - StreamInfo queryPlaybackByDevice(String deviceId, String code); + + StreamInfo queryPlaybackByDevice(String deviceId, String channelId); void updatePlatformCatchInfo(ParentPlatformCatch parentPlatformCatch); @@ -84,6 +84,7 @@ public interface IRedisCatchStorage { /** * 查询RTP推送信息缓存 + * * @param platformGbId * @param channelId * @return sendRtpItem @@ -92,6 +93,7 @@ public interface IRedisCatchStorage { /** * 删除RTP推送信息缓存 + * * @param platformGbId * @param channelId */ @@ -99,18 +101,21 @@ public interface IRedisCatchStorage { /** * 查询某个通道是否存在上级点播(RTP推送) + * * @param channelId */ boolean isChannelSendingRTP(String channelId); /** * 更新媒体流列表 + * * @param mediaList */ void updateMediaList(List mediaList); /** * 获取当前媒体流列表 + * * @return List */ List getMediaList(int start, int end); 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 386a6262..b2260e22 100644 --- a/src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorager.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorager.java @@ -2,9 +2,9 @@ package com.genersoft.iot.vmp.storager; import com.genersoft.iot.vmp.gb28181.bean.Device; import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; +import com.genersoft.iot.vmp.gb28181.bean.MobilePosition; import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; import com.genersoft.iot.vmp.vmanager.platform.bean.ChannelReduce; -import com.genersoft.iot.vmp.gb28181.bean.MobilePosition; import com.github.pagehelper.PageInfo; import java.util.List; @@ -22,7 +22,7 @@ public interface IVideoManagerStorager { * @param deviceId 设备ID * @return true:存在 false:不存在 */ - public boolean exists(String deviceId); + boolean exists(String deviceId); /** * 视频设备创建 @@ -30,7 +30,7 @@ public interface IVideoManagerStorager { * @param device 设备对象 * @return true:创建成功 false:创建失败 */ - public boolean create(Device device); + boolean create(Device device); /** * 视频设备更新 @@ -38,7 +38,7 @@ public interface IVideoManagerStorager { * @param device 设备对象 * @return true:创建成功 false:创建失败 */ - public boolean updateDevice(Device device); + boolean updateDevice(Device device); /** * 添加设备通道 @@ -46,7 +46,7 @@ public interface IVideoManagerStorager { * @param deviceId 设备id * @param channel 通道 */ - public void updateChannel(String deviceId, DeviceChannel channel); + void updateChannel(String deviceId, DeviceChannel channel); /** * 开始播放 @@ -55,7 +55,7 @@ public interface IVideoManagerStorager { * @param channelId 通道ID * @param streamId 流地址 */ - public void startPlay(String deviceId, String channelId, String streamId); + void startPlay(String deviceId, String channelId, String streamId); /** * 停止播放 @@ -63,7 +63,7 @@ public interface IVideoManagerStorager { * @param deviceId 设备id * @param channelId 通道ID */ - public void stopPlay(String deviceId, String channelId); + void stopPlay(String deviceId, String channelId); /** * 获取设备 @@ -71,7 +71,7 @@ public interface IVideoManagerStorager { * @param deviceId 设备ID * @return DShadow 设备对象 */ - public Device queryVideoDevice(String deviceId); + Device queryVideoDevice(String deviceId); /** * 获取某个设备的通道列表 @@ -81,7 +81,7 @@ public interface IVideoManagerStorager { * @param count 每页数量 * @return */ - public PageInfo queryChannelsByDeviceId(String deviceId, String query, Boolean hasSubChannel, Boolean online, int page, int count); + PageInfo queryChannelsByDeviceId(String deviceId, String query, Boolean hasSubChannel, Boolean online, int page, int count); /** * 获取某个设备的通道列表 @@ -89,7 +89,7 @@ public interface IVideoManagerStorager { * @param deviceId 设备ID * @return */ - public List queryChannelsByDeviceId(String deviceId); + List queryChannelsByDeviceId(String deviceId); /** * 获取某个设备的通道 @@ -97,7 +97,7 @@ public interface IVideoManagerStorager { * @param deviceId 设备ID * @param channelId 通道ID */ - public DeviceChannel queryChannel(String deviceId, String channelId); + DeviceChannel queryChannel(String deviceId, String channelId); /** * 获取多个设备 @@ -106,14 +106,14 @@ public interface IVideoManagerStorager { * @param count 每页数量 * @return List 设备对象数组 */ - public PageInfo queryVideoDeviceList(int page, int count); + PageInfo queryVideoDeviceList(int page, int count); /** * 获取多个设备 * * @return List 设备对象数组 */ - public List queryVideoDeviceList(); + List queryVideoDeviceList(); /** * 删除设备 @@ -121,7 +121,7 @@ public interface IVideoManagerStorager { * @param deviceId 设备ID * @return true:删除成功 false:删除失败 */ - public boolean delete(String deviceId); + boolean delete(String deviceId); /** * 更新设备在线 @@ -129,7 +129,7 @@ public interface IVideoManagerStorager { * @param deviceId 设备ID * @return true:更新成功 false:更新失败 */ - public boolean online(String deviceId); + boolean online(String deviceId); /** * 更新设备离线 @@ -137,7 +137,7 @@ public interface IVideoManagerStorager { * @param deviceId 设备ID * @return true:更新成功 false:更新失败 */ - public boolean outline(String deviceId); + boolean outline(String deviceId); /** @@ -160,85 +160,85 @@ public interface IVideoManagerStorager { void cleanChannelsForDevice(String deviceId); /** - * 添加Mobile Position设备移动位置 + * 更新上级平台 + * + * @param parentPlatform + */ + boolean updateParentPlatform(ParentPlatform parentPlatform); + + + /** + * 添加上级平台 + * + * @param parentPlatform + */ + boolean addParentPlatform(ParentPlatform parentPlatform); + + /** + * 删除上级平台 + * + * @param parentPlatform + */ + boolean deleteParentPlatform(ParentPlatform parentPlatform); + + + /** + * 分页获取上级平台 + * + * @param page + * @param count + * @return + */ + PageInfo queryParentPlatformList(int page, int count); + + /** + * 获取所有已启用的平台 + * + * @return + */ + List queryEnableParentPlatformList(boolean enable); + + /** + * 获取上级平台 * - * @param MobilePosition + * @param platformGbId * @return */ - public boolean insertMobilePosition(MobilePosition mobilePosition); - - /** - * 更新上级平台 - * @param parentPlatform - */ - boolean updateParentPlatform(ParentPlatform parentPlatform); - - - /** - * 添加上级平台 - * @param parentPlatform - */ - boolean addParentPlatform(ParentPlatform parentPlatform); - - /** - * 删除上级平台 - * @param parentPlatform - */ - boolean deleteParentPlatform(ParentPlatform parentPlatform); - - - /** - * 分页获取上级平台 - * @param page - * @param count - * @return - */ - PageInfo queryParentPlatformList(int page, int count); - - /** - * 获取所有已启用的平台 - * @return - */ - List queryEnableParentPlatformList(boolean enable); - - /** - * 获取上级平台 - * @param platformGbId - * @return - */ - ParentPlatform queryParentPlatById(String platformGbId); - - /** - * 所有平台离线 - */ - void outlineForAllParentPlatform(); - - /** - * 查询通道信息,不区分设备(已关联平台或全部) - */ - PageInfo queryAllChannelList(int page, int count, String query, Boolean online, Boolean channelType, String platformId, Boolean inPlatform); - - /** - * 查询设备的通道信息 - */ - List queryChannelListInParentPlatform(String platformId); - - - /** - * 更新上级平台的通道信息 - * @param platformId - * @param channelReduces - * @return - */ - int updateChannelForGB(String platformId, List channelReduces); - - /** - * 移除上级平台的通道信息 - * @param platformId - * @param channelReduces - * @return - */ - int delChannelForGB(String platformId, List channelReduces); + ParentPlatform queryParentPlatById(String platformGbId); + + /** + * 所有平台离线 + */ + void outlineForAllParentPlatform(); + + /** + * 查询通道信息,不区分设备(已关联平台或全部) + */ + PageInfo queryAllChannelList(int page, int count, String query, Boolean online, Boolean channelType, String platformId, Boolean inPlatform); + + /** + * 查询设备的通道信息 + */ + List queryChannelListInParentPlatform(String platformId); + + + /** + * 更新上级平台的通道信息 + * + * @param platformId + * @param channelReduces + * @return + */ + int updateChannelForGB(String platformId, List channelReduces); + + /** + * 移除上级平台的通道信息 + * + * @param platformId + * @param channelReduces + * @return + */ + int delChannelForGB(String platformId, List channelReduces); DeviceChannel queryChannelInParentPlatform(String platformId, String channelId); @@ -246,12 +246,13 @@ public interface IVideoManagerStorager { Device queryVideoDeviceByPlatformIdAndChannelId(String platformId, String channelId); - /** - * 添加Mobile Position设备移动位置 - * @param MobilePosition - * @return - */ - public boolean insertMobilePosition(MobilePosition mobilePosition); + /** + * 添加Mobile Position设备移动位置 + * + * @param mobilePosition + * @return + */ + boolean insertMobilePosition(MobilePosition mobilePosition); /** * 查询移动位置轨迹 @@ -260,19 +261,19 @@ public interface IVideoManagerStorager { * @param startTime * @param endTime */ - public List queryMobilePositions(String deviceId, String startTime, String endTime); + List queryMobilePositions(String deviceId, String startTime, String endTime); /** * 查询最新移动位置 * * @param deviceId */ - public MobilePosition queryLatestPosition(String deviceId); + MobilePosition queryLatestPosition(String deviceId); /** * 删除指定设备的所有移动位置 * * @param deviceId */ - public int clearMobilePositionsByDeviceId(String deviceId); + int clearMobilePositionsByDeviceId(String deviceId); } diff --git a/src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java b/src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java index 5ee98744..de81c2c7 100644 --- a/src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java @@ -4,7 +4,10 @@ import com.genersoft.iot.vmp.common.RealVideo; import com.genersoft.iot.vmp.common.StreamInfo; import com.genersoft.iot.vmp.common.VideoManagerConstants; import com.genersoft.iot.vmp.conf.MediaServerConfig; -import com.genersoft.iot.vmp.gb28181.bean.*; +import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; +import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; +import com.genersoft.iot.vmp.gb28181.bean.ParentPlatformCatch; +import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem; import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.storager.dao.DeviceChannelMapper; import com.genersoft.iot.vmp.utils.redis.RedisUtil; @@ -12,9 +15,9 @@ import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import java.util.*; import java.util.ArrayList; import java.util.List; +import java.util.Set; @SuppressWarnings("rawtypes") @Component @@ -142,6 +145,28 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { return redis.del(key); } + @Override + public StreamInfo queryPlaybackByDevice(String deviceId, String channelId) { + String keyByChannel = getKey(VideoManagerConstants.PLAY_BLACK_PREFIX, + null, + channelId, + deviceId + ); + List playLeys = redis.scan(keyByChannel); + if (playLeys == null || playLeys.size() == 0) { + String keyByDevice = getKey(VideoManagerConstants.PLAY_BLACK_PREFIX, + null, + null, + deviceId + ); + playLeys = redis.scan(keyByDevice); + } + if (playLeys == null || playLeys.size() == 0) { + return null; + } + return (StreamInfo) redis.get(playLeys.get(0).toString()); + } + @Override public StreamInfo queryPlaybackByStreamId(String channelId, String steamId) { String key = getKey(VideoManagerConstants.PLAY_BLACK_PREFIX, @@ -211,7 +236,7 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { @Override public ParentPlatformCatch queryPlatformCatchInfo(String platformGbId) { - return (ParentPlatformCatch)redis.get(VideoManagerConstants.PLATFORM_CATCH_PREFIX + platformGbId); + return (ParentPlatformCatch) redis.get(VideoManagerConstants.PLATFORM_CATCH_PREFIX + platformGbId); } @Override @@ -239,7 +264,7 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { @Override public String queryPlatformRegisterInfo(String callId) { - return (String)redis.get(VideoManagerConstants.PLATFORM_REGISTER_INFO_PREFIX + callId); + return (String) redis.get(VideoManagerConstants.PLATFORM_REGISTER_INFO_PREFIX + callId); } @Override @@ -264,11 +289,12 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { @Override public SendRtpItem querySendRTPServer(String platformGbId, String channelId) { String key = VideoManagerConstants.PLATFORM_SEND_RTP_INFO_PREFIX + platformGbId + "_" + channelId; - return (SendRtpItem)redis.get(key); + return (SendRtpItem) redis.get(key); } /** * 删除RTP推送信息缓存 + * * @param platformGbId * @param channelId */ @@ -280,6 +306,7 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { /** * 查询某个通道是否存在上级点播(RTP推送) + * * @param channelId */ @Override @@ -296,6 +323,7 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { /** * 更新媒体流列表 + * * @param mediaList */ @Override @@ -311,6 +339,7 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { /** * 获取当前媒体流列表 + * * @return List */ @Override diff --git a/src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStoragerImpl.java b/src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStoragerImpl.java index ac2ed5b0..d0380f3e 100644 --- a/src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStoragerImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStoragerImpl.java @@ -1,391 +1,388 @@ package com.genersoft.iot.vmp.storager.impl; -import java.util.*; - -import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; -import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; -import com.genersoft.iot.vmp.gb28181.bean.ParentPlatformCatch; +import com.genersoft.iot.vmp.gb28181.bean.*; import com.genersoft.iot.vmp.storager.IRedisCatchStorage; -import com.genersoft.iot.vmp.gb28181.bean.MobilePosition; -import com.genersoft.iot.vmp.storager.dao.DeviceChannelMapper; -import com.genersoft.iot.vmp.storager.dao.DeviceMapper; -import com.genersoft.iot.vmp.storager.dao.ParentPlatformMapper; -import com.genersoft.iot.vmp.storager.dao.PatformChannelMapper; +import com.genersoft.iot.vmp.storager.IVideoManagerStorager; +import com.genersoft.iot.vmp.storager.dao.*; import com.genersoft.iot.vmp.vmanager.platform.bean.ChannelReduce; -import com.genersoft.iot.vmp.storager.dao.DeviceMobilePositionMapper; import com.github.pagehelper.PageHelper; import com.github.pagehelper.PageInfo; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; - -import com.genersoft.iot.vmp.gb28181.bean.Device; -import com.genersoft.iot.vmp.storager.IVideoManagerStorager; import org.springframework.transaction.annotation.Transactional; -/** +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** * @Description:视频设备数据存储-jdbc实现 * @author: swwheihei - * @date: 2020年5月6日 下午2:31:42 + * @date: 2020年5月6日 下午2:31:42 */ @SuppressWarnings("rawtypes") @Component public class VideoManagerStoragerImpl implements IVideoManagerStorager { - @Autowired + @Autowired private DeviceMapper deviceMapper; - @Autowired - private DeviceChannelMapper deviceChannelMapper; + @Autowired + private DeviceChannelMapper deviceChannelMapper; - @Autowired - private DeviceMobilePositionMapper deviceMobilePositionMapper; + @Autowired + private DeviceMobilePositionMapper deviceMobilePositionMapper; - @Autowired + @Autowired private ParentPlatformMapper platformMapper; - @Autowired + @Autowired private IRedisCatchStorage redisCatchStorage; - @Autowired + @Autowired private PatformChannelMapper patformChannelMapper; - - - /** - * 根据设备ID判断设备是否存在 - * - * @param deviceId 设备ID - * @return true:存在 false:不存在 - */ - @Override - public boolean exists(String deviceId) { - return deviceMapper.getDeviceByDeviceId(deviceId) != null; - } - - /** - * 视频设备创建 - * - * @param device 设备对象 - * @return true:创建成功 false:创建失败 - */ - @Override - public synchronized boolean create(Device device) { - return deviceMapper.add(device) > 0; - } - - - - /** - * 视频设备更新 - * - * @param device 设备对象 - * @return true:更新成功 false:更新失败 - */ - @Override - public synchronized boolean updateDevice(Device device) { - Device deviceByDeviceId = deviceMapper.getDeviceByDeviceId(device.getDeviceId()); - if (deviceByDeviceId == null) { - return deviceMapper.add(device) > 0; - }else { - return deviceMapper.update(device) > 0; - } - - } - - @Override - public synchronized void updateChannel(String deviceId, DeviceChannel channel) { - String channelId = channel.getChannelId(); - channel.setDeviceId(deviceId); - DeviceChannel deviceChannel = deviceChannelMapper.queryChannel(deviceId, channelId); - if (deviceChannel == null) { - deviceChannelMapper.add(channel); - }else { - deviceChannelMapper.update(channel); - } - } - - @Override - public void startPlay(String deviceId, String channelId, String streamId) { - deviceChannelMapper.startPlay(deviceId, channelId, streamId); - } - - @Override - public void stopPlay(String deviceId, String channelId) { - deviceChannelMapper.stopPlay(deviceId, channelId); - } - - /** - * 获取设备 - * - * @param deviceId 设备ID - * @return Device 设备对象 - */ - @Override - public Device queryVideoDevice(String deviceId) { - return deviceMapper.getDeviceByDeviceId(deviceId); - } - - @Override - public PageInfo queryChannelsByDeviceId(String deviceId, String query, Boolean hasSubChannel, Boolean online, int page, int count) { - // 获取到所有正在播放的流 - PageHelper.startPage(page, count); - List all = deviceChannelMapper.queryChannelsByDeviceId(deviceId, null, query, hasSubChannel, online); - return new PageInfo<>(all); - } - - @Override - public List queryChannelsByDeviceId(String deviceId) { - return deviceChannelMapper.queryChannelsByDeviceId(deviceId, null,null, null, null); - } - - @Override - public PageInfo querySubChannels(String deviceId, String parentChannelId, String query, Boolean hasSubChannel, String online, int page, int count) { - PageHelper.startPage(page, count); - List all = deviceChannelMapper.queryChannelsByDeviceId(deviceId, parentChannelId, null, null, null); - return new PageInfo<>(all); - } - - @Override - public DeviceChannel queryChannel(String deviceId, String channelId) { - return deviceChannelMapper.queryChannel(deviceId, channelId); - } - - - /** - * 获取多个设备 - * - * @param page 当前页数 - * @param count 每页数量 - * @return PageInfo 分页设备对象数组 - */ - @Override - public PageInfo queryVideoDeviceList(int page, int count) { - PageHelper.startPage(page, count); - List all = deviceMapper.getDevices(); - return new PageInfo<>(all); - } - - /** - * 获取多个设备 - * - * @return List 设备对象数组 - */ - @Override - public List queryVideoDeviceList() { - - List deviceList = deviceMapper.getDevices(); - return deviceList; - } - - /** - * 删除设备 - * - * @param deviceId 设备ID - * @return true:删除成功 false:删除失败 - */ - @Override - public boolean delete(String deviceId) { - int result = deviceMapper.del(deviceId); - - return result > 0; - } - - /** - * 更新设备在线 - * - * @param deviceId 设备ID - * @return true:更新成功 false:更新失败 - */ - @Override - public synchronized boolean online(String deviceId) { - Device device = deviceMapper.getDeviceByDeviceId(deviceId); - if (device == null) { - return false; - } - device.setOnline(1); - System.out.println("更新设备在线"); - return deviceMapper.update(device) > 0; - } - - /** - * 更新设备离线 - * - * @param deviceId 设备ID - * @return true:更新成功 false:更新失败 - */ - @Override - public synchronized boolean outline(String deviceId) { - Device device = deviceMapper.getDeviceByDeviceId(deviceId); - device.setOnline(0); - System.out.println("更新设备离线"); - return deviceMapper.update(device) > 0; - } - - /** - * 清空通道 - * @param deviceId - */ - @Override - public void cleanChannelsForDevice(String deviceId) { - deviceChannelMapper.cleanChannelsByDeviceId(deviceId); - } - - /** - * 添加Mobile Position设备移动位置 - * @param MobilePosition - */ - @Override - public synchronized boolean insertMobilePosition(MobilePosition mobilePosition) { - return deviceMobilePositionMapper.insertNewPosition(mobilePosition) > 0; - } - - /** - * 查询移动位置轨迹 - * @param deviceId - * @param startTime - * @param endTime - */ - @Override - public synchronized List queryMobilePositions(String deviceId, String startTime, String endTime) { - return deviceMobilePositionMapper.queryPositionByDeviceIdAndTime(deviceId, startTime, endTime); - } - - @Override - public boolean addParentPlatform(ParentPlatform parentPlatform) { - int result = platformMapper.addParentPlatform(parentPlatform); - return result > 0; - } - - @Override - public boolean updateParentPlatform(ParentPlatform parentPlatform) { - int result = 0; - ParentPlatformCatch parentPlatformCatch = redisCatchStorage.queryPlatformCatchInfo(parentPlatform.getServerGBId()); // .getDeviceGBId()); - if ( platformMapper.getParentPlatById(parentPlatform.getServerGBId()) == null) { - result = platformMapper.addParentPlatform(parentPlatform); - - if (parentPlatformCatch == null) { - parentPlatformCatch = new ParentPlatformCatch(); - parentPlatformCatch.setParentPlatform(parentPlatform); - parentPlatformCatch.setId(parentPlatform.getServerGBId()); - } - }else { - result = platformMapper.updateParentPlatform(parentPlatform); - } - // 更新缓存 - parentPlatformCatch.setParentPlatform(parentPlatform); - redisCatchStorage.updatePlatformCatchInfo(parentPlatformCatch); - return result > 0; - } - - @Transactional - @Override - public boolean deleteParentPlatform(ParentPlatform parentPlatform) { - int result = platformMapper.delParentPlatform(parentPlatform); - // 删除关联的通道 - patformChannelMapper.cleanChannelForGB(parentPlatform.getServerGBId()); - return result > 0; - } - - @Override - public PageInfo queryParentPlatformList(int page, int count) { - PageHelper.startPage(page, count); - List all = platformMapper.getParentPlatformList(); - return new PageInfo<>(all); - } - - @Override - public ParentPlatform queryParentPlatById(String platformGbId) { - return platformMapper.getParentPlatById(platformGbId); - } - - @Override - public List queryEnableParentPlatformList(boolean enable) { - return platformMapper.getEnableParentPlatformList(enable); - } - - @Override - public void outlineForAllParentPlatform() { - platformMapper.outlineForAllParentPlatform(); - } - - - @Override - public PageInfo queryAllChannelList(int page, int count, String query, Boolean online, - Boolean channelType, String platformId, Boolean inPlatform) { - PageHelper.startPage(page, count); - List all = deviceChannelMapper.queryChannelListInAll(query, online, channelType, platformId, inPlatform); - return new PageInfo<>(all); - } - - @Override - public List queryChannelListInParentPlatform(String platformId) { - - return deviceChannelMapper.queryChannelListInAll(null, null, null, platformId, true); - } - - @Override - public int updateChannelForGB(String platformId, List channelReduces) { - - Map deviceAndChannels = new HashMap<>(); - for (ChannelReduce channelReduce : channelReduces) { - deviceAndChannels.put(channelReduce.getDeviceId() + "_" + channelReduce.getChannelId(), channelReduce); - } - List deviceAndChannelList = new ArrayList<>(deviceAndChannels.keySet()); - // 查询当前已经存在的 - List relatedPlatformchannels = patformChannelMapper.findChannelRelatedPlatform(platformId, deviceAndChannelList); - if (relatedPlatformchannels != null) { - deviceAndChannelList.removeAll(relatedPlatformchannels); - } - for (String relatedPlatformchannel : relatedPlatformchannels) { - deviceAndChannels.remove(relatedPlatformchannel); - } - List channelReducesToAdd = new ArrayList<>(deviceAndChannels.values()); - // 对剩下的数据进行存储 - int result = 0; - if (channelReducesToAdd.size() > 0) { - result = patformChannelMapper.addChannels(platformId, channelReducesToAdd); - } - - return result; - } - - - @Override - public int delChannelForGB(String platformId, List channelReduces) { - - int result = patformChannelMapper.delChannelForGB(platformId, channelReduces); - - return result; - } - - @Override - public DeviceChannel queryChannelInParentPlatform(String platformId, String channelId) { - DeviceChannel channel = patformChannelMapper.queryChannelInParentPlatform(platformId, channelId); - return channel; - } - - @Override - public Device queryVideoDeviceByPlatformIdAndChannelId(String platformId, String channelId) { - Device device = patformChannelMapper.queryVideoDeviceByPlatformIdAndChannelId(platformId, channelId); - return device; - } - - /** - * 查询最新移动位置 - * @param deviceId - */ - @Override - public MobilePosition queryLatestPosition(String deviceId) { - return deviceMobilePositionMapper.queryLatestPositionByDevice(deviceId); - } - - /** - * 删除指定设备的所有移动位置 - * @param deviceId - */ - public int clearMobilePositionsByDeviceId(String deviceId) { - return deviceMobilePositionMapper.clearMobilePositionsByDeviceId(deviceId); - } + /** + * 根据设备ID判断设备是否存在 + * + * @param deviceId 设备ID + * @return true:存在 false:不存在 + */ + @Override + public boolean exists(String deviceId) { + return deviceMapper.getDeviceByDeviceId(deviceId) != null; + } + + /** + * 视频设备创建 + * + * @param device 设备对象 + * @return true:创建成功 false:创建失败 + */ + @Override + public synchronized boolean create(Device device) { + return deviceMapper.add(device) > 0; + } + + + /** + * 视频设备更新 + * + * @param device 设备对象 + * @return true:更新成功 false:更新失败 + */ + @Override + public synchronized boolean updateDevice(Device device) { + Device deviceByDeviceId = deviceMapper.getDeviceByDeviceId(device.getDeviceId()); + if (deviceByDeviceId == null) { + return deviceMapper.add(device) > 0; + } else { + return deviceMapper.update(device) > 0; + } + + } + + @Override + public synchronized void updateChannel(String deviceId, DeviceChannel channel) { + String channelId = channel.getChannelId(); + channel.setDeviceId(deviceId); + DeviceChannel deviceChannel = deviceChannelMapper.queryChannel(deviceId, channelId); + if (deviceChannel == null) { + deviceChannelMapper.add(channel); + } else { + deviceChannelMapper.update(channel); + } + } + + @Override + public void startPlay(String deviceId, String channelId, String streamId) { + deviceChannelMapper.startPlay(deviceId, channelId, streamId); + } + + @Override + public void stopPlay(String deviceId, String channelId) { + deviceChannelMapper.stopPlay(deviceId, channelId); + } + + /** + * 获取设备 + * + * @param deviceId 设备ID + * @return Device 设备对象 + */ + @Override + public Device queryVideoDevice(String deviceId) { + return deviceMapper.getDeviceByDeviceId(deviceId); + } + + @Override + public PageInfo queryChannelsByDeviceId(String deviceId, String query, Boolean hasSubChannel, Boolean online, int page, int count) { + // 获取到所有正在播放的流 + PageHelper.startPage(page, count); + List all = deviceChannelMapper.queryChannelsByDeviceId(deviceId, null, query, hasSubChannel, online); + return new PageInfo<>(all); + } + + @Override + public List queryChannelsByDeviceId(String deviceId) { + return deviceChannelMapper.queryChannelsByDeviceId(deviceId, null, null, null, null); + } + + @Override + public PageInfo querySubChannels(String deviceId, String parentChannelId, String query, Boolean hasSubChannel, String online, int page, int count) { + PageHelper.startPage(page, count); + List all = deviceChannelMapper.queryChannelsByDeviceId(deviceId, parentChannelId, null, null, null); + return new PageInfo<>(all); + } + + @Override + public DeviceChannel queryChannel(String deviceId, String channelId) { + return deviceChannelMapper.queryChannel(deviceId, channelId); + } + + + /** + * 获取多个设备 + * + * @param page 当前页数 + * @param count 每页数量 + * @return PageInfo 分页设备对象数组 + */ + @Override + public PageInfo queryVideoDeviceList(int page, int count) { + PageHelper.startPage(page, count); + List all = deviceMapper.getDevices(); + return new PageInfo<>(all); + } + + /** + * 获取多个设备 + * + * @return List 设备对象数组 + */ + @Override + public List queryVideoDeviceList() { + + List deviceList = deviceMapper.getDevices(); + return deviceList; + } + + /** + * 删除设备 + * + * @param deviceId 设备ID + * @return true:删除成功 false:删除失败 + */ + @Override + public boolean delete(String deviceId) { + int result = deviceMapper.del(deviceId); + + return result > 0; + } + + /** + * 更新设备在线 + * + * @param deviceId 设备ID + * @return true:更新成功 false:更新失败 + */ + @Override + public synchronized boolean online(String deviceId) { + Device device = deviceMapper.getDeviceByDeviceId(deviceId); + if (device == null) { + return false; + } + device.setOnline(1); + System.out.println("更新设备在线"); + return deviceMapper.update(device) > 0; + } + + /** + * 更新设备离线 + * + * @param deviceId 设备ID + * @return true:更新成功 false:更新失败 + */ + @Override + public synchronized boolean outline(String deviceId) { + Device device = deviceMapper.getDeviceByDeviceId(deviceId); + device.setOnline(0); + System.out.println("更新设备离线"); + return deviceMapper.update(device) > 0; + } + + /** + * 清空通道 + * + * @param deviceId + */ + @Override + public void cleanChannelsForDevice(String deviceId) { + deviceChannelMapper.cleanChannelsByDeviceId(deviceId); + } + + /** + * 添加Mobile Position设备移动位置 + * + * @param mobilePosition + */ + @Override + public synchronized boolean insertMobilePosition(MobilePosition mobilePosition) { + return deviceMobilePositionMapper.insertNewPosition(mobilePosition) > 0; + } + + /** + * 查询移动位置轨迹 + * + * @param deviceId + * @param startTime + * @param endTime + */ + @Override + public synchronized List queryMobilePositions(String deviceId, String startTime, String endTime) { + return deviceMobilePositionMapper.queryPositionByDeviceIdAndTime(deviceId, startTime, endTime); + } + + @Override + public boolean addParentPlatform(ParentPlatform parentPlatform) { + int result = platformMapper.addParentPlatform(parentPlatform); + return result > 0; + } + + @Override + public boolean updateParentPlatform(ParentPlatform parentPlatform) { + int result = 0; + ParentPlatformCatch parentPlatformCatch = redisCatchStorage.queryPlatformCatchInfo(parentPlatform.getServerGBId()); // .getDeviceGBId()); + if (platformMapper.getParentPlatById(parentPlatform.getServerGBId()) == null) { + result = platformMapper.addParentPlatform(parentPlatform); + + if (parentPlatformCatch == null) { + parentPlatformCatch = new ParentPlatformCatch(); + parentPlatformCatch.setParentPlatform(parentPlatform); + parentPlatformCatch.setId(parentPlatform.getServerGBId()); + } + } else { + result = platformMapper.updateParentPlatform(parentPlatform); + } + // 更新缓存 + parentPlatformCatch.setParentPlatform(parentPlatform); + redisCatchStorage.updatePlatformCatchInfo(parentPlatformCatch); + return result > 0; + } + + @Transactional + @Override + public boolean deleteParentPlatform(ParentPlatform parentPlatform) { + int result = platformMapper.delParentPlatform(parentPlatform); + // 删除关联的通道 + patformChannelMapper.cleanChannelForGB(parentPlatform.getServerGBId()); + return result > 0; + } + + @Override + public PageInfo queryParentPlatformList(int page, int count) { + PageHelper.startPage(page, count); + List all = platformMapper.getParentPlatformList(); + return new PageInfo<>(all); + } + + @Override + public ParentPlatform queryParentPlatById(String platformGbId) { + return platformMapper.getParentPlatById(platformGbId); + } + + @Override + public List queryEnableParentPlatformList(boolean enable) { + return platformMapper.getEnableParentPlatformList(enable); + } + + @Override + public void outlineForAllParentPlatform() { + platformMapper.outlineForAllParentPlatform(); + } + + + @Override + public PageInfo queryAllChannelList(int page, int count, String query, Boolean online, + Boolean channelType, String platformId, Boolean inPlatform) { + PageHelper.startPage(page, count); + List all = deviceChannelMapper.queryChannelListInAll(query, online, channelType, platformId, inPlatform); + return new PageInfo<>(all); + } + + @Override + public List queryChannelListInParentPlatform(String platformId) { + + return deviceChannelMapper.queryChannelListInAll(null, null, null, platformId, true); + } + + @Override + public int updateChannelForGB(String platformId, List channelReduces) { + + Map deviceAndChannels = new HashMap<>(); + for (ChannelReduce channelReduce : channelReduces) { + deviceAndChannels.put(channelReduce.getDeviceId() + "_" + channelReduce.getChannelId(), channelReduce); + } + List deviceAndChannelList = new ArrayList<>(deviceAndChannels.keySet()); + // 查询当前已经存在的 + List relatedPlatformchannels = patformChannelMapper.findChannelRelatedPlatform(platformId, deviceAndChannelList); + if (relatedPlatformchannels != null) { + deviceAndChannelList.removeAll(relatedPlatformchannels); + } + for (String relatedPlatformchannel : relatedPlatformchannels) { + deviceAndChannels.remove(relatedPlatformchannel); + } + List channelReducesToAdd = new ArrayList<>(deviceAndChannels.values()); + // 对剩下的数据进行存储 + int result = 0; + if (channelReducesToAdd.size() > 0) { + result = patformChannelMapper.addChannels(platformId, channelReducesToAdd); + } + + return result; + } + + + @Override + public int delChannelForGB(String platformId, List channelReduces) { + + int result = patformChannelMapper.delChannelForGB(platformId, channelReduces); + + return result; + } + + @Override + public DeviceChannel queryChannelInParentPlatform(String platformId, String channelId) { + DeviceChannel channel = patformChannelMapper.queryChannelInParentPlatform(platformId, channelId); + return channel; + } + + @Override + public Device queryVideoDeviceByPlatformIdAndChannelId(String platformId, String channelId) { + Device device = patformChannelMapper.queryVideoDeviceByPlatformIdAndChannelId(platformId, channelId); + return device; + } + + /** + * 查询最新移动位置 + * + * @param deviceId + */ + @Override + public MobilePosition queryLatestPosition(String deviceId) { + return deviceMobilePositionMapper.queryLatestPositionByDevice(deviceId); + } + + /** + * 删除指定设备的所有移动位置 + * + * @param deviceId + */ + @Override + public int clearMobilePositionsByDeviceId(String deviceId) { + return deviceMobilePositionMapper.clearMobilePositionsByDeviceId(deviceId); + } } 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 c4a8af4c..f1c4f34e 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 @@ -420,7 +420,7 @@ public class RedisUtil { * @param value * @param score */ - public void zAdd(String key, String value, double score) { + public void zAdd(Object key, Object value, double score) { redisTemplate.opsForZSet().add(key, value, score); } @@ -430,7 +430,7 @@ public class RedisUtil { * @param key * @param value */ - public void zRemove(String key, String value) { + public void zRemove(Object key, Object value) { redisTemplate.opsForZSet().remove(key, value); } @@ -441,7 +441,7 @@ public class RedisUtil { * @param value * @param score */ - public Double zIncrScore(String key, String value, double score) { + public Double zIncrScore(Object key, Object value, double score) { return redisTemplate.opsForZSet().incrementScore(key, value, score); } @@ -452,7 +452,7 @@ public class RedisUtil { * @param value * @return */ - public Double zScore(String key, String value) { + public Double zScore(Object key, Object value) { return redisTemplate.opsForZSet().score(key, value); } @@ -463,7 +463,7 @@ public class RedisUtil { * @param value * @return */ - public Long zRank(String key, String value) { + public Long zRank(Object key, Object value) { return redisTemplate.opsForZSet().rank(key, value); } @@ -473,7 +473,7 @@ public class RedisUtil { * @param key * @return */ - public Long zSize(String key) { + public Long zSize(Object key) { return redisTemplate.opsForZSet().zCard(key); } @@ -487,7 +487,7 @@ public class RedisUtil { * @param end * @return */ - public Set ZRange(String key, int start, int end) { + public Set ZRange(Object key, int start, int end) { return redisTemplate.opsForZSet().range(key, start, end); } @@ -499,7 +499,7 @@ public class RedisUtil { * @param end * @return */ - public Set> zRangeWithScore(String key, int start, int end) { + public Set> zRangeWithScore(Object key, int start, int end) { return redisTemplate.opsForZSet().rangeWithScores(key, start, end); } @@ -513,7 +513,7 @@ public class RedisUtil { * @param end * @return */ - public Set zRevRange(String key, int start, int end) { + public Set zRevRange(Object key, int start, int end) { return redisTemplate.opsForZSet().reverseRange(key, start, end); } @@ -525,7 +525,7 @@ public class RedisUtil { * @param max * @return */ - public Set zSortRange(String key, int min, int max) { + public Set zSortRange(Object key, int min, int max) { return redisTemplate.opsForZSet().rangeByScore(key, min, max); } 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 f6f5bc4c..59c3a19a 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,19 +1,16 @@ package com.genersoft.iot.vmp.vmanager.play; -import com.alibaba.fastjson.JSON; 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.Device; import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; -import com.genersoft.iot.vmp.gb28181.bean.Device; import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils; import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.storager.IVideoManagerStorager; -import com.genersoft.iot.vmp.vmanager.play.bean.PlayResult; import com.genersoft.iot.vmp.vmanager.service.IPlayService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -21,20 +18,8 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; -import org.springframework.web.bind.annotation.CrossOrigin; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -import com.alibaba.fastjson.JSONObject; -import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; -import com.genersoft.iot.vmp.storager.IVideoManagerStorager; import org.springframework.web.context.request.async.DeferredResult; -import java.util.UUID; - import javax.sip.message.Response; @CrossOrigin @@ -68,66 +53,7 @@ public class PlayController { @GetMapping("/play/{deviceId}/{channelId}") public DeferredResult> play(@PathVariable String deviceId, @PathVariable String channelId) { - Device device = storager.queryVideoDevice(deviceId); - - RequestMessage msg = playService.createCallbackPlayMsg(); - DeferredResult> result = new DeferredResult<>(); - // 超时处理 - result.onTimeout(() -> { - logger.warn(String.format("设备点播超时,deviceId:%s ,channelId:%s", deviceId, channelId)); - // 释放rtpserver - cmder.closeRTPServer(device, channelId); - StreamInfo streamInfo = streamSession.getPlayStreamInfo(channelId); - streamSession.remove(streamInfo); - msg.setData("Timeout"); - resultHolder.invokeResult(msg); - }); - resultHolder.put(msg.getId(), result); - - // 判断是否已经存在点播 - StreamInfo oldStreamInfo = streamSession.getPlayStreamInfo(channelId); - if (oldStreamInfo == null) { - // 发送点播消息 - playStreamCmd(device, channelId, msg); - return result; - } - - // 若已有人点播,直接播放 - String streamId = oldStreamInfo.getStreamId(); - String mediaServerIp = oldStreamInfo.getMediaServerIp(); - JSONObject rtpInfo = zlmresTfulUtils.getRtpInfo(mediaServerIp, streamId); - if (rtpInfo.getBoolean("exist")) { - msg.setData(JSON.toJSONString(oldStreamInfo)); - resultHolder.invokeResult(msg); - return result; - } - - // 若已有人点播,但已超时自动断开,则重新发起点播 - storager.stopPlay(oldStreamInfo.getDeviceID(), oldStreamInfo.getChannelId()); - streamSession.remove(oldStreamInfo); - - playStreamCmd(device, channelId, msg); - return result; - } - - private void playStreamCmd(Device device, String channelId, RequestMessage msg) { - cmder.playStreamCmd(device, channelId, (JSONObject response) -> { - logger.info("收到点播回调消息: " + response.toJSONString()); - playService.onPublishHandlerForPlay(response, device.getDeviceId(), channelId, msg); - }, event -> { - StreamInfo streamInfo = streamSession.getPlayStreamInfo(channelId); - streamSession.remove(streamInfo); - Response response = event.getResponse(); - int statusCode = response.getStatusCode(); - String errMsg; - if (503 == statusCode) { - errMsg = "点播失败,请检查在NVR上是否可以正常打开监控,并检查NVR和SIP是否连通, 错误码: %s, %s"; - } else { - errMsg = "点播失败,错误码: %s, %s"; - } - msg.setData(String.format(errMsg, statusCode, response.getReasonPhrase())); - resultHolder.invokeResult(msg); - }); + return playService.play(deviceId, channelId, null, null); } @PostMapping("/play/{channelId}/{streamId}/stop") @@ -232,15 +158,15 @@ public class PlayController { result.put("msg", "success"); } else { - } - }else { - result.put("code", 1); - result.put("msg", "delFFmpegSource fail"); - } - return new ResponseEntity( result.toJSONString(), HttpStatus.OK); - } + } + } else { + result.put("code", 1); + result.put("msg", "delFFmpegSource fail"); + } + return new ResponseEntity(result.toJSONString(), HttpStatus.OK); + } - /** + /** * 语音广播命令API接口 * * @param deviceId @@ -252,34 +178,34 @@ public class PlayController { logger.debug("语音广播API调用"); } Device device = storager.queryVideoDevice(deviceId); - cmder.audioBroadcastCmd(device, event -> { - Response response = event.getResponse(); - RequestMessage msg = new RequestMessage(); - msg.setId(DeferredResultHolder.CALLBACK_CMD_BROADCAST + deviceId); - JSONObject json = new JSONObject(); - json.put("DeviceID", deviceId); - json.put("CmdType", "Broadcast"); - json.put("Result", "Failed"); - json.put("Description", String.format("语音广播操作失败,错误码: %s, %s", response.getStatusCode(), response.getReasonPhrase())); - msg.setData(json); - resultHolder.invokeResult(msg); - }); + cmder.audioBroadcastCmd(device, event -> { + Response response = event.getResponse(); + RequestMessage msg = new RequestMessage(); + msg.setId(DeferredResultHolder.CALLBACK_CMD_BROADCAST + deviceId); + JSONObject json = new JSONObject(); + json.put("DeviceID", deviceId); + json.put("CmdType", "Broadcast"); + json.put("Result", "Failed"); + json.put("Description", String.format("语音广播操作失败,错误码: %s, %s", response.getStatusCode(), response.getReasonPhrase())); + msg.setData(json); + resultHolder.invokeResult(msg); + }); DeferredResult> result = new DeferredResult>(3 * 1000L); - result.onTimeout(() -> { - logger.warn(String.format("语音广播操作超时, 设备未返回应答指令")); - RequestMessage msg = new RequestMessage(); - msg.setId(DeferredResultHolder.CALLBACK_CMD_BROADCAST + deviceId); - JSONObject json = new JSONObject(); - json.put("DeviceID", deviceId); - json.put("CmdType", "Broadcast"); - json.put("Result", "Failed"); - json.put("Error", "Timeout. Device did not response to broadcast command."); - msg.setData(json); - resultHolder.invokeResult(msg); - }); - resultHolder.put(DeferredResultHolder.CALLBACK_CMD_BROADCAST + deviceId, result); - return result; - } + result.onTimeout(() -> { + logger.warn(String.format("语音广播操作超时, 设备未返回应答指令")); + RequestMessage msg = new RequestMessage(); + msg.setId(DeferredResultHolder.CALLBACK_CMD_BROADCAST + deviceId); + JSONObject json = new JSONObject(); + json.put("DeviceID", deviceId); + json.put("CmdType", "Broadcast"); + json.put("Result", "Failed"); + json.put("Error", "Timeout. Device did not response to broadcast command."); + msg.setData(json); + resultHolder.invokeResult(msg); + }); + resultHolder.put(DeferredResultHolder.CALLBACK_CMD_BROADCAST + deviceId, result); + return result; + } } diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/play/bean/PlayResult.java b/src/main/java/com/genersoft/iot/vmp/vmanager/play/bean/PlayResult.java deleted file mode 100644 index 3d21349e..00000000 --- a/src/main/java/com/genersoft/iot/vmp/vmanager/play/bean/PlayResult.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.genersoft.iot.vmp.vmanager.play.bean; - -import com.genersoft.iot.vmp.gb28181.bean.Device; -import org.springframework.http.ResponseEntity; -import org.springframework.web.context.request.async.DeferredResult; - -public class PlayResult { - - private DeferredResult> result; - private String uuid; - - private Device device; - - public DeferredResult> getResult() { - return result; - } - - public void setResult(DeferredResult> result) { - this.result = result; - } - - public String getUuid() { - return uuid; - } - - public void setUuid(String uuid) { - this.uuid = uuid; - } - - public Device getDevice() { - return device; - } - - public void setDevice(Device device) { - this.device = device; - } -} diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/service/IPlayService.java b/src/main/java/com/genersoft/iot/vmp/vmanager/service/IPlayService.java index feb5178d..e919e82d 100644 --- a/src/main/java/com/genersoft/iot/vmp/vmanager/service/IPlayService.java +++ b/src/main/java/com/genersoft/iot/vmp/vmanager/service/IPlayService.java @@ -1,10 +1,11 @@ package com.genersoft.iot.vmp.vmanager.service; import com.alibaba.fastjson.JSONObject; -import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; +import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe; -import com.genersoft.iot.vmp.vmanager.play.bean.PlayResult; +import org.springframework.http.ResponseEntity; +import org.springframework.web.context.request.async.DeferredResult; /** * 点播处理 @@ -16,5 +17,5 @@ public interface IPlayService { void onPublishHandlerForPlay(JSONObject resonse, String deviceId, String channelId, RequestMessage msg); - PlayResult play(String deviceId, String channelId, ZLMHttpHookSubscribe.Event event, SipSubscribe.Event errorEvent); + DeferredResult> play(String deviceId, String channelId, ZLMHttpHookSubscribe.Event event, SipSubscribe.Event errorEvent); } diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/service/impl/PlayServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/vmanager/service/impl/PlayServiceImpl.java index 381aad9f..4379d5b6 100644 --- a/src/main/java/com/genersoft/iot/vmp/vmanager/service/impl/PlayServiceImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/vmanager/service/impl/PlayServiceImpl.java @@ -3,7 +3,6 @@ package com.genersoft.iot.vmp.vmanager.service.impl; import com.alibaba.fastjson.JSON; 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.Device; import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; @@ -15,7 +14,6 @@ import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe; import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils; import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.storager.IVideoManagerStorager; -import com.genersoft.iot.vmp.vmanager.play.bean.PlayResult; import com.genersoft.iot.vmp.vmanager.service.IPlayService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -27,8 +25,6 @@ import org.springframework.web.context.request.async.DeferredResult; import javax.sip.message.Response; import java.util.UUID; -import java.util.UUID; - @Service public class PlayServiceImpl implements IPlayService { @@ -52,66 +48,80 @@ public class PlayServiceImpl implements IPlayService { @Autowired private ZLMRESTfulUtils zlmresTfulUtils; - @Override - public PlayResult play(String deviceId, String channelId, ZLMHttpHookSubscribe.Event hookEvent, SipSubscribe.Event errorEvent) { - PlayResult playResult = new PlayResult(); + public DeferredResult> play(String deviceId, String channelId, ZLMHttpHookSubscribe.Event hookEvent, SipSubscribe.Event errorEvent) { Device device = storager.queryVideoDevice(deviceId); - StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channelId); - playResult.setDevice(device); - UUID uuid = UUID.randomUUID(); - playResult.setUuid(uuid.toString()); - DeferredResult> result = new DeferredResult>(); - playResult.setResult(result); - // 录像查询以channelId作为deviceId查询 - resultHolder.put(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid, result); - - if (streamInfo == null) { + + RequestMessage msg = this.createCallbackPlayMsg(); + DeferredResult> result = new DeferredResult<>(); + // 超时处理 + result.onTimeout(() -> { + logger.warn(String.format("设备点播超时,deviceId:%s ,channelId:%s", deviceId, channelId)); + // 释放rtpserver + cmder.closeRTPServer(device, channelId); + StreamInfo streamInfo = streamSession.getPlayStreamInfo(channelId); + streamSession.remove(streamInfo); + msg.setData("Timeout"); + resultHolder.invokeResult(msg); + if (errorEvent != null) { + errorEvent.response(null); + } + }); + resultHolder.put(msg.getId(), result); + + // 判断是否已经存在点播 + StreamInfo oldStreamInfo = streamSession.getPlayStreamInfo(channelId); + if (oldStreamInfo == null) { // 发送点播消息 - cmder.playStreamCmd(device, channelId, (JSONObject response) -> { - logger.info("收到订阅消息: " + response.toJSONString()); - onPublishHandlerForPlay(response, deviceId, channelId, uuid.toString()); - if (hookEvent != null) { - hookEvent.response(response); - } - }, event -> { - RequestMessage msg = new RequestMessage(); - msg.setId(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid); - Response response = event.getResponse(); - msg.setData(String.format("点播失败, 错误码: %s, %s", response.getStatusCode(), response.getReasonPhrase())); - resultHolder.invokeResult(msg); - if (errorEvent != null) { - errorEvent.response(event); - } - }); - } else { - String streamId = streamInfo.getStreamId(); - JSONObject rtpInfo = zlmresTfulUtils.getRtpInfo(streamId); - if (rtpInfo.getBoolean("exist")) { - RequestMessage msg = new RequestMessage(); - msg.setId(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid); - msg.setData(JSON.toJSONString(streamInfo)); - resultHolder.invokeResult(msg); - if (hookEvent != null) { - hookEvent.response(JSONObject.parseObject(JSON.toJSONString(streamInfo))); - } - } else { - redisCatchStorage.stopPlay(streamInfo); - storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId()); - cmder.playStreamCmd(device, channelId, (JSONObject response) -> { - logger.info("收到订阅消息: " + response.toJSONString()); - onPublishHandlerForPlay(response, deviceId, channelId, uuid.toString()); - }, event -> { - RequestMessage msg = new RequestMessage(); - msg.setId(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid); - Response response = event.getResponse(); - msg.setData(String.format("点播失败, 错误码: %s, %s", response.getStatusCode(), response.getReasonPhrase())); - resultHolder.invokeResult(msg); - }); + playStreamCmd(device, channelId, msg, hookEvent, errorEvent); + return result; + } + + // 若已有人点播,直接播放 + String streamId = oldStreamInfo.getStreamId(); + String mediaServerIp = oldStreamInfo.getMediaServerIp(); + JSONObject rtpInfo = zlmresTfulUtils.getRtpInfo(mediaServerIp, streamId); + if (rtpInfo.getBoolean("exist")) { + msg.setData(JSON.toJSONString(oldStreamInfo)); + resultHolder.invokeResult(msg); + if (hookEvent != null) { + hookEvent.response(null); } + return result; } - return playResult; + // 若已有人点播,但已超时自动断开,则重新发起点播 + storager.stopPlay(oldStreamInfo.getDeviceID(), oldStreamInfo.getChannelId()); + streamSession.remove(oldStreamInfo); + + playStreamCmd(device, channelId, msg, hookEvent, errorEvent); + return result; + } + + private void playStreamCmd(Device device, String channelId, RequestMessage msg, ZLMHttpHookSubscribe.Event hookEvent, SipSubscribe.Event errorEvent) { + cmder.playStreamCmd(device, channelId, (JSONObject response) -> { + logger.info("收到点播回调消息: " + response.toJSONString()); + this.onPublishHandlerForPlay(response, device.getDeviceId(), channelId, msg); + if (hookEvent != null) { + hookEvent.response(response); + } + }, event -> { + StreamInfo streamInfo = streamSession.getPlayStreamInfo(channelId); + streamSession.remove(streamInfo); + Response response = event.getResponse(); + int statusCode = response.getStatusCode(); + String errMsg; + if (503 == statusCode) { + errMsg = "点播失败,请检查在NVR上是否可以正常打开监控,并检查NVR和SIP是否连通, 错误码: %s, %s"; + } else { + errMsg = "点播失败,错误码: %s, %s"; + } + msg.setData(String.format(errMsg, statusCode, response.getReasonPhrase())); + resultHolder.invokeResult(msg); + if (errorEvent != null) { + errorEvent.response(event); + } + }); } @Override diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml index bf8d3f4d..aa697345 100644 --- a/src/main/resources/application-dev.yml +++ b/src/main/resources/application-dev.yml @@ -1,102 +1,102 @@ spring: - # REDIS数据库配置 - redis: - # [必须修改] Redis服务器IP, REDIS安装在本机的,使用127.0.0.1 - host: 127.0.0.1 - # [必须修改] 端口号 - port: 6379 - # [可选] 数据库 DB - database: 6 - # [可选] 访问密码,若你的redis服务器没有设置密码,就不需要用密码去连接 - password: - # [可选] 超时时间 - timeout: 10000 - poolMaxTotal: 1000 - poolMaxIdle: 50 - poolMaxWait: 500 - # [可选] jdbc数据库配置, 项目使用sqlite作为数据库,一般不需要配置 - datasource: - # name: eiot - # url: jdbc:mysql://127.0.0.1:3306/eiot?useUnicode=true&characterEncoding=UTF8&rewriteBatchedStatements=true - # username: - # password: - # type: com.alibaba.druid.pool.DruidDataSource - # driver-class-name: com.mysql.jdbc.Driver - name: eiot - url: jdbc:sqlite::resource:wvp.sqlite - username: - password: - type: com.alibaba.druid.pool.DruidDataSource - driver-class-name: org.sqlite.JDBC - max-active: 1 - min-idle: 1 + # REDIS数据库配置 + redis: + # [必须修改] Redis服务器IP, REDIS安装在本机的,使用127.0.0.1 + host: 127.0.0.1 + # [必须修改] 端口号 + port: 6379 + # [可选] 数据库 DB + database: 6 + # [可选] 访问密码,若你的redis服务器没有设置密码,就不需要用密码去连接 + password: 111111 + # [可选] 超时时间 + timeout: 10000 + poolMaxTotal: 1000 + poolMaxIdle: 50 + poolMaxWait: 500 + # [可选] jdbc数据库配置, 项目使用sqlite作为数据库,一般不需要配置 + datasource: + # name: eiot + # url: jdbc:mysql://127.0.0.1:3306/eiot?useUnicode=true&characterEncoding=UTF8&rewriteBatchedStatements=true + # username: + # password: + # type: com.alibaba.druid.pool.DruidDataSource + # driver-class-name: com.mysql.jdbc.Driver + name: eiot + url: jdbc:sqlite::resource:wvp.sqlite + username: + password: + type: com.alibaba.druid.pool.DruidDataSource + driver-class-name: org.sqlite.JDBC + max-active: 1 + min-idle: 1 # [可选] WVP监听的HTTP端口, 网页和接口调用都是这个端口 server: - port: 18080 + port: 18080 # 作为28181服务器的配置 sip: - # [必须修改] 本机的内网IP, 必须是网卡上的IP - ip: 192.168.0.100 - # [可选] 28181服务监听的端口 - port: 5060 - # 根据国标6.1.2中规定,domain宜采用ID统一编码的前十位编码。国标附录D中定义前8位为中心编码(由省级、市级、区级、基层编号组成,参照GB/T 2260-2007) - # 后两位为行业编码,定义参照附录D.3 - # 3701020049标识山东济南历下区 信息行业接入 - # [可选] - domain: 4401020049 - # [可选] - id: 44010200492000000001 - # [可选] 默认设备认证密码,后续扩展使用设备单独密码 - password: admin123 + # [必须修改] 本机的内网IP, 必须是网卡上的IP + ip: 192.168.1.105 + # [可选] 28181服务监听的端口 + port: 5060 + # 根据国标6.1.2中规定,domain宜采用ID统一编码的前十位编码。国标附录D中定义前8位为中心编码(由省级、市级、区级、基层编号组成,参照GB/T 2260-2007) + # 后两位为行业编码,定义参照附录D.3 + # 3701020049标识山东济南历下区 信息行业接入 + # [可选] + domain: 4401020049 + # [可选] + id: 44010200492000000001 + # [可选] 默认设备认证密码,后续扩展使用设备单独密码 + password: admin123 # 登陆的用户名密码 auth: - # [可选] 用户名 - username: admin - # [可选] 密码, 默认为admin - password: 21232f297a57a5a743894a0e4a801fc3 + # [可选] 用户名 + username: admin + # [可选] 密码, 默认为admin + password: 21232f297a57a5a743894a0e4a801fc3 #zlm服务器配置 media: - # [必须修改] zlm服务器的IP(内网公网IP均可),配置多台时IP用逗号隔开 - ip: 192.168.0.100 - # [可选] zlm服务器的公网IP, 内网部署置空即可 - wanIp: - # [可选] zlm服务器的hook所使用的IP, 默认使用sip.ip - hookIp: - # [必须修改] zlm服务器的http.port - port: 80 - # [可选] 是否自动配置ZLM, 如果希望手动配置ZLM, 可以设为false, 不建议新接触的用户修改 - autoConfig: true - # [可选] zlm服务器的hook.admin_params=secret - secret: 035c73f7-bb6b-4889-a715-d9eb2d1925cc - # [可选] zlm服务器的general.streamNoneReaderDelayMS - streamNoneReaderDelayMS: 18000 # 无人观看多久自动关闭流, -1表示永不自动关闭,即 关闭按需拉流 - # [可选] 自动点播, 使用固定流地址进行播放时,如果未点播则自动进行点播, 需要rtp.enable=true - autoApplyPlay: false - # [可选] 部分设备需要扩展SDP,需要打开此设置 - seniorSdp: false - # 启用udp多端口模式 - rtp: - # [可选] 是否启用udp多端口模式, 开启后会在udpPortRange范围内选择端口用于媒体流传输 - enable: true - # [可选] 在此范围内选择端口用于媒体流传输, 不只是udp, 使用TCP被动传输模式时,也是从这个范围内选择端口 - udpPortRange: 30000,30500 # 端口范围 + # [必须修改] zlm服务器的IP(内网公网IP均可),配置多台时IP用逗号隔开 + ip: 192.168.1.105 + # [可选] zlm服务器的公网IP, 内网部署置空即可 + wanIp: + # [可选] zlm服务器的hook所使用的IP, 默认使用sip.ip + hookIp: + # [必须修改] zlm服务器的http.port + port: 80 + # [可选] 是否自动配置ZLM, 如果希望手动配置ZLM, 可以设为false, 不建议新接触的用户修改 + autoConfig: true + # [可选] zlm服务器的hook.admin_params=secret + secret: 035c73f7-bb6b-4889-a715-d9eb2d1925cc + # [可选] zlm服务器的general.streamNoneReaderDelayMS + streamNoneReaderDelayMS: 18000 # 无人观看多久自动关闭流, -1表示永不自动关闭,即 关闭按需拉流 + # [可选] 自动点播, 使用固定流地址进行播放时,如果未点播则自动进行点播, 需要rtp.enable=true + autoApplyPlay: false + # [可选] 部分设备需要扩展SDP,需要打开此设置 + seniorSdp: false + # 启用udp多端口模式 + rtp: + # [可选] 是否启用udp多端口模式, 开启后会在udpPortRange范围内选择端口用于媒体流传输 + enable: true + # [可选] 在此范围内选择端口用于媒体流传输, 不只是udp, 使用TCP被动传输模式时,也是从这个范围内选择端口 + udpPortRange: 30000,30500 # 端口范围 # [可选] 日志配置, 一般不需要改 logging: - file: - name: logs/wvp.log - max-history: 30 - max-size: 10MB - total-size-cap: 300MB - level: - com: - genersoft: - iot: debug + file: + name: logs/wvp.log + max-history: 30 + max-size: 10MB + total-size-cap: 300MB + level: + com: + genersoft: + iot: debug # [根据业务需求配置] userSettings: - # 保存移动位置历史轨迹:true:保留历史数据,false:仅保留最后的位置(默认) - savePositionHistory: false \ No newline at end of file + # 保存移动位置历史轨迹:true:保留历史数据,false:仅保留最后的位置(默认) + savePositionHistory: false \ No newline at end of file diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index ef46c2ad..caf4dfcd 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -1,3 +1,3 @@ spring: profiles: - active: local \ No newline at end of file + active: dev \ No newline at end of file