648540858
2020-11-24 ecaf8750dd9c537e581ae05c65be9a26db5e67a7
完成向上级联->注册
11个文件已修改
5个文件已添加
429 ■■■■■ 已修改文件
README.md 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/SipLayer.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/event/EventPublisher.java 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/event/platformNotRegister/PlatformNotRegisterEvent.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/event/platformNotRegister/PlatformNotRegisterEventLister.java 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorFactory.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommanderForPlatform.java 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java 72 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommanderFroPlatform.java 81 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/response/impl/RegisterResponseProcessor.java 83 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorager.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/storager/jdbc/VideoManagerJdbcStoragerImpl.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/storager/redis/VideoManagerRedisStoragerImpl.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/vmanager/platform/PlatformController.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
web_src/src/components/platformEdit.vue 42 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
README.md
@@ -38,7 +38,8 @@
# 2.0 支持特性 
- [ ] 国标通道向上级联  
    - [X] WEB添加上级平台
    - [ ] 注册
    - [X] 注册
    - [ ] 心跳保活
    - [ ] 通道选择
    - [ ] 通道推送
    - [ ] 点播
src/main/java/com/genersoft/iot/vmp/gb28181/SipLayer.java
@@ -123,7 +123,7 @@
    public void processResponse(ResponseEvent evt) {
        Response response = evt.getResponse();
        int status = response.getStatusCode();
        if ((status >= 200) && (status < 300)) { // Success!
        if (((status >= 200) && (status < 300)) || status == 401) { // Success!
            ISIPResponseProcessor processor = processorFactory.createResponseProcessor(evt);
            try {
                processor.process(evt, this, sipConfig);
src/main/java/com/genersoft/iot/vmp/gb28181/event/EventPublisher.java
@@ -1,5 +1,8 @@
package com.genersoft.iot.vmp.gb28181.event;
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
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;
@@ -31,4 +34,14 @@
        outEvent.setFrom(from);
        applicationEventPublisher.publishEvent(outEvent);
    }
    /**
     * 平台未注册事件
     * @param platformGbId
     */
    public void platformNotRegisterEventPublish(String platformGbId){
        PlatformNotRegisterEvent platformNotRegisterEvent = new PlatformNotRegisterEvent(this);
        platformNotRegisterEvent.setPlatformGbID(platformGbId);
        applicationEventPublisher.publishEvent(platformNotRegisterEvent);
    }
}
src/main/java/com/genersoft/iot/vmp/gb28181/event/platformNotRegister/PlatformNotRegisterEvent.java
New file
@@ -0,0 +1,21 @@
package com.genersoft.iot.vmp.gb28181.event.platformNotRegister;
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
import org.springframework.context.ApplicationEvent;
public class PlatformNotRegisterEvent extends ApplicationEvent {
    private String platformGbID;
    public PlatformNotRegisterEvent(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/platformNotRegister/PlatformNotRegisterEventLister.java
New file
@@ -0,0 +1,45 @@
package com.genersoft.iot.vmp.gb28181.event.platformNotRegister;
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.storager.IVideoManagerStorager;
import com.genersoft.iot.vmp.utils.redis.RedisUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
/**
 * @Description: 平台未注册事件,来源有二:
 *               1、平台新添加
 *               2、平台心跳超时
 * @author: panll
 * @date: 2020年11月24日 10:00
 */
@Component
public class PlatformNotRegisterEventLister implements ApplicationListener<PlatformNotRegisterEvent> {
    private final static Logger logger = LoggerFactory.getLogger(PlatformNotRegisterEventLister.class);
    @Autowired
    private IVideoManagerStorager storager;
    @Autowired
    private RedisUtil redis;
    @Override
    public void onApplicationEvent(PlatformNotRegisterEvent event) {
        if (logger.isDebugEnabled()) {
            logger.debug("平台未注册事件触发,平台国标ID:" + event.getPlatformGbID());
        }
        ParentPlatform parentPlatform = storager.queryParentPlatById(event.getPlatformGbID());
        if (parentPlatform == null) {
            logger.debug("平台未注册事件触发,但平台已经删除!!! 平台国标ID:" + event.getPlatformGbID());
            return;
        }
    }
}
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorFactory.java
@@ -8,6 +8,7 @@
import javax.sip.message.Response;
import com.alibaba.fastjson.JSON;
import com.genersoft.iot.vmp.gb28181.transmit.response.impl.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@@ -30,10 +31,6 @@
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;
@@ -80,6 +77,9 @@
    
    @Autowired
    private CancelResponseProcessor cancelResponseProcessor;
    @Autowired
    private RegisterResponseProcessor registerResponseProcessor;
    
    @Autowired
    private OtherResponseProcessor otherResponseProcessor;
@@ -154,6 +154,8 @@
            return byeResponseProcessor;
        } else if (Request.CANCEL.equals(method)) {
            return cancelResponseProcessor;
        }else if (Request.REGISTER.equals(method)) {
            return registerResponseProcessor;
        } else {
            return otherResponseProcessor;
        }
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java
@@ -2,6 +2,7 @@
import com.genersoft.iot.vmp.common.StreamInfo;
import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
/**    
 * @Description:设备能力接口,用于定义设备的控制、查询能力   
@@ -212,4 +213,6 @@
     * @param device 视频设备
     */
    public boolean mobilePostitionQuery(Device device);
}
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommanderForPlatform.java
New file
@@ -0,0 +1,13 @@
package com.genersoft.iot.vmp.gb28181.transmit.cmd;
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
public interface ISIPCommanderForPlatform {
    /**
     * 向上级平台注册
     * @param parentPlatform
     * @return
     */
    boolean register(ParentPlatform parentPlatform, String callId, String realm, String nonce, String scheme);
}
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java
@@ -11,7 +11,9 @@
import javax.sip.address.SipURI;
import javax.sip.header.*;
import javax.sip.message.Request;
import javax.validation.constraints.NotNull;
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;
@@ -19,6 +21,7 @@
import com.genersoft.iot.vmp.conf.SipConfig;
import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.bean.Host;
import org.springframework.util.DigestUtils;
/**
 * @Description:摄像头命令request创造器 TODO 冗余代码太多待优化
@@ -168,4 +171,73 @@
        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/impl/SIPCommanderFroPlatform.java
New file
@@ -0,0 +1,81 @@
package com.genersoft.iot.vmp.gb28181.transmit.cmd.impl;
import com.genersoft.iot.vmp.conf.SipConfig;
import com.genersoft.iot.vmp.gb28181.bean.Device;
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.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;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Component;
import javax.sip.*;
import javax.sip.message.Request;
import java.text.ParseException;
@Component
public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
    @Autowired
    private SipConfig sipConfig;
    @Autowired
    private SIPRequestHeaderProvider headerProvider;
    @Autowired
    private VideoStreamSessionManager streamSession;
    @Autowired
    private IVideoManagerStorager storager;
    @Autowired
    @Qualifier(value="tcpSipProvider")
    private SipProvider tcpSipProvider;
    @Autowired
    @Qualifier(value="udpSipProvider")
    private SipProvider udpSipProvider;
    @Autowired
    private ZLMUtils zlmUtils;
    @Value("${media.rtp.enable}")
    private boolean rtpEnable;
    @Override
    public boolean register(ParentPlatform parentPlatform, @Nullable String callId, @Nullable String realm, @Nullable String nonce, @Nullable String scheme ) {
        try {
            Request request = null;
            if (realm == null || nonce == null) {
                request = headerProvider.createRegisterRequest(parentPlatform, null, null);
            }else {
                request = headerProvider.createRegisterRequest(parentPlatform, null, null, callId, realm, nonce, scheme);
            }
            transmitRequest(parentPlatform, request);
            return true;
        } catch (ParseException e) {
            e.printStackTrace();
        } catch (InvalidArgumentException e) {
            e.printStackTrace();
        } catch (PeerUnavailableException e) {
            e.printStackTrace();
        } catch (SipException e) {
            e.printStackTrace();
        }
        return false;
    }
    private void transmitRequest(ParentPlatform parentPlatform, Request request) throws SipException {
        if("TCP".equals(parentPlatform.getTransport())) {
            tcpSipProvider.sendRequest(request);
        } else if("UDP".equals(parentPlatform.getTransport())) {
            udpSipProvider.sendRequest(request);
        }
    }
}
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/response/impl/RegisterResponseProcessor.java
New file
@@ -0,0 +1,83 @@
package com.genersoft.iot.vmp.gb28181.transmit.response.impl;
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.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.IVideoManagerStorager;
import gov.nist.core.Host;
import gov.nist.javax.sip.address.AddressImpl;
import gov.nist.javax.sip.address.SipUri;
import gov.nist.javax.sip.header.To;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.sip.ResponseEvent;
import javax.sip.address.Address;
import javax.sip.address.URI;
import javax.sip.header.CallIdHeader;
import javax.sip.header.ToHeader;
import javax.sip.header.WWWAuthenticateHeader;
import javax.sip.message.Response;
/**
 * @Description:Register响应处理器
 * @author: swwheihei
 * @date:   2020年5月3日 下午5:32:23
 */
@Component
public class RegisterResponseProcessor implements ISIPResponseProcessor {
    private Logger logger = LoggerFactory.getLogger(RegisterRequestProcessor.class);
    @Autowired
    private ISIPCommanderForPlatform sipCommanderForPlatform;
    @Autowired
    private IVideoManagerStorager storager;
    /**
     * 处理Register响应
     *
      * @param evt
     * @param layer
     * @param config
     */
    @Override
    public void process(ResponseEvent evt, SipLayer layer, SipConfig config) {
        // TODO Auto-generated method stub
        Response response = evt.getResponse();
        ToHeader toHeader = (ToHeader) response.getHeader(ToHeader.NAME);
        SipUri uri = (SipUri)toHeader.getAddress().getURI();
        String platformGBId = uri.getAuthority().getUser();
        logger.info(String.format("收到 %s 的注册%S请求", platformGBId, response.getStatusCode() ));
        ParentPlatform parentPlatform = storager.queryParentPlatById(platformGBId);
        if (parentPlatform == null) {
            logger.warn(String.format("收到 %s 的注册%S请求, 但是平台信息未查询到!!!", platformGBId, response.getStatusCode()));
            return;
        }
        if (response.getStatusCode() == 401) {
            WWWAuthenticateHeader www = (WWWAuthenticateHeader)response.getHeader(WWWAuthenticateHeader.NAME);
            String realm = www.getRealm();
            String nonce = www.getNonce();
            String scheme = www.getScheme();
            CallIdHeader callIdHeader = (CallIdHeader)response.getHeader(CallIdHeader.NAME);
            String callId = callIdHeader.getCallId();
            sipCommanderForPlatform.register(parentPlatform, callId, realm, nonce, scheme);
        }else if (response.getStatusCode() == 200){
            // 注册成功
            logger.info(String.format("%s 注册成功", platformGBId ));
            parentPlatform.setStatus(true);
            storager.updateParentPlatform(parentPlatform);
        }
    }
}
src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorager.java
@@ -213,4 +213,11 @@
     * @return
     */
    public PageResult<ParentPlatform> queryParentPlatformList(int page, int count);
    /**
     * 获取上级平台
     * @param platformGbId
     * @return
     */
    public ParentPlatform queryParentPlatById(String platformGbId);
}
src/main/java/com/genersoft/iot/vmp/storager/jdbc/VideoManagerJdbcStoragerImpl.java
@@ -229,4 +229,9 @@
    public PageResult<ParentPlatform> queryParentPlatformList(int page, int count) {
        return null;
    }
    @Override
    public ParentPlatform queryParentPlatById(String platformGbId) {
        return null;
    }
}
src/main/java/com/genersoft/iot/vmp/storager/redis/VideoManagerRedisStoragerImpl.java
@@ -561,6 +561,7 @@
    @Override
    public boolean updateParentPlatform(ParentPlatform parentPlatform) {
        // 存储device
        return redis.set(VideoManagerConstants.PLATFORM_PREFIX + parentPlatform.getDeviceGBId(), parentPlatform);
    }
@@ -587,4 +588,9 @@
        pageResult.setData(resultData);
        return pageResult;
    }
    @Override
    public ParentPlatform queryParentPlatById(String platformGbId) {
        return (ParentPlatform)redis.get(VideoManagerConstants.PLATFORM_PREFIX + platformGbId);
    }
}
src/main/java/com/genersoft/iot/vmp/vmanager/platform/PlatformController.java
@@ -3,6 +3,8 @@
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 org.slf4j.Logger;
@@ -23,6 +25,9 @@
    @Autowired
    private IVideoManagerStorager storager;
    @Autowired
    private ISIPCommanderForPlatform commanderForPlatform;
    @GetMapping("/platforms/{count}/{page}")
    public PageResult<ParentPlatform> platforms(@PathVariable int page, @PathVariable int count){
@@ -53,8 +58,13 @@
        ){
            return new ResponseEntity<>("missing parameters", HttpStatus.BAD_REQUEST);
        }
        // TODO 检查是否已经存在,且注册成功, 如果注册成功,需要先注销之前再,修改并注册
        boolean updateResult = storager.updateParentPlatform(parentPlatform);
        if (updateResult) {
            commanderForPlatform.register(parentPlatform, null, null, null, null);
            return new ResponseEntity<>("success", HttpStatus.OK);
        }else {
            return new ResponseEntity<>("fail", HttpStatus.OK);
@@ -79,4 +89,17 @@
            return new ResponseEntity<>("fail", HttpStatus.OK);
        }
    }
    @RequestMapping("/platforms/exit/{deviceGbId}")
    @ResponseBody
    public ResponseEntity<String> exitPlatform(@PathVariable String deviceGbId){
        if (logger.isDebugEnabled()) {
            logger.debug("查询所有上级设备API调用");
        }
        ParentPlatform parentPlatform = storager.queryParentPlatById(deviceGbId);
        return new ResponseEntity<>(String.valueOf(parentPlatform != null), HttpStatus.OK);
    }
}
web_src/src/components/platformEdit.vue
@@ -30,7 +30,7 @@
                        <el-form-item label="本地端口" prop="devicePort">
                            <el-input v-model="platform.devicePort" :disabled="true"></el-input>
                        </el-form-item>
                    </el-form>
                </el-col>
                <el-col :span="12">
@@ -61,8 +61,8 @@
                        </el-form-item>
                        <el-form-item label="其他选项" >
                            <el-checkbox label="启用" v-model="platform.enable" ></el-checkbox>
                            <el-checkbox label="允许云台控制" v-model="platform.PTZEnable"></el-checkbox>
                            <el-checkbox label="启用RTCP保活" v-model="platform.rtcp"></el-checkbox>
                            <el-checkbox label="云台控制" v-model="platform.PTZEnable"></el-checkbox>
                            <el-checkbox label="RTCP保活" v-model="platform.rtcp"></el-checkbox>
                        </el-form-item>
                        <el-form-item>
                            <el-button type="primary" @click="onSubmit">{{onSubmit_text}}</el-button>
@@ -81,10 +81,26 @@
    name: 'platformEdit',
    props: {},
    computed: {
    },
    created() {},
    data() {
        var deviceGBIdRules = async (rule, value, callback) => {
          console.log(value)
          if (value === '') {
            callback(new Error('请输入设备国标编号'));
          } else {
            var exit = await this.deviceGBIdExit(value);
            console.log(exit)
            console.log(exit == "true")
            console.log(exit === "true")
            if (exit) {
              callback(new Error('设备国标编号已存在'));
            }else {
              callback();
            }
          }
        };
        return {
            listChangeCallback: null,
            showDialog: false,
@@ -145,7 +161,7 @@
                    { required: true, message:"请输入SIP服务端口",   trigger: 'blur' }
                ],
                deviceGBId: [
                    { required: true, message:"请输入设备国标编号",   trigger: 'blur' }
                    {validator: deviceGBIdRules,  trigger: 'blur' }
                ],
                username: [
                    { required: false, message:"请输入SIP认证用户名",   trigger: 'blur' }
@@ -176,7 +192,7 @@
                this.platform = platform;
                this.onSubmit_text = "保存"
            }
        },
        onSubmit: function () {
            console.log('onSubmit');
@@ -206,7 +222,19 @@
            this.showDialog = false;
            this.$refs.platform1.resetFields();
            this.$refs.platform2.resetFields();
        },
        deviceGBIdExit: async function (deviceGbId) {
          var result = false;
          var that = this
          await that.$axios.post(`/api/platforms/exit/${deviceGbId}`)
            .then(function (res) {
              result = res.data;
            })
            .catch(function (error) {
              console.log(error);
            });
            return result;
        }
    }