648540858
2022-09-05 aa6bce35c710750b68d4e6c53095e9be4e1afd8d
Merge branch 'wvp-28181-2.0'

# Conflicts:
# src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/SIPRequestProcessorParent.java
# src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java
# src/main/java/com/genersoft/iot/vmp/service/impl/MediaServiceImpl.java
27个文件已修改
1个文件已添加
415 ■■■■■ 已修改文件
src/main/java/com/genersoft/iot/vmp/conf/GlobalExceptionHandler.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/conf/GlobalResponseAdvice.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/conf/ProxyServletConfig.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/SipLayer.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/auth/DigestServerAuthenticationHelper.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/bean/ParentPlatform.java 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/conf/SipLoggerPass.java 106 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorObserver.java 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderPlarformProvider.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java 52 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommanderFroPlatform.java 24 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/SIPRequestProcessorParent.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java 12 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/SubscribeRequestProcessor.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/info/InfoRequestProcessor.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/DeviceStatusResponseMessageHandler.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/PresetQueryResponseMessageHandler.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java 88 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/service/impl/MediaServiceImpl.java 11 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/service/impl/PlatformServiceImpl.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/service/impl/StreamProxyServiceImpl.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/storager/dao/StreamPushMapper.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/MobilePosition/MobilePositionController.java 17 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceControl.java 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/platform/PlatformController.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
web_src/config/index.js 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
web_src/src/components/StreamProxyList.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/conf/GlobalExceptionHandler.java
@@ -32,6 +32,7 @@
        return WVPResult.fail(ErrorCode.ERROR500.getCode(), e.getMessage());
    }
    /**
     * 自定义异常处理, 处理controller中返回的错误
     * @param e 异常
src/main/java/com/genersoft/iot/vmp/conf/GlobalResponseAdvice.java
@@ -1,16 +1,22 @@
package com.genersoft.iot.vmp.conf;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
import org.jetbrains.annotations.NotNull;
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
import org.springframework.context.annotation.Bean;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
import java.util.List;
/**
 * 全局统一返回结果
@@ -24,6 +30,7 @@
    public boolean supports(@NotNull MethodParameter returnType, @NotNull Class<? extends HttpMessageConverter<?>> converterType) {
        return true;
    }
    @Override
    public Object beforeBodyWrite(Object body, @NotNull MethodParameter returnType, @NotNull MediaType selectedContentType, @NotNull Class<? extends HttpMessageConverter<?>> selectedConverterType, @NotNull ServerHttpRequest request, @NotNull ServerHttpResponse response) {
@@ -50,4 +57,13 @@
        return WVPResult.success(body);
    }
    /**
     * 防止返回string时出错
     * @return
     */
    @Bean
    public HttpMessageConverters custHttpMessageConverter() {
        return new HttpMessageConverters(new FastJsonHttpMessageConverter());
    }
}
src/main/java/com/genersoft/iot/vmp/conf/ProxyServletConfig.java
@@ -128,7 +128,7 @@
        MediaServerItem getMediaInfoByUri(String uri){
            String[] split = uri.split("/");
            String mediaServerId = split[2];
            if ("default".equals(mediaServerId)) {
            if ("default".equalsIgnoreCase(mediaServerId)) {
                return mediaServerService.getDefaultMediaServer();
            }else {
                return mediaServerService.getOne(mediaServerId);
@@ -246,7 +246,7 @@
        MediaServerItem getMediaInfoByUri(String uri){
            String[] split = uri.split("/");
            String mediaServerId = split[2];
            if ("default".equals(mediaServerId)) {
            if ("default".equalsIgnoreCase(mediaServerId)) {
                return mediaServerService.getDefaultMediaServer();
            }else {
                return mediaServerService.getOne(mediaServerId);
src/main/java/com/genersoft/iot/vmp/gb28181/SipLayer.java
@@ -47,12 +47,16 @@
        /**
         * 完整配置参考 gov.nist.javax.sip.SipStackImpl,需要下载源码
         * gov/nist/javax/sip/SipStackImpl.class
         * sip消息的解析在 gov.nist.javax.sip.stack.UDPMessageChannel的processIncomingDataPacket方法
         */
//         * gov/nist/javax/sip/SipStackImpl.class
        if (logger.isDebugEnabled()) {
            properties.setProperty("gov.nist.javax.sip.LOG_MESSAGE_CONTENT", "false");
        }
        // 接收所有notify请求,即使没有订阅
        properties.setProperty("gov.nist.javax.sip.DELIVER_UNSOLICITED_NOTIFY", "true");
        properties.setProperty("gov.nist.javax.sip.AUTOMATIC_DIALOG_ERROR_HANDLING", "false");
        properties.setProperty("gov.nist.javax.sip.CANCEL_CLIENT_TRANSACTION_CHECKED", "false");
        // 为_NULL _对话框传递_终止的_事件
        properties.setProperty("gov.nist.javax.sip.DELIVER_TERMINATED_EVENT_FOR_NULL_DIALOG", "true");
        // 会话清理策略
@@ -64,6 +68,7 @@
         * sip_server_log.log 和 sip_debug_log.log ERROR, INFO, WARNING, OFF, DEBUG, TRACE
         */
        properties.setProperty("gov.nist.javax.sip.TRACE_LEVEL", "ERROR");
//        properties.setProperty("gov.nist.javax.sip.SIP_MESSAGE_VALVE", "com.genersoft.iot.vmp.gb28181.session.SipMessagePreprocessing");
//        if (logger.isDebugEnabled()) {
//            properties.setProperty("gov.nist.javax.sip.TRACE_LEVEL", "DEBUG");
//        }
src/main/java/com/genersoft/iot/vmp/gb28181/auth/DigestServerAuthenticationHelper.java
@@ -218,7 +218,7 @@
        logger.debug("qop: " + qop);
        String KD = HA1 + ":" + nonce;
        if (qop != null && qop.equals("auth") ) {
        if (qop != null && qop.equalsIgnoreCase("auth") ) {
            if (nc != -1) {
                KD += ":" + ncStr;
            }
src/main/java/com/genersoft/iot/vmp/gb28181/bean/ParentPlatform.java
@@ -90,7 +90,7 @@
     * 心跳周期(秒)
     */
    @Schema(description = "心跳周期(秒)")
    private String keepTimeout;
    private int keepTimeout;
    /**
     * 传输协议
@@ -294,11 +294,11 @@
        this.expires = expires;
    }
    public String getKeepTimeout() {
    public int getKeepTimeout() {
        return keepTimeout;
    }
    public void setKeepTimeout(String keepTimeout) {
    public void setKeepTimeout(int keepTimeout) {
        this.keepTimeout = keepTimeout;
    }
src/main/java/com/genersoft/iot/vmp/gb28181/conf/SipLoggerPass.java
New file
@@ -0,0 +1,106 @@
package com.genersoft.iot.vmp.gb28181.conf;
import gov.nist.core.StackLogger;
import java.util.Properties;
/**
 * sip日志格式化
 */
public class SipLoggerPass implements StackLogger {
    @Override
    public void logStackTrace() {
    }
    @Override
    public void logStackTrace(int traceLevel) {
    }
    @Override
    public int getLineCount() {
        return 0;
    }
    @Override
    public void logException(Throwable ex) {
    }
    @Override
    public void logDebug(String message) {
    }
    @Override
    public void logDebug(String message, Exception ex) {
    }
    @Override
    public void logTrace(String message) {
    }
    @Override
    public void logFatalError(String message) {
    }
    @Override
    public void logError(String message) {
    }
    @Override
    public boolean isLoggingEnabled() {
        return false;
    }
    @Override
    public boolean isLoggingEnabled(int logLevel) {
        return false;
    }
    @Override
    public void logError(String message, Exception ex) {
    }
    @Override
    public void logWarning(String string) {
    }
    @Override
    public void logInfo(String string) {
    }
    @Override
    public void disableLogging() {
    }
    @Override
    public void enableLogging() {
    }
    @Override
    public void setBuildTimeStamp(String buildTimeStamp) {
    }
    @Override
    public void setStackProperties(Properties stackProperties) {
    }
    @Override
    public String getLoggerName() {
        return null;
    }
}
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorObserver.java
@@ -28,7 +28,7 @@
    private final static Logger logger = LoggerFactory.getLogger(SIPProcessorObserver.class);
    private static Map<String, ISIPRequestProcessor> requestProcessorMap = new ConcurrentHashMap<>();
    private static Map<String,  ISIPRequestProcessor> requestProcessorMap = new ConcurrentHashMap<>();
    private static Map<String, ISIPResponseProcessor> responseProcessorMap = new ConcurrentHashMap<>();
    private static ITimeoutProcessor timeoutProcessor;
@@ -72,6 +72,9 @@
    @Async
    public void processRequest(RequestEvent requestEvent) {
        String method = requestEvent.getRequest().getMethod();
        if ("NOTIFY".equalsIgnoreCase(requestEvent.getRequest().getMethod())) {
            System.out.println();
        }
        ISIPRequestProcessor sipRequestProcessor = requestProcessorMap.get(method);
        if (sipRequestProcessor == null) {
            logger.warn("不支持方法{}的request", method);
@@ -91,7 +94,8 @@
        Response response = responseEvent.getResponse();
        int status = response.getStatusCode();
        if (((status >= 200) && (status < 300)) || status == Response.UNAUTHORIZED) { // Success!
        // Success
        if (((status >= Response.OK) && (status < Response.MULTIPLE_CHOICES)) || status == Response.UNAUTHORIZED) {
            CSeqHeader cseqHeader = (CSeqHeader) responseEvent.getResponse().getHeader(CSeqHeader.NAME);
            String method = cseqHeader.getMethod();
            ISIPResponseProcessor sipRequestProcessor = responseProcessorMap.get(method);
@@ -109,7 +113,7 @@
                    }
                }
            }
        } else if ((status >= 100) && (status < 200)) {
        } else if ((status >= Response.TRYING) && (status < Response.OK)) {
            // 增加其它无需回复的响应,如101、180等
        } else {
            logger.warn("接收到失败的response响应!status:" + status + ",message:" + response.getReasonPhrase());
@@ -151,7 +155,9 @@
                    logger.info("[发送错误订阅]");
                    SipSubscribe.Event subscribe = sipSubscribe.getErrorSubscribe(callIdHeader.getCallId());
                    SipSubscribe.EventResult eventResult = new SipSubscribe.EventResult(timeoutEvent);
                    subscribe.response(eventResult);
                    if (subscribe != null){
                        subscribe.response(eventResult);
                    }
                    sipSubscribe.removeOkSubscribe(callIdHeader.getCallId());
                    sipSubscribe.removeErrorSubscribe(callIdHeader.getCallId());
                }
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderPlarformProvider.java
@@ -146,12 +146,12 @@
        String cNonce = null;
        String nc = "00000001";
        if (qop != null) {
            if ("auth".equals(qop)) {
            if ("auth".equalsIgnoreCase(qop)) {
                // 客户端随机数,这是一个不透明的字符串值,由客户端提供,并且客户端和服务器都会使用,以避免用明文文本。
                // 这使得双方都可以查验对方的身份,并对消息的完整性提供一些保护
                cNonce = UUID.randomUUID().toString();
            }else if ("auth-int".equals(qop)){
            }else if ("auth-int".equalsIgnoreCase(qop)){
                // TODO
            }
        }
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
@@ -249,7 +249,7 @@
            
            String tm = Long.toString(System.currentTimeMillis());
            CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
            CallIdHeader callIdHeader = device.getTransport().equalsIgnoreCase("TCP") ? tcpSipProvider.getNewCallId()
                    : udpSipProvider.getNewCallId();
            Request request = headerProvider.createMessageRequest(device, ptzXml.toString(), "z9hG4bK-ViaPtz-" + tm, "FromPtz" + tm, null, callIdHeader);
@@ -292,7 +292,7 @@
            
            String tm = Long.toString(System.currentTimeMillis());
            CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
            CallIdHeader callIdHeader = device.getTransport().equalsIgnoreCase("TCP") ? tcpSipProvider.getNewCallId()
                    : udpSipProvider.getNewCallId();
            Request request = headerProvider.createMessageRequest(device, ptzXml.toString(), "z9hG4bK-ViaPtz-" + tm, "FromPtz" + tm, null, callIdHeader);
@@ -328,7 +328,7 @@
            
            String tm = Long.toString(System.currentTimeMillis());
            CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
            CallIdHeader callIdHeader = device.getTransport().equalsIgnoreCase("TCP") ? tcpSipProvider.getNewCallId()
                    : udpSipProvider.getNewCallId();
            Request request = headerProvider.createMessageRequest(device, ptzXml.toString(), "z9hG4bK-ViaPtz-" + tm, "FromPtz" + tm, null, callIdHeader);
@@ -355,7 +355,7 @@
            if (device == null) {
                return;
            }
            String streamMode = device.getStreamMode().toUpperCase();
//            String streamMode = device.getStreamMode().toUpperCase();
            logger.info("{} 分配的ZLM为: {} [{}:{}]", stream, mediaServerItem.getId(), mediaServerItem.getIp(), ssrcInfo.getPort());
            HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", stream, true, "rtmp", mediaServerItem.getId());
@@ -374,11 +374,11 @@
            content.append("t=0 0\r\n");
            if (userSetting.isSeniorSdp()) {
                if("TCP-PASSIVE".equals(streamMode)) {
                if("TCP-PASSIVE".equalsIgnoreCase(device.getStreamMode())) {
                    content.append("m=video "+ ssrcInfo.getPort() +" TCP/RTP/AVP 96 126 125 99 34 98 97\r\n");
                }else if ("TCP-ACTIVE".equals(streamMode)) {
                }else if ("TCP-ACTIVE".equalsIgnoreCase(device.getStreamMode())) {
                    content.append("m=video "+ ssrcInfo.getPort() +" TCP/RTP/AVP 96 126 125 99 34 98 97\r\n");
                }else if("UDP".equals(streamMode)) {
                }else if("UDP".equalsIgnoreCase(device.getStreamMode())) {
                    content.append("m=video "+ ssrcInfo.getPort() +" RTP/AVP 96 126 125 99 34 98 97\r\n");
                }
                content.append("a=recvonly\r\n");
@@ -390,19 +390,19 @@
                content.append("a=rtpmap:99 H265/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被动模式
                if("TCP-PASSIVE".equalsIgnoreCase(device.getStreamMode())){ // tcp被动模式
                    content.append("a=setup:passive\r\n");
                    content.append("a=connection:new\r\n");
                }else if ("TCP-ACTIVE".equals(streamMode)) { // tcp主动模式
                }else if ("TCP-ACTIVE".equalsIgnoreCase(device.getStreamMode())) { // tcp主动模式
                    content.append("a=setup:active\r\n");
                    content.append("a=connection:new\r\n");
                }
            }else {
                if("TCP-PASSIVE".equals(streamMode)) {
                if("TCP-PASSIVE".equalsIgnoreCase(device.getStreamMode())) {
                    content.append("m=video "+ ssrcInfo.getPort() +" TCP/RTP/AVP 96 97 98 99\r\n");
                }else if ("TCP-ACTIVE".equals(streamMode)) {
                }else if ("TCP-ACTIVE".equalsIgnoreCase(device.getStreamMode())) {
                    content.append("m=video "+ ssrcInfo.getPort() +" TCP/RTP/AVP 96 97 98 99\r\n");
                }else if("UDP".equals(streamMode)) {
                }else if("UDP".equalsIgnoreCase(device.getStreamMode())) {
                    content.append("m=video "+ ssrcInfo.getPort() +" RTP/AVP 96 97 98 99\r\n");
                }
                content.append("a=recvonly\r\n");
@@ -410,10 +410,10 @@
                content.append("a=rtpmap:98 H264/90000\r\n");
                content.append("a=rtpmap:97 MPEG4/90000\r\n");
                content.append("a=rtpmap:99 H265/90000\r\n");
                if ("TCP-PASSIVE".equals(streamMode)) { // tcp被动模式
                if ("TCP-PASSIVE".equalsIgnoreCase(device.getStreamMode())) { // tcp被动模式
                    content.append("a=setup:passive\r\n");
                    content.append("a=connection:new\r\n");
                } else if ("TCP-ACTIVE".equals(streamMode)) { // tcp主动模式
                } else if ("TCP-ACTIVE".equalsIgnoreCase(device.getStreamMode())) { // tcp主动模式
                    content.append("a=setup:active\r\n");
                    content.append("a=connection:new\r\n");
                }
@@ -425,7 +425,7 @@
            String tm = Long.toString(System.currentTimeMillis());
            CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
            CallIdHeader callIdHeader = device.getTransport().equalsIgnoreCase("TCP") ? tcpSipProvider.getNewCallId()
                    : udpSipProvider.getNewCallId();
            Request request = headerProvider.createInviteRequest(device, channelId, content.toString(), null, "FromInvt" + tm, null, ssrcInfo.getSsrc(), callIdHeader);
@@ -472,14 +472,14 @@
            content.append("t="+DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(startTime)+" "
                    +DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(endTime) +"\r\n");
            String streamMode = device.getStreamMode().toUpperCase();
            String streamMode = device.getStreamMode();
            if (userSetting.isSeniorSdp()) {
                if("TCP-PASSIVE".equals(streamMode)) {
                if("TCP-PASSIVE".equalsIgnoreCase(streamMode)) {
                    content.append("m=video "+ ssrcInfo.getPort() +" TCP/RTP/AVP 96 126 125 99 34 98 97\r\n");
                }else if ("TCP-ACTIVE".equals(streamMode)) {
                }else if ("TCP-ACTIVE".equalsIgnoreCase(streamMode)) {
                    content.append("m=video "+ ssrcInfo.getPort() +" TCP/RTP/AVP 96 126 125 99 34 98 97\r\n");
                }else if("UDP".equals(streamMode)) {
                }else if("UDP".equalsIgnoreCase(streamMode)) {
                    content.append("m=video "+ ssrcInfo.getPort() +" RTP/AVP 96 126 125 99 34 98 97\r\n");
                }
                content.append("a=recvonly\r\n");
@@ -491,19 +491,19 @@
                content.append("a=rtpmap:99 H265/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被动模式
                if("TCP-PASSIVE".equalsIgnoreCase(streamMode)){ // tcp被动模式
                    content.append("a=setup:passive\r\n");
                    content.append("a=connection:new\r\n");
                }else if ("TCP-ACTIVE".equals(streamMode)) { // tcp主动模式
                }else if ("TCP-ACTIVE".equalsIgnoreCase(streamMode)) { // tcp主动模式
                    content.append("a=setup:active\r\n");
                    content.append("a=connection:new\r\n");
                }
            }else {
                if("TCP-PASSIVE".equals(streamMode)) {
                if("TCP-PASSIVE".equalsIgnoreCase(streamMode)) {
                    content.append("m=video "+ ssrcInfo.getPort() +" TCP/RTP/AVP 96 97 98 99\r\n");
                }else if ("TCP-ACTIVE".equals(streamMode)) {
                }else if ("TCP-ACTIVE".equalsIgnoreCase(streamMode)) {
                    content.append("m=video "+ ssrcInfo.getPort() +" TCP/RTP/AVP 96 97 98 99\r\n");
                }else if("UDP".equals(streamMode)) {
                }else if("UDP".equalsIgnoreCase(streamMode)) {
                    content.append("m=video "+ ssrcInfo.getPort() +" RTP/AVP 96 97 98 99\r\n");
                }
                content.append("a=recvonly\r\n");
@@ -511,10 +511,10 @@
                content.append("a=rtpmap:97 MPEG4/90000\r\n");
                content.append("a=rtpmap:98 H264/90000\r\n");
                content.append("a=rtpmap:99 H265/90000\r\n");
                if("TCP-PASSIVE".equals(streamMode)){ // tcp被动模式
                if("TCP-PASSIVE".equalsIgnoreCase(streamMode)){ // tcp被动模式
                    content.append("a=setup:passive\r\n");
                    content.append("a=connection:new\r\n");
                }else if ("TCP-ACTIVE".equals(streamMode)) { // tcp主动模式
                }else if ("TCP-ACTIVE".equalsIgnoreCase(streamMode)) { // tcp主动模式
                    content.append("a=setup:active\r\n");
                    content.append("a=connection:new\r\n");
                }
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommanderFroPlatform.java
@@ -93,10 +93,10 @@
            String tm = Long.toString(System.currentTimeMillis());
            if (!registerAgain ) {
                CallIdHeader callIdHeader = null;
                if(parentPlatform.getTransport().equals("TCP")) {
                if(parentPlatform.getTransport().equalsIgnoreCase("TCP")) {
                    callIdHeader = tcpSipProvider.getNewCallId();
                }
                if(parentPlatform.getTransport().equals("UDP")) {
                if(parentPlatform.getTransport().equalsIgnoreCase("UDP")) {
                    callIdHeader = udpSipProvider.getNewCallId();
                }
@@ -120,7 +120,7 @@
                });
            }else {
                CallIdHeader callIdHeader = parentPlatform.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
                CallIdHeader callIdHeader = parentPlatform.getTransport().equalsIgnoreCase("TCP") ? tcpSipProvider.getNewCallId()
                        : udpSipProvider.getNewCallId();
                request = headerProviderPlarformProvider.createRegisterRequest(parentPlatform, "FromRegister" + tm, null, callId, www, callIdHeader, isRegister);
            }
@@ -153,7 +153,7 @@
            keepaliveXml.append("<Status>OK</Status>\r\n");
            keepaliveXml.append("</Notify>\r\n");
            CallIdHeader callIdHeader = parentPlatform.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
            CallIdHeader callIdHeader = parentPlatform.getTransport().equalsIgnoreCase("TCP") ? tcpSipProvider.getNewCallId()
                    : udpSipProvider.getNewCallId();
            Request request = headerProviderPlarformProvider.createKeetpaliveMessageRequest(
@@ -181,10 +181,10 @@
    private void transmitRequest(ParentPlatform parentPlatform, Request request, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent) throws SipException {
        logger.debug("\n发送消息:\n{}", request);
        if("TCP".equals(parentPlatform.getTransport())) {
        if("TCP".equalsIgnoreCase(parentPlatform.getTransport())) {
            tcpSipProvider.sendRequest(request);
        } else if("UDP".equals(parentPlatform.getTransport())) {
        } else if("UDP".equalsIgnoreCase(parentPlatform.getTransport())) {
            udpSipProvider.sendRequest(request);
        }
@@ -220,7 +220,7 @@
            String catalogXml = getCatalogXml(channels, sn, parentPlatform, size);
            // callid
            CallIdHeader callIdHeader = parentPlatform.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
            CallIdHeader callIdHeader = parentPlatform.getTransport().equalsIgnoreCase("TCP") ? tcpSipProvider.getNewCallId()
                    : udpSipProvider.getNewCallId();
            Request request = headerProviderPlarformProvider.createMessageRequest(parentPlatform, catalogXml.toString(), fromTag, callIdHeader);
@@ -306,7 +306,7 @@
            }
            String catalogXml = getCatalogXml(deviceChannels, sn, parentPlatform, channels.size());
            // callid
            CallIdHeader callIdHeader = parentPlatform.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
            CallIdHeader callIdHeader = parentPlatform.getTransport().equalsIgnoreCase("TCP") ? tcpSipProvider.getNewCallId()
                    : udpSipProvider.getNewCallId();
            Request request = headerProviderPlarformProvider.createMessageRequest(parentPlatform, catalogXml, fromTag, callIdHeader);
@@ -346,7 +346,7 @@
            deviceInfoXml.append("<Result>OK</Result>\r\n");
            deviceInfoXml.append("</Response>\r\n");
            CallIdHeader callIdHeader = parentPlatform.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
            CallIdHeader callIdHeader = parentPlatform.getTransport().equalsIgnoreCase("TCP") ? tcpSipProvider.getNewCallId()
                    : udpSipProvider.getNewCallId();
            Request request = headerProviderPlarformProvider.createMessageRequest(parentPlatform, deviceInfoXml.toString(), fromTag, callIdHeader);
@@ -384,7 +384,7 @@
            deviceStatusXml.append("<Status>OK</Status>\r\n");
            deviceStatusXml.append("</Response>\r\n");
            CallIdHeader callIdHeader = parentPlatform.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
            CallIdHeader callIdHeader = parentPlatform.getTransport().equalsIgnoreCase("TCP") ? tcpSipProvider.getNewCallId()
                    : udpSipProvider.getNewCallId();
            Request request = headerProviderPlarformProvider.createMessageRequest(parentPlatform, deviceStatusXml.toString(), fromTag, callIdHeader);
@@ -422,7 +422,7 @@
            deviceStatusXml.append("<Altitude>" + gpsMsgInfo.getAltitude() + "</Altitude>\r\n");
            deviceStatusXml.append("</Notify>\r\n");
            CallIdHeader callIdHeader = parentPlatform.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
            CallIdHeader callIdHeader = parentPlatform.getTransport().equalsIgnoreCase("TCP") ? tcpSipProvider.getNewCallId()
                    : udpSipProvider.getNewCallId();
            callIdHeader.setCallId(subscribeInfo.getCallId());
@@ -467,7 +467,7 @@
            deviceStatusXml.append("</info>\r\n");
            deviceStatusXml.append("</Notify>\r\n");
            CallIdHeader callIdHeader = parentPlatform.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
            CallIdHeader callIdHeader = parentPlatform.getTransport().equalsIgnoreCase("TCP") ? tcpSipProvider.getNewCallId()
                    : udpSipProvider.getNewCallId();
            String tm = Long.toString(System.currentTimeMillis());
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/SIPRequestProcessorParent.java
@@ -139,7 +139,7 @@
            return;
        }
        serverTransaction.sendResponse(response);
        if (statusCode >= 200 && !"NOTIFY".equals(evt.getRequest().getMethod())) {
        if (statusCode >= 200 && !"NOTIFY".equalsIgnoreCase(evt.getRequest().getMethod())) {
            if (serverTransaction.getDialog() != null) {
                serverTransaction.getDialog().delete();
@@ -152,7 +152,7 @@
        response.setReasonPhrase(msg);
        ServerTransaction serverTransaction = getServerTransaction(evt);
        serverTransaction.sendResponse(response);
        if (statusCode >= 200 && !"NOTIFY".equals(evt.getRequest().getMethod())) {
        if (statusCode >= 200 && !"NOTIFY".equalsIgnoreCase(evt.getRequest().getMethod())) {
            if (serverTransaction.getDialog() != null) {
                serverTransaction.getDialog().delete();
            }
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java
@@ -278,16 +278,16 @@
                        String protocol = media.getProtocol();
                        // 区分TCP发流还是udp, 当前默认udp
                        if ("TCP/RTP/AVP".equals(protocol)) {
                        if ("TCP/RTP/AVP".equalsIgnoreCase(protocol)) {
                            String setup = mediaDescription.getAttribute("setup");
                            if (setup != null) {
                                mediaTransmissionTCP = true;
                                if ("active".equals(setup)) {
                                if ("active".equalsIgnoreCase(setup)) {
                                    tcpActive = true;
                                    // 不支持tcp主动
                                    responseAck(evt, Response.NOT_IMPLEMENTED, "tcp active not support"); // 目录不支持点播
                                    return;
                                } else if ("passive".equals(setup)) {
                                } else if ("passive".equalsIgnoreCase(setup)) {
                                    tcpActive = false;
                                }
                            }
@@ -332,7 +332,7 @@
                        return;
                    }
                    sendRtpItem.setCallId(callIdHeader.getCallId());
                    sendRtpItem.setPlayType("Play".equals(sessionName) ? InviteStreamType.PLAY : InviteStreamType.PLAYBACK);
                    sendRtpItem.setPlayType("Play".equalsIgnoreCase(sessionName) ? InviteStreamType.PLAY : InviteStreamType.PLAYBACK);
                    Long finalStartTime = startTime;
                    Long finalStopTime = stopTime;
@@ -351,7 +351,7 @@
                        content.append("o=" + channelId + " 0 0 IN IP4 " + mediaServerItemInUSe.getSdpIp() + "\r\n");
                        content.append("s=" + sessionName + "\r\n");
                        content.append("c=IN IP4 " + mediaServerItemInUSe.getSdpIp() + "\r\n");
                        if ("Playback".equals(sessionName)) {
                        if ("Playback".equalsIgnoreCase(sessionName)) {
                            content.append("t=" + finalStartTime + " " + finalStopTime + "\r\n");
                        } else {
                            content.append("t=0 0\r\n");
@@ -395,7 +395,7 @@
                        }
                    });
                    sendRtpItem.setApp("rtp");
                    if ("Playback".equals(sessionName)) {
                    if ("Playback".equalsIgnoreCase(sessionName)) {
                        sendRtpItem.setPlayType(InviteStreamType.PLAYBACK);
                        SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, null, true, true);
                        sendRtpItem.setStreamId(ssrcInfo.getStream());
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java
@@ -159,7 +159,7 @@
                // 判断TCP还是UDP
                ViaHeader reqViaHeader = (ViaHeader) request.getHeader(ViaHeader.NAME);
                String transport = reqViaHeader.getTransport();
                device.setTransport("TCP".equals(transport) ? "TCP" : "UDP");
                device.setTransport("TCP".equalsIgnoreCase(transport) ? "TCP" : "UDP");
            }
            sendResponse(evt, response);
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/SubscribeRequestProcessor.java
@@ -132,7 +132,7 @@
            return;
        }
        if (evt.getServerTransaction() == null) {
            ServerTransaction serverTransaction = "TCP".equals(platform.getTransport()) ? tcpSipProvider.getNewServerTransaction(evt.getRequest())
            ServerTransaction serverTransaction = "TCP".equalsIgnoreCase(platform.getTransport()) ? tcpSipProvider.getNewServerTransaction(evt.getRequest())
                    : udpSipProvider.getNewServerTransaction(evt.getRequest());
            subscribeInfo.setTransaction(serverTransaction);
            Dialog dialog = serverTransaction.getDialog();
@@ -188,7 +188,7 @@
        }
        SubscribeInfo subscribeInfo = new SubscribeInfo(evt, platformId);
        if (evt.getServerTransaction() == null) {
            ServerTransaction serverTransaction = "TCP".equals(platform.getTransport()) ? tcpSipProvider.getNewServerTransaction(evt.getRequest())
            ServerTransaction serverTransaction = "TCP".equalsIgnoreCase(platform.getTransport()) ? tcpSipProvider.getNewServerTransaction(evt.getRequest())
                    : udpSipProvider.getNewServerTransaction(evt.getRequest());
            subscribeInfo.setTransaction(serverTransaction);
            Dialog dialog = serverTransaction.getDialog();
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/info/InfoRequestProcessor.java
@@ -96,7 +96,7 @@
                ContentTypeHeader header = (ContentTypeHeader)evt.getRequest().getHeader(ContentTypeHeader.NAME);
                String contentType = header.getContentType();
                String contentSubType = header.getContentSubType();
                if ("Application".equals(contentType) && "MANSRTSP".equals(contentSubType)) {
                if ("Application".equalsIgnoreCase(contentType) && "MANSRTSP".equalsIgnoreCase(contentSubType)) {
                    SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(null, null, null, callIdHeader.getCallId());
                    String streamId = sendRtpItem.getStreamId();
                    StreamInfo streamInfo = redisCatchStorage.queryPlayback(null, null, streamId, null);
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/DeviceStatusResponseMessageHandler.java
@@ -76,7 +76,7 @@
            logger.debug(json.toJSONString());
        }
        String text = onlineElement.getText();
        if (Objects.equals(text.trim().toUpperCase(), "ONLINE")) {
        if ("ONLINE".equalsIgnoreCase(text.trim())) {
            deviceService.online(device);
        }else {
            deviceService.offline(device.getDeviceId());
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/PresetQueryResponseMessageHandler.java
@@ -77,7 +77,7 @@
                                Element itemOne = itemListIterator.next();
                                String name = itemOne.getName();
                                String textTrim = itemOne.getTextTrim();
                                if("PresetID".equals(name)){
                                if("PresetID".equalsIgnoreCase(name)){
                                    presetQuerySipReq.setPresetId(textTrim);
                                }else {
                                    presetQuerySipReq.setPresetName(textTrim);
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java
@@ -103,7 +103,7 @@
     */
    @ResponseBody
    @PostMapping(value = "/on_server_keepalive", produces = "application/json;charset=UTF-8")
    public ResponseEntity<String> onServerKeepalive(@RequestBody JSONObject json){
    public JSONObject onServerKeepalive(@RequestBody JSONObject json){
        logger.info("[ ZLM HOOK ] on_server_keepalive API调用,参数:" + json.toString());
        String mediaServerId = json.getString("mediaServerId");
@@ -118,7 +118,8 @@
        JSONObject ret = new JSONObject();
        ret.put("code", 0);
        ret.put("msg", "success");
        return new ResponseEntity<String>(ret.toString(),HttpStatus.OK);
        return ret;
    }
    /**
@@ -127,16 +128,15 @@
     */
    @ResponseBody
    @PostMapping(value = "/on_flow_report", produces = "application/json;charset=UTF-8")
    public ResponseEntity<String> onFlowReport(@RequestBody JSONObject json){
    public JSONObject onFlowReport(@RequestBody JSONObject json){
        
        if (logger.isDebugEnabled()) {
            logger.debug("[ ZLM HOOK ]on_flow_report API调用,参数:" + json.toString());
        }
        String mediaServerId = json.getString("mediaServerId");
        JSONObject ret = new JSONObject();
        ret.put("code", 0);
        ret.put("msg", "success");
        return new ResponseEntity<String>(ret.toString(),HttpStatus.OK);
        return ret;
    }
    
    /**
@@ -145,7 +145,7 @@
     */
    @ResponseBody
    @PostMapping(value = "/on_http_access", produces = "application/json;charset=UTF-8")
    public ResponseEntity<String> onHttpAccess(@RequestBody JSONObject json){
    public JSONObject onHttpAccess(@RequestBody JSONObject json){
        
        if (logger.isDebugEnabled()) {
            logger.debug("[ ZLM HOOK ]on_http_access API 调用,参数:" + json.toString());
@@ -156,7 +156,7 @@
        ret.put("err", "");
        ret.put("path", "");
        ret.put("second", 600);
        return new ResponseEntity<String>(ret.toString(),HttpStatus.OK);
        return ret;
    }
    
    /**
@@ -165,7 +165,7 @@
     */
    @ResponseBody
    @PostMapping(value = "/on_play", produces = "application/json;charset=UTF-8")
    public ResponseEntity<String> onPlay(@RequestBody OnPlayHookParam param){
    public JSONObject onPlay(@RequestBody OnPlayHookParam param){
        JSONObject json = (JSONObject)JSON.toJSON(param);
@@ -184,17 +184,16 @@
        if (!"rtp".equals(param.getApp())) {
            Map<String, String> paramMap = urlParamToMap(param.getParams());
            StreamAuthorityInfo streamAuthorityInfo = redisCatchStorage.getStreamAuthorityInfo(param.getApp(), param.getStream());
            if (streamAuthorityInfo == null
                    || (streamAuthorityInfo.getCallId() != null && !streamAuthorityInfo.getCallId().equals(paramMap.get("callId")))) {
            if (streamAuthorityInfo != null && streamAuthorityInfo.getCallId() != null && !streamAuthorityInfo.getCallId().equals(paramMap.get("callId"))) {
                ret.put("code", 401);
                ret.put("msg", "Unauthorized");
                return new ResponseEntity<>(ret.toString(),HttpStatus.OK);
                return ret;
            }
        }
        ret.put("code", 0);
        ret.put("msg", "success");
        return new ResponseEntity<>(ret.toString(),HttpStatus.OK);
        return ret;
    }
    
    /**
@@ -203,7 +202,7 @@
     */
    @ResponseBody
    @PostMapping(value = "/on_publish", produces = "application/json;charset=UTF-8")
    public ResponseEntity<String> onPublish(@RequestBody OnPublishHookParam param) {
    public JSONObject onPublish(@RequestBody OnPublishHookParam param) {
        JSONObject json = (JSONObject) JSON.toJSON(param);
@@ -217,7 +216,7 @@
                logger.info("推流鉴权失败: 缺少不要参数:sign=md5(user表的pushKey)");
                ret.put("code", 401);
                ret.put("msg", "Unauthorized");
                return new ResponseEntity<>(ret.toString(), HttpStatus.OK);
                return ret;
            }
            Map<String, String> paramMap = urlParamToMap(param.getParams());
            String sign = paramMap.get("sign");
@@ -225,7 +224,7 @@
                logger.info("推流鉴权失败: 缺少不要参数:sign=md5(user表的pushKey)");
                ret.put("code", 401);
                ret.put("msg", "Unauthorized");
                return new ResponseEntity<>(ret.toString(), HttpStatus.OK);
                return ret;
            }
            // 推流自定义播放鉴权码
            String callId = paramMap.get("callId");
@@ -235,7 +234,7 @@
                logger.info("推流鉴权失败: sign 无权限: callId={}. sign={}", callId, sign);
                ret.put("code", 401);
                ret.put("msg", "Unauthorized");
                return new ResponseEntity<>(ret.toString(), HttpStatus.OK);
                return ret;
            }
            StreamAuthorityInfo streamAuthorityInfo = StreamAuthorityInfo.getInstanceByHook(param);
            streamAuthorityInfo.setCallId(callId);
@@ -243,11 +242,11 @@
            // 鉴权通过
            redisCatchStorage.updateStreamAuthorityInfo(param.getApp(), param.getStream(), streamAuthorityInfo);
            // 通知assist新的callId
            taskExecutor.execute(()->{
                if (mediaInfo != null && mediaInfo.getRecordAssistPort() > 0) {
            if (mediaInfo != null && mediaInfo.getRecordAssistPort() > 0) {
                taskExecutor.execute(()->{
                    assistRESTfulUtils.addStreamCallInfo(mediaInfo, param.getApp(), param.getStream(), callId, null);
                }
            });
                });
            }
        }else {
            zlmMediaListManager.sendStreamEvent(param.getApp(),param.getStream(), param.getMediaServerId());
        }
@@ -291,10 +290,7 @@
            }
        }
        return new ResponseEntity<String>(ret.toString(), HttpStatus.OK);
        return ret;
    }
@@ -305,7 +301,7 @@
     */
    @ResponseBody
    @PostMapping(value = "/on_record_mp4", produces = "application/json;charset=UTF-8")
    public ResponseEntity<String> onRecordMp4(@RequestBody JSONObject json){
    public JSONObject onRecordMp4(@RequestBody JSONObject json){
        
        if (logger.isDebugEnabled()) {
            logger.debug("[ ZLM HOOK ]on_record_mp4 API调用,参数:" + json.toString());
@@ -314,7 +310,7 @@
        JSONObject ret = new JSONObject();
        ret.put("code", 0);
        ret.put("msg", "success");
        return new ResponseEntity<String>(ret.toString(),HttpStatus.OK);
        return ret;
    }
    /**
     * 录制hls完成后通知事件;此事件对回复不敏感。
@@ -322,7 +318,7 @@
     */
    @ResponseBody
    @PostMapping(value = "/on_record_ts", produces = "application/json;charset=UTF-8")
    public ResponseEntity<String> onRecordTs(@RequestBody JSONObject json){
    public JSONObject onRecordTs(@RequestBody JSONObject json){
        if (logger.isDebugEnabled()) {
            logger.debug("[ ZLM HOOK ]on_record_ts API调用,参数:" + json.toString());
@@ -331,7 +327,7 @@
        JSONObject ret = new JSONObject();
        ret.put("code", 0);
        ret.put("msg", "success");
        return new ResponseEntity<String>(ret.toString(),HttpStatus.OK);
        return ret;
    }
    
    /**
@@ -340,7 +336,7 @@
     */
    @ResponseBody
    @PostMapping(value = "/on_rtsp_realm", produces = "application/json;charset=UTF-8")
    public ResponseEntity<String> onRtspRealm(@RequestBody JSONObject json){
    public JSONObject onRtspRealm(@RequestBody JSONObject json){
        
        if (logger.isDebugEnabled()) {
            logger.debug("[ ZLM HOOK ]on_rtsp_realm API调用,参数:" + json.toString());
@@ -349,7 +345,7 @@
        JSONObject ret = new JSONObject();
        ret.put("code", 0);
        ret.put("realm", "");
        return new ResponseEntity<String>(ret.toString(),HttpStatus.OK);
        return ret;
    }
    
    
@@ -359,7 +355,7 @@
     */
    @ResponseBody
    @PostMapping(value = "/on_rtsp_auth", produces = "application/json;charset=UTF-8")
    public ResponseEntity<String> onRtspAuth(@RequestBody JSONObject json){
    public JSONObject onRtspAuth(@RequestBody JSONObject json){
        
        if (logger.isDebugEnabled()) {
            logger.debug("[ ZLM HOOK ]on_rtsp_auth API调用,参数:" + json.toString());
@@ -369,7 +365,7 @@
        ret.put("code", 0);
        ret.put("encrypted", false);
        ret.put("passwd", "test");
        return new ResponseEntity<String>(ret.toString(),HttpStatus.OK);
        return ret;
    }
    
    /**
@@ -378,7 +374,7 @@
     */
    @ResponseBody
    @PostMapping(value = "/on_shell_login", produces = "application/json;charset=UTF-8")
    public ResponseEntity<String> onShellLogin(@RequestBody JSONObject json){
    public JSONObject onShellLogin(@RequestBody JSONObject json){
        
        if (logger.isDebugEnabled()) {
            logger.debug("[ ZLM HOOK ]on_shell_login API调用,参数:" + json.toString());
@@ -396,7 +392,7 @@
        JSONObject ret = new JSONObject();
        ret.put("code", 0);
        ret.put("msg", "success");
        return new ResponseEntity<String>(ret.toString(),HttpStatus.OK);
        return ret;
    }
    
    /**
@@ -405,7 +401,7 @@
     */
    @ResponseBody
    @PostMapping(value = "/on_stream_changed", produces = "application/json;charset=UTF-8")
    public ResponseEntity<String> onStreamChanged(@RequestBody MediaItem item){
    public JSONObject onStreamChanged(@RequestBody MediaItem item){
        logger.info("[ ZLM HOOK ]on_stream_changed API调用,参数:" + JSONObject.toJSONString(item));
        String mediaServerId = item.getMediaServerId();
@@ -475,8 +471,12 @@
                    if (mediaServerItem != null){
                        if (regist) {
                            StreamAuthorityInfo streamAuthorityInfo = redisCatchStorage.getStreamAuthorityInfo(app, stream);
                            String callId = null;
                            if (streamAuthorityInfo != null) {
                                callId = streamAuthorityInfo.getCallId();
                            }
                            StreamInfo streamInfoByAppAndStream = mediaService.getStreamInfoByAppAndStream(mediaServerItem,
                                    app, stream, tracks, streamAuthorityInfo.getCallId());
                                    app, stream, tracks, callId);
                            item.setStreamInfo(streamInfoByAppAndStream);
                            redisCatchStorage.addStream(mediaServerItem, type, app, stream, item);
                            if (item.getOriginType() == OriginType.RTSP_PUSH.ordinal()
@@ -516,7 +516,7 @@
        JSONObject ret = new JSONObject();
        ret.put("code", 0);
        ret.put("msg", "success");
        return new ResponseEntity<String>(ret.toString(),HttpStatus.OK);
        return ret;
    }
    
    /**
@@ -525,7 +525,7 @@
     */
    @ResponseBody
    @PostMapping(value = "/on_stream_none_reader", produces = "application/json;charset=UTF-8")
    public ResponseEntity<String> onStreamNoneReader(@RequestBody JSONObject json){
    public JSONObject onStreamNoneReader(@RequestBody JSONObject json){
        logger.info("[ ZLM HOOK ]on_stream_none_reader API调用,参数:" + json.toString());
        String mediaServerId = json.getString("mediaServerId");
@@ -570,7 +570,7 @@
            if (mediaServerItem != null && mediaServerItem.getStreamNoneReaderDelayMS() == -1) {
                ret.put("close", false);
            }
            return new ResponseEntity<String>(ret.toString(),HttpStatus.OK);
            return ret;
        }else {
            StreamProxyItem streamProxyItem = streamProxyService.getStreamProxyByAppAndStream(app, streamId);
            if (streamProxyItem != null && streamProxyItem.isEnable_remove_none_reader()) {
@@ -581,7 +581,7 @@
            }else {
                ret.put("close", false);
            }
            return new ResponseEntity<String>(ret.toString(),HttpStatus.OK);
            return ret;
        }
    }
    
@@ -591,7 +591,7 @@
     */
    @ResponseBody
    @PostMapping(value = "/on_stream_not_found", produces = "application/json;charset=UTF-8")
    public ResponseEntity<String> onStreamNotFound(@RequestBody JSONObject json){
    public JSONObject onStreamNotFound(@RequestBody JSONObject json){
        if (logger.isDebugEnabled()) {
            logger.debug("[ ZLM HOOK ]on_stream_not_found API调用,参数:" + json.toString());
        }
@@ -616,7 +616,7 @@
        JSONObject ret = new JSONObject();
        ret.put("code", 0);
        ret.put("msg", "success");
        return new ResponseEntity<>(ret.toString(),HttpStatus.OK);
        return ret;
    }
    
    /**
@@ -625,7 +625,7 @@
     */
    @ResponseBody
    @PostMapping(value = "/on_server_started", produces = "application/json;charset=UTF-8")
    public ResponseEntity<String> onServerStarted(HttpServletRequest request, @RequestBody JSONObject jsonObject){
    public JSONObject onServerStarted(HttpServletRequest request, @RequestBody JSONObject jsonObject){
        
        if (logger.isDebugEnabled()) {
            logger.debug("[ ZLM HOOK ]on_server_started API调用,参数:" + jsonObject.toString());
@@ -646,7 +646,7 @@
        JSONObject ret = new JSONObject();
        ret.put("code", 0);
        ret.put("msg", "success");
        return new ResponseEntity<>(ret.toString(),HttpStatus.OK);
        return ret;
    }
    private Map<String, String> urlParamToMap(String params) {
src/main/java/com/genersoft/iot/vmp/service/impl/MediaServiceImpl.java
@@ -25,7 +25,11 @@
    private IRedisCatchStorage redisCatchStorage;
    @Autowired
    private IVideoManagerStorage storager;
    @Autowired
    private IMediaServerService mediaServerService;
    @Autowired
    private MediaConfig mediaConfig;
@@ -50,9 +54,10 @@
        if (mediaInfo == null) {
            return null;
        }
        String calld = null;
        StreamAuthorityInfo streamAuthorityInfo = redisCatchStorage.getStreamAuthorityInfo(app, stream);
        if (streamAuthorityInfo == null) {
            return null;
        if (streamAuthorityInfo != null) {
            calld = streamAuthorityInfo.getCallId();
        }
        JSONObject mediaList = zlmresTfulUtils.getMediaList(mediaInfo, app, stream);
        if (mediaList != null) {
@@ -64,7 +69,7 @@
                JSONObject mediaJSON = JSON.parseObject(JSON.toJSONString(data.get(0)), JSONObject.class);
                JSONArray tracks = mediaJSON.getJSONArray("tracks");
                if (authority) {
                    streamInfo = getStreamInfoByAppAndStream(mediaInfo, app, stream, tracks, addr,streamAuthorityInfo.getCallId(), true);
                    streamInfo = getStreamInfoByAppAndStream(mediaInfo, app, stream, tracks, addr, calld);
                }else {
                    streamInfo = getStreamInfoByAppAndStream(mediaInfo, app, stream, tracks, addr,null, true);
                }
src/main/java/com/genersoft/iot/vmp/service/impl/PlatformServiceImpl.java
@@ -125,7 +125,7 @@
        dynamicTask.startDelay(registerTaskKey,
                // 注册失败(注册成功时由程序直接调用了online方法)
                ()->commanderForPlatform.register(parentPlatform, eventResult -> offline(parentPlatform),null),
                parentPlatform.getExpires()*1000);
                (parentPlatform.getExpires() - 10) *1000);
        final String keepaliveTaskKey = KEEPALIVE_KEY_PREFIX + parentPlatform.getServerGBId();
        if (!dynamicTask.contains(keepaliveTaskKey)) {
@@ -164,7 +164,7 @@
                            redisCatchStorage.updatePlatformCatchInfo(platformCatch);
                        }
                    }),
                    parentPlatform.getExpires()*1000);
                    (parentPlatform.getKeepTimeout() - 10)*1000);
        }
    }
@@ -213,7 +213,6 @@
                param.put("stream", sendRtpItem.getStreamId());
                zlmrtpServerFactory.stopSendRtpStream(mediaInfo, param);
            }
        }
    }
src/main/java/com/genersoft/iot/vmp/service/impl/StreamProxyServiceImpl.java
@@ -290,7 +290,7 @@
    public boolean start(String app, String stream) {
        boolean result = false;
        StreamProxyItem streamProxy = videoManagerStorager.queryStreamProxy(app, stream);
        if (!streamProxy.isEnable() ) {
        if (streamProxy != null && !streamProxy.isEnable() ) {
            JSONObject jsonObject = addStreamProxyToZlm(streamProxy);
            if (jsonObject == null) {
                return false;
src/main/java/com/genersoft/iot/vmp/storager/dao/StreamPushMapper.java
@@ -76,8 +76,8 @@
            "WHERE " +
            "1=1 " +
            " <if test='query != null'> AND (st.app LIKE '%${query}%' OR st.stream LIKE '%${query}%' OR gs.gbId LIKE '%${query}%' OR gs.name LIKE '%${query}%')</if> " +
            " <if test='pushing == true' > AND (gs.gbId is null OR st.status=1)</if>" +
            " <if test='pushing == false' > AND st.status=0</if>" +
            " <if test='pushing == true' > AND (gs.gbId is null OR st.pushIng=1)</if>" +
            " <if test='pushing == false' > AND st.pushIng=0</if>" +
            " <if test='mediaServerId != null' > AND st.mediaServerId=#{mediaServerId} </if>" +
            "order by st.createTime desc" +
            " </script>"})
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/MobilePosition/MobilePositionController.java
@@ -3,6 +3,7 @@
import java.util.List;
import java.util.UUID;
import com.genersoft.iot.vmp.conf.exception.ControllerException;
import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.bean.MobilePosition;
import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
@@ -10,6 +11,7 @@
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
import com.genersoft.iot.vmp.service.IDeviceService;
import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
import com.github.pagehelper.util.StringUtil;
@@ -136,13 +138,9 @@
    @Parameter(name = "expires", description = "订阅超时时间", required = true)
    @Parameter(name = "interval", description = "上报时间间隔", required = true)
    @GetMapping("/subscribe/{deviceId}")
    public String positionSubscribe(@PathVariable String deviceId,
    public void positionSubscribe(@PathVariable String deviceId,
                                                    @RequestParam String expires,
                                                    @RequestParam String interval) {
        String msg = ((expires.equals("0")) ? "取消" : "") + "订阅设备" + deviceId + "的移动位置";
        if (logger.isDebugEnabled()) {
            logger.debug(msg);
        }
        if (StringUtil.isEmpty(interval)) {
            interval = "5";
@@ -151,13 +149,8 @@
        device.setSubscribeCycleForMobilePosition(Integer.parseInt(expires));
        device.setMobilePositionSubmissionInterval(Integer.parseInt(interval));
        deviceService.updateDevice(device);
        String result = msg;
        if (deviceService.removeMobilePositionSubscribe(device)) {
            result += ",成功";
        } else {
            result += ",失败";
        if (!deviceService.removeMobilePositionSubscribe(device)) {
            throw new ControllerException(ErrorCode.ERROR100);
        }
        return result;
    }
}
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceControl.java
@@ -56,20 +56,14 @@
    @Operation(summary = "远程启动控制命令")
    @Parameter(name = "deviceId", description = "设备国标编号", required = true)
    @GetMapping("/teleboot/{deviceId}")
    public String teleBootApi(@PathVariable String deviceId) {
    public void teleBootApi(@PathVariable String deviceId) {
        if (logger.isDebugEnabled()) {
            logger.debug("设备远程启动API调用");
        }
        Device device = storager.queryVideoDevice(deviceId);
        boolean sucsess = cmder.teleBootCmd(device);
        if (sucsess) {
            JSONObject json = new JSONObject();
            json.put("DeviceID", deviceId);
            json.put("Result", "OK");
            return json.toJSONString();
        } else {
            logger.warn("设备远程启动API调用失败!");
            throw new ControllerException(ErrorCode.ERROR100.getCode(), "设备远程启动API调用失败!");
        if (!cmder.teleBootCmd(device)) {
            logger.warn("设备远程启动API调用失败!");
            throw new ControllerException(ErrorCode.ERROR100);
        }
    }
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/platform/PlatformController.java
@@ -244,7 +244,7 @@
    @Parameter(name = "serverGBId", description = "上级平台的国标编号")
    @DeleteMapping("/delete/{serverGBId}")
    @ResponseBody
    public String deletePlatform(@PathVariable String serverGBId) {
    public void deletePlatform(@PathVariable String serverGBId) {
        if (logger.isDebugEnabled()) {
            logger.debug("删除上级平台API调用");
@@ -278,9 +278,7 @@
        dynamicTask.stop(key);
        // 删除缓存的订阅信息
        subscribeHolder.removeAllSubscribe(parentPlatform.getServerGBId());
        if (deleteResult) {
            return null;
        } else {
        if (!deleteResult) {
            throw new ControllerException(ErrorCode.ERROR100);
        }
    }
web_src/config/index.js
@@ -12,14 +12,14 @@
    assetsPublicPath: '/',
    proxyTable: {
      '/debug': {
        target: 'http://localhost:18080',
        target: 'http://localhost:38080',
        changeOrigin: true,
        pathRewrite: {
          '^/debug': '/'
        }
      },
      '/static/snap': {
        target: 'http://localhost:18080',
        target: 'http://localhost:38080',
        changeOrigin: true,
        // pathRewrite: {
        //   '^/static/snap': '/static/snap'
web_src/src/components/StreamProxyList.vue
@@ -220,7 +220,7 @@
                this.getListLoading = true;
                this.$axios({
                    method: 'get',
                    url:`/api/media/stream_info_by_app_and_stream`,
                    url:`/api/push/getPlayUrl`,
                    params: {
                        app: row.app,
                        stream: row.stream,