Commit 509d9b3cbba7ba8fdc7466c34e46db70d41517a8

Authored by 648540858
2 parents e5856a9f 5f096921

Merge branch 'wvp-28181-2.0' into main-dev

# Conflicts:
#	src/main/java/com/genersoft/iot/vmp/gb28181/bean/Device.java
#	src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
#	src/main/java/com/genersoft/iot/vmp/service/IPlayService.java
#	src/main/java/com/genersoft/iot/vmp/service/impl/DeviceServiceImpl.java
#	src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
#	src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceMapper.java
Showing 32 changed files with 1104 additions and 253 deletions
README.md
... ... @@ -49,6 +49,7 @@ https://gitee.com/pan648540858/wvp-GB28181-pro.git
49 49 - [X] 支持电子地图,支持接入WGS84和GCJ02两种坐标系,并且自动转化为合适的坐标系进行展示和分发
50 50 - [X] 接入设备
51 51 - [X] 视频预览
  52 + - [X] 支持主码流子码流切换
52 53 - [X] 无限制接入路数,能接入多少设备只取决于你的服务器性能
53 54 - [X] 云台控制,控制设备转向,拉近,拉远
54 55 - [X] 预置位查询,使用与设置
... ...
src/main/java/com/genersoft/iot/vmp/common/InviteInfo.java
1 1 package com.genersoft.iot.vmp.common;
2 2  
3 3 import com.genersoft.iot.vmp.service.bean.SSRCInfo;
4   -import io.swagger.v3.oas.annotations.media.Schema;
5 4  
6 5 /**
7 6 * 记录每次发送invite消息的状态
... ... @@ -125,20 +124,4 @@ public class InviteInfo {
125 124 this.streamMode = streamMode;
126 125 }
127 126  
128   -
129   - /*=========================设备主子码流逻辑START====================*/
130   - @Schema(description = "是否为子码流(true-是,false-主码流)")
131   - private boolean subStream;
132   -
133   - public boolean isSubStream() {
134   - return subStream;
135   - }
136   -
137   - public void setSubStream(boolean subStream) {
138   - this.subStream = subStream;
139   - }
140   -
141   -
142   -
143   -
144 127 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/bean/Device.java
... ... @@ -452,27 +452,11 @@ public class Device {
452 452 public void setSipTransactionInfo(SipTransactionInfo sipTransactionInfo) {
453 453 this.sipTransactionInfo = sipTransactionInfo;
454 454 }
  455 + public boolean isBroadcastPushAfterAck() {
  456 + return broadcastPushAfterAck;
  457 + }
455 458  
456   - /*======================设备主子码流逻辑START=========================*/
457   - @Schema(description = "开启主子码流切换的开关(false-不开启,true-开启)")
458   - private boolean switchPrimarySubStream;
459   -
460   - public boolean isSwitchPrimarySubStream() {
461   - return switchPrimarySubStream;
462   - }
463   -
464   - public void setSwitchPrimarySubStream(boolean switchPrimarySubStream) {
465   - this.switchPrimarySubStream = switchPrimarySubStream;
466   - }
467   -
468   - /*======================设备主子码流逻辑END=========================*/
469   -
470   -
471   - public boolean isBroadcastPushAfterAck() {
472   - return broadcastPushAfterAck;
473   - }
474   -
475   - public void setBroadcastPushAfterAck(boolean broadcastPushAfterAck) {
476   - this.broadcastPushAfterAck = broadcastPushAfterAck;
477   - }
  459 + public void setBroadcastPushAfterAck(boolean broadcastPushAfterAck) {
  460 + this.broadcastPushAfterAck = broadcastPushAfterAck;
  461 + }
478 462 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/bean/DeviceChannel.java
... ... @@ -246,6 +246,10 @@ public class DeviceChannel {
246 246 @Schema(description = "GPS的更新时间")
247 247 private String gpsTime;
248 248  
  249 + @Schema(description = "码流标识,优先级高于设备中码流标识," +
  250 + "用于选择码流时组成码流标识。默认为null,不设置。可选值: stream/streamnumber/streamprofile/streamMode")
  251 + private String streamIdentification;
  252 +
249 253 public int getId() {
250 254 return id;
251 255 }
... ... @@ -574,4 +578,12 @@ public class DeviceChannel {
574 578 public void setGpsTime(String gpsTime) {
575 579 this.gpsTime = gpsTime;
576 580 }
  581 +
  582 + public String getStreamIdentification() {
  583 + return streamIdentification;
  584 + }
  585 +
  586 + public void setStreamIdentification(String streamIdentification) {
  587 + this.streamIdentification = streamIdentification;
  588 + }
577 589 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/bean/GbSteamIdentification.java 0 → 100644
  1 +package com.genersoft.iot.vmp.gb28181.bean;
  2 +
  3 +/**
  4 + * 码流索引标识
  5 + */
  6 +public enum GbSteamIdentification {
  7 + /**
  8 + * 主码流 stream:0
  9 + * 子码流 stream:1s
  10 + */
  11 + streamMain("stream", new String[]{"0","1"}),
  12 + /**
  13 + * 国标28181-2022定义的方式
  14 + * 主码流 streamnumber:0
  15 + * 子码流 streamnumber:1
  16 + */
  17 + streamnumber("streamnumber", new String[]{"0","1"}),
  18 + /**
  19 + * 主码流 streamprofile:0
  20 + * 子码流 streamprofile:1
  21 + */
  22 + streamprofile("streamprofile", new String[]{"0","1"}),
  23 + /**
  24 + * 适用的品牌: TP-LINK
  25 + */
  26 + streamMode("streamMode", new String[]{"main","sub"}),
  27 + ;
  28 +
  29 + GbSteamIdentification(String value, String[] indexArray) {
  30 + this.value = value;
  31 + this.indexArray = indexArray;
  32 + }
  33 +
  34 + private String value;
  35 + private String[] indexArray;
  36 +
  37 + public String getValue() {
  38 + return value;
  39 + }
  40 +
  41 + public String[] getIndexArray() {
  42 + return indexArray;
  43 + }
  44 +}
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/bean/SubscribeHolder.java
... ... @@ -52,7 +52,7 @@ public class SubscribeHolder {
52 52 Runnable runnable = dynamicTask.get(taskOverdueKey);
53 53 if (runnable instanceof ISubscribeTask) {
54 54 ISubscribeTask subscribeTask = (ISubscribeTask) runnable;
55   - subscribeTask.stop();
  55 + subscribeTask.stop(null);
56 56 }
57 57 // 添加任务处理订阅过期
58 58 dynamicTask.stop(taskOverdueKey);
... ... @@ -87,7 +87,7 @@ public class SubscribeHolder {
87 87 Runnable runnable = dynamicTask.get(taskOverdueKey);
88 88 if (runnable instanceof ISubscribeTask) {
89 89 ISubscribeTask subscribeTask = (ISubscribeTask) runnable;
90   - subscribeTask.stop();
  90 + subscribeTask.stop(null);
91 91 }
92 92 // 添加任务处理订阅过期
93 93 dynamicTask.stop(taskOverdueKey);
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/event/SipSubscribe.java
... ... @@ -2,6 +2,8 @@ package com.genersoft.iot.vmp.gb28181.event;
2 2  
3 3 import com.genersoft.iot.vmp.gb28181.bean.DeviceNotFoundEvent;
4 4 import gov.nist.javax.sip.message.SIPRequest;
  5 +import gov.nist.javax.sip.message.SIPResponse;
  6 +import org.apache.commons.lang3.ObjectUtils;
5 7 import org.slf4j.Logger;
6 8 import org.slf4j.LoggerFactory;
7 9 import org.springframework.scheduling.annotation.Scheduled;
... ... @@ -11,8 +13,7 @@ import javax.sip.DialogTerminatedEvent;
11 13 import javax.sip.ResponseEvent;
12 14 import javax.sip.TimeoutEvent;
13 15 import javax.sip.TransactionTerminatedEvent;
14   -import javax.sip.header.CallIdHeader;
15   -import javax.sip.message.Response;
  16 +import javax.sip.header.WarningHeader;
16 17 import java.time.Instant;
17 18 import java.util.Map;
18 19 import java.util.concurrent.ConcurrentHashMap;
... ... @@ -97,14 +98,27 @@ public class SipSubscribe {
97 98 this.event = event;
98 99 if (event instanceof ResponseEvent) {
99 100 ResponseEvent responseEvent = (ResponseEvent)event;
100   - Response response = responseEvent.getResponse();
  101 + SIPResponse response = (SIPResponse)responseEvent.getResponse();
101 102 this.type = EventResultType.response;
102 103 if (response != null) {
103   - this.msg = response.getReasonPhrase();
  104 + WarningHeader warningHeader = (WarningHeader)response.getHeader(WarningHeader.NAME);
  105 + if (warningHeader != null && !ObjectUtils.isEmpty(warningHeader.getText())) {
  106 + this.msg = "";
  107 + if (warningHeader.getCode() > 0) {
  108 + this.msg += warningHeader.getCode() + ":";
  109 + }
  110 + if (warningHeader.getAgent() != null) {
  111 + this.msg += warningHeader.getCode() + ":";
  112 + }
  113 + if (warningHeader.getText() != null) {
  114 + this.msg += warningHeader.getText();
  115 + }
  116 + }else {
  117 + this.msg = response.getReasonPhrase();
  118 + }
104 119 this.statusCode = response.getStatusCode();
  120 + this.callId = response.getCallIdHeader().getCallId();
105 121 }
106   - this.callId = ((CallIdHeader)response.getHeader(CallIdHeader.NAME)).getCallId();
107   -
108 122 }else if (event instanceof TimeoutEvent) {
109 123 TimeoutEvent timeoutEvent = (TimeoutEvent)event;
110 124 this.type = EventResultType.timeout;
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/session/CommonSessionManager.java 0 → 100755
  1 +package com.genersoft.iot.vmp.gb28181.session;
  2 +
  3 +import com.genersoft.iot.vmp.common.CommonCallback;
  4 +import org.springframework.scheduling.annotation.Scheduled;
  5 +import org.springframework.stereotype.Component;
  6 +
  7 +import java.util.Calendar;
  8 +import java.util.Map;
  9 +import java.util.concurrent.ConcurrentHashMap;
  10 +
  11 +/**
  12 + * 通用回调管理
  13 + */
  14 +@Component
  15 +public class CommonSessionManager {
  16 +
  17 + public static Map<String, CommonSession> callbackMap = new ConcurrentHashMap<>();
  18 +
  19 + /**
  20 + * 存储回调相关的信息
  21 + */
  22 + class CommonSession{
  23 + public String session;
  24 + public long createTime;
  25 + public int timeout;
  26 +
  27 + public CommonCallback<Object> callback;
  28 + public CommonCallback<String> timeoutCallback;
  29 + }
  30 +
  31 + /**
  32 + * 添加回调
  33 + * @param sessionId 唯一标识
  34 + * @param callback 回调
  35 + * @param timeout 超时时间, 单位分钟
  36 + */
  37 + public void add(String sessionId, CommonCallback<Object> callback, CommonCallback<String> timeoutCallback,
  38 + Integer timeout) {
  39 + CommonSession commonSession = new CommonSession();
  40 + commonSession.session = sessionId;
  41 + commonSession.callback = callback;
  42 + commonSession.createTime = System.currentTimeMillis();
  43 + if (timeoutCallback != null) {
  44 + commonSession.timeoutCallback = timeoutCallback;
  45 + }
  46 + if (timeout != null) {
  47 + commonSession.timeout = timeout;
  48 + }
  49 + callbackMap.put(sessionId, commonSession);
  50 + }
  51 +
  52 + public void add(String sessionId, CommonCallback<Object> callback) {
  53 + add(sessionId, callback, null, 1);
  54 + }
  55 +
  56 + public CommonCallback<Object> get(String sessionId, boolean destroy) {
  57 + CommonSession commonSession = callbackMap.get(sessionId);
  58 + if (destroy) {
  59 + callbackMap.remove(sessionId);
  60 + }
  61 + return commonSession.callback;
  62 + }
  63 +
  64 + public CommonCallback<Object> get(String sessionId) {
  65 + return get(sessionId, false);
  66 + }
  67 +
  68 + public void delete(String sessionID) {
  69 + callbackMap.remove(sessionID);
  70 + }
  71 +
  72 + @Scheduled(fixedRate= 60) //每分钟执行一次
  73 + public void execute(){
  74 + Calendar cal = Calendar.getInstance();
  75 + cal.add(Calendar.MINUTE, -1);
  76 + for (String session : callbackMap.keySet()) {
  77 + if (callbackMap.get(session).createTime < cal.getTimeInMillis()) {
  78 + // 超时
  79 + if (callbackMap.get(session).timeoutCallback != null) {
  80 + callbackMap.get(session).timeoutCallback.run("timeout");
  81 + }
  82 + callbackMap.remove(session);
  83 + }
  84 + }
  85 + }
  86 +}
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/task/ISubscribeTask.java
1 1 package com.genersoft.iot.vmp.gb28181.task;
2 2  
3   -import javax.sip.DialogState;
  3 +import com.genersoft.iot.vmp.common.CommonCallback;
4 4  
5 5 /**
6 6 * @author lin
7 7 */
8 8 public interface ISubscribeTask extends Runnable{
9   - void stop();
  9 + void stop(CommonCallback<Boolean> callback);
10 10 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/task/impl/CatalogSubscribeTask.java
1 1 package com.genersoft.iot.vmp.gb28181.task.impl;
2 2  
  3 +import com.genersoft.iot.vmp.common.CommonCallback;
3 4 import com.genersoft.iot.vmp.conf.DynamicTask;
4 5 import com.genersoft.iot.vmp.gb28181.bean.Device;
5 6 import com.genersoft.iot.vmp.gb28181.task.ISubscribeTask;
... ... @@ -7,14 +8,13 @@ import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
7 8 import gov.nist.javax.sip.message.SIPRequest;
8 9 import org.slf4j.Logger;
9 10 import org.slf4j.LoggerFactory;
10   -import org.springframework.scheduling.annotation.Async;
11   -import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
12 11  
13   -import javax.sip.*;
  12 +import javax.sip.DialogState;
  13 +import javax.sip.InvalidArgumentException;
  14 +import javax.sip.ResponseEvent;
  15 +import javax.sip.SipException;
14 16 import javax.sip.header.ToHeader;
15 17 import java.text.ParseException;
16   -import java.util.Timer;
17   -import java.util.TimerTask;
18 18  
19 19 /**
20 20 * 目录订阅任务
... ... @@ -71,7 +71,7 @@ public class CatalogSubscribeTask implements ISubscribeTask {
71 71 }
72 72  
73 73 @Override
74   - public void stop() {
  74 + public void stop(CommonCallback<Boolean> callback) {
75 75 /**
76 76 * dialog 的各个状态
77 77 * EARLY-> Early state状态-初始请求发送以后,收到了一个临时响应消息
... ... @@ -94,6 +94,9 @@ public class CatalogSubscribeTask implements ISubscribeTask {
94 94 // 成功
95 95 logger.info("[取消目录订阅]成功: {}", device.getDeviceId());
96 96 }
  97 + if (callback != null) {
  98 + callback.run(event.getResponse().getRawContent() != null);
  99 + }
97 100 },eventResult -> {
98 101 // 失败
99 102 logger.warn("[取消目录订阅]失败,信令发送失败: {}-{} ", device.getDeviceId(), eventResult.msg);
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/task/impl/MobilePositionSubscribeHandlerTask.java
1 1 package com.genersoft.iot.vmp.gb28181.task.impl;
2 2  
3   -import com.genersoft.iot.vmp.conf.DynamicTask;
4   -import com.genersoft.iot.vmp.gb28181.bean.*;
  3 +import com.genersoft.iot.vmp.common.CommonCallback;
5 4 import com.genersoft.iot.vmp.gb28181.task.ISubscribeTask;
6   -import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
7 5 import com.genersoft.iot.vmp.service.IPlatformService;
8   -import com.genersoft.iot.vmp.service.bean.GPSMsgInfo;
9   -import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
10   -import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
11 6 import com.genersoft.iot.vmp.utils.SpringBeanFactory;
12   -import org.slf4j.Logger;
13   -import org.slf4j.LoggerFactory;
14   -import org.springframework.scheduling.annotation.Async;
15   -
16   -import javax.sip.DialogState;
17   -import java.util.List;
18 7  
19 8 /**
20 9 * 向已经订阅(移动位置)的上级发送MobilePosition消息
... ... @@ -38,7 +27,7 @@ public class MobilePositionSubscribeHandlerTask implements ISubscribeTask {
38 27 }
39 28  
40 29 @Override
41   - public void stop() {
  30 + public void stop(CommonCallback<Boolean> callback) {
42 31  
43 32 }
44 33 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/task/impl/MobilePositionSubscribeTask.java
1 1 package com.genersoft.iot.vmp.gb28181.task.impl;
2 2  
  3 +import com.genersoft.iot.vmp.common.CommonCallback;
3 4 import com.genersoft.iot.vmp.conf.DynamicTask;
4 5 import com.genersoft.iot.vmp.gb28181.bean.Device;
5 6 import com.genersoft.iot.vmp.gb28181.task.ISubscribeTask;
6 7 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
7 8 import gov.nist.javax.sip.message.SIPRequest;
8   -import gov.nist.javax.sip.message.SIPResponse;
9   -import org.dom4j.Element;
10 9 import org.slf4j.Logger;
11 10 import org.slf4j.LoggerFactory;
12   -import org.springframework.scheduling.annotation.Async;
13 11  
14   -import javax.sip.*;
  12 +import javax.sip.InvalidArgumentException;
  13 +import javax.sip.ResponseEvent;
  14 +import javax.sip.SipException;
15 15 import javax.sip.header.ToHeader;
16 16 import java.text.ParseException;
17   -import java.util.Timer;
18   -import java.util.TimerTask;
19 17  
20 18 /**
21 19 * 移动位置订阅的定时更新
... ... @@ -70,7 +68,7 @@ public class MobilePositionSubscribeTask implements ISubscribeTask {
70 68 }
71 69  
72 70 @Override
73   - public void stop() {
  71 + public void stop(CommonCallback<Boolean> callback) {
74 72 /**
75 73 * dialog 的各个状态
76 74 * EARLY-> Early state状态-初始请求发送以后,收到了一个临时响应消息
... ... @@ -92,6 +90,9 @@ public class MobilePositionSubscribeTask implements ISubscribeTask {
92 90 // 成功
93 91 logger.info("[取消移动位置订阅]成功: {}", device.getDeviceId());
94 92 }
  93 + if (callback != null) {
  94 + callback.run(event.getResponse().getRawContent() != null);
  95 + }
95 96 },eventResult -> {
96 97 // 失败
97 98 logger.warn("[取消移动位置订阅]失败,信令发送失败: {}-{} ", device.getDeviceId(), eventResult.msg);
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java
... ... @@ -5,6 +5,7 @@ import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException;
5 5 import com.genersoft.iot.vmp.gb28181.bean.*;
6 6 import com.genersoft.iot.vmp.gb28181.bean.Device;
7 7 import com.genersoft.iot.vmp.gb28181.bean.DeviceAlarm;
  8 +import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
8 9 import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
9 10 import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe;
10 11 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
... ... @@ -97,9 +98,9 @@ public interface ISIPCommander {
97 98 /**
98 99 * 请求预览视频流
99 100 * @param device 视频设备
100   - * @param channelId 预览通道
  101 + * @param channel 预览通道
101 102 */
102   - void playStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, ZlmHttpHookSubscribe.Event event, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
  103 + void playStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, DeviceChannel channel, ZlmHttpHookSubscribe.Event event, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
103 104  
104 105 /**
105 106 * 请求回放视频流
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
... ... @@ -7,6 +7,10 @@ import com.genersoft.iot.vmp.conf.UserSetting;
7 7 import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException;
8 8 import com.genersoft.iot.vmp.gb28181.SipLayer;
9 9 import com.genersoft.iot.vmp.gb28181.bean.*;
  10 +import com.genersoft.iot.vmp.gb28181.bean.Device;
  11 +import com.genersoft.iot.vmp.gb28181.bean.DeviceAlarm;
  12 +import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
  13 +import com.genersoft.iot.vmp.gb28181.bean.SsrcTransaction;
10 14 import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
11 15 import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
12 16 import com.genersoft.iot.vmp.gb28181.transmit.SIPSender;
... ... @@ -266,12 +270,12 @@ public class SIPCommander implements ISIPCommander {
266 270 * 请求预览视频流
267 271 *
268 272 * @param device 视频设备
269   - * @param channelId 预览通道
  273 + * @param channel 预览通道
270 274 * @param event hook订阅
271 275 * @param errorEvent sip错误订阅
272 276 */
273 277 @Override
274   - public void playStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId,
  278 + public void playStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, DeviceChannel channel,
275 279 ZlmHttpHookSubscribe.Event event, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException {
276 280 String stream = ssrcInfo.getStream();
277 281  
... ... @@ -295,7 +299,7 @@ public class SIPCommander implements ISIPCommander {
295 299 }
296 300 StringBuffer content = new StringBuffer(200);
297 301 content.append("v=0\r\n");
298   - content.append("o=" + channelId + " 0 0 IN IP4 " + sdpIp + "\r\n");
  302 + content.append("o=" + channel.getChannelId() + " 0 0 IN IP4 " + sdpIp + "\r\n");
299 303 content.append("s=Play\r\n");
300 304 content.append("c=IN IP4 " + sdpIp + "\r\n");
301 305 content.append("t=0 0\r\n");
... ... @@ -346,20 +350,8 @@ public class SIPCommander implements ISIPCommander {
346 350 }
347 351 }
348 352  
349   - if( device.isSwitchPrimarySubStream() ){
350   - if("TP-LINK".equals(device.getManufacturer())){
351   - if (device.isSwitchPrimarySubStream()){
352   - content.append("a=streamMode:sub\r\n");
353   - }else {
354   - content.append("a=streamMode:main\r\n");
355   - }
356   - }else {
357   - if (device.isSwitchPrimarySubStream()){
358   - content.append("a=streamprofile:1\r\n");
359   - }else {
360   - content.append("a=streamprofile:0\r\n");
361   - }
362   - }
  353 + if (!ObjectUtils.isEmpty(channel.getStreamIdentification())) {
  354 + content.append("a=" + channel.getStreamIdentification() + "\r\n");
363 355 }
364 356  
365 357 content.append("y=" + ssrcInfo.getSsrc() + "\r\n");//ssrc
... ... @@ -368,16 +360,16 @@ public class SIPCommander implements ISIPCommander {
368 360  
369 361  
370 362  
371   - Request request = headerProvider.createInviteRequest(device, channelId, content.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null, ssrcInfo.getSsrc(),sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()));
  363 + Request request = headerProvider.createInviteRequest(device, channel.getChannelId(), content.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null, ssrcInfo.getSsrc(),sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()));
372 364 sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, (e -> {
373   - streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream());
  365 + streamSession.remove(device.getDeviceId(), channel.getChannelId(), ssrcInfo.getStream());
374 366 mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc());
375 367 errorEvent.response(e);
376 368 }), e -> {
377 369 ResponseEvent responseEvent = (ResponseEvent) e.event;
378 370 SIPResponse response = (SIPResponse) responseEvent.getResponse();
379 371 String callId = response.getCallIdHeader().getCallId();
380   - streamSession.put(device.getDeviceId(), channelId, callId, stream, ssrcInfo.getSsrc(), mediaServerItem.getId(), response,
  372 + streamSession.put(device.getDeviceId(), channel.getChannelId(), callId, stream, ssrcInfo.getSsrc(), mediaServerItem.getId(), response,
381 373 InviteSessionType.PLAY);
382 374 okEvent.response(e);
383 375 });
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/NotifyRequestProcessor.java
... ... @@ -6,7 +6,6 @@ import com.genersoft.iot.vmp.conf.SipConfig;
6 6 import com.genersoft.iot.vmp.conf.UserSetting;
7 7 import com.genersoft.iot.vmp.gb28181.bean.*;
8 8 import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
9   -import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent;
10 9 import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver;
11 10 import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
12 11 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
... ... @@ -38,7 +37,6 @@ import javax.sip.SipException;
38 37 import javax.sip.header.FromHeader;
39 38 import javax.sip.message.Response;
40 39 import java.text.ParseException;
41   -import java.util.Iterator;
42 40 import java.util.List;
43 41 import java.util.concurrent.ConcurrentLinkedQueue;
44 42  
... ... @@ -222,7 +220,6 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements
222 220 mobilePosition.getLongitude(), mobilePosition.getLatitude());
223 221 mobilePosition.setReportSource("Mobile Position");
224 222  
225   -
226 223 // 更新device channel 的经纬度
227 224 DeviceChannel deviceChannel = new DeviceChannel();
228 225 deviceChannel.setDeviceId(device.getDeviceId());
... ... @@ -242,6 +239,8 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements
242 239 }
243 240  
244 241 storager.updateChannelPosition(deviceChannel);
  242 + // 向关联了该通道并且开启移动位置订阅的上级平台发送移动位置订阅消息
  243 +
245 244  
246 245 // 发送redis消息。 通知位置信息的变化
247 246 JSONObject jsonObject = new JSONObject();
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/KeepaliveNotifyMessageHandler.java
... ... @@ -82,8 +82,9 @@ public class KeepaliveNotifyMessageHandler extends SIPRequestProcessorParent imp
82 82 device.setIp(remoteAddressInfo.getIp());
83 83 // 设备地址变化会引起目录订阅任务失效,需要重新添加
84 84 if (device.getSubscribeCycleForCatalog() > 0) {
85   - deviceService.removeCatalogSubscribe(device);
86   - deviceService.addCatalogSubscribe(device);
  85 + deviceService.removeCatalogSubscribe(device, result->{
  86 + deviceService.addCatalogSubscribe(device);
  87 + });
87 88 }
88 89 }
89 90 if (device.getKeepaliveTime() == null) {
... ...
src/main/java/com/genersoft/iot/vmp/service/IDeviceChannelService.java
... ... @@ -87,4 +87,9 @@ public interface IDeviceChannelService {
87 87 * 直接批量添加
88 88 */
89 89 void batchAddChannel(List<DeviceChannel> deviceChannels);
  90 +
  91 + /**
  92 + * 修改通道的码流类型
  93 + */
  94 + void updateChannelStreamIdentification(DeviceChannel channel);
90 95 }
... ...
src/main/java/com/genersoft/iot/vmp/service/IDeviceService.java
1 1 package com.genersoft.iot.vmp.service;
2 2  
  3 +import com.genersoft.iot.vmp.common.CommonCallback;
3 4 import com.genersoft.iot.vmp.gb28181.bean.Device;
4 5 import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
5 6 import com.genersoft.iot.vmp.gb28181.bean.SipTransactionInfo;
... ... @@ -39,7 +40,7 @@ public interface IDeviceService {
39 40 * @param device 设备信息
40 41 * @return 布尔
41 42 */
42   - boolean removeCatalogSubscribe(Device device);
  43 + boolean removeCatalogSubscribe(Device device, CommonCallback<Boolean> callback);
43 44  
44 45 /**
45 46 * 添加移动位置订阅
... ... @@ -53,7 +54,7 @@ public interface IDeviceService {
53 54 * @param device 设备信息
54 55 * @return 布尔
55 56 */
56   - boolean removeMobilePositionSubscribe(Device device);
  57 + boolean removeMobilePositionSubscribe(Device device, CommonCallback<Boolean> callback);
57 58  
58 59 /**
59 60 * 移除移动位置订阅
... ...
src/main/java/com/genersoft/iot/vmp/service/IPlayService.java
... ... @@ -6,6 +6,7 @@ import com.genersoft.iot.vmp.conf.exception.ServiceException;
6 6 import com.genersoft.iot.vmp.gb28181.bean.Device;
7 7 import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
8 8 import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem;
  9 +import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
9 10 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
10 11 import com.genersoft.iot.vmp.media.zlm.dto.hook.HookParam;
11 12 import com.genersoft.iot.vmp.service.bean.ErrorCallback;
... ... @@ -25,7 +26,7 @@ import java.util.Map;
25 26 */
26 27 public interface IPlayService {
27 28  
28   - void play(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId,
  29 + void play(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, DeviceChannel channelId,
29 30 ErrorCallback<Object> callback);
30 31 SSRCInfo play(MediaServerItem mediaServerItem, String deviceId, String channelId, String ssrc, ErrorCallback<Object> callback);
31 32  
... ...
src/main/java/com/genersoft/iot/vmp/service/impl/DeviceChannelServiceImpl.java
... ... @@ -18,6 +18,7 @@ import org.slf4j.Logger;
18 18 import org.slf4j.LoggerFactory;
19 19 import org.springframework.beans.factory.annotation.Autowired;
20 20 import org.springframework.stereotype.Service;
  21 +import org.springframework.util.ObjectUtils;
21 22  
22 23 import java.util.ArrayList;
23 24 import java.util.HashMap;
... ... @@ -267,5 +268,16 @@ public class DeviceChannelServiceImpl implements IDeviceChannelService {
267 268 }
268 269 }
269 270  
270   -
  271 + @Override
  272 + public void updateChannelStreamIdentification(DeviceChannel channel) {
  273 + assert !ObjectUtils.isEmpty(channel.getDeviceId());
  274 + assert !ObjectUtils.isEmpty(channel.getStreamIdentification());
  275 + if (ObjectUtils.isEmpty(channel.getStreamIdentification())) {
  276 + logger.info("[重置通道码流类型] 设备: {}, 码流: {}", channel.getDeviceId(), channel.getStreamIdentification());
  277 + }else {
  278 + logger.info("[更新通道码流类型] 设备: {}, 通道:{}, 码流: {}", channel.getDeviceId(), channel.getChannelId(),
  279 + channel.getStreamIdentification());
  280 + }
  281 + channelMapper.updateChannelStreamIdentification(channel);
  282 + }
271 283 }
... ...
src/main/java/com/genersoft/iot/vmp/service/impl/DeviceServiceImpl.java
1 1 package com.genersoft.iot.vmp.service.impl;
2 2  
3 3 import com.baomidou.dynamic.datasource.annotation.DS;
  4 +import com.genersoft.iot.vmp.common.CommonCallback;
4 5 import com.genersoft.iot.vmp.common.VideoManagerConstants;
5 6 import com.genersoft.iot.vmp.conf.DynamicTask;
6 7 import com.genersoft.iot.vmp.conf.UserSetting;
7   -import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException;
8 8 import com.genersoft.iot.vmp.gb28181.bean.*;
9 9 import com.genersoft.iot.vmp.gb28181.session.AudioBroadcastManager;
10 10 import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
... ... @@ -145,10 +145,6 @@ public class DeviceServiceImpl implements IDeviceService {
145 145 }
146 146 sync(device);
147 147 }else {
148   -
149   - if (deviceInDb != null) {
150   - device.setSwitchPrimarySubStream(deviceInDb.isSwitchPrimarySubStream());
151   - }
152 148 if(!device.isOnLine()){
153 149 device.setOnLine(true);
154 150 device.setCreateTime(now);
... ... @@ -238,12 +234,8 @@ public class DeviceServiceImpl implements IDeviceService {
238 234 }
239 235 }
240 236 // 移除订阅
241   - removeCatalogSubscribe(device);
242   - removeMobilePositionSubscribe(device);
243   - if (userSetting.getDeviceStatusNotify()) {
244   - // 发送redis消息
245   - redisCatchStorage.sendDeviceOrChannelStatus(device.getDeviceId(), null, false);
246   - }
  237 + removeCatalogSubscribe(device, null);
  238 + removeMobilePositionSubscribe(device, null);
247 239  
248 240 List<AudioBroadcastCatch> audioBroadcastCatches = audioBroadcastManager.get(deviceId);
249 241 if (audioBroadcastCatches.size() > 0) {
... ... @@ -281,7 +273,7 @@ public class DeviceServiceImpl implements IDeviceService {
281 273 }
282 274  
283 275 @Override
284   - public boolean removeCatalogSubscribe(Device device) {
  276 + public boolean removeCatalogSubscribe(Device device, CommonCallback<Boolean> callback) {
285 277 if (device == null || device.getSubscribeCycleForCatalog() < 0) {
286 278 return false;
287 279 }
... ... @@ -291,7 +283,7 @@ public class DeviceServiceImpl implements IDeviceService {
291 283 Runnable runnable = dynamicTask.get(taskKey);
292 284 if (runnable instanceof ISubscribeTask) {
293 285 ISubscribeTask subscribeTask = (ISubscribeTask) runnable;
294   - subscribeTask.stop();
  286 + subscribeTask.stop(callback);
295 287 }
296 288 }
297 289 dynamicTask.stop(taskKey);
... ... @@ -314,7 +306,7 @@ public class DeviceServiceImpl implements IDeviceService {
314 306 }
315 307  
316 308 @Override
317   - public boolean removeMobilePositionSubscribe(Device device) {
  309 + public boolean removeMobilePositionSubscribe(Device device, CommonCallback<Boolean> callback) {
318 310 if (device == null || device.getSubscribeCycleForCatalog() < 0) {
319 311 return false;
320 312 }
... ... @@ -324,7 +316,7 @@ public class DeviceServiceImpl implements IDeviceService {
324 316 Runnable runnable = dynamicTask.get(taskKey);
325 317 if (runnable instanceof ISubscribeTask) {
326 318 ISubscribeTask subscribeTask = (ISubscribeTask) runnable;
327   - subscribeTask.stop();
  319 + subscribeTask.stop(callback);
328 320 }
329 321 }
330 322 dynamicTask.stop(taskKey);
... ... @@ -515,21 +507,6 @@ public class DeviceServiceImpl implements IDeviceService {
515 507 logger.warn("更新设备时未找到设备信息");
516 508 return;
517 509 }
518   - if(deviceInStore.isSwitchPrimarySubStream() != device.isSwitchPrimarySubStream()){
519   - //当修改设备的主子码流开关时,需要校验是否存在流,如果存在流则直接关闭
520   - List<SsrcTransaction> ssrcTransactionForAll = streamSession.getSsrcTransactionForAll(device.getDeviceId(), null, null, null);
521   - if(ssrcTransactionForAll != null){
522   - for (SsrcTransaction ssrcTransaction: ssrcTransactionForAll) {
523   - try {
524   - cmder.streamByeCmd(device, ssrcTransaction.getChannelId(), ssrcTransaction.getStream(), null, null);
525   - } catch (InvalidArgumentException | SsrcTransactionNotFoundException | ParseException | SipException e) {
526   - throw new RuntimeException(e);
527   - }
528   - }
529   - }
530   - deviceChannelMapper.clearPlay(device.getDeviceId());
531   - inviteStreamService.clearInviteInfo(device.getDeviceId());
532   - }
533 510  
534 511 if (!ObjectUtils.isEmpty(device.getName())) {
535 512 deviceInStore.setName(device.getName());
... ... @@ -552,39 +529,54 @@ public class DeviceServiceImpl implements IDeviceService {
552 529 if (!ObjectUtils.isEmpty(device.getStreamMode())) {
553 530 deviceInStore.setStreamMode(device.getStreamMode());
554 531 }
555   -
556   -
557 532 // 目录订阅相关的信息
558 533 if (deviceInStore.getSubscribeCycleForCatalog() != device.getSubscribeCycleForCatalog()) {
559 534 if (device.getSubscribeCycleForCatalog() > 0) {
560 535 // 若已开启订阅,但订阅周期不同,则先取消
561 536 if (deviceInStore.getSubscribeCycleForCatalog() != 0) {
562   - removeCatalogSubscribe(deviceInStore);
  537 + removeCatalogSubscribe(deviceInStore, result->{
  538 + // 开启订阅
  539 + deviceInStore.setSubscribeCycleForCatalog(device.getSubscribeCycleForCatalog());
  540 + addCatalogSubscribe(deviceInStore);
  541 + // 因为是异步执行,需要在这里更新下数据
  542 + deviceMapper.updateCustom(deviceInStore);
  543 + redisCatchStorage.updateDevice(deviceInStore);
  544 + });
  545 + }else {
  546 + // 开启订阅
  547 + deviceInStore.setSubscribeCycleForCatalog(device.getSubscribeCycleForCatalog());
  548 + addCatalogSubscribe(deviceInStore);
563 549 }
564   - // 开启订阅
565   - deviceInStore.setSubscribeCycleForCatalog(device.getSubscribeCycleForCatalog());
566   - addCatalogSubscribe(deviceInStore);
  550 +
567 551 }else if (device.getSubscribeCycleForCatalog() == 0) {
568 552 // 取消订阅
569   - deviceInStore.setSubscribeCycleForCatalog(device.getSubscribeCycleForCatalog());
570   - removeCatalogSubscribe(deviceInStore);
  553 + deviceInStore.setSubscribeCycleForCatalog(0);
  554 + removeCatalogSubscribe(deviceInStore, null);
571 555 }
572 556 }
573   -
574 557 // 移动位置订阅相关的信息
575   - if (device.getSubscribeCycleForMobilePosition() > 0) {
576   - if (deviceInStore.getSubscribeCycleForMobilePosition() == 0 || deviceInStore.getSubscribeCycleForMobilePosition() != device.getSubscribeCycleForMobilePosition()) {
577   - deviceInStore.setMobilePositionSubmissionInterval(device.getMobilePositionSubmissionInterval());
578   - deviceInStore.setSubscribeCycleForMobilePosition(device.getSubscribeCycleForMobilePosition());
579   - // 开启订阅
580   - addMobilePositionSubscribe(deviceInStore);
581   - }
582   - }else if (device.getSubscribeCycleForMobilePosition() == 0) {
583   - if (deviceInStore.getSubscribeCycleForMobilePosition() != 0) {
584   - deviceInStore.setMobilePositionSubmissionInterval(device.getMobilePositionSubmissionInterval());
585   - deviceInStore.setSubscribeCycleForMobilePosition(device.getSubscribeCycleForMobilePosition());
  558 + if (deviceInStore.getSubscribeCycleForMobilePosition() != device.getSubscribeCycleForMobilePosition()) {
  559 + if (device.getSubscribeCycleForMobilePosition() > 0) {
  560 + // 若已开启订阅,但订阅周期不同,则先取消
  561 + if (deviceInStore.getSubscribeCycleForMobilePosition() != 0) {
  562 + removeMobilePositionSubscribe(deviceInStore, result->{
  563 + // 开启订阅
  564 + deviceInStore.setSubscribeCycleForMobilePosition(device.getSubscribeCycleForMobilePosition());
  565 + addMobilePositionSubscribe(deviceInStore);
  566 + // 因为是异步执行,需要在这里更新下数据
  567 + deviceMapper.updateCustom(deviceInStore);
  568 + redisCatchStorage.updateDevice(deviceInStore);
  569 + });
  570 + }else {
  571 + // 开启订阅
  572 + deviceInStore.setSubscribeCycleForMobilePosition(device.getSubscribeCycleForMobilePosition());
  573 + addMobilePositionSubscribe(deviceInStore);
  574 + }
  575 +
  576 + }else if (device.getSubscribeCycleForMobilePosition() == 0) {
586 577 // 取消订阅
587   - removeMobilePositionSubscribe(deviceInStore);
  578 + deviceInStore.setSubscribeCycleForCatalog(0);
  579 + removeCatalogSubscribe(deviceInStore, null);
588 580 }
589 581 }
590 582 if (deviceInStore.getGeoCoordSys() != null) {
... ... @@ -603,10 +595,9 @@ public class DeviceServiceImpl implements IDeviceService {
603 595 deviceInStore.setSsrcCheck(device.isSsrcCheck());
604 596 //作为消息通道
605 597 deviceInStore.setAsMessageChannel(device.isAsMessageChannel());
606   -
607   - // 更新redis
  598 +
608 599 deviceMapper.updateCustom(deviceInStore);
609   - redisCatchStorage.removeDevice(deviceInStore.getDeviceId());
  600 + redisCatchStorage.updateDevice(deviceInStore);
610 601 }
611 602  
612 603 @Override
... ...
src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
... ... @@ -20,6 +20,8 @@ import com.genersoft.iot.vmp.gb28181.session.SSRCFactory;
20 20 import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
21 21 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
22 22 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
  23 +import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
  24 +import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform;
23 25 import com.genersoft.iot.vmp.gb28181.utils.SipUtils;
24 26 import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
25 27 import com.genersoft.iot.vmp.media.zlm.ZLMServerFactory;
... ... @@ -29,6 +31,10 @@ import com.genersoft.iot.vmp.media.zlm.*;
29 31 import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeFactory;
30 32 import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForStreamChange;
31 33 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
  34 +import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeFactory;
  35 +import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForRecordMp4;
  36 +import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForStreamChange;
  37 +import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
32 38 import com.genersoft.iot.vmp.media.zlm.dto.hook.HookParam;
33 39 import com.genersoft.iot.vmp.media.zlm.dto.hook.OnRecordMp4HookParam;
34 40 import com.genersoft.iot.vmp.media.zlm.dto.hook.OnStreamChangedHookParam;
... ... @@ -39,9 +45,12 @@ import com.genersoft.iot.vmp.service.bean.InviteErrorCode;
39 45 import com.genersoft.iot.vmp.service.bean.RequestPushStreamMsg;
40 46 import com.genersoft.iot.vmp.service.bean.SSRCInfo;
41 47 import com.genersoft.iot.vmp.service.redisMsg.RedisGbPlayMsgListener;
  48 +import com.genersoft.iot.vmp.service.bean.DownloadFileInfo;
  49 +import com.genersoft.iot.vmp.service.bean.ErrorCallback;
  50 +import com.genersoft.iot.vmp.service.bean.InviteErrorCode;
  51 +import com.genersoft.iot.vmp.service.bean.SSRCInfo;
42 52 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
43 53 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
44   -import com.genersoft.iot.vmp.storager.dao.CloudRecordServiceMapper;
45 54 import com.genersoft.iot.vmp.utils.CloudRecordUtils;
46 55 import com.genersoft.iot.vmp.utils.DateUtil;
47 56 import com.genersoft.iot.vmp.vmanager.bean.AudioBroadcastResult;
... ... @@ -80,7 +89,7 @@ public class PlayServiceImpl implements IPlayService {
80 89 private IVideoManagerStorage storager;
81 90  
82 91 @Autowired
83   - private SIPCommander cmder;
  92 + private ISIPCommander cmder;
84 93  
85 94 @Autowired
86 95 private AudioBroadcastManager audioBroadcastManager;
... ... @@ -122,6 +131,9 @@ public class PlayServiceImpl implements IPlayService {
122 131 private UserSetting userSetting;
123 132  
124 133 @Autowired
  134 + private IDeviceChannelService channelService;
  135 +
  136 + @Autowired
125 137 private SipConfig sipConfig;
126 138  
127 139 @Autowired
... ... @@ -163,6 +175,11 @@ public class PlayServiceImpl implements IPlayService {
163 175 logger.warn("[点播] 单端口收流时不支持TCP主动方式收流 deviceId: {},channelId:{}", deviceId, channelId);
164 176 throw new ControllerException(ErrorCode.ERROR100.getCode(), "单端口收流时不支持TCP主动方式收流");
165 177 }
  178 + DeviceChannel channel = channelService.getOne(deviceId, channelId);
  179 + if (channel == null) {
  180 + logger.warn("[点播] 未找到通道 deviceId: {},channelId:{}", deviceId, channelId);
  181 + throw new ControllerException(ErrorCode.ERROR100.getCode(), "未找到通道");
  182 + }
166 183 InviteInfo inviteInfo = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, deviceId, channelId);
167 184 if (inviteInfo != null ) {
168 185 if (inviteInfo.getStreamInfo() == null) {
... ... @@ -211,7 +228,7 @@ public class PlayServiceImpl implements IPlayService {
211 228 null);
212 229 return null;
213 230 }
214   - play(mediaServerItem, ssrcInfo, device, channelId, callback);
  231 + play(mediaServerItem, ssrcInfo, device, channel, callback);
215 232 return ssrcInfo;
216 233 }
217 234  
... ... @@ -358,7 +375,7 @@ public class PlayServiceImpl implements IPlayService {
358 375  
359 376  
360 377 @Override
361   - public void play(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId,
  378 + public void play(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, DeviceChannel channel,
362 379 ErrorCallback<Object> callback) {
363 380  
364 381 if (mediaServerItem == null || ssrcInfo == null) {
... ... @@ -367,111 +384,109 @@ public class PlayServiceImpl implements IPlayService {
367 384 null);
368 385 return;
369 386 }
370   - logger.info("[点播开始] deviceId: {}, channelId: {},码流类型:{}, 收流端口: {}, STREAM:{}, 收流模式:{}, SSRC: {}, SSRC校验:{}",
371   - device.getDeviceId(), channelId, device.isSwitchPrimarySubStream() ? "辅码流" : "主码流", ssrcInfo.getPort(), ssrcInfo.getStream(),
  387 + logger.info("[点播开始] deviceId: {}, channelId: {},码流类型:{}, 收流端口: {}, 码流:{}, 收流模式:{}, SSRC: {}, SSRC校验:{}",
  388 + device.getDeviceId(), channel.getChannelId(), channel.getStreamIdentification(), ssrcInfo.getPort(), ssrcInfo.getStream(),
372 389 device.getStreamMode(), ssrcInfo.getSsrc(), device.isSsrcCheck());
373 390 //端口获取失败的ssrcInfo 没有必要发送点播指令
374 391 if (ssrcInfo.getPort() <= 0) {
375   - logger.info("[点播端口分配异常],deviceId={},channelId={},ssrcInfo={}", device.getDeviceId(), channelId, ssrcInfo);
  392 + logger.info("[点播端口分配异常],deviceId={},channelId={},ssrcInfo={}", device.getDeviceId(), channel.getChannelId(), ssrcInfo);
376 393 // 释放ssrc
377 394 mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc());
378   - streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream());
  395 + streamSession.remove(device.getDeviceId(), channel.getChannelId(), ssrcInfo.getStream());
379 396  
380 397 callback.run(InviteErrorCode.ERROR_FOR_RESOURCE_EXHAUSTION.getCode(), "点播端口分配异常", null);
381   - inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId, null,
  398 + inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channel.getChannelId(), null,
382 399 InviteErrorCode.ERROR_FOR_RESOURCE_EXHAUSTION.getCode(), "点播端口分配异常", null);
383 400 return;
384 401 }
385 402  
386 403 // 初始化redis中的invite消息状态
387   - InviteInfo inviteInfo = InviteInfo.getInviteInfo(device.getDeviceId(), channelId, ssrcInfo.getStream(), ssrcInfo,
  404 + InviteInfo inviteInfo = InviteInfo.getInviteInfo(device.getDeviceId(), channel.getChannelId(), ssrcInfo.getStream(), ssrcInfo,
388 405 mediaServerItem.getSdpIp(), ssrcInfo.getPort(), device.getStreamMode(), InviteSessionType.PLAY,
389 406 InviteSessionStatus.ready);
390   - inviteInfo.setSubStream(device.isSwitchPrimarySubStream());
391 407 inviteStreamService.updateInviteInfo(inviteInfo);
392 408 // 超时处理
393 409 String timeOutTaskKey = UUID.randomUUID().toString();
394 410 dynamicTask.startDelay(timeOutTaskKey, () -> {
395 411 // 执行超时任务时查询是否已经成功,成功了则不执行超时任务,防止超时任务取消失败的情况
396   - InviteInfo inviteInfoForTimeOut = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, device.getDeviceId(), channelId);
  412 + InviteInfo inviteInfoForTimeOut = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, device.getDeviceId(), channel.getChannelId());
397 413 if (inviteInfoForTimeOut == null || inviteInfoForTimeOut.getStreamInfo() == null) {
398   - logger.info("[点播超时] 收流超时 deviceId: {}, channelId: {},码流类型:{},端口:{}, SSRC: {}",
399   - device.getDeviceId(), channelId, device.isSwitchPrimarySubStream() ? "辅码流" : "主码流",
  414 + logger.info("[点播超时] 收流超时 deviceId: {}, channelId: {},码流:{},端口:{}, SSRC: {}",
  415 + device.getDeviceId(), channel.getChannelId(), channel.getStreamIdentification(),
400 416 ssrcInfo.getPort(), ssrcInfo.getSsrc());
401 417  
402 418 callback.run(InviteErrorCode.ERROR_FOR_STREAM_TIMEOUT.getCode(), InviteErrorCode.ERROR_FOR_STREAM_TIMEOUT.getMsg(), null);
403   - inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId, null,
  419 + inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channel.getChannelId(), null,
404 420 InviteErrorCode.ERROR_FOR_STREAM_TIMEOUT.getCode(), InviteErrorCode.ERROR_FOR_STREAM_TIMEOUT.getMsg(), null);
405   - inviteStreamService.removeInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, device.getDeviceId(), channelId);
  421 + inviteStreamService.removeInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, device.getDeviceId(), channel.getChannelId());
406 422  
407 423 try {
408   - cmder.streamByeCmd(device, channelId, ssrcInfo.getStream(), null);
409   - } catch (InvalidArgumentException | ParseException | SipException |
410   - SsrcTransactionNotFoundException e) {
  424 + cmder.streamByeCmd(device, channel.getChannelId(), ssrcInfo.getStream(), null);
  425 + } catch (InvalidArgumentException | ParseException | SipException | SsrcTransactionNotFoundException e) {
411 426 logger.error("[点播超时], 发送BYE失败 {}", e.getMessage());
412 427 } finally {
413 428 mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc());
414 429 mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream());
415   - streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream());
  430 + streamSession.remove(device.getDeviceId(), channel.getChannelId(), ssrcInfo.getStream());
416 431 mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream());
417 432 // 取消订阅消息监听
418 433 HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", ssrcInfo.getStream(), true, "rtsp", mediaServerItem.getId());
419 434 subscribe.removeSubscribe(hookSubscribe);
420 435 }
421 436 }else {
422   - logger.info("[点播超时] 收流超时 deviceId: {}, channelId: {},码流类型:{},端口:{}, SSRC: {}",
423   - device.getDeviceId(), channelId, device.isSwitchPrimarySubStream() ? "辅码流" : "主码流",
  437 + logger.info("[点播超时] 收流超时 deviceId: {}, channelId: {},码流:{},端口:{}, SSRC: {}",
  438 + device.getDeviceId(), channel.getChannelId(), channel.getStreamIdentification(),
424 439 ssrcInfo.getPort(), ssrcInfo.getSsrc());
425 440  
426 441 mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc());
427 442  
428 443 mediaServerService.closeRTPServer(mediaServerItem.getId(), ssrcInfo.getStream());
429   - streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream());
  444 + streamSession.remove(device.getDeviceId(), channel.getChannelId(), ssrcInfo.getStream());
430 445 }
431 446 }, userSetting.getPlayTimeout());
432 447  
433 448 try {
434   - cmder.playStreamCmd(mediaServerItem, ssrcInfo, device, channelId, (mediaServerItemInuse, hookParam ) -> {
  449 + cmder.playStreamCmd(mediaServerItem, ssrcInfo, device, channel, (mediaServerItemInuse, hookParam ) -> {
435 450 logger.info("收到订阅消息: " + hookParam);
436 451 dynamicTask.stop(timeOutTaskKey);
437 452 // hook响应
438   - StreamInfo streamInfo = onPublishHandlerForPlay(mediaServerItemInuse, hookParam, device.getDeviceId(), channelId);
  453 + StreamInfo streamInfo = onPublishHandlerForPlay(mediaServerItemInuse, hookParam, device.getDeviceId(), channel.getChannelId());
439 454 if (streamInfo == null){
440 455 callback.run(InviteErrorCode.ERROR_FOR_STREAM_PARSING_EXCEPTIONS.getCode(),
441 456 InviteErrorCode.ERROR_FOR_STREAM_PARSING_EXCEPTIONS.getMsg(), null);
442   - inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId, null,
  457 + inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channel.getChannelId(), null,
443 458 InviteErrorCode.ERROR_FOR_STREAM_PARSING_EXCEPTIONS.getCode(),
444 459 InviteErrorCode.ERROR_FOR_STREAM_PARSING_EXCEPTIONS.getMsg(), null);
445 460 return;
446 461 }
447 462 callback.run(InviteErrorCode.SUCCESS.getCode(), InviteErrorCode.SUCCESS.getMsg(), streamInfo);
448   - inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId, null,
  463 + inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channel.getChannelId(), null,
449 464 InviteErrorCode.SUCCESS.getCode(),
450 465 InviteErrorCode.SUCCESS.getMsg(),
451 466 streamInfo);
452   - logger.info("[点播成功] deviceId: {}, channelId:{}, 码流类型:{}", device.getDeviceId(), channelId,
453   - device.isSwitchPrimarySubStream() ? "辅码流" : "主码流");
454   - snapOnPlay(mediaServerItemInuse, device.getDeviceId(), channelId, ssrcInfo.getStream());
  467 + logger.info("[点播成功] deviceId: {}, channelId:{}, 码流类型:{}", device.getDeviceId(), channel.getChannelId(),
  468 + channel.getStreamIdentification());
  469 + snapOnPlay(mediaServerItemInuse, device.getDeviceId(), channel.getChannelId(), ssrcInfo.getStream());
455 470 }, (eventResult) -> {
456 471 // 处理收到200ok后的TCP主动连接以及SSRC不一致的问题
457   - InviteOKHandler(eventResult, ssrcInfo, mediaServerItem, device, channelId,
  472 + InviteOKHandler(eventResult, ssrcInfo, mediaServerItem, device, channel.getChannelId(),
458 473 timeOutTaskKey, callback, inviteInfo, InviteSessionType.PLAY);
459 474 }, (event) -> {
460   - logger.info("[点播失败] deviceId: {}, channelId:{}, {}: {}", device.getDeviceId(), channelId, event.statusCode, event.msg);
  475 + logger.info("[点播失败] deviceId: {}, channelId:{}, {}: {}", device.getDeviceId(), channel.getChannelId(), event.statusCode, event.msg);
461 476 dynamicTask.stop(timeOutTaskKey);
462 477 mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream());
463 478 // 释放ssrc
464 479 mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc());
465 480  
466   - streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream());
  481 + streamSession.remove(device.getDeviceId(), channel.getChannelId(), ssrcInfo.getStream());
467 482  
468 483 callback.run(InviteErrorCode.ERROR_FOR_SIGNALLING_ERROR.getCode(),
469 484 String.format("点播失败, 错误码: %s, %s", event.statusCode, event.msg), null);
470   - inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId, null,
  485 + inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channel.getChannelId(), null,
471 486 InviteErrorCode.ERROR_FOR_RESET_SSRC.getCode(),
472 487 String.format("点播失败, 错误码: %s, %s", event.statusCode, event.msg), null);
473 488  
474   - inviteStreamService.removeInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, device.getDeviceId(), channelId);
  489 + inviteStreamService.removeInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, device.getDeviceId(), channel.getChannelId());
475 490 });
476 491 } catch (InvalidArgumentException | SipException | ParseException e) {
477 492  
... ... @@ -481,15 +496,15 @@ public class PlayServiceImpl implements IPlayService {
481 496 // 释放ssrc
482 497 mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc());
483 498  
484   - streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream());
  499 + streamSession.remove(device.getDeviceId(), channel.getChannelId(), ssrcInfo.getStream());
485 500  
486 501 callback.run(InviteErrorCode.ERROR_FOR_SIP_SENDING_FAILED.getCode(),
487 502 InviteErrorCode.ERROR_FOR_SIP_SENDING_FAILED.getMsg(), null);
488   - inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId, null,
  503 + inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channel.getChannelId(), null,
489 504 InviteErrorCode.ERROR_FOR_SIP_SENDING_FAILED.getCode(),
490 505 InviteErrorCode.ERROR_FOR_SIP_SENDING_FAILED.getMsg(), null);
491 506  
492   - inviteStreamService.removeInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, device.getDeviceId(), channelId);
  507 + inviteStreamService.removeInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, device.getDeviceId(), channel.getChannelId());
493 508 }
494 509 }
495 510  
... ... @@ -626,7 +641,7 @@ public class PlayServiceImpl implements IPlayService {
626 641  
627 642 @Override
628 643 public void playBack(String deviceId, String channelId, String startTime,
629   - String endTime, ErrorCallback<Object> callback) {
  644 + String endTime, ErrorCallback<Object> callback) {
630 645 Device device = storager.queryVideoDevice(deviceId);
631 646 if (device == null) {
632 647 logger.warn("[录像回放] 未找到设备 deviceId: {},channelId:{}", deviceId, channelId);
... ... @@ -651,8 +666,8 @@ public class PlayServiceImpl implements IPlayService {
651 666  
652 667 @Override
653 668 public void playBack(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo,
654   - String deviceId, String channelId, String startTime,
655   - String endTime, ErrorCallback<Object> callback) {
  669 + String deviceId, String channelId, String startTime,
  670 + String endTime, ErrorCallback<Object> callback) {
656 671 if (mediaServerItem == null || ssrcInfo == null) {
657 672 callback.run(InviteErrorCode.ERROR_FOR_PARAMETER_ERROR.getCode(),
658 673 InviteErrorCode.ERROR_FOR_PARAMETER_ERROR.getMsg(),
... ... @@ -1548,16 +1563,16 @@ public class PlayServiceImpl implements IPlayService {
1548 1563  
1549 1564 MediaServerItem newMediaServerItem = getNewMediaServerItem(device);
1550 1565 play(newMediaServerItem, deviceId, channelId, null, (code, msg, data)->{
1551   - if (code == InviteErrorCode.SUCCESS.getCode()) {
1552   - InviteInfo inviteInfoForPlay = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, deviceId, channelId);
1553   - if (inviteInfoForPlay != null && inviteInfoForPlay.getStreamInfo() != null) {
1554   - getSnap(deviceId, channelId, fileName, errorCallback);
1555   - }else {
1556   - errorCallback.run(InviteErrorCode.FAIL.getCode(), InviteErrorCode.FAIL.getMsg(), null);
1557   - }
1558   - }else {
1559   - errorCallback.run(InviteErrorCode.FAIL.getCode(), InviteErrorCode.FAIL.getMsg(), null);
1560   - }
  1566 + if (code == InviteErrorCode.SUCCESS.getCode()) {
  1567 + InviteInfo inviteInfoForPlay = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, deviceId, channelId);
  1568 + if (inviteInfoForPlay != null && inviteInfoForPlay.getStreamInfo() != null) {
  1569 + getSnap(deviceId, channelId, fileName, errorCallback);
  1570 + }else {
  1571 + errorCallback.run(InviteErrorCode.FAIL.getCode(), InviteErrorCode.FAIL.getMsg(), null);
  1572 + }
  1573 + }else {
  1574 + errorCallback.run(InviteErrorCode.FAIL.getCode(), InviteErrorCode.FAIL.getMsg(), null);
  1575 + }
1561 1576 });
1562 1577 }
1563 1578  
... ...
src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceChannelMapper.java
... ... @@ -20,11 +20,11 @@ public interface DeviceChannelMapper {
20 20 @Insert("INSERT INTO wvp_device_channel (channel_id, device_id, name, manufacture, model, owner, civil_code, block, " +
21 21 "address, parental, parent_id, safety_way, register_way, cert_num, certifiable, err_code, secrecy, " +
22 22 "ip_address, port, password, ptz_type, status, stream_id, longitude, latitude, longitude_gcj02, latitude_gcj02, " +
23   - "longitude_wgs84, latitude_wgs84, has_audio, create_time, update_time, business_group_id, gps_time) " +
  23 + "longitude_wgs84, latitude_wgs84, has_audio, create_time, update_time, business_group_id, gps_time, stream_identification) " +
24 24 "VALUES (#{channelId}, #{deviceId}, #{name}, #{manufacture}, #{model}, #{owner}, #{civilCode}, #{block}," +
25 25 "#{address}, #{parental}, #{parentId}, #{safetyWay}, #{registerWay}, #{certNum}, #{certifiable}, #{errCode}, #{secrecy}, " +
26 26 "#{ipAddress}, #{port}, #{password}, #{PTZType}, #{status}, #{streamId}, #{longitude}, #{latitude}, #{longitudeGcj02}, " +
27   - "#{latitudeGcj02}, #{longitudeWgs84}, #{latitudeWgs84}, #{hasAudio}, #{createTime}, #{updateTime}, #{businessGroupId}, #{gpsTime})")
  27 + "#{latitudeGcj02}, #{longitudeWgs84}, #{latitudeWgs84}, #{hasAudio}, #{createTime}, #{updateTime}, #{businessGroupId}, #{gpsTime}, #{streamIdentification})")
28 28 int add(DeviceChannel channel);
29 29  
30 30 @Update(value = {" <script>" +
... ... @@ -60,6 +60,7 @@ public interface DeviceChannelMapper {
60 60 "<if test='latitudeWgs84 != null'>, latitude_wgs84=#{latitudeWgs84}</if>" +
61 61 "<if test='businessGroupId != null'>, business_group_id=#{businessGroupId}</if>" +
62 62 "<if test='gpsTime != null'>, gps_time=#{gpsTime}</if>" +
  63 + "<if test='streamIdentification != null'>, stream_identification=#{streamIdentification}</if>" +
63 64 "WHERE device_id=#{deviceId} AND channel_id=#{channelId}"+
64 65 " </script>"})
65 66 int update(DeviceChannel channel);
... ... @@ -102,6 +103,7 @@ public interface DeviceChannelMapper {
102 103 "dc.longitude_wgs84, " +
103 104 "dc.latitude_wgs84, " +
104 105 "dc.business_group_id, " +
  106 + "dc.stream_identification, " +
105 107 "dc.gps_time " +
106 108 "from " +
107 109 "wvp_device_channel dc " +
... ... @@ -241,7 +243,7 @@ public interface DeviceChannelMapper {
241 243 "(channel_id, device_id, name, manufacture, model, owner, civil_code, block, sub_count, " +
242 244 " address, parental, parent_id, safety_way, register_way, cert_num, certifiable, err_code, secrecy, " +
243 245 " ip_address,port,password,ptz_type,status,stream_id,longitude,latitude,longitude_gcj02,latitude_gcj02,"+
244   - " longitude_wgs84,latitude_wgs84,has_audio,create_time,update_time,business_group_id,gps_time)"+
  246 + " longitude_wgs84,latitude_wgs84,has_audio,create_time,update_time,business_group_id,gps_time,stream_identification)"+
245 247 "values " +
246 248 "<foreach collection='addChannels' index='index' item='item' separator=','> " +
247 249 "(#{item.channelId}, #{item.deviceId}, #{item.name}, #{item.manufacture}, #{item.model}, " +
... ... @@ -251,7 +253,7 @@ public interface DeviceChannelMapper {
251 253 "#{item.ipAddress}, #{item.port}, #{item.password}, #{item.PTZType}, #{item.status}, " +
252 254 "#{item.streamId}, #{item.longitude}, #{item.latitude},#{item.longitudeGcj02}, " +
253 255 "#{item.latitudeGcj02},#{item.longitudeWgs84}, #{item.latitudeWgs84}, #{item.hasAudio}, now(), now(), " +
254   - "#{item.businessGroupId}, #{item.gpsTime}) " +
  256 + "#{item.businessGroupId}, #{item.gpsTime}, #{item.streamIdentification}) " +
255 257 "</foreach> " +
256 258 "</script>")
257 259 int batchAdd(@Param("addChannels") List<DeviceChannel> addChannels);
... ... @@ -349,6 +351,7 @@ public interface DeviceChannelMapper {
349 351 "<if test='item.latitudeWgs84 != null'>, latitude_wgs84=#{item.latitudeWgs84}</if>" +
350 352 "<if test='item.businessGroupId != null'>, business_group_id=#{item.businessGroupId}</if>" +
351 353 "<if test='item.gpsTime != null'>, gps_time=#{item.gpsTime}</if>" +
  354 + "<if test='item.streamIdentification != null'>, stream_identification=#{item.streamIdentification}</if>" +
352 355 "<if test='item.id > 0'>WHERE id=#{item.id}</if>" +
353 356 "<if test='item.id == 0'>WHERE device_id=#{item.deviceId} AND channel_id=#{item.channelId}</if>" +
354 357 "</foreach>" +
... ... @@ -542,4 +545,9 @@ public interface DeviceChannelMapper {
542 545 " </script>"})
543 546 List<DeviceChannel> getSubChannelsByDeviceId(@Param("deviceId") String deviceId, @Param("parentId") String parentId, @Param("onlyCatalog") boolean onlyCatalog);
544 547  
  548 + @Update("<script>" +
  549 + "UPDATE wvp_device_channel SET stream_identification=#{streamIdentification} WHERE device_id=#{deviceId}" +
  550 + " <if test='channelId != null'> and channel_id = #{channelId} </if>" +
  551 + "</script>")
  552 + void updateChannelStreamIdentification(DeviceChannel channel);
545 553 }
... ...
src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceMapper.java
... ... @@ -43,7 +43,6 @@ public interface DeviceMapper {
43 43 "geo_coord_sys," +
44 44 "on_line," +
45 45 "media_server_id," +
46   - "switch_primary_sub_stream," +
47 46 "broadcast_push_after_ack," +
48 47 "(SELECT count(0) FROM wvp_device_channel WHERE device_id=wvp_device.device_id) as channel_count "+
49 48 " FROM wvp_device WHERE device_id = #{deviceId}")
... ... @@ -163,7 +162,6 @@ public interface DeviceMapper {
163 162 "geo_coord_sys,"+
164 163 "on_line,"+
165 164 "media_server_id,"+
166   - "switch_primary_sub_stream switchPrimarySubStream,"+
167 165 "(SELECT count(0) FROM wvp_device_channel WHERE device_id=de.device_id) as channel_count " +
168 166 "FROM wvp_device de" +
169 167 "<if test=\"onLine != null\"> where on_line=${onLine}</if>"+
... ... @@ -256,7 +254,6 @@ public interface DeviceMapper {
256 254 "<if test=\"asMessageChannel != null\">, as_message_channel=#{asMessageChannel}</if>" +
257 255 "<if test=\"broadcastPushAfterAck != null\">, broadcast_push_after_ack=#{broadcastPushAfterAck}</if>" +
258 256 "<if test=\"geoCoordSys != null\">, geo_coord_sys=#{geoCoordSys}</if>" +
259   - "<if test=\"switchPrimarySubStream != null\">, switch_primary_sub_stream=#{switchPrimarySubStream}</if>" +
260 257 "<if test=\"mediaServerId != null\">, media_server_id=#{mediaServerId}</if>" +
261 258 "WHERE device_id=#{deviceId}"+
262 259 " </script>"})
... ... @@ -275,8 +272,7 @@ public interface DeviceMapper {
275 272 "broadcastPushAfterAck,"+
276 273 "geo_coord_sys,"+
277 274 "on_line,"+
278   - "media_server_id,"+
279   - "switch_primary_sub_stream"+
  275 + "media_server_id"+
280 276 ") VALUES (" +
281 277 "#{deviceId}," +
282 278 "#{name}," +
... ... @@ -290,8 +286,7 @@ public interface DeviceMapper {
290 286 "#{broadcastPushAfterAck}," +
291 287 "#{geoCoordSys}," +
292 288 "#{onLine}," +
293   - "#{mediaServerId}," +
294   - "#{switchPrimarySubStream}" +
  289 + "#{mediaServerId}" +
295 290 ")")
296 291 void addCustomDevice(Device device);
297 292  
... ...
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/MobilePosition/MobilePositionController.java
... ... @@ -153,10 +153,7 @@ public class MobilePositionController {
153 153 Device device = storager.queryVideoDevice(deviceId);
154 154 device.setSubscribeCycleForMobilePosition(Integer.parseInt(expires));
155 155 device.setMobilePositionSubmissionInterval(Integer.parseInt(interval));
156   - deviceService.updateDevice(device);
157   - if (!deviceService.removeMobilePositionSubscribe(device)) {
158   - throw new ControllerException(ErrorCode.ERROR100);
159   - }
  156 + deviceService.updateCustomDevice(device);
160 157 }
161 158  
162 159 /**
... ...
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceQuery.java
... ... @@ -199,7 +199,7 @@ public class DeviceQuery {
199 199 Runnable runnable = dynamicTask.get(key);
200 200 if (runnable instanceof ISubscribeTask) {
201 201 ISubscribeTask subscribeTask = (ISubscribeTask) runnable;
202   - subscribeTask.stop();
  202 + subscribeTask.stop(null);
203 203 }
204 204 dynamicTask.stop(key);
205 205 }
... ... @@ -264,6 +264,14 @@ public class DeviceQuery {
264 264 deviceChannelService.updateChannel(deviceId, channel);
265 265 }
266 266  
  267 + @Operation(summary = "修改通道的码流类型", security = @SecurityRequirement(name = JwtUtils.HEADER))
  268 + @Parameter(name = "deviceId", description = "设备国标编号", required = true)
  269 + @Parameter(name = "channel", description = "通道信息", required = true)
  270 + @PostMapping("/channel/stream/identification/update/")
  271 + public void updateChannelStreamIdentification(DeviceChannel channel){
  272 + deviceChannelService.updateChannelStreamIdentification(channel);
  273 + }
  274 +
267 275 /**
268 276 * 修改数据流传输模式
269 277 * @param deviceId 设备id
... ...
web_src/src/components/channelList.vue
... ... @@ -13,24 +13,30 @@
13 13 prefix-icon="el-icon-search" v-model="searchSrt" clearable></el-input>
14 14  
15 15 通道类型:
16   - <el-select size="mini" @change="search" style="margin-right: 1rem;" v-model="channelType" placeholder="请选择"
  16 + <el-select size="mini" @change="search" style="width: 8rem; margin-right: 1rem;" v-model="channelType" placeholder="请选择"
17 17 default-first-option>
18 18 <el-option label="全部" value=""></el-option>
19 19 <el-option label="设备" value="false"></el-option>
20 20 <el-option label="子目录" value="true"></el-option>
21 21 </el-select>
22 22 在线状态:
23   - <el-select size="mini" style="margin-right: 1rem;" @change="search" v-model="online" placeholder="请选择"
  23 + <el-select size="mini" style="width: 8rem; margin-right: 1rem;" @change="search" v-model="online" placeholder="请选择"
24 24 default-first-option>
25 25 <el-option label="全部" value=""></el-option>
26 26 <el-option label="在线" value="true"></el-option>
27 27 <el-option label="离线" value="false"></el-option>
28 28 </el-select>
29   - 清晰度:
30   - <el-select size="mini" style="margin-right: 1rem;" @change="search" v-model="isSubStream" placeholder="请选择"
31   - default-first-option>
32   - <el-option label="原画" :value="false"></el-option>
33   - <el-option label="流畅" :value="true"></el-option>
  29 + 码流类型重置:
  30 + <el-select size="mini" style="width: 16rem; margin-right: 1rem;" @change="subStreamChange" v-model="subStream"
  31 + placeholder="请选择码流类型" default-first-option >
  32 + <el-option label="stream:0(主码流)" value="stream:0"></el-option>
  33 + <el-option label="stream:1(子码流)" value="stream:1"></el-option>
  34 + <el-option label="streamnumber:0(主码流-2022)" value="streamnumber:0"></el-option>
  35 + <el-option label="streamnumber:1(子码流-2022)" value="streamnumber:1"></el-option>
  36 + <el-option label="streamprofile:0(主码流-大华)" value="streamprofile:0"></el-option>
  37 + <el-option label="streamprofile:1(子码流-大华)" value="streamprofile:1"></el-option>
  38 + <el-option label="streamMode:main(主码流-水星+TP-LINK)" value="streamMode:main"></el-option>
  39 + <el-option label="streamMode:sub(子码流-水星+TP-LINK)" value="streamMode:sub"></el-option>
34 40 </el-select>
35 41 </div>
36 42 <el-button icon="el-icon-refresh-right" circle size="mini" @click="refresh()"></el-button>
... ... @@ -46,11 +52,11 @@
46 52 <el-main style="padding: 5px;">
47 53 <el-table ref="channelListTable" :data="deviceChannelList" :height="winHeight" style="width: 100%"
48 54 header-row-class-name="table-header">
49   - <el-table-column prop="channelId" label="通道编号" min-width="200">
  55 + <el-table-column prop="channelId" label="通道编号" min-width="180">
50 56 </el-table-column>
51   - <el-table-column prop="deviceId" label="设备编号" min-width="200">
  57 + <el-table-column prop="deviceId" label="设备编号" min-width="180">
52 58 </el-table-column>
53   - <el-table-column prop="name" label="通道名称" min-width="200">
  59 + <el-table-column prop="name" label="通道名称" min-width="180">
54 60 <template v-slot:default="scope">
55 61 <el-input
56 62 v-show="scope.row.edit"
... ... @@ -63,7 +69,7 @@
63 69 <span v-show="!scope.row.edit">{{ scope.row.name }}</span>
64 70 </template>
65 71 </el-table-column>
66   - <el-table-column label="快照" min-width="120">
  72 + <el-table-column label="快照" min-width="100">
67 73 <template v-slot:default="scope">
68 74 <el-image
69 75 :src="getSnap(scope.row)"
... ... @@ -77,11 +83,11 @@
77 83 </el-image>
78 84 </template>
79 85 </el-table-column>
80   - <el-table-column prop="subCount" label="子节点数" min-width="120">
  86 + <el-table-column prop="subCount" label="子节点数" min-width="100">
81 87 </el-table-column>
82   - <el-table-column prop="manufacture" label="厂家" min-width="120">
  88 + <el-table-column prop="manufacture" label="厂家" min-width="100">
83 89 </el-table-column>
84   - <el-table-column label="位置信息" min-width="200">
  90 + <el-table-column label="位置信息" min-width="120">
85 91 <template v-slot:default="scope">
86 92 <el-input
87 93 v-show="scope.row.edit"
... ... @@ -94,7 +100,7 @@
94 100 <span v-show="!scope.row.edit">{{ scope.row.location }}</span>
95 101 </template>
96 102 </el-table-column>
97   - <el-table-column prop="PTZType" label="云台类型" min-width="120">
  103 + <el-table-column prop="PTZType" label="云台类型" min-width="100">
98 104 <template v-slot:default="scope">
99 105 <el-select v-show="scope.row.edit" v-model="scope.row.PTZType"
100 106 placeholder="云台类型" filterable>
... ... @@ -108,13 +114,28 @@
108 114 <div v-show="!scope.row.edit">{{ scope.row.PTZTypeText }}</div>
109 115 </template>
110 116 </el-table-column>
111   - <el-table-column label="开启音频" min-width="120">
  117 + <el-table-column label="开启音频" min-width="100">
112 118 <template slot-scope="scope">
113 119 <el-switch @change="updateChannel(scope.row)" v-model="scope.row.hasAudio" active-color="#409EFF">
114 120 </el-switch>
115 121 </template>
116 122 </el-table-column>
117   - <el-table-column label="状态" min-width="120">
  123 + <el-table-column label="码流类型" min-width="180">
  124 + <template slot-scope="scope">
  125 + <el-select size="mini" style="margin-right: 1rem;" @change="channelSubStreamChange(scope.row)" v-model="scope.row.streamIdentification"
  126 + placeholder="请选择码流类型" default-first-option >
  127 + <el-option label="stream:0(主码流)" value="stream:0"></el-option>
  128 + <el-option label="stream:1(子码流)" value="stream:1"></el-option>
  129 + <el-option label="streamnumber:0(主码流-2022)" value="streamnumber:0"></el-option>
  130 + <el-option label="streamnumber:1(子码流-2022)" value="streamnumber:1"></el-option>
  131 + <el-option label="streamprofile:0(主码流-大华)" value="streamprofile:0"></el-option>
  132 + <el-option label="streamprofile:1(子码流-大华)" value="streamprofile:1"></el-option>
  133 + <el-option label="streamMode:main(主码流-水星+TP-LINK)" value="streamMode:main"></el-option>
  134 + <el-option label="streamMode:sub(子码流-水星+TP-LINK)" value="streamMode:sub"></el-option>
  135 + </el-select>
  136 + </template>
  137 + </el-table-column>
  138 + <el-table-column label="状态" min-width="100">
118 139 <template slot-scope="scope">
119 140 <div slot="reference" class="name-wrapper">
120 141 <el-tag size="medium" v-if="scope.row.status === true">在线</el-tag>
... ... @@ -122,8 +143,6 @@
122 143 </div>
123 144 </template>
124 145 </el-table-column>
125   -
126   -
127 146 <el-table-column label="操作" min-width="340" fixed="right">
128 147 <template slot-scope="scope">
129 148 <el-button size="medium" v-bind:disabled="device == null || device.online === 0" icon="el-icon-video-play"
... ... @@ -213,7 +232,7 @@ export default {
213 232 searchSrt: "",
214 233 channelType: "",
215 234 online: "",
216   - isSubStream: false,
  235 + subStream: "",
217 236 winHeight: window.innerHeight - 200,
218 237 currentPage: 1,
219 238 count: 15,
... ... @@ -495,6 +514,43 @@ export default {
495 514 console.log(JSON.stringify(res));
496 515 });
497 516 },
  517 + subStreamChange: function () {
  518 + this.$confirm('确定重置所有通道的码流类型?', '提示', {
  519 + confirmButtonText: '确定',
  520 + cancelButtonText: '取消',
  521 + type: 'warning'
  522 + }).then(() => {
  523 + this.$axios({
  524 + method: 'post',
  525 + url: `/api/device/query/channel/stream/identification/update/`,
  526 + params: {
  527 + deviceId: this.deviceId,
  528 + streamIdentification: this.subStream
  529 + }
  530 + }).then((res)=> {
  531 + console.log(JSON.stringify(res));
  532 + this.initData()
  533 + }).finally(()=>{
  534 + this.subStream = ""
  535 + })
  536 + }).catch(() => {
  537 + this.subStream = ""
  538 + });
  539 +
  540 + },
  541 + channelSubStreamChange: function (row) {
  542 + this.$axios({
  543 + method: 'post',
  544 + url: `/api/device/query/channel/stream/identification/update/`,
  545 + params: {
  546 + deviceId: this.deviceId,
  547 + channelId: row.channelId,
  548 + streamIdentification: row.streamIdentification
  549 + }
  550 + }).then(function (res) {
  551 + console.log(JSON.stringify(res));
  552 + });
  553 + },
498 554 refresh: function () {
499 555 this.initData();
500 556 },
... ...
web_src/src/components/dialog/deviceEdit.vue
... ... @@ -61,12 +61,6 @@
61 61 <el-form-item v-if="form.subscribeCycleForMobilePosition > 0" label="移动位置报送间隔" prop="subscribeCycleForCatalog" >
62 62 <el-input v-model="form.mobilePositionSubmissionInterval" clearable ></el-input>
63 63 </el-form-item>
64   - <el-form-item label="主子码流开关" prop="switchPrimarySubStream" >
65   - <el-select v-model="form.switchPrimarySubStream" style="float: left; width: 100%" >
66   - <el-option key="true" label="开启" :value="true"></el-option>
67   - <el-option key="false" label="关闭" :value="false"></el-option>
68   - </el-select>
69   - </el-form-item>
70 64 <el-form-item label="其他选项">
71 65 <el-checkbox label="SSRC校验" v-model="form.ssrcCheck" style="float: left"></el-checkbox>
72 66 <el-checkbox label="作为消息通道" v-model="form.asMessageChannel" style="float: left"></el-checkbox>
... ...
数据库/2.7.0/初始化-mysql-2.7.0.sql 0 → 100644
  1 +/*建表*/
  2 +create table wvp_device (
  3 + id serial primary key ,
  4 + device_id character varying(50) not null ,
  5 + name character varying(255),
  6 + manufacturer character varying(255),
  7 + model character varying(255),
  8 + firmware character varying(255),
  9 + transport character varying(50),
  10 + stream_mode character varying(50),
  11 + on_line bool default false,
  12 + register_time character varying(50),
  13 + keepalive_time character varying(50),
  14 + ip character varying(50),
  15 + create_time character varying(50),
  16 + update_time character varying(50),
  17 + port integer,
  18 + expires integer,
  19 + subscribe_cycle_for_catalog integer DEFAULT 0,
  20 + subscribe_cycle_for_mobile_position integer DEFAULT 0,
  21 + mobile_position_submission_interval integer DEFAULT 5,
  22 + subscribe_cycle_for_alarm integer DEFAULT 0,
  23 + host_address character varying(50),
  24 + charset character varying(50),
  25 + ssrc_check bool default false,
  26 + geo_coord_sys character varying(50),
  27 + media_server_id character varying(50),
  28 + custom_name character varying(255),
  29 + sdp_ip character varying(50),
  30 + local_ip character varying(50),
  31 + password character varying(255),
  32 + as_message_channel bool default false,
  33 + keepalive_interval_time integer,
  34 + switch_primary_sub_stream bool default false,
  35 + broadcast_push_after_ack bool default false,
  36 + constraint uk_device_device unique (device_id)
  37 +);
  38 +
  39 +create table wvp_device_alarm (
  40 + id serial primary key ,
  41 + device_id character varying(50) not null,
  42 + channel_id character varying(50) not null,
  43 + alarm_priority character varying(50),
  44 + alarm_method character varying(50),
  45 + alarm_time character varying(50),
  46 + alarm_description character varying(255),
  47 + longitude double precision,
  48 + latitude double precision,
  49 + alarm_type character varying(50),
  50 + create_time character varying(50) not null
  51 +);
  52 +
  53 +create table wvp_device_channel (
  54 + id serial primary key ,
  55 + channel_id character varying(50) not null,
  56 + name character varying(255),
  57 + custom_name character varying(255),
  58 + manufacture character varying(50),
  59 + model character varying(50),
  60 + owner character varying(50),
  61 + civil_code character varying(50),
  62 + block character varying(50),
  63 + address character varying(50),
  64 + parent_id character varying(50),
  65 + safety_way integer,
  66 + register_way integer,
  67 + cert_num character varying(50),
  68 + certifiable integer,
  69 + err_code integer,
  70 + end_time character varying(50),
  71 + secrecy character varying(50),
  72 + ip_address character varying(50),
  73 + port integer,
  74 + password character varying(255),
  75 + ptz_type integer,
  76 + custom_ptz_type integer,
  77 + status bool default false,
  78 + longitude double precision,
  79 + custom_longitude double precision,
  80 + latitude double precision,
  81 + custom_latitude double precision,
  82 + stream_id character varying(255),
  83 + device_id character varying(50) not null,
  84 + parental character varying(50),
  85 + has_audio bool default false,
  86 + create_time character varying(50) not null,
  87 + update_time character varying(50) not null,
  88 + sub_count integer,
  89 + longitude_gcj02 double precision,
  90 + latitude_gcj02 double precision,
  91 + longitude_wgs84 double precision,
  92 + latitude_wgs84 double precision,
  93 + business_group_id character varying(50),
  94 + gps_time character varying(50),
  95 + stream_identification character varying(50),
  96 + constraint uk_wvp_device_channel_unique_device_channel unique (device_id, channel_id)
  97 +);
  98 +
  99 +create table wvp_device_mobile_position (
  100 + id serial primary key,
  101 + device_id character varying(50) not null,
  102 + channel_id character varying(50) not null,
  103 + device_name character varying(255),
  104 + time character varying(50),
  105 + longitude double precision,
  106 + latitude double precision,
  107 + altitude double precision,
  108 + speed double precision,
  109 + direction double precision,
  110 + report_source character varying(50),
  111 + longitude_gcj02 double precision,
  112 + latitude_gcj02 double precision,
  113 + longitude_wgs84 double precision,
  114 + latitude_wgs84 double precision,
  115 + create_time character varying(50)
  116 +);
  117 +
  118 +create table wvp_gb_stream (
  119 + gb_stream_id serial primary key,
  120 + app character varying(255) not null,
  121 + stream character varying(255) not null,
  122 + gb_id character varying(50) not null,
  123 + name character varying(255),
  124 + longitude double precision,
  125 + latitude double precision,
  126 + stream_type character varying(50),
  127 + media_server_id character varying(50),
  128 + create_time character varying(50),
  129 + constraint uk_gb_stream_unique_gb_id unique (gb_id),
  130 + constraint uk_gb_stream_unique_app_stream unique (app, stream)
  131 +);
  132 +
  133 +create table wvp_log (
  134 + id serial primary key ,
  135 + name character varying(50),
  136 + type character varying(50),
  137 + uri character varying(200),
  138 + address character varying(50),
  139 + result character varying(50),
  140 + timing bigint,
  141 + username character varying(50),
  142 + create_time character varying(50)
  143 +);
  144 +
  145 +create table wvp_media_server (
  146 + id character varying(255) primary key ,
  147 + ip character varying(50),
  148 + hook_ip character varying(50),
  149 + sdp_ip character varying(50),
  150 + stream_ip character varying(50),
  151 + http_port integer,
  152 + http_ssl_port integer,
  153 + rtmp_port integer,
  154 + rtmp_ssl_port integer,
  155 + rtp_proxy_port integer,
  156 + rtsp_port integer,
  157 + rtsp_ssl_port integer,
  158 + auto_config bool default false,
  159 + secret character varying(50),
  160 + rtp_enable bool default false,
  161 + rtp_port_range character varying(50),
  162 + send_rtp_port_range character varying(50),
  163 + record_assist_port integer,
  164 + default_server bool default false,
  165 + create_time character varying(50),
  166 + update_time character varying(50),
  167 + hook_alive_interval integer,
  168 + record_path character varying(255),
  169 + record_day integer default 7,
  170 + constraint uk_media_server_unique_ip_http_port unique (ip, http_port)
  171 +);
  172 +
  173 +create table wvp_platform (
  174 + id serial primary key ,
  175 + enable bool default false,
  176 + name character varying(255),
  177 + server_gb_id character varying(50),
  178 + server_gb_domain character varying(50),
  179 + server_ip character varying(50),
  180 + server_port integer,
  181 + device_gb_id character varying(50),
  182 + device_ip character varying(50),
  183 + device_port character varying(50),
  184 + username character varying(255),
  185 + password character varying(50),
  186 + expires character varying(50),
  187 + keep_timeout character varying(50),
  188 + transport character varying(50),
  189 + character_set character varying(50),
  190 + catalog_id character varying(50),
  191 + ptz bool default false,
  192 + rtcp bool default false,
  193 + status bool default false,
  194 + start_offline_push bool default false,
  195 + administrative_division character varying(50),
  196 + catalog_group integer,
  197 + create_time character varying(50),
  198 + update_time character varying(50),
  199 + as_message_channel bool default false,
  200 + auto_push_channel bool default false,
  201 + constraint uk_platform_unique_server_gb_id unique (server_gb_id)
  202 +);
  203 +
  204 +create table wvp_platform_catalog (
  205 + id character varying(50),
  206 + platform_id character varying(50),
  207 + name character varying(255),
  208 + parent_id character varying(50),
  209 + civil_code character varying(50),
  210 + business_group_id character varying(50),
  211 + constraint uk_platform_catalog_id_platform_id unique (id, platform_id)
  212 +);
  213 +
  214 +create table wvp_platform_gb_channel (
  215 + id serial primary key ,
  216 + platform_id character varying(50),
  217 + catalog_id character varying(50),
  218 + device_channel_id integer,
  219 + constraint uk_platform_gb_channel_platform_id_catalog_id_device_channel_id unique (platform_id, catalog_id, device_channel_id)
  220 +);
  221 +
  222 +create table wvp_platform_gb_stream (
  223 + id serial primary key,
  224 + platform_id character varying(50),
  225 + catalog_id character varying(50),
  226 + gb_stream_id integer,
  227 + constraint uk_platform_gb_stream_platform_id_catalog_id_gb_stream_id unique (platform_id, catalog_id, gb_stream_id)
  228 +);
  229 +
  230 +create table wvp_stream_proxy (
  231 + id serial primary key,
  232 + type character varying(50),
  233 + app character varying(255),
  234 + stream character varying(255),
  235 + url character varying(255),
  236 + src_url character varying(255),
  237 + dst_url character varying(255),
  238 + timeout_ms integer,
  239 + ffmpeg_cmd_key character varying(255),
  240 + rtp_type character varying(50),
  241 + media_server_id character varying(50),
  242 + enable_audio bool default false,
  243 + enable_mp4 bool default false,
  244 + enable bool default false,
  245 + status boolean,
  246 + enable_remove_none_reader bool default false,
  247 + create_time character varying(50),
  248 + name character varying(255),
  249 + update_time character varying(50),
  250 + stream_key character varying(255),
  251 + enable_disable_none_reader bool default false,
  252 + constraint uk_stream_proxy_app_stream unique (app, stream)
  253 +);
  254 +
  255 +create table wvp_stream_push (
  256 + id serial primary key,
  257 + app character varying(255),
  258 + stream character varying(255),
  259 + total_reader_count character varying(50),
  260 + origin_type integer,
  261 + origin_type_str character varying(50),
  262 + create_time character varying(50),
  263 + alive_second integer,
  264 + media_server_id character varying(50),
  265 + server_id character varying(50),
  266 + push_time character varying(50),
  267 + status bool default false,
  268 + update_time character varying(50),
  269 + push_ing bool default false,
  270 + self bool default false,
  271 + constraint uk_stream_push_app_stream unique (app, stream)
  272 +);
  273 +create table wvp_cloud_record (
  274 + id serial primary key,
  275 + app character varying(255),
  276 + stream character varying(255),
  277 + call_id character varying(255),
  278 + start_time bigint,
  279 + end_time bigint,
  280 + media_server_id character varying(50),
  281 + file_name character varying(255),
  282 + folder character varying(255),
  283 + file_path character varying(255),
  284 + collect bool default false,
  285 + file_size bigint,
  286 + time_len bigint,
  287 + constraint uk_stream_push_app_stream_path unique (app, stream, file_path)
  288 +);
  289 +
  290 +create table wvp_user (
  291 + id serial primary key,
  292 + username character varying(255),
  293 + password character varying(255),
  294 + role_id integer,
  295 + create_time character varying(50),
  296 + update_time character varying(50),
  297 + push_key character varying(50),
  298 + constraint uk_user_username unique (username)
  299 +);
  300 +
  301 +create table wvp_user_role (
  302 + id serial primary key,
  303 + name character varying(50),
  304 + authority character varying(50),
  305 + create_time character varying(50),
  306 + update_time character varying(50)
  307 +);
  308 +create table wvp_resources_tree (
  309 + id serial primary key ,
  310 + is_catalog bool default true,
  311 + device_channel_id integer ,
  312 + gb_stream_id integer,
  313 + name character varying(255),
  314 + parentId integer,
  315 + path character varying(255)
  316 +);
  317 +
  318 +
  319 +/*初始数据*/
  320 +INSERT INTO wvp_user VALUES (1, 'admin','21232f297a57a5a743894a0e4a801fc3',1,'2021-04-13 14:14:57','2021-04-13 14:14:57','3e80d1762a324d5b0ff636e0bd16f1e3');
  321 +INSERT INTO wvp_user_role VALUES (1, 'admin','0','2021-04-13 14:14:57','2021-04-13 14:14:57');
  322 +
  323 +
  324 +
... ...
数据库/2.7.0/初始化-postgresql-kingbase-2.7.0.sql 0 → 100644
  1 +/*建表*/
  2 +create table wvp_device (
  3 + id serial primary key ,
  4 + device_id character varying(50) not null ,
  5 + name character varying(255),
  6 + manufacturer character varying(255),
  7 + model character varying(255),
  8 + firmware character varying(255),
  9 + transport character varying(50),
  10 + stream_mode character varying(50),
  11 + on_line bool default false,
  12 + register_time character varying(50),
  13 + keepalive_time character varying(50),
  14 + ip character varying(50),
  15 + create_time character varying(50),
  16 + update_time character varying(50),
  17 + port integer,
  18 + expires integer,
  19 + subscribe_cycle_for_catalog integer DEFAULT 0,
  20 + subscribe_cycle_for_mobile_position integer DEFAULT 0,
  21 + mobile_position_submission_interval integer DEFAULT 5,
  22 + subscribe_cycle_for_alarm integer DEFAULT 0,
  23 + host_address character varying(50),
  24 + charset character varying(50),
  25 + ssrc_check bool default false,
  26 + geo_coord_sys character varying(50),
  27 + media_server_id character varying(50),
  28 + custom_name character varying(255),
  29 + sdp_ip character varying(50),
  30 + local_ip character varying(50),
  31 + password character varying(255),
  32 + as_message_channel bool default false,
  33 + keepalive_interval_time integer,
  34 + switch_primary_sub_stream bool default false,
  35 + broadcast_push_after_ack bool default false,
  36 + constraint uk_device_device unique (device_id)
  37 +);
  38 +
  39 +create table wvp_device_alarm (
  40 + id serial primary key ,
  41 + device_id character varying(50) not null,
  42 + channel_id character varying(50) not null,
  43 + alarm_priority character varying(50),
  44 + alarm_method character varying(50),
  45 + alarm_time character varying(50),
  46 + alarm_description character varying(255),
  47 + longitude double precision,
  48 + latitude double precision,
  49 + alarm_type character varying(50),
  50 + create_time character varying(50) not null
  51 +);
  52 +
  53 +create table wvp_device_channel (
  54 + id serial primary key ,
  55 + channel_id character varying(50) not null,
  56 + name character varying(255),
  57 + custom_name character varying(255),
  58 + manufacture character varying(50),
  59 + model character varying(50),
  60 + owner character varying(50),
  61 + civil_code character varying(50),
  62 + block character varying(50),
  63 + address character varying(50),
  64 + parent_id character varying(50),
  65 + safety_way integer,
  66 + register_way integer,
  67 + cert_num character varying(50),
  68 + certifiable integer,
  69 + err_code integer,
  70 + end_time character varying(50),
  71 + secrecy character varying(50),
  72 + ip_address character varying(50),
  73 + port integer,
  74 + password character varying(255),
  75 + ptz_type integer,
  76 + custom_ptz_type integer,
  77 + status bool default false,
  78 + longitude double precision,
  79 + custom_longitude double precision,
  80 + latitude double precision,
  81 + custom_latitude double precision,
  82 + stream_id character varying(255),
  83 + device_id character varying(50) not null,
  84 + parental character varying(50),
  85 + has_audio bool default false,
  86 + create_time character varying(50) not null,
  87 + update_time character varying(50) not null,
  88 + sub_count integer,
  89 + longitude_gcj02 double precision,
  90 + latitude_gcj02 double precision,
  91 + longitude_wgs84 double precision,
  92 + latitude_wgs84 double precision,
  93 + business_group_id character varying(50),
  94 + gps_time character varying(50),
  95 + stream_identification character varying(50),
  96 + constraint uk_wvp_device_channel_unique_device_channel unique (device_id, channel_id)
  97 +);
  98 +
  99 +create table wvp_device_mobile_position (
  100 + id serial primary key,
  101 + device_id character varying(50) not null,
  102 + channel_id character varying(50) not null,
  103 + device_name character varying(255),
  104 + time character varying(50),
  105 + longitude double precision,
  106 + latitude double precision,
  107 + altitude double precision,
  108 + speed double precision,
  109 + direction double precision,
  110 + report_source character varying(50),
  111 + longitude_gcj02 double precision,
  112 + latitude_gcj02 double precision,
  113 + longitude_wgs84 double precision,
  114 + latitude_wgs84 double precision,
  115 + create_time character varying(50)
  116 +);
  117 +
  118 +create table wvp_gb_stream (
  119 + gb_stream_id serial primary key,
  120 + app character varying(255) not null,
  121 + stream character varying(255) not null,
  122 + gb_id character varying(50) not null,
  123 + name character varying(255),
  124 + longitude double precision,
  125 + latitude double precision,
  126 + stream_type character varying(50),
  127 + media_server_id character varying(50),
  128 + create_time character varying(50),
  129 + constraint uk_gb_stream_unique_gb_id unique (gb_id),
  130 + constraint uk_gb_stream_unique_app_stream unique (app, stream)
  131 +);
  132 +
  133 +create table wvp_log (
  134 + id serial primary key ,
  135 + name character varying(50),
  136 + type character varying(50),
  137 + uri character varying(200),
  138 + address character varying(50),
  139 + result character varying(50),
  140 + timing bigint,
  141 + username character varying(50),
  142 + create_time character varying(50)
  143 +);
  144 +
  145 +create table wvp_media_server (
  146 + id character varying(255) primary key ,
  147 + ip character varying(50),
  148 + hook_ip character varying(50),
  149 + sdp_ip character varying(50),
  150 + stream_ip character varying(50),
  151 + http_port integer,
  152 + http_ssl_port integer,
  153 + rtmp_port integer,
  154 + rtmp_ssl_port integer,
  155 + rtp_proxy_port integer,
  156 + rtsp_port integer,
  157 + rtsp_ssl_port integer,
  158 + auto_config bool default false,
  159 + secret character varying(50),
  160 + rtp_enable bool default false,
  161 + rtp_port_range character varying(50),
  162 + send_rtp_port_range character varying(50),
  163 + record_assist_port integer,
  164 + default_server bool default false,
  165 + create_time character varying(50),
  166 + update_time character varying(50),
  167 + hook_alive_interval integer,
  168 + record_path character varying(255),
  169 + record_day integer default 7,
  170 + constraint uk_media_server_unique_ip_http_port unique (ip, http_port)
  171 +);
  172 +
  173 +create table wvp_platform (
  174 + id serial primary key ,
  175 + enable bool default false,
  176 + name character varying(255),
  177 + server_gb_id character varying(50),
  178 + server_gb_domain character varying(50),
  179 + server_ip character varying(50),
  180 + server_port integer,
  181 + device_gb_id character varying(50),
  182 + device_ip character varying(50),
  183 + device_port character varying(50),
  184 + username character varying(255),
  185 + password character varying(50),
  186 + expires character varying(50),
  187 + keep_timeout character varying(50),
  188 + transport character varying(50),
  189 + character_set character varying(50),
  190 + catalog_id character varying(50),
  191 + ptz bool default false,
  192 + rtcp bool default false,
  193 + status bool default false,
  194 + start_offline_push bool default false,
  195 + administrative_division character varying(50),
  196 + catalog_group integer,
  197 + create_time character varying(50),
  198 + update_time character varying(50),
  199 + as_message_channel bool default false,
  200 + auto_push_channel bool default false,
  201 + constraint uk_platform_unique_server_gb_id unique (server_gb_id)
  202 +);
  203 +
  204 +create table wvp_platform_catalog (
  205 + id character varying(50),
  206 + platform_id character varying(50),
  207 + name character varying(255),
  208 + parent_id character varying(50),
  209 + civil_code character varying(50),
  210 + business_group_id character varying(50),
  211 + constraint uk_platform_catalog_id_platform_id unique (id, platform_id)
  212 +);
  213 +
  214 +create table wvp_platform_gb_channel (
  215 + id serial primary key ,
  216 + platform_id character varying(50),
  217 + catalog_id character varying(50),
  218 + device_channel_id integer,
  219 + constraint uk_platform_gb_channel_platform_id_catalog_id_device_channel_id unique (platform_id, catalog_id, device_channel_id)
  220 +);
  221 +
  222 +create table wvp_platform_gb_stream (
  223 + id serial primary key,
  224 + platform_id character varying(50),
  225 + catalog_id character varying(50),
  226 + gb_stream_id integer,
  227 + constraint uk_platform_gb_stream_platform_id_catalog_id_gb_stream_id unique (platform_id, catalog_id, gb_stream_id)
  228 +);
  229 +
  230 +create table wvp_stream_proxy (
  231 + id serial primary key,
  232 + type character varying(50),
  233 + app character varying(255),
  234 + stream character varying(255),
  235 + url character varying(255),
  236 + src_url character varying(255),
  237 + dst_url character varying(255),
  238 + timeout_ms integer,
  239 + ffmpeg_cmd_key character varying(255),
  240 + rtp_type character varying(50),
  241 + media_server_id character varying(50),
  242 + enable_audio bool default false,
  243 + enable_mp4 bool default false,
  244 + enable bool default false,
  245 + status boolean,
  246 + enable_remove_none_reader bool default false,
  247 + create_time character varying(50),
  248 + name character varying(255),
  249 + update_time character varying(50),
  250 + stream_key character varying(255),
  251 + enable_disable_none_reader bool default false,
  252 + constraint uk_stream_proxy_app_stream unique (app, stream)
  253 +);
  254 +
  255 +create table wvp_stream_push (
  256 + id serial primary key,
  257 + app character varying(255),
  258 + stream character varying(255),
  259 + total_reader_count character varying(50),
  260 + origin_type integer,
  261 + origin_type_str character varying(50),
  262 + create_time character varying(50),
  263 + alive_second integer,
  264 + media_server_id character varying(50),
  265 + server_id character varying(50),
  266 + push_time character varying(50),
  267 + status bool default false,
  268 + update_time character varying(50),
  269 + push_ing bool default false,
  270 + self bool default false,
  271 + constraint uk_stream_push_app_stream unique (app, stream)
  272 +);
  273 +create table wvp_cloud_record (
  274 + id serial primary key,
  275 + app character varying(255),
  276 + stream character varying(255),
  277 + call_id character varying(255),
  278 + start_time int8,
  279 + end_time int8,
  280 + media_server_id character varying(50),
  281 + file_name character varying(255),
  282 + folder character varying(255),
  283 + file_path character varying(255),
  284 + collect bool default false,
  285 + file_size int8,
  286 + time_len int8,
  287 + constraint uk_stream_push_app_stream_path unique (app, stream, file_path)
  288 +);
  289 +
  290 +create table wvp_user (
  291 + id serial primary key,
  292 + username character varying(255),
  293 + password character varying(255),
  294 + role_id integer,
  295 + create_time character varying(50),
  296 + update_time character varying(50),
  297 + push_key character varying(50),
  298 + constraint uk_user_username unique (username)
  299 +);
  300 +
  301 +create table wvp_user_role (
  302 + id serial primary key,
  303 + name character varying(50),
  304 + authority character varying(50),
  305 + create_time character varying(50),
  306 + update_time character varying(50)
  307 +);
  308 +create table wvp_resources_tree (
  309 + id serial primary key ,
  310 + is_catalog bool default true,
  311 + device_channel_id integer ,
  312 + gb_stream_id integer,
  313 + name character varying(255),
  314 + parentId integer,
  315 + path character varying(255)
  316 +);
  317 +
  318 +
  319 +/*初始数据*/
  320 +INSERT INTO wvp_user VALUES (1, 'admin','21232f297a57a5a743894a0e4a801fc3',1,'2021-04-13 14:14:57','2021-04-13 14:14:57','3e80d1762a324d5b0ff636e0bd16f1e3');
  321 +INSERT INTO wvp_user_role VALUES (1, 'admin','0','2021-04-13 14:14:57','2021-04-13 14:14:57');
  322 +
  323 +
  324 +
... ...
数据库/2.7.0/更新-mysql-2.7.0.sql 0 → 100644
  1 +alter table wvp_device_channel
  2 + add stream_identification character varying(50);
  3 +
  4 +alter table wvp_device
  5 + drop switch_primary_sub_stream;
0 6 \ No newline at end of file
... ...
数据库/2.7.0/更新-postgresql-kingbase-2.7.0.sql 0 → 100644
  1 +alter table wvp_device_channel
  2 + add stream_identification character varying(50);
  3 +
  4 +alter table wvp_device
  5 + drop switch_primary_sub_stream;
0 6 \ No newline at end of file
... ...