panlinlin
2021-01-06 627a14f37e49d5e33cc5f593277ee24f913875b8
完成向上级联->保活
21个文件已修改
7个文件已添加
803 ■■■■■ 已修改文件
README.md 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/common/VideoManagerConstants.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/auth/DigestServerAuthenticationHelper.java 92 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/bean/ParentPlatformCatch.java 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/bean/PlatformRegister.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/event/EventPublisher.java 13 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/event/offline/KeepaliveTimeoutListenerForPlatform.java 64 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/event/platformKeepaliveExpire/PlatformKeepaliveExpireEvent.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/event/platformKeepaliveExpire/PlatformKeepaliveExpireEventLister.java 85 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/event/platformNotRegister/PlatformNotRegisterEventLister.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorFactory.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommanderForPlatform.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderPlarformProvider.java 150 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommanderFroPlatform.java 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/MessageRequestProcessor.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/response/impl/RegisterResponseProcessor.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorager.java 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceChannelMapper.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceMapper.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/storager/dao/ParentPlatformMapper.java 54 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStoragerImpl.java 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/vmanager/platform/PlatformController.java 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/wvp.sqlite 补丁 | 查看 | 原始文档 | blame | 历史
web_src/src/components/ParentPlatformList.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
web_src/src/router/index.js 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
README.md
@@ -39,7 +39,7 @@
- [ ] 国标通道向上级联  
    - [X] WEB添加上级平台
    - [X] 注册
    - [ ] 心跳保活
    - [X] 心跳保活
    - [ ] 通道选择
    - [ ] 通道推送
    - [ ] 点播
src/main/java/com/genersoft/iot/vmp/common/VideoManagerConstants.java
@@ -20,7 +20,15 @@
    public static final String PLAY_BLACK_PREFIX = "VMP_playback_";
    public static final String PLATFORM_PREFIX = "VMP_platform_";
    public static final String PLATFORM_PREFIX = "VMP_platform";
    public static final String PLATFORM_KEEPLIVEKEY_PREFIX = "VMP_platform_keeplive_";
    public static final String PLATFORM_CATCH_PREFIX = "VMP_platform_catch_";
    public static final String PLATFORM_REGISTER_PREFIX = "VMP_platform_register_";
    public static final String Pattern_Topic = "VMP_keeplive_platform_";
    public static final String EVENT_ONLINE_REGISTER = "1";
    
src/main/java/com/genersoft/iot/vmp/gb28181/auth/DigestServerAuthenticationHelper.java
@@ -1,28 +1,28 @@
/*
* Conditions Of Use
*
* This software was developed by employees of the National Institute of
* Standards and Technology (NIST), an agency of the Federal Government.
* Pursuant to title 15 Untied States Code Section 105, works of NIST
* employees are not subject to copyright protection in the United States
* and are considered to be in the public domain.  As a result, a formal
* license is not needed to use the software.
*
* This software is provided by NIST as a service and is expressly
* provided "AS IS."  NIST MAKES NO WARRANTY OF ANY KIND, EXPRESS, IMPLIED
* OR STATUTORY, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTY OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT
* AND DATA ACCURACY.  NIST does not warrant or make any representations
* regarding the use of the software or the results thereof, including but
* not limited to the correctness, accuracy, reliability or usefulness of
* the software.
*
* Permission to use this software is contingent upon your acceptance
* of the terms of this agreement
*
* .
*
*/
 * Conditions Of Use
 *
 * This software was developed by employees of the National Institute of
 * Standards and Technology (NIST), an agency of the Federal Government.
 * Pursuant to title 15 Untied States Code Section 105, works of NIST
 * employees are not subject to copyright protection in the United States
 * and are considered to be in the public domain.  As a result, a formal
 * license is not needed to use the software.
 *
 * This software is provided by NIST as a service and is expressly
 * provided "AS IS."  NIST MAKES NO WARRANTY OF ANY KIND, EXPRESS, IMPLIED
 * OR STATUTORY, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTY OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT
 * AND DATA ACCURACY.  NIST does not warrant or make any representations
 * regarding the use of the software or the results thereof, including but
 * not limited to the correctness, accuracy, reliability or usefulness of
 * the software.
 *
 * Permission to use this software is contingent upon your acceptance
 * of the terms of this agreement
 *
 * .
 *
 */
package com.genersoft.iot.vmp.gb28181.auth;
import java.security.MessageDigest;
@@ -42,18 +42,18 @@
/**
 * Implements the HTTP digest authentication method server side functionality.
 *
 *
 * @author M. Ranganathan
 * @author Marc Bednarek
 */
public class DigestServerAuthenticationHelper  {
    private MessageDigest messageDigest;
    public static final String DEFAULT_ALGORITHM = "MD5";
    public static final String DEFAULT_SCHEME = "Digest";
@@ -63,11 +63,11 @@
    /**
     * Default constructor.
     * @throws NoSuchAlgorithmException
     * @throws NoSuchAlgorithmException
     */
    public DigestServerAuthenticationHelper()
        throws NoSuchAlgorithmException {
            messageDigest = MessageDigest.getInstance(DEFAULT_ALGORITHM);
    public DigestServerAuthenticationHelper()
            throws NoSuchAlgorithmException {
        messageDigest = MessageDigest.getInstance(DEFAULT_ALGORITHM);
    }
    public static String toHexString(byte b[]) {
@@ -79,7 +79,7 @@
        }
        return new String(c);
    }
    /**
     * Generate the challenge string.
     *
@@ -121,34 +121,34 @@
     *
     * @param request - the request to authenticate.
     * @param hashedPassword -- the MD5 hashed string of username:realm:plaintext password.
     *
     *
     * @return true if authentication succeded and false otherwise.
     */
    public boolean doAuthenticateHashedPassword(Request request, String hashedPassword) {
        AuthorizationHeader authHeader = (AuthorizationHeader) request.getHeader(AuthorizationHeader.NAME);
        AuthorizationHeader authHeader = (AuthorizationHeader) request.getHeader(AuthorizationHeader.NAME);
        if ( authHeader == null ) return false;
        String realm = authHeader.getRealm();
        String username = authHeader.getUsername();
        if ( username == null || realm == null ) {
            return false;
        }
        String nonce = authHeader.getNonce();
        URI uri = authHeader.getURI();
        if (uri == null) {
            return false;
        }
        String A2 = request.getMethod().toUpperCase() + ":" + uri.toString();
        String HA1 = hashedPassword;
        byte[] mdbytes = messageDigest.digest(A2.getBytes());
        String HA2 = toHexString(mdbytes);
        String cnonce = authHeader.getCNonce();
        String KD = HA1 + ":" + nonce;
        if (cnonce != null) {
@@ -158,7 +158,7 @@
        mdbytes = messageDigest.digest(KD.getBytes());
        String mdString = toHexString(mdbytes);
        String response = authHeader.getResponse();
        return mdString.equals(response);
    }
@@ -168,11 +168,11 @@
     *
     * @param request - the request to authenticate.
     * @param pass -- the plain text password.
     *
     *
     * @return true if authentication succeded and false otherwise.
     */
    public boolean doAuthenticatePlainTextPassword(Request request, String pass) {
        AuthorizationHeader authHeader = (AuthorizationHeader) request.getHeader(AuthorizationHeader.NAME);
        AuthorizationHeader authHeader = (AuthorizationHeader) request.getHeader(AuthorizationHeader.NAME);
        if ( authHeader == null ) return false;
        String realm = authHeader.getRealm().trim();
        String username = authHeader.getUsername().trim();
@@ -184,7 +184,7 @@
        String nonce = authHeader.getNonce();
        URI uri = authHeader.getURI();
        if (uri == null) {
           return false;
            return false;
        }
        // qop 保护质量 包含auth(默认的)和auth-int(增加了报文完整性检测)两种策略
        String qop = authHeader.getQop();
@@ -233,7 +233,7 @@
        String response = authHeader.getResponse();
        System.out.println("response: " + response);
        return mdString.equals(response);
    }
src/main/java/com/genersoft/iot/vmp/gb28181/bean/ParentPlatformCatch.java
New file
@@ -0,0 +1,36 @@
package com.genersoft.iot.vmp.gb28181.bean;
public class ParentPlatformCatch {
    private String id;
    // 心跳未回复次数
    private int keepAliveReply;
    // 注册未回复次数
    private int registerAliveReply;
    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
    public int getKeepAliveReply() {
        return keepAliveReply;
    }
    public void setKeepAliveReply(int keepAliveReply) {
        this.keepAliveReply = keepAliveReply;
    }
    public int getRegisterAliveReply() {
        return registerAliveReply;
    }
    public void setRegisterAliveReply(int registerAliveReply) {
        this.registerAliveReply = registerAliveReply;
    }
}
src/main/java/com/genersoft/iot/vmp/gb28181/bean/PlatformRegister.java
New file
@@ -0,0 +1,15 @@
package com.genersoft.iot.vmp.gb28181.bean;
public class PlatformRegister {
    // 未回复次数
    private int reply;
    public int getReply() {
        return reply;
    }
    public void setReply(int reply) {
        this.reply = reply;
    }
}
src/main/java/com/genersoft/iot/vmp/gb28181/event/EventPublisher.java
@@ -1,8 +1,7 @@
package com.genersoft.iot.vmp.gb28181.event;
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
import com.genersoft.iot.vmp.gb28181.event.platformKeepaliveExpire.PlatformKeepaliveExpireEvent;
import com.genersoft.iot.vmp.gb28181.event.platformNotRegister.PlatformNotRegisterEvent;
import com.genersoft.iot.vmp.vmanager.platform.PlatformController;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Component;
@@ -36,6 +35,16 @@
    }
    /**
     * 平台心跳到期事件
     * @param platformGbId
     */
    public void platformKeepaliveExpireEventPublish(String platformGbId){
        PlatformKeepaliveExpireEvent platformNotRegisterEvent = new PlatformKeepaliveExpireEvent(this);
        platformNotRegisterEvent.setPlatformGbID(platformGbId);
        applicationEventPublisher.publishEvent(platformNotRegisterEvent);
    }
    /**
     * 平台未注册事件
     * @param platformGbId
     */
src/main/java/com/genersoft/iot/vmp/gb28181/event/offline/KeepaliveTimeoutListenerForPlatform.java
New file
@@ -0,0 +1,64 @@
package com.genersoft.iot.vmp.gb28181.event.offline;
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.data.redis.connection.Message;
import org.springframework.data.redis.connection.MessageListener;
import org.springframework.data.redis.listener.KeyExpirationEventMessageListener;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.stereotype.Component;
import com.genersoft.iot.vmp.common.VideoManagerConstants;
import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
import java.nio.charset.StandardCharsets;
/**
 * @Description:设备心跳超时监听,借助redis过期特性,进行监听,监听到说明设备心跳超时,发送离线事件
 * @author: swwheihei
 * @date:   2020年5月6日 上午11:35:46
 */
@Component
public class KeepaliveTimeoutListenerForPlatform extends KeyExpirationEventMessageListener {
    @Autowired
    private EventPublisher publisher;
    public KeepaliveTimeoutListenerForPlatform(RedisMessageListenerContainer listenerContainer) {
        super(listenerContainer);
    }
    /**
     * 监听失效的key
     * @param message
     * @param bytes
     */
    @Override
    public void onMessage(Message message, byte[] pattern) {
        //  获取失效的key
        String expiredKey = message.toString();
        System.out.println(expiredKey);
        if(!expiredKey.startsWith(VideoManagerConstants.PLATFORM_PREFIX)){
            System.out.println("收到redis过期监听,但开头不是"+VideoManagerConstants.PLATFORM_PREFIX+",忽略");
            return;
        }
        // 平台心跳到期,需要重发, 判断是否已经多次未收到心跳回复, 多次未收到,则重新发起注册, 注册尝试多次未得到回复,则认为平台离线
        if (expiredKey.startsWith(VideoManagerConstants.PLATFORM_KEEPLIVEKEY_PREFIX)) {
            String platformGBId = expiredKey.substring(VideoManagerConstants.PLATFORM_KEEPLIVEKEY_PREFIX.length(),expiredKey.length());
            publisher.platformKeepaliveExpireEventPublish(platformGBId);
        }else if (expiredKey.startsWith(VideoManagerConstants.PLATFORM_REGISTER_PREFIX)) {
            System.out.println("11111111111111");
            String platformGBId = expiredKey.substring(VideoManagerConstants.PLATFORM_REGISTER_PREFIX.length(),expiredKey.length());
            publisher.platformNotRegisterEventPublish(platformGBId);
        }else{
            String deviceId = expiredKey.substring(VideoManagerConstants.KEEPLIVEKEY_PREFIX.length(),expiredKey.length());
            publisher.outlineEventPublish(deviceId, VideoManagerConstants.EVENT_OUTLINE_TIMEOUT);
        }
    }
}
src/main/java/com/genersoft/iot/vmp/gb28181/event/platformKeepaliveExpire/PlatformKeepaliveExpireEvent.java
New file
@@ -0,0 +1,23 @@
package com.genersoft.iot.vmp.gb28181.event.platformKeepaliveExpire;
import org.springframework.context.ApplicationEvent;
/**
 *  平台心跳超时事件
 */
public class PlatformKeepaliveExpireEvent extends ApplicationEvent {
    private String platformGbID;
    public PlatformKeepaliveExpireEvent(Object source) {
        super(source);
    }
    public String getPlatformGbID() {
        return platformGbID;
    }
    public void setPlatformGbID(String platformGbID) {
        this.platformGbID = platformGbID;
    }
}
src/main/java/com/genersoft/iot/vmp/gb28181/event/platformKeepaliveExpire/PlatformKeepaliveExpireEventLister.java
New file
@@ -0,0 +1,85 @@
package com.genersoft.iot.vmp.gb28181.event.platformKeepaliveExpire;
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatformCatch;
import com.genersoft.iot.vmp.gb28181.bean.PlatformRegister;
import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
import javax.sip.ResponseEvent;
import javax.sip.message.Response;
/**
 * @Description: 平台心跳超时事件
 * @author: panll
 * @date: 2020年11月5日 10:00
 */
@Component
public class PlatformKeepaliveExpireEventLister implements ApplicationListener<PlatformKeepaliveExpireEvent> {
    private final static Logger logger = LoggerFactory.getLogger(PlatformKeepaliveExpireEventLister.class);
    @Autowired
    private IVideoManagerStorager storager;
    @Autowired
    private IRedisCatchStorage redisCatchStorage;
    @Autowired
    private ISIPCommanderForPlatform sipCommanderForPlatform;
    @Autowired
    private SipSubscribe sipSubscribe;
    @Autowired
    private EventPublisher publisher;
    @Override
    public void onApplicationEvent(@NotNull PlatformKeepaliveExpireEvent event) {
        if (logger.isDebugEnabled()) {
            logger.debug("平台心跳到期事件事件触发,平台国标ID:" + event.getPlatformGbID());
        }
        ParentPlatform parentPlatform = storager.queryParentPlatById(event.getPlatformGbID());
        ParentPlatformCatch parentPlatformCatch = redisCatchStorage.queryPlatformCatchInfo(event.getPlatformGbID());
        if (parentPlatform == null) {
            logger.debug("平台心跳到期事件事件触发,但平台已经删除!!! 平台国标ID:" + event.getPlatformGbID());
            return;
        }
        if (parentPlatformCatch == null) {
            return;
        }
        // 发送心跳
        if (parentPlatformCatch.getKeepAliveReply() >= 3) {
            // 有3次未收到心跳回复, 设置平台状态为离线, 开始重新注册
            logger.warn("有3次未收到心跳回复,标记设置平台状态为离线, 并重新注册 平台国标ID:" + event.getPlatformGbID());
            publisher.platformNotRegisterEventPublish(event.getPlatformGbID());
        }else {
            // 再次发送心跳
            String callId = sipCommanderForPlatform.keepalive(parentPlatform);
            parentPlatformCatch.setKeepAliveReply( parentPlatformCatch.getKeepAliveReply() + 1);
            // 存储心跳信息, 并设置状态为未回复, 如果多次过期仍未收到回复,则认为上级平台已经离线
            redisCatchStorage.updatePlatformKeepalive(parentPlatform);
            redisCatchStorage.updatePlatformCatchInfo(parentPlatformCatch);
            sipSubscribe.addOkSubscribe(callId, (ResponseEvent responseEvent) ->{
                if (responseEvent.getResponse().getStatusCode() == Response.OK) {
                    // 收到心跳响应信息,
                    parentPlatformCatch.setKeepAliveReply(0);
                    redisCatchStorage.updatePlatformCatchInfo(parentPlatformCatch);
                }
            } );
        }
    }
}
src/main/java/com/genersoft/iot/vmp/gb28181/event/platformNotRegister/PlatformNotRegisterEventLister.java
@@ -3,6 +3,7 @@
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
import com.genersoft.iot.vmp.gb28181.event.online.OnlineEvent;
import com.genersoft.iot.vmp.gb28181.event.online.OnlineEventListener;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform;
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
import com.genersoft.iot.vmp.utils.redis.RedisUtil;
import org.slf4j.Logger;
@@ -26,6 +27,8 @@
    @Autowired
    private IVideoManagerStorager storager;
    @Autowired
    private SIPCommanderFroPlatform sipCommanderFroPlatform;
    @Autowired
    private RedisUtil redis;
@@ -33,13 +36,13 @@
    @Override
    public void onApplicationEvent(PlatformNotRegisterEvent event) {
        if (logger.isDebugEnabled()) {
            logger.debug("平台未注册事件触发,平台国标ID:" + event.getPlatformGbID());
        }
        logger.debug("平台未注册事件触发,平台国标ID:" + event.getPlatformGbID());
        ParentPlatform parentPlatform = storager.queryParentPlatById(event.getPlatformGbID());
        if (parentPlatform == null) {
            logger.debug("平台未注册事件触发,但平台已经删除!!! 平台国标ID:" + event.getPlatformGbID());
            return;
        }
        sipCommanderFroPlatform.register(parentPlatform);
    }
}
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorFactory.java
@@ -4,6 +4,8 @@
import javax.sip.ResponseEvent;
import javax.sip.SipProvider;
import javax.sip.header.CSeqHeader;
import javax.sip.header.CallIdHeader;
import javax.sip.header.Header;
import javax.sip.message.Request;
import javax.sip.message.Response;
@@ -11,6 +13,7 @@
import com.alibaba.fastjson.JSON;
import com.genersoft.iot.vmp.gb28181.transmit.response.impl.*;
import com.genersoft.iot.vmp.gb28181.transmit.response.impl.*;
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@@ -34,6 +37,10 @@
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.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.storager.IVideoManagerStorager;
import com.genersoft.iot.vmp.utils.SpringBeanFactory;
import com.genersoft.iot.vmp.utils.redis.RedisUtil;
@@ -88,6 +95,7 @@
    @Lazy
    private RegisterResponseProcessor registerResponseProcessor;
    @Autowired
    private OtherResponseProcessor otherResponseProcessor;
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommanderForPlatform.java
@@ -9,5 +9,14 @@
     * @param parentPlatform
     * @return
     */
    boolean register(ParentPlatform parentPlatform);
    boolean register(ParentPlatform parentPlatform, String callId, String realm, String nonce, String scheme);
    /**
     * 向上级平发送心跳信息
     * @param parentPlatform
     * @return callId(作为接受回复的判定)
     */
    String keepalive(ParentPlatform parentPlatform);
}
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderPlarformProvider.java
New file
@@ -0,0 +1,150 @@
package com.genersoft.iot.vmp.gb28181.transmit.cmd;
import com.genersoft.iot.vmp.conf.SipConfig;
import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.bean.Host;
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
import org.springframework.util.DigestUtils;
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 javax.validation.constraints.NotNull;
import java.text.ParseException;
import java.util.ArrayList;
/**
 * @Description:摄像头命令request创造器 TODO 冗余代码太多待优化
 * @author: swwheihei
 * @date: 2020年5月6日 上午9:29:02
 */
@Component
public class SIPRequestHeaderPlarformProvider {
    @Autowired
    private SipConfig sipConfig;
    @Autowired
    private SipFactory sipFactory;
    @Autowired
    @Qualifier(value="tcpSipProvider")
    private SipProvider tcpSipProvider;
    @Autowired
    @Qualifier(value="udpSipProvider")
    private SipProvider udpSipProvider;
    public Request createKeetpaliveMessageRequest(ParentPlatform parentPlatform, String content, String viaTag, String fromTag, String toTag) throws ParseException, InvalidArgumentException, PeerUnavailableException {
        Request request = null;
        // sipuri
        SipURI requestURI = sipFactory.createAddressFactory().createSipURI(parentPlatform.getServerGBId(), parentPlatform.getServerIP() + ":" + parentPlatform.getServerPort());
        // via
        ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>();
        ViaHeader viaHeader = sipFactory.createHeaderFactory().createViaHeader(sipConfig.getSipIp(), sipConfig.getSipPort(),
                parentPlatform.getTransport(), viaTag);
        viaHeader.setRPort();
        viaHeaders.add(viaHeader);
        // from
        SipURI fromSipURI = sipFactory.createAddressFactory().createSipURI(parentPlatform.getDeviceGBId(),
                sipConfig.getSipIp() + ":" + sipConfig.getSipPort());
        Address fromAddress = sipFactory.createAddressFactory().createAddress(fromSipURI);
        FromHeader fromHeader = sipFactory.createHeaderFactory().createFromHeader(fromAddress, fromTag);
        // to
        SipURI toSipURI = sipFactory.createAddressFactory().createSipURI(parentPlatform.getServerGBId(), parentPlatform.getServerIP() + ":" + parentPlatform.getServerPort() );
        Address toAddress = sipFactory.createAddressFactory().createAddress(toSipURI);
        ToHeader toHeader = sipFactory.createHeaderFactory().createToHeader(toAddress, toTag);
        // callid
        CallIdHeader callIdHeader = parentPlatform.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
                : udpSipProvider.getNewCallId();
        // 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 createRegisterRequest(@NotNull ParentPlatform platform, String fromTag, String viaTag) throws ParseException, InvalidArgumentException, PeerUnavailableException {
        Request request = null;
        String sipAddress = sipConfig.getSipIp() + ":" + sipConfig.getSipPort();
        //请求行
        SipURI requestLine = sipFactory.createAddressFactory().createSipURI(platform.getDeviceGBId(),
                platform.getServerIP() + ":" + platform.getServerPort());
        //via
        ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>();
        ViaHeader viaHeader = sipFactory.createHeaderFactory().createViaHeader(platform.getServerIP(), platform.getServerPort(), platform.getTransport(), viaTag);
        viaHeader.setRPort();
        viaHeaders.add(viaHeader);
        //from
        SipURI fromSipURI = sipFactory.createAddressFactory().createSipURI(platform.getDeviceGBId(),sipAddress);
        Address fromAddress = sipFactory.createAddressFactory().createAddress(fromSipURI);
        FromHeader fromHeader = sipFactory.createHeaderFactory().createFromHeader(fromAddress, fromTag);
        //to
        SipURI toSipURI = sipFactory.createAddressFactory().createSipURI(platform.getDeviceGBId(),sipAddress);
        Address toAddress = sipFactory.createAddressFactory().createAddress(toSipURI);
        ToHeader toHeader = sipFactory.createHeaderFactory().createToHeader(toAddress,null);
        //callid
        CallIdHeader callIdHeader = null;
        if(platform.getTransport().equals("TCP")) {
            callIdHeader = tcpSipProvider.getNewCallId();
        }
        if(platform.getTransport().equals("UDP")) {
            callIdHeader = udpSipProvider.getNewCallId();
        }
        //Forwards
        MaxForwardsHeader maxForwards = sipFactory.createHeaderFactory().createMaxForwardsHeader(70);
        //ceq
        CSeqHeader cSeqHeader = sipFactory.createHeaderFactory().createCSeqHeader(1L, Request.REGISTER);
        request = sipFactory.createMessageFactory().createRequest(requestLine, Request.REGISTER, callIdHeader,
                cSeqHeader,fromHeader, toHeader, viaHeaders, maxForwards);
        Address concatAddress = sipFactory.createAddressFactory().createAddress(sipFactory.createAddressFactory()
                .createSipURI(platform.getDeviceGBId(), sipAddress));
        request.addHeader(sipFactory.createHeaderFactory().createContactHeader(concatAddress));
        return request;
    }
    public Request createRegisterRequest(@NotNull ParentPlatform parentPlatform, String fromTag, String viaTag,
                                         String callId, String realm, String nonce, String scheme) throws ParseException, PeerUnavailableException, InvalidArgumentException {
        Request registerRequest = createRegisterRequest(parentPlatform, fromTag, viaTag);
        CallIdHeader callIdHeader = (CallIdHeader)registerRequest.getHeader(CallIdHeader.NAME);
        callIdHeader.setCallId(callId);
        String uri = "sip:" + parentPlatform.getServerGBId() +
                "@" + parentPlatform.getServerIP() +
                ":" + parentPlatform.getServerPort();
        String HA1 = DigestUtils.md5DigestAsHex((parentPlatform.getDeviceGBId() + ":" + realm + ":" + parentPlatform.getPassword()).getBytes());
        String HA2=DigestUtils.md5DigestAsHex((Request.REGISTER + ":" + uri).getBytes());
        String RESPONSE = DigestUtils.md5DigestAsHex((HA1 + ":" + nonce + ":" +  HA2).getBytes());
        String authorizationHeaderContent = scheme + " username=\"" + parentPlatform.getDeviceGBId() + "\", " + "realm=\""
                + realm + "\", uri=\"" + uri  + "\", response=\"" + RESPONSE + "\", nonce=\""
                + nonce + "\"";
        AuthorizationHeader authorizationHeader = sipFactory.createHeaderFactory().createAuthorizationHeader(authorizationHeaderContent);
        registerRequest.addHeader(authorizationHeader);
        return registerRequest;
    }
}
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java
@@ -238,4 +238,38 @@
        return registerRequest;
    }
//    public Request createKeetpaliveMessageRequest(ParentPlatform parentPlatform, String content, String fromTag, String toTag, Object o) throws PeerUnavailableException, ParseException, InvalidArgumentException {
//        Request request = null;
//        // sipuri
//        SipURI requestURI = sipFactory.createAddressFactory().createSipURI(parentPlatform.getServerGBId(), parentPlatform.getServerIP() + ":" + parentPlatform.getServerPort());
//        // via
//        ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>();
//        ViaHeader viaHeader = sipFactory.createHeaderFactory().createViaHeader(sipConfig.getSipIp(), sipConfig.getSipPort(),
//                parentPlatform.getTransport(), null);
//        viaHeader.setRPort();
//        viaHeaders.add(viaHeader);
//        // from
//        SipURI fromSipURI = sipFactory.createAddressFactory().createSipURI(parentPlatform.getServerGBId(),
//                sipConfig.getSipIp() + ":" + sipConfig.getSipPort());
//        Address fromAddress = sipFactory.createAddressFactory().createAddress(fromSipURI);
//        FromHeader fromHeader = sipFactory.createHeaderFactory().createFromHeader(fromAddress, fromTag);
//        // to
//        SipURI toSipURI = sipFactory.createAddressFactory().createSipURI(parentPlatform.getServerGBId(), parentPlatform.getServerGBDomain());
//        Address toAddress = sipFactory.createAddressFactory().createAddress(toSipURI);
//        ToHeader toHeader = sipFactory.createHeaderFactory().createToHeader(toAddress, toTag);
//        // callid
//        CallIdHeader callIdHeader = parentPlatform.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
//                : udpSipProvider.getNewCallId();
//        // 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;
//    }
}
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommanderFroPlatform.java
@@ -5,8 +5,8 @@
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.SIPRequestHeaderPlarformProvider;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.SIPRequestHeaderProvider;
import com.genersoft.iot.vmp.media.zlm.ZLMUtils;
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
@@ -15,8 +15,10 @@
import org.springframework.stereotype.Component;
import javax.sip.*;
import javax.sip.header.CallIdHeader;
import javax.sip.message.Request;
import java.text.ParseException;
import java.util.UUID;
@Component
public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
@@ -26,6 +28,9 @@
    @Autowired
    private SIPRequestHeaderProvider headerProvider;
    @Autowired
    private SIPRequestHeaderPlarformProvider headerProviderPlarformProvider;
    @Autowired
    private VideoStreamSessionManager streamSession;
@@ -41,11 +46,13 @@
    @Qualifier(value="udpSipProvider")
    private SipProvider udpSipProvider;
    @Autowired
    private ZLMUtils zlmUtils;
    @Value("${media.rtp.enable}")
    private boolean rtpEnable;
    @Override
    public boolean register(ParentPlatform parentPlatform) {
        return register(parentPlatform, null, null, null, null);
    }
    @Override
    public boolean register(ParentPlatform parentPlatform, @Nullable String callId, @Nullable String realm, @Nullable String nonce, @Nullable String scheme ) {
@@ -71,6 +78,35 @@
        return false;
    }
    @Override
    public String keepalive(ParentPlatform parentPlatform) {
        String callId = null;
        try {
            StringBuffer keepaliveXml = new StringBuffer(200);
            keepaliveXml.append("<?xml version=\"1.0\" encoding=\"GB2312\" ?>\r\n");
            keepaliveXml.append("<Notify>\r\n");
            keepaliveXml.append("<CmdType>Keepalive</CmdType>\r\n");
            keepaliveXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
            keepaliveXml.append("<DeviceID>" + parentPlatform.getServerGBId() + "</DeviceID>\r\n");
            keepaliveXml.append("<Status>OK</Status>\r\n");
            keepaliveXml.append("</Notify>\r\n");
            Request request = headerProviderPlarformProvider.createKeetpaliveMessageRequest(
                    parentPlatform,
                    keepaliveXml.toString(),
                    UUID.randomUUID().toString().replace("-", ""),
                    UUID.randomUUID().toString().replace("-", ""),
                    null);
            transmitRequest(parentPlatform, request);
            CallIdHeader callIdHeader = (CallIdHeader)request.getHeader(CallIdHeader.NAME);
            callId = callIdHeader.getCallId();
        } catch (ParseException | InvalidArgumentException | SipException e) {
            e.printStackTrace();
        }
        return callId;
    }
    private void transmitRequest(ParentPlatform parentPlatform, Request request) throws SipException {
        if("TCP".equals(parentPlatform.getTransport())) {
            tcpSipProvider.sendRequest(request);
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/MessageRequestProcessor.java
@@ -460,6 +460,7 @@
                    cmder.streamByeCmd(streamInfo.getStreamId());
                }
            }
        } catch (ParseException | SipException | InvalidArgumentException | DocumentException e) {
            e.printStackTrace();
        }
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/response/impl/RegisterResponseProcessor.java
@@ -3,9 +3,11 @@
import com.genersoft.iot.vmp.conf.SipConfig;
import com.genersoft.iot.vmp.gb28181.SipLayer;
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatformCatch;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
import com.genersoft.iot.vmp.gb28181.transmit.request.impl.RegisterRequestProcessor;
import com.genersoft.iot.vmp.gb28181.transmit.response.ISIPResponseProcessor;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
import gov.nist.core.Host;
import gov.nist.javax.sip.address.AddressImpl;
@@ -39,6 +41,12 @@
    @Autowired
    private IVideoManagerStorager storager;
    @Autowired
    private IRedisCatchStorage redisCatchStorage;
    public RegisterResponseProcessor() {
    }
    /**
     * 处理Register响应
@@ -77,6 +85,17 @@
            logger.info(String.format("%s 注册成功", platformGBId ));
            parentPlatform.setStatus(true);
            storager.updateParentPlatform(parentPlatform);
            //
            redisCatchStorage.updatePlatformRegister(parentPlatform);
            redisCatchStorage.updatePlatformKeepalive(parentPlatform);
            ParentPlatformCatch parentPlatformCatch = redisCatchStorage.queryPlatformCatchInfo(parentPlatform.getDeviceGBId());
            if (parentPlatformCatch == null) {
                parentPlatformCatch = new ParentPlatformCatch();
                parentPlatformCatch.setId(parentPlatform.getDeviceGBId());
            }
            redisCatchStorage.updatePlatformCatchInfo(parentPlatformCatch);
        }
    }
src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java
@@ -2,6 +2,9 @@
import com.genersoft.iot.vmp.common.StreamInfo;
import com.genersoft.iot.vmp.conf.MediaServerConfig;
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatformCatch;
import com.genersoft.iot.vmp.gb28181.bean.PlatformRegister;
import java.util.Map;
@@ -55,4 +58,13 @@
    boolean stopPlayback(StreamInfo streamInfo);
    StreamInfo queryPlaybackByDevice(String deviceId, String code);
    void updatePlatformCatchInfo(ParentPlatformCatch parentPlatformCatch);
    ParentPlatformCatch queryPlatformCatchInfo(String platformGbId);
    void updatePlatformKeepalive(ParentPlatform parentPlatform);
    void updatePlatformRegister(ParentPlatform parentPlatform);
}
src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorager.java
@@ -1,9 +1,12 @@
package com.genersoft.iot.vmp.storager;
import java.util.List;
import java.util.Map;
import com.genersoft.iot.vmp.common.StreamInfo;
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.github.pagehelper.PageInfo;
/**    
@@ -136,4 +139,39 @@
     */
    void cleanChannelsForDevice(String deviceId);
    /**
     * 更新上级平台
     * @param parentPlatform
     */
    boolean updateParentPlatform(ParentPlatform parentPlatform);
    /**
     * 添加上级平台
     * @param parentPlatform
     */
    boolean addParentPlatform(ParentPlatform parentPlatform);
    /**
     * 删除上级平台
     * @param parentPlatform
     */
    boolean deleteParentPlatform(ParentPlatform parentPlatform);
    /**
     * 分页获取上级平台
     * @param page
     * @param count
     * @return
     */
    PageInfo<ParentPlatform> queryParentPlatformList(int page, int count);
    /**
     * 获取上级平台
     * @param platformGbId
     * @return
     */
    ParentPlatform queryParentPlatById(String platformGbId);
}
src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceChannelMapper.java
@@ -1,6 +1,7 @@
package com.genersoft.iot.vmp.storager.dao;
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
import org.apache.ibatis.annotations.*;
import java.util.List;
@@ -48,4 +49,6 @@
    @Delete("DELETE FROM device_channel WHERE deviceId=#{deviceId}")
    int cleanChannelsByDeviceId(String deviceId);
}
src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceMapper.java
@@ -1,6 +1,7 @@
package com.genersoft.iot.vmp.storager.dao;
import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
import org.apache.ibatis.annotations.*;
import org.springframework.stereotype.Repository;
@@ -63,4 +64,5 @@
    @Delete("DELETE FROM device WHERE deviceId=#{deviceId}")
    int del(String deviceId);
}
src/main/java/com/genersoft/iot/vmp/storager/dao/ParentPlatformMapper.java
New file
@@ -0,0 +1,54 @@
package com.genersoft.iot.vmp.storager.dao;
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
import org.apache.ibatis.annotations.*;
import org.springframework.stereotype.Repository;
import java.util.List;
/**
 * 用于存储上级平台
 */
@Mapper
@Repository
public interface ParentPlatformMapper {
    @Insert("INSERT INTO parent_platform (enable, name, serverGBId, serverGBDomain, serverIP, serverPort, deviceGBId, deviceIp,  " +
            "            devicePort, username, password, expires, keepTimeout, transport, characterSet, PTZEnable, rtcp, " +
            "            status) " +
            "            VALUES (${enable}, '${name}', '${serverGBId}', '${serverGBDomain}', '${serverIP}', ${serverPort}, '${deviceGBId}', '${deviceIp}', " +
            "            '${devicePort}', '${username}', '${password}', '${expires}', '${keepTimeout}', '${transport}', '${characterSet}', ${PTZEnable}, ${rtcp}, " +
            "            ${status})")
    int addParentPlatform(ParentPlatform parentPlatform);
    @Update("UPDATE parent_platform " +
            "SET enable=#{enable}, " +
            "name=#{name}," +
            "serverGBId=#{serverGBId}," +
            "serverGBDomain=#{serverGBDomain}, " +
            "serverIP=#{serverIP}," +
            "serverPort=#{serverPort}, " +
            "deviceIp=#{deviceIp}, " +
            "devicePort=#{devicePort}, " +
            "username=#{username}, " +
            "password=#{password}, " +
            "expires=#{expires}, " +
            "keepTimeout=#{keepTimeout}, " +
            "transport=#{transport}, " +
            "characterSet=#{characterSet}, " +
            "PTZEnable=#{PTZEnable}, " +
            "rtcp=#{rtcp}, " +
            "status=#{status} " +
            "WHERE deviceGBId=#{deviceGBId}")
    int updateParentPlatform(ParentPlatform parentPlatform);
    @Delete("DELETE FROM parent_platform WHERE deviceGBId=#{deviceGBId}")
    int delParentPlatform(ParentPlatform parentPlatform);
    @Select("SELECT * FROM parent_platform")
    List<ParentPlatform> getParentPlatformList();
    @Select("SELECT * FROM parent_platform WHERE deviceGBId=#{platformGbId}")
    ParentPlatform getParentPlatById(String platformGbId);
}
src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java
@@ -4,6 +4,9 @@
import com.genersoft.iot.vmp.common.VideoManagerConstants;
import com.genersoft.iot.vmp.conf.MediaServerConfig;
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.PlatformRegister;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import com.genersoft.iot.vmp.storager.dao.DeviceChannelMapper;
import com.genersoft.iot.vmp.utils.redis.RedisUtil;
@@ -163,4 +166,27 @@
        if (playLeys == null || playLeys.size() == 0) return null;
        return (StreamInfo)redis.get(playLeys.get(0).toString());
    }
    @Override
    public void updatePlatformCatchInfo(ParentPlatformCatch parentPlatformCatch) {
        String key = VideoManagerConstants.PLATFORM_CATCH_PREFIX + parentPlatformCatch.getId();
        redis.set(key, parentPlatformCatch);
    }
    @Override
    public void updatePlatformKeepalive(ParentPlatform parentPlatform) {
        String key = VideoManagerConstants.PLATFORM_KEEPLIVEKEY_PREFIX + parentPlatform.getDeviceGBId();
        redis.set(key, "", Integer.parseInt(parentPlatform.getKeepTimeout()));
    }
    @Override
    public void updatePlatformRegister(ParentPlatform parentPlatform) {
        String key = VideoManagerConstants.PLATFORM_REGISTER_PREFIX + parentPlatform.getDeviceGBId();
        redis.set(key, "", Integer.parseInt(parentPlatform.getExpires()));
    }
    @Override
    public ParentPlatformCatch queryPlatformCatchInfo(String platformGbId) {
        return (ParentPlatformCatch)redis.get(VideoManagerConstants.PLATFORM_CATCH_PREFIX + platformGbId);
    }
}
src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStoragerImpl.java
@@ -3,17 +3,17 @@
import java.util.*;
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
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.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import io.swagger.models.auth.In;
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.util.StringUtils;
/**    
 * @Description:视频设备数据存储-jdbc实现
@@ -28,6 +28,9 @@
    @Autowired
    private DeviceChannelMapper deviceChannelMapper;
    @Autowired
    private ParentPlatformMapper platformMapper;
    /**
@@ -198,5 +201,40 @@
        int result = deviceChannelMapper.cleanChannelsByDeviceId(deviceId);
    }
    @Override
    public boolean addParentPlatform(ParentPlatform parentPlatform) {
        int result = platformMapper.addParentPlatform(parentPlatform);
        return result > 0;
    }
    @Override
    public boolean updateParentPlatform(ParentPlatform parentPlatform) {
        int result = 0;
        if ( platformMapper.getParentPlatById(parentPlatform.getDeviceGBId()) == null) {
            result = platformMapper.addParentPlatform(parentPlatform);
        }else {
            result = platformMapper.updateParentPlatform(parentPlatform);
        }
        return result > 0;
    }
    @Override
    public boolean deleteParentPlatform(ParentPlatform parentPlatform) {
        int result = platformMapper.delParentPlatform(parentPlatform);
        return result > 0;
    }
    @Override
    public PageInfo<ParentPlatform> queryParentPlatformList(int page, int count) {
        PageHelper.startPage(page, count);
        List<ParentPlatform> all = platformMapper.getParentPlatformList();
        return new PageInfo<>(all);
    }
    @Override
    public ParentPlatform queryParentPlatById(String platformGbId) {
        return platformMapper.getParentPlatById(platformGbId);
    }
}
src/main/java/com/genersoft/iot/vmp/vmanager/platform/PlatformController.java
@@ -1,19 +1,15 @@
package com.genersoft.iot.vmp.vmanager.platform;
import com.alibaba.fastjson.JSONObject;
import com.genersoft.iot.vmp.common.PageResult;
import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
import com.genersoft.iot.vmp.vmanager.device.DeviceController;
import com.github.pagehelper.PageInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import com.genersoft.iot.vmp.conf.SipConfig;
@@ -46,7 +42,7 @@
    }
    @GetMapping("/platforms/{count}/{page}")
    public PageResult<ParentPlatform> platforms(@PathVariable int page, @PathVariable int count){
    public PageInfo<ParentPlatform> platforms(@PathVariable int page, @PathVariable int count){
        if (logger.isDebugEnabled()) {
            logger.debug("查询所有上级设备API调用");
src/main/resources/wvp.sqlite
Binary files differ
web_src/src/components/ParentPlatformList.vue
@@ -152,7 +152,7 @@
      this.$axios.get(`/api/platforms/${that.count}/${that.currentPage - 1}`)
        .then(function (res) {
          that.total = res.data.total;
          that.platformList = res.data.data;
          that.platformList = res.data.list;
        })
        .catch(function (error) {
          console.log(error);
web_src/src/router/index.js
@@ -35,7 +35,7 @@
      path: '/channelList/:deviceId/:parentChannelId/:count/:page',
      name: 'channelList',
      component: channelList,
    },
    },,
    {
      path: '/parentPlatformList/:count/:page',
      name: 'parentPlatformList',