Commit b9a33f03d649d786315e345a00c004d96158df62

Authored by 648540858
1 parent a34db2ee

国标级联支持添加通道后主动推动到上级

sql/2.6.9更新.sql
1 1 alter table wvp_device_channel
2   - change stream_id stream_id varying(255)
3 2 \ No newline at end of file
  3 + change stream_id stream_id varying(255)
  4 +
  5 +alter table wvp_platform
  6 + add auto_push_channel bool default false
... ...
sql/初始化.sql
... ... @@ -194,6 +194,7 @@ create table wvp_platform (
194 194 create_time character varying(50),
195 195 update_time character varying(50),
196 196 as_message_channel bool default false,
  197 + auto_push_channel bool default false,
197 198 constraint uk_platform_unique_server_gb_id unique (server_gb_id)
198 199 );
199 200  
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/bean/ParentPlatform.java
... ... @@ -186,6 +186,9 @@ public class ParentPlatform {
186 186 @Schema(description = "是否作为消息通道")
187 187 private boolean asMessageChannel;
188 188  
  189 + @Schema(description = "是否作为消息通道")
  190 + private boolean autoPushChannel;
  191 +
189 192 public Integer getId() {
190 193 return id;
191 194 }
... ... @@ -425,4 +428,12 @@ public class ParentPlatform {
425 428 public void setAsMessageChannel(boolean asMessageChannel) {
426 429 this.asMessageChannel = asMessageChannel;
427 430 }
  431 +
  432 + public boolean isAutoPushChannel() {
  433 + return autoPushChannel;
  434 + }
  435 +
  436 + public void setAutoPushChannel(boolean autoPushChannel) {
  437 + this.autoPushChannel = autoPushChannel;
  438 + }
428 439 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/bean/SubscribeHolder.java
... ... @@ -32,11 +32,13 @@ public class SubscribeHolder {
32 32  
33 33 public void putCatalogSubscribe(String platformId, SubscribeInfo subscribeInfo) {
34 34 catalogMap.put(platformId, subscribeInfo);
35   - // 添加订阅到期
36   - String taskOverdueKey = taskOverduePrefix + "catalog_" + platformId;
37   - // 添加任务处理订阅过期
38   - dynamicTask.startDelay(taskOverdueKey, () -> removeCatalogSubscribe(subscribeInfo.getId()),
39   - subscribeInfo.getExpires() * 1000);
  35 + if (subscribeInfo.getExpires() > 0) {
  36 + // 添加订阅到期
  37 + String taskOverdueKey = taskOverduePrefix + "catalog_" + platformId;
  38 + // 添加任务处理订阅过期
  39 + dynamicTask.startDelay(taskOverdueKey, () -> removeCatalogSubscribe(subscribeInfo.getId()),
  40 + subscribeInfo.getExpires() * 1000);
  41 + }
40 42 }
41 43  
42 44 public SubscribeInfo getCatalogSubscribe(String platformId) {
... ... @@ -63,11 +65,13 @@ public class SubscribeHolder {
63 65 dynamicTask.startCron(key, new MobilePositionSubscribeHandlerTask(platformId),
64 66 subscribeInfo.getGpsInterval() * 1000);
65 67 String taskOverdueKey = taskOverduePrefix + "MobilePosition_" + platformId;
66   - // 添加任务处理订阅过期
67   - dynamicTask.startDelay(taskOverdueKey, () -> {
68   - removeMobilePositionSubscribe(subscribeInfo.getId());
69   - },
70   - subscribeInfo.getExpires() * 1000);
  68 + if (subscribeInfo.getExpires() > 0) {
  69 + // 添加任务处理订阅过期
  70 + dynamicTask.startDelay(taskOverdueKey, () -> {
  71 + removeMobilePositionSubscribe(subscribeInfo.getId());
  72 + },
  73 + subscribeInfo.getExpires() * 1000);
  74 + }
71 75 }
72 76  
73 77 public SubscribeInfo getMobilePositionSubscribe(String platformId) {
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/bean/SubscribeInfo.java
... ... @@ -18,6 +18,9 @@ public class SubscribeInfo {
18 18  
19 19 }
20 20  
  21 + public SubscribeInfo() {
  22 + }
  23 +
21 24 private String id;
22 25  
23 26 private SIPRequest request;
... ... @@ -33,6 +36,21 @@ public class SubscribeInfo {
33 36 private String sn;
34 37 private int gpsInterval;
35 38  
  39 + /**
  40 + * 模拟的FromTag
  41 + */
  42 + private String simulatedFromTag;
  43 +
  44 + /**
  45 + * 模拟的ToTag
  46 + */
  47 + private String simulatedToTag;
  48 +
  49 + /**
  50 + * 模拟的CallID
  51 + */
  52 + private String simulatedCallId;
  53 +
36 54 public String getId() {
37 55 return id;
38 56 }
... ... @@ -96,4 +114,28 @@ public class SubscribeInfo {
96 114 public void setGpsInterval(int gpsInterval) {
97 115 this.gpsInterval = gpsInterval;
98 116 }
  117 +
  118 + public String getSimulatedFromTag() {
  119 + return simulatedFromTag;
  120 + }
  121 +
  122 + public void setSimulatedFromTag(String simulatedFromTag) {
  123 + this.simulatedFromTag = simulatedFromTag;
  124 + }
  125 +
  126 + public String getSimulatedCallId() {
  127 + return simulatedCallId;
  128 + }
  129 +
  130 + public void setSimulatedCallId(String simulatedCallId) {
  131 + this.simulatedCallId = simulatedCallId;
  132 + }
  133 +
  134 + public String getSimulatedToTag() {
  135 + return simulatedToTag;
  136 + }
  137 +
  138 + public void setSimulatedToTag(String simulatedToTag) {
  139 + this.simulatedToTag = simulatedToTag;
  140 + }
99 141 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderPlarformProvider.java
... ... @@ -227,11 +227,11 @@ public class SIPRequestHeaderPlarformProvider {
227 227 SipURI fromSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(parentPlatform.getDeviceGBId(),
228 228 parentPlatform.getDeviceIp() + ":" + parentPlatform.getDevicePort());
229 229 Address fromAddress = SipFactory.getInstance().createAddressFactory().createAddress(fromSipURI);
230   - FromHeader fromHeader = SipFactory.getInstance().createHeaderFactory().createFromHeader(fromAddress, subscribeInfo.getResponse().getToTag());
  230 + FromHeader fromHeader = SipFactory.getInstance().createHeaderFactory().createFromHeader(fromAddress, subscribeInfo.getResponse() != null ? subscribeInfo.getResponse().getToTag(): subscribeInfo.getSimulatedToTag());
231 231 // to
232 232 SipURI toSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(parentPlatform.getServerGBId(), parentPlatform.getServerGBDomain());
233 233 Address toAddress = SipFactory.getInstance().createAddressFactory().createAddress(toSipURI);
234   - ToHeader toHeader = SipFactory.getInstance().createHeaderFactory().createToHeader(toAddress, subscribeInfo.getRequest().getFromTag());
  234 + ToHeader toHeader = SipFactory.getInstance().createHeaderFactory().createToHeader(toAddress, subscribeInfo.getRequest() != null ?subscribeInfo.getRequest().getFromTag(): subscribeInfo.getSimulatedFromTag());
235 235  
236 236 // Forwards
237 237 MaxForwardsHeader maxForwards = SipFactory.getInstance().createHeaderFactory().createMaxForwardsHeader(70);
... ... @@ -241,7 +241,7 @@ public class SIPRequestHeaderPlarformProvider {
241 241 // 设置编码, 防止中文乱码
242 242 messageFactory.setDefaultContentEncodingCharset("gb2312");
243 243  
244   - CallIdHeader callIdHeader = SipFactory.getInstance().createHeaderFactory().createCallIdHeader(subscribeInfo.getRequest().getCallIdHeader().getCallId());
  244 + CallIdHeader callIdHeader = SipFactory.getInstance().createHeaderFactory().createCallIdHeader(subscribeInfo.getRequest() != null ? subscribeInfo.getRequest().getCallIdHeader().getCallId(): subscribeInfo.getSimulatedCallId());
245 245  
246 246 request = (SIPRequest) messageFactory.createRequest(requestURI, Request.NOTIFY, callIdHeader, cSeqHeader, fromHeader,
247 247 toHeader, viaHeaders, maxForwards);
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommanderFroPlatform.java
... ... @@ -148,13 +148,13 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
148 148  
149 149 CallIdHeader callIdHeader = sipSender.getNewCallIdHeader(parentPlatform.getDeviceIp(),parentPlatform.getTransport());
150 150  
151   - Request request = headerProviderPlatformProvider.createMessageRequest(
152   - parentPlatform,
153   - keepaliveXml.toString(),
154   - SipUtils.getNewFromTag(),
155   - SipUtils.getNewViaTag(),
156   - callIdHeader);
157   - sipSender.transmitRequest(parentPlatform.getDeviceIp(), request, errorEvent, okEvent);
  151 + Request request = headerProviderPlatformProvider.createMessageRequest(
  152 + parentPlatform,
  153 + keepaliveXml.toString(),
  154 + SipUtils.getNewFromTag(),
  155 + SipUtils.getNewViaTag(),
  156 + callIdHeader);
  157 + sipSender.transmitRequest(parentPlatform.getDeviceIp(), request, errorEvent, okEvent);
158 158 return callIdHeader.getCallId();
159 159 }
160 160  
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/SubscribeRequestProcessor.java
... ... @@ -10,6 +10,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.event.request.ISIPRequestProcessor
10 10 import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
11 11 import com.genersoft.iot.vmp.gb28181.utils.SipUtils;
12 12 import com.genersoft.iot.vmp.gb28181.utils.XmlUtil;
  13 +import com.genersoft.iot.vmp.service.IPlatformService;
13 14 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
14 15 import gov.nist.javax.sip.message.SIPRequest;
15 16 import gov.nist.javax.sip.message.SIPResponse;
... ... @@ -50,6 +51,10 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme
50 51 @Autowired
51 52 private SIPSender sipSender;
52 53  
  54 +
  55 + @Autowired
  56 + private IPlatformService platformService;
  57 +
53 58 @Override
54 59 public void afterPropertiesSet() throws Exception {
55 60 // 添加消息处理的订阅
... ... @@ -191,5 +196,8 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme
191 196 } catch (SipException | InvalidArgumentException | ParseException e) {
192 197 logger.error("未处理的异常 ", e);
193 198 }
  199 + if (subscribeHolder.getCatalogSubscribe(platformId) == null && platform.isAutoPushChannel()) {
  200 + platformService.addSimulatedSubscribeInfo(platform);
  201 + }
194 202 }
195 203 }
... ...
src/main/java/com/genersoft/iot/vmp/service/IPlatformService.java
... ... @@ -55,4 +55,6 @@ public interface IPlatformService {
55 55 * @param platformId 平台
56 56 */
57 57 void sendNotifyMobilePosition(String platformId);
  58 +
  59 + void addSimulatedSubscribeInfo(ParentPlatform parentPlatform);
58 60 }
... ...
src/main/java/com/genersoft/iot/vmp/service/impl/GbStreamServiceImpl.java
... ... @@ -18,6 +18,7 @@ import org.springframework.jdbc.datasource.DataSourceTransactionManager;
18 18 import org.springframework.stereotype.Service;
19 19 import org.springframework.transaction.TransactionDefinition;
20 20 import org.springframework.transaction.TransactionStatus;
  21 +import org.springframework.transaction.annotation.Transactional;
21 22 import org.springframework.util.ObjectUtils;
22 23  
23 24 import java.util.ArrayList;
... ...
src/main/java/com/genersoft/iot/vmp/service/impl/PlatformServiceImpl.java
... ... @@ -6,6 +6,7 @@ import com.genersoft.iot.vmp.gb28181.bean.*;
6 6 import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
7 7 import com.genersoft.iot.vmp.gb28181.session.SSRCFactory;
8 8 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform;
  9 +import com.genersoft.iot.vmp.gb28181.utils.SipUtils;
9 10 import com.genersoft.iot.vmp.media.zlm.ZLMServerFactory;
10 11 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
11 12 import com.genersoft.iot.vmp.service.IMediaServerService;
... ... @@ -16,17 +17,22 @@ import com.genersoft.iot.vmp.storager.dao.*;
16 17 import com.genersoft.iot.vmp.utils.DateUtil;
17 18 import com.github.pagehelper.PageHelper;
18 19 import com.github.pagehelper.PageInfo;
  20 +import gov.nist.javax.sip.message.SIPRequest;
19 21 import org.slf4j.Logger;
20 22 import org.slf4j.LoggerFactory;
21 23 import org.springframework.beans.factory.annotation.Autowired;
22 24 import org.springframework.stereotype.Service;
23 25  
24 26 import javax.sip.InvalidArgumentException;
  27 +import javax.sip.PeerUnavailableException;
25 28 import javax.sip.SipException;
  29 +import javax.sip.SipFactory;
  30 +import javax.sip.address.Address;
  31 +import javax.sip.address.SipURI;
  32 +import javax.sip.header.*;
  33 +import javax.sip.message.Request;
26 34 import java.text.ParseException;
27   -import java.util.HashMap;
28   -import java.util.List;
29   -import java.util.Map;
  35 +import java.util.*;
30 36  
31 37 /**
32 38 * @author lin
... ... @@ -182,6 +188,7 @@ public class PlatformServiceImpl implements IPlatformService {
182 188 }
183 189 }
184 190  
  191 +
185 192 return false;
186 193 }
187 194  
... ... @@ -256,6 +263,31 @@ public class PlatformServiceImpl implements IPlatformService {
256 263 },
257 264 (parentPlatform.getKeepTimeout())*1000);
258 265 }
  266 + if (parentPlatform.isAutoPushChannel()) {
  267 + if (subscribeHolder.getCatalogSubscribe(parentPlatform.getServerGBId()) == null) {
  268 + addSimulatedSubscribeInfo(parentPlatform);
  269 + }
  270 + }else {
  271 + SubscribeInfo catalogSubscribe = subscribeHolder.getCatalogSubscribe(parentPlatform.getServerGBId());
  272 + if (catalogSubscribe != null && catalogSubscribe.getExpires() == -1) {
  273 + subscribeHolder.removeCatalogSubscribe(parentPlatform.getServerGBId());
  274 + }
  275 + }
  276 + }
  277 +
  278 + @Override
  279 + public void addSimulatedSubscribeInfo(ParentPlatform parentPlatform) {
  280 + // 自动添加一条模拟的订阅信息
  281 + SubscribeInfo subscribeInfo = new SubscribeInfo();
  282 + subscribeInfo.setId(parentPlatform.getServerGBId());
  283 + subscribeInfo.setExpires(-1);
  284 + subscribeInfo.setEventType("Catalog");
  285 + int random = (int) Math.floor(Math.random() * 10000);
  286 + subscribeInfo.setEventId(random + "");
  287 + subscribeInfo.setSimulatedCallId(UUID.randomUUID().toString().replace("-", "") + "@" + parentPlatform.getServerIP());
  288 + subscribeInfo.setSimulatedFromTag(UUID.randomUUID().toString().replace("-", ""));
  289 + subscribeInfo.setSimulatedToTag(UUID.randomUUID().toString().replace("-", ""));
  290 + subscribeHolder.putCatalogSubscribe(parentPlatform.getServerGBId(), subscribeInfo);
259 291 }
260 292  
261 293 private void registerTask(ParentPlatform parentPlatform, SipTransactionInfo sipTransactionInfo){
... ...
src/main/java/com/genersoft/iot/vmp/service/impl/StreamPushServiceImpl.java
... ... @@ -440,7 +440,7 @@ public class StreamPushServiceImpl implements IStreamPushService {
440 440  
441 441 }
442 442 }
443   - if (streamPushItemListFroPlatform.size() > 0) {
  443 + if (!streamPushItemListFroPlatform.isEmpty()) {
444 444 platformGbStreamMapper.batchAdd(streamPushItemListFroPlatform);
445 445 // 发送通知
446 446 for (String platformId : platformForEvent.keySet()) {
... ...
src/main/java/com/genersoft/iot/vmp/storager/dao/ParentPlatformMapper.java
... ... @@ -16,10 +16,10 @@ import java.util.List;
16 16 public interface ParentPlatformMapper {
17 17  
18 18 @Insert("INSERT INTO wvp_platform (enable, name, server_gb_id, server_gb_domain, server_ip, server_port,device_gb_id,device_ip,"+
19   - "device_port,username,password,expires,keep_timeout,transport,character_set,ptz,rtcp,as_message_channel,"+
  19 + "device_port,username,password,expires,keep_timeout,transport,character_set,ptz,rtcp,as_message_channel,auto_push_channel,"+
20 20 "status,start_offline_push,catalog_id,administrative_division,catalog_group,create_time,update_time) " +
21 21 " VALUES (#{enable}, #{name}, #{serverGBId}, #{serverGBDomain}, #{serverIP}, #{serverPort}, #{deviceGBId}, #{deviceIp}, " +
22   - " #{devicePort}, #{username}, #{password}, #{expires}, #{keepTimeout}, #{transport}, #{characterSet}, #{ptz}, #{rtcp}, #{asMessageChannel}, " +
  22 + " #{devicePort}, #{username}, #{password}, #{expires}, #{keepTimeout}, #{transport}, #{characterSet}, #{ptz}, #{rtcp}, #{asMessageChannel}, #{autoPushChannel}, " +
23 23 " #{status}, #{startOfflinePush}, #{catalogId}, #{administrativeDivision}, #{catalogGroup}, #{createTime}, #{updateTime})")
24 24 int addParentPlatform(ParentPlatform parentPlatform);
25 25  
... ... @@ -42,6 +42,7 @@ public interface ParentPlatformMapper {
42 42 "ptz=#{ptz}, " +
43 43 "rtcp=#{rtcp}, " +
44 44 "as_message_channel=#{asMessageChannel}, " +
  45 + "auto_push_channel=#{autoPushChannel}, " +
45 46 "status=#{status}, " +
46 47 "start_offline_push=#{startOfflinePush}, " +
47 48 "catalog_group=#{catalogGroup}, " +
... ...
web_src/src/components/dialog/platformEdit.vue
... ... @@ -91,9 +91,10 @@
91 91 <el-form-item label="其他选项">
92 92 <el-checkbox label="启用" v-model="platform.enable" @change="checkExpires"></el-checkbox>
93 93 <!-- <el-checkbox label="云台控制" v-model="platform.ptz"></el-checkbox>-->
94   - <el-checkbox label="拉起离线推流" v-model="platform.startOfflinePush"></el-checkbox>
  94 + <el-checkbox label="拉起推流" v-model="platform.startOfflinePush"></el-checkbox>
95 95 <el-checkbox label="RTCP保活" v-model="platform.rtcp" @change="rtcpCheckBoxChange"></el-checkbox>
96   - <el-checkbox label="作为消息通道" v-model="platform.asMessageChannel" ></el-checkbox>
  96 + <el-checkbox label="消息通道" v-model="platform.asMessageChannel" ></el-checkbox>
  97 + <el-checkbox label="推送通道" v-model="platform.autoPushChannel" ></el-checkbox>
97 98 </el-form-item>
98 99 <el-form-item>
99 100 <el-button type="primary" @click="onSubmit">{{
... ... @@ -141,6 +142,7 @@ export default {
141 142 ptz: true,
142 143 rtcp: false,
143 144 asMessageChannel: false,
  145 + autoPushChannel: false,
144 146 name: null,
145 147 serverGBId: null,
146 148 serverGBDomain: null,
... ... @@ -208,6 +210,7 @@ export default {
208 210 this.platform.ptz = platform.ptz;
209 211 this.platform.rtcp = platform.rtcp;
210 212 this.platform.asMessageChannel = platform.asMessageChannel;
  213 + this.platform.autoPushChannel = platform.autoPushChannel;
211 214 this.platform.name = platform.name;
212 215 this.platform.serverGBId = platform.serverGBId;
213 216 this.platform.serverGBDomain = platform.serverGBDomain;
... ... @@ -284,6 +287,7 @@ export default {
284 287 ptz: true,
285 288 rtcp: false,
286 289 asMessageChannel: false,
  290 + autoPushChannel: false,
287 291 name: null,
288 292 serverGBId: null,
289 293 administrativeDivision: null,
... ...