Sfoglia il codice sorgente

完成向上级联->注册

648540858 5 anni fa
parent
commit
ecaf8750dd

+ 2 - 1
README.md

@@ -38,7 +38,8 @@ https://gitee.com/18010473990/wvp-GB28181.git
 # 2.0 支持特性 
 - [ ] 国标通道向上级联  
     - [X] WEB添加上级平台
-    - [ ] 注册
+    - [X] 注册
+    - [ ] 心跳保活
     - [ ] 通道选择
     - [ ] 通道推送
     - [ ] 点播

+ 1 - 1
src/main/java/com/genersoft/iot/vmp/gb28181/SipLayer.java

@@ -123,7 +123,7 @@ public class SipLayer implements SipListener {
 	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);

+ 13 - 0
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 @@ public class EventPublisher {
 		outEvent.setFrom(from);
         applicationEventPublisher.publishEvent(outEvent);
     }
+
+	/**
+	 * 平台未注册事件
+	 * @param platformGbId
+	 */
+	public void platformNotRegisterEventPublish(String platformGbId){
+		PlatformNotRegisterEvent platformNotRegisterEvent = new PlatformNotRegisterEvent(this);
+		platformNotRegisterEvent.setPlatformGbID(platformGbId);
+        applicationEventPublisher.publishEvent(platformNotRegisterEvent);
+    }
 }

+ 21 - 0
src/main/java/com/genersoft/iot/vmp/gb28181/event/platformNotRegister/PlatformNotRegisterEvent.java

@@ -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;
+    }
+}

+ 45 - 0
src/main/java/com/genersoft/iot/vmp/gb28181/event/platformNotRegister/PlatformNotRegisterEventLister.java

@@ -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;
+        }
+    }
+}

+ 6 - 4
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorFactory.java

@@ -8,6 +8,7 @@ import javax.sip.message.Request;
 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.OtherRequestProcessor
 import com.genersoft.iot.vmp.gb28181.transmit.request.impl.RegisterRequestProcessor;
 import com.genersoft.iot.vmp.gb28181.transmit.request.impl.SubscribeRequestProcessor;
 import com.genersoft.iot.vmp.gb28181.transmit.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 @@ public class SIPProcessorFactory {
 	
 	@Autowired
 	private CancelResponseProcessor cancelResponseProcessor;
+
+	@Autowired
+	private RegisterResponseProcessor registerResponseProcessor;
 	
 	@Autowired
 	private OtherResponseProcessor otherResponseProcessor;
@@ -154,6 +154,8 @@ public class SIPProcessorFactory {
 			return byeResponseProcessor;
 		} else if (Request.CANCEL.equals(method)) {
 			return cancelResponseProcessor;
+		}else if (Request.REGISTER.equals(method)) {
+			return registerResponseProcessor;
 		} else {
 			return otherResponseProcessor;
 		}

+ 3 - 0
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java

@@ -2,6 +2,7 @@ package com.genersoft.iot.vmp.gb28181.transmit.cmd;
 
 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 @@ public interface ISIPCommander {
 	 * @param device 视频设备
 	 */
 	public boolean mobilePostitionQuery(Device device);
+
+
 }

+ 13 - 0
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommanderForPlatform.java

@@ -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);
+}

+ 72 - 0
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java

@@ -11,7 +11,9 @@ 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 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 org.springframework.stereotype.Component;
 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 @@ public class SIPRequestHeaderProvider {
 		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;
+	}
 }

+ 81 - 0
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommanderFroPlatform.java

@@ -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);
+        }
+    }
+}

+ 83 - 0
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/response/impl/RegisterResponseProcessor.java

@@ -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);
+		}
+	}
+
+}

+ 7 - 0
src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorager.java

@@ -213,4 +213,11 @@ public interface IVideoManagerStorager {
 	 * @return
 	 */
 	public PageResult<ParentPlatform> queryParentPlatformList(int page, int count);
+
+	/**
+	 * 获取上级平台
+	 * @param platformGbId
+	 * @return
+	 */
+	public ParentPlatform queryParentPlatById(String platformGbId);
 }

+ 5 - 0
src/main/java/com/genersoft/iot/vmp/storager/jdbc/VideoManagerJdbcStoragerImpl.java

@@ -229,4 +229,9 @@ public class VideoManagerJdbcStoragerImpl implements IVideoManagerStorager {
 	public PageResult<ParentPlatform> queryParentPlatformList(int page, int count) {
 		return null;
 	}
+
+	@Override
+	public ParentPlatform queryParentPlatById(String platformGbId) {
+		return null;
+	}
 }

+ 6 - 0
src/main/java/com/genersoft/iot/vmp/storager/redis/VideoManagerRedisStoragerImpl.java

@@ -561,6 +561,7 @@ public class VideoManagerRedisStoragerImpl implements IVideoManagerStorager {
 
 	@Override
 	public boolean updateParentPlatform(ParentPlatform parentPlatform) {
+
 		// 存储device
 		return redis.set(VideoManagerConstants.PLATFORM_PREFIX + parentPlatform.getDeviceGBId(), parentPlatform);
 	}
@@ -587,4 +588,9 @@ public class VideoManagerRedisStoragerImpl implements IVideoManagerStorager {
 		pageResult.setData(resultData);
 		return pageResult;
 	}
+
+	@Override
+	public ParentPlatform queryParentPlatById(String platformGbId) {
+		return (ParentPlatform)redis.get(VideoManagerConstants.PLATFORM_PREFIX + platformGbId);
+	}
 }

+ 23 - 0
src/main/java/com/genersoft/iot/vmp/vmanager/platform/PlatformController.java

@@ -3,6 +3,8 @@ package com.genersoft.iot.vmp.vmanager.platform;
 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;
@@ -24,6 +26,9 @@ public class PlatformController {
     @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 @@ public class PlatformController {
         ){
             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 @@ public class PlatformController {
             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);
+    }
+
+
 }

+ 35 - 7
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 @@ export default {
     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 @@ export default {
                     { 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 @@ export default {
                 this.platform = platform;
                 this.onSubmit_text = "保存"
             }
-            
+
         },
         onSubmit: function () {
             console.log('onSubmit');
@@ -206,7 +222,19 @@ export default {
             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;
+
         }
 
     }