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,6 +49,7 @@ https://gitee.com/pan648540858/wvp-GB28181-pro.git
49 - [X] 支持电子地图,支持接入WGS84和GCJ02两种坐标系,并且自动转化为合适的坐标系进行展示和分发 49 - [X] 支持电子地图,支持接入WGS84和GCJ02两种坐标系,并且自动转化为合适的坐标系进行展示和分发
50 - [X] 接入设备 50 - [X] 接入设备
51 - [X] 视频预览 51 - [X] 视频预览
  52 + - [X] 支持主码流子码流切换
52 - [X] 无限制接入路数,能接入多少设备只取决于你的服务器性能 53 - [X] 无限制接入路数,能接入多少设备只取决于你的服务器性能
53 - [X] 云台控制,控制设备转向,拉近,拉远 54 - [X] 云台控制,控制设备转向,拉近,拉远
54 - [X] 预置位查询,使用与设置 55 - [X] 预置位查询,使用与设置
src/main/java/com/genersoft/iot/vmp/common/InviteInfo.java
1 package com.genersoft.iot.vmp.common; 1 package com.genersoft.iot.vmp.common;
2 2
3 import com.genersoft.iot.vmp.service.bean.SSRCInfo; 3 import com.genersoft.iot.vmp.service.bean.SSRCInfo;
4 -import io.swagger.v3.oas.annotations.media.Schema;  
5 4
6 /** 5 /**
7 * 记录每次发送invite消息的状态 6 * 记录每次发送invite消息的状态
@@ -125,20 +124,4 @@ public class InviteInfo { @@ -125,20 +124,4 @@ public class InviteInfo {
125 this.streamMode = streamMode; 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,27 +452,11 @@ public class Device {
452 public void setSipTransactionInfo(SipTransactionInfo sipTransactionInfo) { 452 public void setSipTransactionInfo(SipTransactionInfo sipTransactionInfo) {
453 this.sipTransactionInfo = sipTransactionInfo; 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,6 +246,10 @@ public class DeviceChannel {
246 @Schema(description = "GPS的更新时间") 246 @Schema(description = "GPS的更新时间")
247 private String gpsTime; 247 private String gpsTime;
248 248
  249 + @Schema(description = "码流标识,优先级高于设备中码流标识," +
  250 + "用于选择码流时组成码流标识。默认为null,不设置。可选值: stream/streamnumber/streamprofile/streamMode")
  251 + private String streamIdentification;
  252 +
249 public int getId() { 253 public int getId() {
250 return id; 254 return id;
251 } 255 }
@@ -574,4 +578,12 @@ public class DeviceChannel { @@ -574,4 +578,12 @@ public class DeviceChannel {
574 public void setGpsTime(String gpsTime) { 578 public void setGpsTime(String gpsTime) {
575 this.gpsTime = gpsTime; 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,7 +52,7 @@ public class SubscribeHolder {
52 Runnable runnable = dynamicTask.get(taskOverdueKey); 52 Runnable runnable = dynamicTask.get(taskOverdueKey);
53 if (runnable instanceof ISubscribeTask) { 53 if (runnable instanceof ISubscribeTask) {
54 ISubscribeTask subscribeTask = (ISubscribeTask) runnable; 54 ISubscribeTask subscribeTask = (ISubscribeTask) runnable;
55 - subscribeTask.stop(); 55 + subscribeTask.stop(null);
56 } 56 }
57 // 添加任务处理订阅过期 57 // 添加任务处理订阅过期
58 dynamicTask.stop(taskOverdueKey); 58 dynamicTask.stop(taskOverdueKey);
@@ -87,7 +87,7 @@ public class SubscribeHolder { @@ -87,7 +87,7 @@ public class SubscribeHolder {
87 Runnable runnable = dynamicTask.get(taskOverdueKey); 87 Runnable runnable = dynamicTask.get(taskOverdueKey);
88 if (runnable instanceof ISubscribeTask) { 88 if (runnable instanceof ISubscribeTask) {
89 ISubscribeTask subscribeTask = (ISubscribeTask) runnable; 89 ISubscribeTask subscribeTask = (ISubscribeTask) runnable;
90 - subscribeTask.stop(); 90 + subscribeTask.stop(null);
91 } 91 }
92 // 添加任务处理订阅过期 92 // 添加任务处理订阅过期
93 dynamicTask.stop(taskOverdueKey); 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,6 +2,8 @@ package com.genersoft.iot.vmp.gb28181.event;
2 2
3 import com.genersoft.iot.vmp.gb28181.bean.DeviceNotFoundEvent; 3 import com.genersoft.iot.vmp.gb28181.bean.DeviceNotFoundEvent;
4 import gov.nist.javax.sip.message.SIPRequest; 4 import gov.nist.javax.sip.message.SIPRequest;
  5 +import gov.nist.javax.sip.message.SIPResponse;
  6 +import org.apache.commons.lang3.ObjectUtils;
5 import org.slf4j.Logger; 7 import org.slf4j.Logger;
6 import org.slf4j.LoggerFactory; 8 import org.slf4j.LoggerFactory;
7 import org.springframework.scheduling.annotation.Scheduled; 9 import org.springframework.scheduling.annotation.Scheduled;
@@ -11,8 +13,7 @@ import javax.sip.DialogTerminatedEvent; @@ -11,8 +13,7 @@ import javax.sip.DialogTerminatedEvent;
11 import javax.sip.ResponseEvent; 13 import javax.sip.ResponseEvent;
12 import javax.sip.TimeoutEvent; 14 import javax.sip.TimeoutEvent;
13 import javax.sip.TransactionTerminatedEvent; 15 import javax.sip.TransactionTerminatedEvent;
14 -import javax.sip.header.CallIdHeader;  
15 -import javax.sip.message.Response; 16 +import javax.sip.header.WarningHeader;
16 import java.time.Instant; 17 import java.time.Instant;
17 import java.util.Map; 18 import java.util.Map;
18 import java.util.concurrent.ConcurrentHashMap; 19 import java.util.concurrent.ConcurrentHashMap;
@@ -97,14 +98,27 @@ public class SipSubscribe { @@ -97,14 +98,27 @@ public class SipSubscribe {
97 this.event = event; 98 this.event = event;
98 if (event instanceof ResponseEvent) { 99 if (event instanceof ResponseEvent) {
99 ResponseEvent responseEvent = (ResponseEvent)event; 100 ResponseEvent responseEvent = (ResponseEvent)event;
100 - Response response = responseEvent.getResponse(); 101 + SIPResponse response = (SIPResponse)responseEvent.getResponse();
101 this.type = EventResultType.response; 102 this.type = EventResultType.response;
102 if (response != null) { 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 this.statusCode = response.getStatusCode(); 119 this.statusCode = response.getStatusCode();
  120 + this.callId = response.getCallIdHeader().getCallId();
105 } 121 }
106 - this.callId = ((CallIdHeader)response.getHeader(CallIdHeader.NAME)).getCallId();  
107 -  
108 }else if (event instanceof TimeoutEvent) { 122 }else if (event instanceof TimeoutEvent) {
109 TimeoutEvent timeoutEvent = (TimeoutEvent)event; 123 TimeoutEvent timeoutEvent = (TimeoutEvent)event;
110 this.type = EventResultType.timeout; 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 package com.genersoft.iot.vmp.gb28181.task; 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 * @author lin 6 * @author lin
7 */ 7 */
8 public interface ISubscribeTask extends Runnable{ 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 package com.genersoft.iot.vmp.gb28181.task.impl; 1 package com.genersoft.iot.vmp.gb28181.task.impl;
2 2
  3 +import com.genersoft.iot.vmp.common.CommonCallback;
3 import com.genersoft.iot.vmp.conf.DynamicTask; 4 import com.genersoft.iot.vmp.conf.DynamicTask;
4 import com.genersoft.iot.vmp.gb28181.bean.Device; 5 import com.genersoft.iot.vmp.gb28181.bean.Device;
5 import com.genersoft.iot.vmp.gb28181.task.ISubscribeTask; 6 import com.genersoft.iot.vmp.gb28181.task.ISubscribeTask;
@@ -7,14 +8,13 @@ import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander; @@ -7,14 +8,13 @@ import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
7 import gov.nist.javax.sip.message.SIPRequest; 8 import gov.nist.javax.sip.message.SIPRequest;
8 import org.slf4j.Logger; 9 import org.slf4j.Logger;
9 import org.slf4j.LoggerFactory; 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 import javax.sip.header.ToHeader; 16 import javax.sip.header.ToHeader;
15 import java.text.ParseException; 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,7 +71,7 @@ public class CatalogSubscribeTask implements ISubscribeTask {
71 } 71 }
72 72
73 @Override 73 @Override
74 - public void stop() { 74 + public void stop(CommonCallback<Boolean> callback) {
75 /** 75 /**
76 * dialog 的各个状态 76 * dialog 的各个状态
77 * EARLY-> Early state状态-初始请求发送以后,收到了一个临时响应消息 77 * EARLY-> Early state状态-初始请求发送以后,收到了一个临时响应消息
@@ -94,6 +94,9 @@ public class CatalogSubscribeTask implements ISubscribeTask { @@ -94,6 +94,9 @@ public class CatalogSubscribeTask implements ISubscribeTask {
94 // 成功 94 // 成功
95 logger.info("[取消目录订阅]成功: {}", device.getDeviceId()); 95 logger.info("[取消目录订阅]成功: {}", device.getDeviceId());
96 } 96 }
  97 + if (callback != null) {
  98 + callback.run(event.getResponse().getRawContent() != null);
  99 + }
97 },eventResult -> { 100 },eventResult -> {
98 // 失败 101 // 失败
99 logger.warn("[取消目录订阅]失败,信令发送失败: {}-{} ", device.getDeviceId(), eventResult.msg); 102 logger.warn("[取消目录订阅]失败,信令发送失败: {}-{} ", device.getDeviceId(), eventResult.msg);
src/main/java/com/genersoft/iot/vmp/gb28181/task/impl/MobilePositionSubscribeHandlerTask.java
1 package com.genersoft.iot.vmp.gb28181.task.impl; 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 import com.genersoft.iot.vmp.gb28181.task.ISubscribeTask; 4 import com.genersoft.iot.vmp.gb28181.task.ISubscribeTask;
6 -import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;  
7 import com.genersoft.iot.vmp.service.IPlatformService; 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 import com.genersoft.iot.vmp.utils.SpringBeanFactory; 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 * 向已经订阅(移动位置)的上级发送MobilePosition消息 9 * 向已经订阅(移动位置)的上级发送MobilePosition消息
@@ -38,7 +27,7 @@ public class MobilePositionSubscribeHandlerTask implements ISubscribeTask { @@ -38,7 +27,7 @@ public class MobilePositionSubscribeHandlerTask implements ISubscribeTask {
38 } 27 }
39 28
40 @Override 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 package com.genersoft.iot.vmp.gb28181.task.impl; 1 package com.genersoft.iot.vmp.gb28181.task.impl;
2 2
  3 +import com.genersoft.iot.vmp.common.CommonCallback;
3 import com.genersoft.iot.vmp.conf.DynamicTask; 4 import com.genersoft.iot.vmp.conf.DynamicTask;
4 import com.genersoft.iot.vmp.gb28181.bean.Device; 5 import com.genersoft.iot.vmp.gb28181.bean.Device;
5 import com.genersoft.iot.vmp.gb28181.task.ISubscribeTask; 6 import com.genersoft.iot.vmp.gb28181.task.ISubscribeTask;
6 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander; 7 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
7 import gov.nist.javax.sip.message.SIPRequest; 8 import gov.nist.javax.sip.message.SIPRequest;
8 -import gov.nist.javax.sip.message.SIPResponse;  
9 -import org.dom4j.Element;  
10 import org.slf4j.Logger; 9 import org.slf4j.Logger;
11 import org.slf4j.LoggerFactory; 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 import javax.sip.header.ToHeader; 15 import javax.sip.header.ToHeader;
16 import java.text.ParseException; 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,7 +68,7 @@ public class MobilePositionSubscribeTask implements ISubscribeTask {
70 } 68 }
71 69
72 @Override 70 @Override
73 - public void stop() { 71 + public void stop(CommonCallback<Boolean> callback) {
74 /** 72 /**
75 * dialog 的各个状态 73 * dialog 的各个状态
76 * EARLY-> Early state状态-初始请求发送以后,收到了一个临时响应消息 74 * EARLY-> Early state状态-初始请求发送以后,收到了一个临时响应消息
@@ -92,6 +90,9 @@ public class MobilePositionSubscribeTask implements ISubscribeTask { @@ -92,6 +90,9 @@ public class MobilePositionSubscribeTask implements ISubscribeTask {
92 // 成功 90 // 成功
93 logger.info("[取消移动位置订阅]成功: {}", device.getDeviceId()); 91 logger.info("[取消移动位置订阅]成功: {}", device.getDeviceId());
94 } 92 }
  93 + if (callback != null) {
  94 + callback.run(event.getResponse().getRawContent() != null);
  95 + }
95 },eventResult -> { 96 },eventResult -> {
96 // 失败 97 // 失败
97 logger.warn("[取消移动位置订阅]失败,信令发送失败: {}-{} ", device.getDeviceId(), eventResult.msg); 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,6 +5,7 @@ import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException;
5 import com.genersoft.iot.vmp.gb28181.bean.*; 5 import com.genersoft.iot.vmp.gb28181.bean.*;
6 import com.genersoft.iot.vmp.gb28181.bean.Device; 6 import com.genersoft.iot.vmp.gb28181.bean.Device;
7 import com.genersoft.iot.vmp.gb28181.bean.DeviceAlarm; 7 import com.genersoft.iot.vmp.gb28181.bean.DeviceAlarm;
  8 +import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
8 import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; 9 import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
9 import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe; 10 import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe;
10 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; 11 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
@@ -97,9 +98,9 @@ public interface ISIPCommander { @@ -97,9 +98,9 @@ public interface ISIPCommander {
97 /** 98 /**
98 * 请求预览视频流 99 * 请求预览视频流
99 * @param device 视频设备 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,6 +7,10 @@ import com.genersoft.iot.vmp.conf.UserSetting;
7 import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException; 7 import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException;
8 import com.genersoft.iot.vmp.gb28181.SipLayer; 8 import com.genersoft.iot.vmp.gb28181.SipLayer;
9 import com.genersoft.iot.vmp.gb28181.bean.*; 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 import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; 14 import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
11 import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; 15 import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
12 import com.genersoft.iot.vmp.gb28181.transmit.SIPSender; 16 import com.genersoft.iot.vmp.gb28181.transmit.SIPSender;
@@ -266,12 +270,12 @@ public class SIPCommander implements ISIPCommander { @@ -266,12 +270,12 @@ public class SIPCommander implements ISIPCommander {
266 * 请求预览视频流 270 * 请求预览视频流
267 * 271 *
268 * @param device 视频设备 272 * @param device 视频设备
269 - * @param channelId 预览通道 273 + * @param channel 预览通道
270 * @param event hook订阅 274 * @param event hook订阅
271 * @param errorEvent sip错误订阅 275 * @param errorEvent sip错误订阅
272 */ 276 */
273 @Override 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 ZlmHttpHookSubscribe.Event event, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException { 279 ZlmHttpHookSubscribe.Event event, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException {
276 String stream = ssrcInfo.getStream(); 280 String stream = ssrcInfo.getStream();
277 281
@@ -295,7 +299,7 @@ public class SIPCommander implements ISIPCommander { @@ -295,7 +299,7 @@ public class SIPCommander implements ISIPCommander {
295 } 299 }
296 StringBuffer content = new StringBuffer(200); 300 StringBuffer content = new StringBuffer(200);
297 content.append("v=0\r\n"); 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 content.append("s=Play\r\n"); 303 content.append("s=Play\r\n");
300 content.append("c=IN IP4 " + sdpIp + "\r\n"); 304 content.append("c=IN IP4 " + sdpIp + "\r\n");
301 content.append("t=0 0\r\n"); 305 content.append("t=0 0\r\n");
@@ -346,20 +350,8 @@ public class SIPCommander implements ISIPCommander { @@ -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 content.append("y=" + ssrcInfo.getSsrc() + "\r\n");//ssrc 357 content.append("y=" + ssrcInfo.getSsrc() + "\r\n");//ssrc
@@ -368,16 +360,16 @@ public class SIPCommander implements ISIPCommander { @@ -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 sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, (e -> { 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 mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); 366 mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc());
375 errorEvent.response(e); 367 errorEvent.response(e);
376 }), e -> { 368 }), e -> {
377 ResponseEvent responseEvent = (ResponseEvent) e.event; 369 ResponseEvent responseEvent = (ResponseEvent) e.event;
378 SIPResponse response = (SIPResponse) responseEvent.getResponse(); 370 SIPResponse response = (SIPResponse) responseEvent.getResponse();
379 String callId = response.getCallIdHeader().getCallId(); 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 InviteSessionType.PLAY); 373 InviteSessionType.PLAY);
382 okEvent.response(e); 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,7 +6,6 @@ import com.genersoft.iot.vmp.conf.SipConfig;
6 import com.genersoft.iot.vmp.conf.UserSetting; 6 import com.genersoft.iot.vmp.conf.UserSetting;
7 import com.genersoft.iot.vmp.gb28181.bean.*; 7 import com.genersoft.iot.vmp.gb28181.bean.*;
8 import com.genersoft.iot.vmp.gb28181.event.EventPublisher; 8 import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
9 -import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent;  
10 import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver; 9 import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver;
11 import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; 10 import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
12 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; 11 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
@@ -38,7 +37,6 @@ import javax.sip.SipException; @@ -38,7 +37,6 @@ import javax.sip.SipException;
38 import javax.sip.header.FromHeader; 37 import javax.sip.header.FromHeader;
39 import javax.sip.message.Response; 38 import javax.sip.message.Response;
40 import java.text.ParseException; 39 import java.text.ParseException;
41 -import java.util.Iterator;  
42 import java.util.List; 40 import java.util.List;
43 import java.util.concurrent.ConcurrentLinkedQueue; 41 import java.util.concurrent.ConcurrentLinkedQueue;
44 42
@@ -222,7 +220,6 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements @@ -222,7 +220,6 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements
222 mobilePosition.getLongitude(), mobilePosition.getLatitude()); 220 mobilePosition.getLongitude(), mobilePosition.getLatitude());
223 mobilePosition.setReportSource("Mobile Position"); 221 mobilePosition.setReportSource("Mobile Position");
224 222
225 -  
226 // 更新device channel 的经纬度 223 // 更新device channel 的经纬度
227 DeviceChannel deviceChannel = new DeviceChannel(); 224 DeviceChannel deviceChannel = new DeviceChannel();
228 deviceChannel.setDeviceId(device.getDeviceId()); 225 deviceChannel.setDeviceId(device.getDeviceId());
@@ -242,6 +239,8 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements @@ -242,6 +239,8 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements
242 } 239 }
243 240
244 storager.updateChannelPosition(deviceChannel); 241 storager.updateChannelPosition(deviceChannel);
  242 + // 向关联了该通道并且开启移动位置订阅的上级平台发送移动位置订阅消息
  243 +
245 244
246 // 发送redis消息。 通知位置信息的变化 245 // 发送redis消息。 通知位置信息的变化
247 JSONObject jsonObject = new JSONObject(); 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,8 +82,9 @@ public class KeepaliveNotifyMessageHandler extends SIPRequestProcessorParent imp
82 device.setIp(remoteAddressInfo.getIp()); 82 device.setIp(remoteAddressInfo.getIp());
83 // 设备地址变化会引起目录订阅任务失效,需要重新添加 83 // 设备地址变化会引起目录订阅任务失效,需要重新添加
84 if (device.getSubscribeCycleForCatalog() > 0) { 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 if (device.getKeepaliveTime() == null) { 90 if (device.getKeepaliveTime() == null) {
src/main/java/com/genersoft/iot/vmp/service/IDeviceChannelService.java
@@ -87,4 +87,9 @@ public interface IDeviceChannelService { @@ -87,4 +87,9 @@ public interface IDeviceChannelService {
87 * 直接批量添加 87 * 直接批量添加
88 */ 88 */
89 void batchAddChannel(List<DeviceChannel> deviceChannels); 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 package com.genersoft.iot.vmp.service; 1 package com.genersoft.iot.vmp.service;
2 2
  3 +import com.genersoft.iot.vmp.common.CommonCallback;
3 import com.genersoft.iot.vmp.gb28181.bean.Device; 4 import com.genersoft.iot.vmp.gb28181.bean.Device;
4 import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; 5 import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
5 import com.genersoft.iot.vmp.gb28181.bean.SipTransactionInfo; 6 import com.genersoft.iot.vmp.gb28181.bean.SipTransactionInfo;
@@ -39,7 +40,7 @@ public interface IDeviceService { @@ -39,7 +40,7 @@ public interface IDeviceService {
39 * @param device 设备信息 40 * @param device 设备信息
40 * @return 布尔 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,7 +54,7 @@ public interface IDeviceService {
53 * @param device 设备信息 54 * @param device 设备信息
54 * @return 布尔 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 +6,7 @@ import com.genersoft.iot.vmp.conf.exception.ServiceException;
6 import com.genersoft.iot.vmp.gb28181.bean.Device; 6 import com.genersoft.iot.vmp.gb28181.bean.Device;
7 import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; 7 import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
8 import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem; 8 import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem;
  9 +import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
9 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; 10 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
10 import com.genersoft.iot.vmp.media.zlm.dto.hook.HookParam; 11 import com.genersoft.iot.vmp.media.zlm.dto.hook.HookParam;
11 import com.genersoft.iot.vmp.service.bean.ErrorCallback; 12 import com.genersoft.iot.vmp.service.bean.ErrorCallback;
@@ -25,7 +26,7 @@ import java.util.Map; @@ -25,7 +26,7 @@ import java.util.Map;
25 */ 26 */
26 public interface IPlayService { 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 ErrorCallback<Object> callback); 30 ErrorCallback<Object> callback);
30 SSRCInfo play(MediaServerItem mediaServerItem, String deviceId, String channelId, String ssrc, ErrorCallback<Object> callback); 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,6 +18,7 @@ import org.slf4j.Logger;
18 import org.slf4j.LoggerFactory; 18 import org.slf4j.LoggerFactory;
19 import org.springframework.beans.factory.annotation.Autowired; 19 import org.springframework.beans.factory.annotation.Autowired;
20 import org.springframework.stereotype.Service; 20 import org.springframework.stereotype.Service;
  21 +import org.springframework.util.ObjectUtils;
21 22
22 import java.util.ArrayList; 23 import java.util.ArrayList;
23 import java.util.HashMap; 24 import java.util.HashMap;
@@ -267,5 +268,16 @@ public class DeviceChannelServiceImpl implements IDeviceChannelService { @@ -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 package com.genersoft.iot.vmp.service.impl; 1 package com.genersoft.iot.vmp.service.impl;
2 2
3 import com.baomidou.dynamic.datasource.annotation.DS; 3 import com.baomidou.dynamic.datasource.annotation.DS;
  4 +import com.genersoft.iot.vmp.common.CommonCallback;
4 import com.genersoft.iot.vmp.common.VideoManagerConstants; 5 import com.genersoft.iot.vmp.common.VideoManagerConstants;
5 import com.genersoft.iot.vmp.conf.DynamicTask; 6 import com.genersoft.iot.vmp.conf.DynamicTask;
6 import com.genersoft.iot.vmp.conf.UserSetting; 7 import com.genersoft.iot.vmp.conf.UserSetting;
7 -import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException;  
8 import com.genersoft.iot.vmp.gb28181.bean.*; 8 import com.genersoft.iot.vmp.gb28181.bean.*;
9 import com.genersoft.iot.vmp.gb28181.session.AudioBroadcastManager; 9 import com.genersoft.iot.vmp.gb28181.session.AudioBroadcastManager;
10 import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; 10 import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
@@ -145,10 +145,6 @@ public class DeviceServiceImpl implements IDeviceService { @@ -145,10 +145,6 @@ public class DeviceServiceImpl implements IDeviceService {
145 } 145 }
146 sync(device); 146 sync(device);
147 }else { 147 }else {
148 -  
149 - if (deviceInDb != null) {  
150 - device.setSwitchPrimarySubStream(deviceInDb.isSwitchPrimarySubStream());  
151 - }  
152 if(!device.isOnLine()){ 148 if(!device.isOnLine()){
153 device.setOnLine(true); 149 device.setOnLine(true);
154 device.setCreateTime(now); 150 device.setCreateTime(now);
@@ -238,12 +234,8 @@ public class DeviceServiceImpl implements IDeviceService { @@ -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 List<AudioBroadcastCatch> audioBroadcastCatches = audioBroadcastManager.get(deviceId); 240 List<AudioBroadcastCatch> audioBroadcastCatches = audioBroadcastManager.get(deviceId);
249 if (audioBroadcastCatches.size() > 0) { 241 if (audioBroadcastCatches.size() > 0) {
@@ -281,7 +273,7 @@ public class DeviceServiceImpl implements IDeviceService { @@ -281,7 +273,7 @@ public class DeviceServiceImpl implements IDeviceService {
281 } 273 }
282 274
283 @Override 275 @Override
284 - public boolean removeCatalogSubscribe(Device device) { 276 + public boolean removeCatalogSubscribe(Device device, CommonCallback<Boolean> callback) {
285 if (device == null || device.getSubscribeCycleForCatalog() < 0) { 277 if (device == null || device.getSubscribeCycleForCatalog() < 0) {
286 return false; 278 return false;
287 } 279 }
@@ -291,7 +283,7 @@ public class DeviceServiceImpl implements IDeviceService { @@ -291,7 +283,7 @@ public class DeviceServiceImpl implements IDeviceService {
291 Runnable runnable = dynamicTask.get(taskKey); 283 Runnable runnable = dynamicTask.get(taskKey);
292 if (runnable instanceof ISubscribeTask) { 284 if (runnable instanceof ISubscribeTask) {
293 ISubscribeTask subscribeTask = (ISubscribeTask) runnable; 285 ISubscribeTask subscribeTask = (ISubscribeTask) runnable;
294 - subscribeTask.stop(); 286 + subscribeTask.stop(callback);
295 } 287 }
296 } 288 }
297 dynamicTask.stop(taskKey); 289 dynamicTask.stop(taskKey);
@@ -314,7 +306,7 @@ public class DeviceServiceImpl implements IDeviceService { @@ -314,7 +306,7 @@ public class DeviceServiceImpl implements IDeviceService {
314 } 306 }
315 307
316 @Override 308 @Override
317 - public boolean removeMobilePositionSubscribe(Device device) { 309 + public boolean removeMobilePositionSubscribe(Device device, CommonCallback<Boolean> callback) {
318 if (device == null || device.getSubscribeCycleForCatalog() < 0) { 310 if (device == null || device.getSubscribeCycleForCatalog() < 0) {
319 return false; 311 return false;
320 } 312 }
@@ -324,7 +316,7 @@ public class DeviceServiceImpl implements IDeviceService { @@ -324,7 +316,7 @@ public class DeviceServiceImpl implements IDeviceService {
324 Runnable runnable = dynamicTask.get(taskKey); 316 Runnable runnable = dynamicTask.get(taskKey);
325 if (runnable instanceof ISubscribeTask) { 317 if (runnable instanceof ISubscribeTask) {
326 ISubscribeTask subscribeTask = (ISubscribeTask) runnable; 318 ISubscribeTask subscribeTask = (ISubscribeTask) runnable;
327 - subscribeTask.stop(); 319 + subscribeTask.stop(callback);
328 } 320 }
329 } 321 }
330 dynamicTask.stop(taskKey); 322 dynamicTask.stop(taskKey);
@@ -515,21 +507,6 @@ public class DeviceServiceImpl implements IDeviceService { @@ -515,21 +507,6 @@ public class DeviceServiceImpl implements IDeviceService {
515 logger.warn("更新设备时未找到设备信息"); 507 logger.warn("更新设备时未找到设备信息");
516 return; 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 if (!ObjectUtils.isEmpty(device.getName())) { 511 if (!ObjectUtils.isEmpty(device.getName())) {
535 deviceInStore.setName(device.getName()); 512 deviceInStore.setName(device.getName());
@@ -552,39 +529,54 @@ public class DeviceServiceImpl implements IDeviceService { @@ -552,39 +529,54 @@ public class DeviceServiceImpl implements IDeviceService {
552 if (!ObjectUtils.isEmpty(device.getStreamMode())) { 529 if (!ObjectUtils.isEmpty(device.getStreamMode())) {
553 deviceInStore.setStreamMode(device.getStreamMode()); 530 deviceInStore.setStreamMode(device.getStreamMode());
554 } 531 }
555 -  
556 -  
557 // 目录订阅相关的信息 532 // 目录订阅相关的信息
558 if (deviceInStore.getSubscribeCycleForCatalog() != device.getSubscribeCycleForCatalog()) { 533 if (deviceInStore.getSubscribeCycleForCatalog() != device.getSubscribeCycleForCatalog()) {
559 if (device.getSubscribeCycleForCatalog() > 0) { 534 if (device.getSubscribeCycleForCatalog() > 0) {
560 // 若已开启订阅,但订阅周期不同,则先取消 535 // 若已开启订阅,但订阅周期不同,则先取消
561 if (deviceInStore.getSubscribeCycleForCatalog() != 0) { 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 }else if (device.getSubscribeCycleForCatalog() == 0) { 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 if (deviceInStore.getGeoCoordSys() != null) { 582 if (deviceInStore.getGeoCoordSys() != null) {
@@ -603,10 +595,9 @@ public class DeviceServiceImpl implements IDeviceService { @@ -603,10 +595,9 @@ public class DeviceServiceImpl implements IDeviceService {
603 deviceInStore.setSsrcCheck(device.isSsrcCheck()); 595 deviceInStore.setSsrcCheck(device.isSsrcCheck());
604 //作为消息通道 596 //作为消息通道
605 deviceInStore.setAsMessageChannel(device.isAsMessageChannel()); 597 deviceInStore.setAsMessageChannel(device.isAsMessageChannel());
606 -  
607 - // 更新redis 598 +
608 deviceMapper.updateCustom(deviceInStore); 599 deviceMapper.updateCustom(deviceInStore);
609 - redisCatchStorage.removeDevice(deviceInStore.getDeviceId()); 600 + redisCatchStorage.updateDevice(deviceInStore);
610 } 601 }
611 602
612 @Override 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,6 +20,8 @@ import com.genersoft.iot.vmp.gb28181.session.SSRCFactory;
20 import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; 20 import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
21 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform; 21 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
22 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; 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 import com.genersoft.iot.vmp.gb28181.utils.SipUtils; 25 import com.genersoft.iot.vmp.gb28181.utils.SipUtils;
24 import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils; 26 import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
25 import com.genersoft.iot.vmp.media.zlm.ZLMServerFactory; 27 import com.genersoft.iot.vmp.media.zlm.ZLMServerFactory;
@@ -29,6 +31,10 @@ import com.genersoft.iot.vmp.media.zlm.*; @@ -29,6 +31,10 @@ import com.genersoft.iot.vmp.media.zlm.*;
29 import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeFactory; 31 import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeFactory;
30 import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForStreamChange; 32 import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForStreamChange;
31 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; 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 import com.genersoft.iot.vmp.media.zlm.dto.hook.HookParam; 38 import com.genersoft.iot.vmp.media.zlm.dto.hook.HookParam;
33 import com.genersoft.iot.vmp.media.zlm.dto.hook.OnRecordMp4HookParam; 39 import com.genersoft.iot.vmp.media.zlm.dto.hook.OnRecordMp4HookParam;
34 import com.genersoft.iot.vmp.media.zlm.dto.hook.OnStreamChangedHookParam; 40 import com.genersoft.iot.vmp.media.zlm.dto.hook.OnStreamChangedHookParam;
@@ -39,9 +45,12 @@ import com.genersoft.iot.vmp.service.bean.InviteErrorCode; @@ -39,9 +45,12 @@ import com.genersoft.iot.vmp.service.bean.InviteErrorCode;
39 import com.genersoft.iot.vmp.service.bean.RequestPushStreamMsg; 45 import com.genersoft.iot.vmp.service.bean.RequestPushStreamMsg;
40 import com.genersoft.iot.vmp.service.bean.SSRCInfo; 46 import com.genersoft.iot.vmp.service.bean.SSRCInfo;
41 import com.genersoft.iot.vmp.service.redisMsg.RedisGbPlayMsgListener; 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 import com.genersoft.iot.vmp.storager.IRedisCatchStorage; 52 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
43 import com.genersoft.iot.vmp.storager.IVideoManagerStorage; 53 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
44 -import com.genersoft.iot.vmp.storager.dao.CloudRecordServiceMapper;  
45 import com.genersoft.iot.vmp.utils.CloudRecordUtils; 54 import com.genersoft.iot.vmp.utils.CloudRecordUtils;
46 import com.genersoft.iot.vmp.utils.DateUtil; 55 import com.genersoft.iot.vmp.utils.DateUtil;
47 import com.genersoft.iot.vmp.vmanager.bean.AudioBroadcastResult; 56 import com.genersoft.iot.vmp.vmanager.bean.AudioBroadcastResult;
@@ -80,7 +89,7 @@ public class PlayServiceImpl implements IPlayService { @@ -80,7 +89,7 @@ public class PlayServiceImpl implements IPlayService {
80 private IVideoManagerStorage storager; 89 private IVideoManagerStorage storager;
81 90
82 @Autowired 91 @Autowired
83 - private SIPCommander cmder; 92 + private ISIPCommander cmder;
84 93
85 @Autowired 94 @Autowired
86 private AudioBroadcastManager audioBroadcastManager; 95 private AudioBroadcastManager audioBroadcastManager;
@@ -122,6 +131,9 @@ public class PlayServiceImpl implements IPlayService { @@ -122,6 +131,9 @@ public class PlayServiceImpl implements IPlayService {
122 private UserSetting userSetting; 131 private UserSetting userSetting;
123 132
124 @Autowired 133 @Autowired
  134 + private IDeviceChannelService channelService;
  135 +
  136 + @Autowired
125 private SipConfig sipConfig; 137 private SipConfig sipConfig;
126 138
127 @Autowired 139 @Autowired
@@ -163,6 +175,11 @@ public class PlayServiceImpl implements IPlayService { @@ -163,6 +175,11 @@ public class PlayServiceImpl implements IPlayService {
163 logger.warn("[点播] 单端口收流时不支持TCP主动方式收流 deviceId: {},channelId:{}", deviceId, channelId); 175 logger.warn("[点播] 单端口收流时不支持TCP主动方式收流 deviceId: {},channelId:{}", deviceId, channelId);
164 throw new ControllerException(ErrorCode.ERROR100.getCode(), "单端口收流时不支持TCP主动方式收流"); 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 InviteInfo inviteInfo = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, deviceId, channelId); 183 InviteInfo inviteInfo = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, deviceId, channelId);
167 if (inviteInfo != null ) { 184 if (inviteInfo != null ) {
168 if (inviteInfo.getStreamInfo() == null) { 185 if (inviteInfo.getStreamInfo() == null) {
@@ -211,7 +228,7 @@ public class PlayServiceImpl implements IPlayService { @@ -211,7 +228,7 @@ public class PlayServiceImpl implements IPlayService {
211 null); 228 null);
212 return null; 229 return null;
213 } 230 }
214 - play(mediaServerItem, ssrcInfo, device, channelId, callback); 231 + play(mediaServerItem, ssrcInfo, device, channel, callback);
215 return ssrcInfo; 232 return ssrcInfo;
216 } 233 }
217 234
@@ -358,7 +375,7 @@ public class PlayServiceImpl implements IPlayService { @@ -358,7 +375,7 @@ public class PlayServiceImpl implements IPlayService {
358 375
359 376
360 @Override 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 ErrorCallback<Object> callback) { 379 ErrorCallback<Object> callback) {
363 380
364 if (mediaServerItem == null || ssrcInfo == null) { 381 if (mediaServerItem == null || ssrcInfo == null) {
@@ -367,111 +384,109 @@ public class PlayServiceImpl implements IPlayService { @@ -367,111 +384,109 @@ public class PlayServiceImpl implements IPlayService {
367 null); 384 null);
368 return; 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 device.getStreamMode(), ssrcInfo.getSsrc(), device.isSsrcCheck()); 389 device.getStreamMode(), ssrcInfo.getSsrc(), device.isSsrcCheck());
373 //端口获取失败的ssrcInfo 没有必要发送点播指令 390 //端口获取失败的ssrcInfo 没有必要发送点播指令
374 if (ssrcInfo.getPort() <= 0) { 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 // 释放ssrc 393 // 释放ssrc
377 mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); 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 callback.run(InviteErrorCode.ERROR_FOR_RESOURCE_EXHAUSTION.getCode(), "点播端口分配异常", null); 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 InviteErrorCode.ERROR_FOR_RESOURCE_EXHAUSTION.getCode(), "点播端口分配异常", null); 399 InviteErrorCode.ERROR_FOR_RESOURCE_EXHAUSTION.getCode(), "点播端口分配异常", null);
383 return; 400 return;
384 } 401 }
385 402
386 // 初始化redis中的invite消息状态 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 mediaServerItem.getSdpIp(), ssrcInfo.getPort(), device.getStreamMode(), InviteSessionType.PLAY, 405 mediaServerItem.getSdpIp(), ssrcInfo.getPort(), device.getStreamMode(), InviteSessionType.PLAY,
389 InviteSessionStatus.ready); 406 InviteSessionStatus.ready);
390 - inviteInfo.setSubStream(device.isSwitchPrimarySubStream());  
391 inviteStreamService.updateInviteInfo(inviteInfo); 407 inviteStreamService.updateInviteInfo(inviteInfo);
392 // 超时处理 408 // 超时处理
393 String timeOutTaskKey = UUID.randomUUID().toString(); 409 String timeOutTaskKey = UUID.randomUUID().toString();
394 dynamicTask.startDelay(timeOutTaskKey, () -> { 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 if (inviteInfoForTimeOut == null || inviteInfoForTimeOut.getStreamInfo() == null) { 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 ssrcInfo.getPort(), ssrcInfo.getSsrc()); 416 ssrcInfo.getPort(), ssrcInfo.getSsrc());
401 417
402 callback.run(InviteErrorCode.ERROR_FOR_STREAM_TIMEOUT.getCode(), InviteErrorCode.ERROR_FOR_STREAM_TIMEOUT.getMsg(), null); 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 InviteErrorCode.ERROR_FOR_STREAM_TIMEOUT.getCode(), InviteErrorCode.ERROR_FOR_STREAM_TIMEOUT.getMsg(), null); 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 try { 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 logger.error("[点播超时], 发送BYE失败 {}", e.getMessage()); 426 logger.error("[点播超时], 发送BYE失败 {}", e.getMessage());
412 } finally { 427 } finally {
413 mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); 428 mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc());
414 mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream()); 429 mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream());
415 - streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream()); 430 + streamSession.remove(device.getDeviceId(), channel.getChannelId(), ssrcInfo.getStream());
416 mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream()); 431 mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream());
417 // 取消订阅消息监听 432 // 取消订阅消息监听
418 HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", ssrcInfo.getStream(), true, "rtsp", mediaServerItem.getId()); 433 HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", ssrcInfo.getStream(), true, "rtsp", mediaServerItem.getId());
419 subscribe.removeSubscribe(hookSubscribe); 434 subscribe.removeSubscribe(hookSubscribe);
420 } 435 }
421 }else { 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 ssrcInfo.getPort(), ssrcInfo.getSsrc()); 439 ssrcInfo.getPort(), ssrcInfo.getSsrc());
425 440
426 mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); 441 mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc());
427 442
428 mediaServerService.closeRTPServer(mediaServerItem.getId(), ssrcInfo.getStream()); 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 }, userSetting.getPlayTimeout()); 446 }, userSetting.getPlayTimeout());
432 447
433 try { 448 try {
434 - cmder.playStreamCmd(mediaServerItem, ssrcInfo, device, channelId, (mediaServerItemInuse, hookParam ) -> { 449 + cmder.playStreamCmd(mediaServerItem, ssrcInfo, device, channel, (mediaServerItemInuse, hookParam ) -> {
435 logger.info("收到订阅消息: " + hookParam); 450 logger.info("收到订阅消息: " + hookParam);
436 dynamicTask.stop(timeOutTaskKey); 451 dynamicTask.stop(timeOutTaskKey);
437 // hook响应 452 // hook响应
438 - StreamInfo streamInfo = onPublishHandlerForPlay(mediaServerItemInuse, hookParam, device.getDeviceId(), channelId); 453 + StreamInfo streamInfo = onPublishHandlerForPlay(mediaServerItemInuse, hookParam, device.getDeviceId(), channel.getChannelId());
439 if (streamInfo == null){ 454 if (streamInfo == null){
440 callback.run(InviteErrorCode.ERROR_FOR_STREAM_PARSING_EXCEPTIONS.getCode(), 455 callback.run(InviteErrorCode.ERROR_FOR_STREAM_PARSING_EXCEPTIONS.getCode(),
441 InviteErrorCode.ERROR_FOR_STREAM_PARSING_EXCEPTIONS.getMsg(), null); 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 InviteErrorCode.ERROR_FOR_STREAM_PARSING_EXCEPTIONS.getCode(), 458 InviteErrorCode.ERROR_FOR_STREAM_PARSING_EXCEPTIONS.getCode(),
444 InviteErrorCode.ERROR_FOR_STREAM_PARSING_EXCEPTIONS.getMsg(), null); 459 InviteErrorCode.ERROR_FOR_STREAM_PARSING_EXCEPTIONS.getMsg(), null);
445 return; 460 return;
446 } 461 }
447 callback.run(InviteErrorCode.SUCCESS.getCode(), InviteErrorCode.SUCCESS.getMsg(), streamInfo); 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 InviteErrorCode.SUCCESS.getCode(), 464 InviteErrorCode.SUCCESS.getCode(),
450 InviteErrorCode.SUCCESS.getMsg(), 465 InviteErrorCode.SUCCESS.getMsg(),
451 streamInfo); 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 }, (eventResult) -> { 470 }, (eventResult) -> {
456 // 处理收到200ok后的TCP主动连接以及SSRC不一致的问题 471 // 处理收到200ok后的TCP主动连接以及SSRC不一致的问题
457 - InviteOKHandler(eventResult, ssrcInfo, mediaServerItem, device, channelId, 472 + InviteOKHandler(eventResult, ssrcInfo, mediaServerItem, device, channel.getChannelId(),
458 timeOutTaskKey, callback, inviteInfo, InviteSessionType.PLAY); 473 timeOutTaskKey, callback, inviteInfo, InviteSessionType.PLAY);
459 }, (event) -> { 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 dynamicTask.stop(timeOutTaskKey); 476 dynamicTask.stop(timeOutTaskKey);
462 mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream()); 477 mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream());
463 // 释放ssrc 478 // 释放ssrc
464 mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); 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 callback.run(InviteErrorCode.ERROR_FOR_SIGNALLING_ERROR.getCode(), 483 callback.run(InviteErrorCode.ERROR_FOR_SIGNALLING_ERROR.getCode(),
469 String.format("点播失败, 错误码: %s, %s", event.statusCode, event.msg), null); 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 InviteErrorCode.ERROR_FOR_RESET_SSRC.getCode(), 486 InviteErrorCode.ERROR_FOR_RESET_SSRC.getCode(),
472 String.format("点播失败, 错误码: %s, %s", event.statusCode, event.msg), null); 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 } catch (InvalidArgumentException | SipException | ParseException e) { 491 } catch (InvalidArgumentException | SipException | ParseException e) {
477 492
@@ -481,15 +496,15 @@ public class PlayServiceImpl implements IPlayService { @@ -481,15 +496,15 @@ public class PlayServiceImpl implements IPlayService {
481 // 释放ssrc 496 // 释放ssrc
482 mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); 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 callback.run(InviteErrorCode.ERROR_FOR_SIP_SENDING_FAILED.getCode(), 501 callback.run(InviteErrorCode.ERROR_FOR_SIP_SENDING_FAILED.getCode(),
487 InviteErrorCode.ERROR_FOR_SIP_SENDING_FAILED.getMsg(), null); 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 InviteErrorCode.ERROR_FOR_SIP_SENDING_FAILED.getCode(), 504 InviteErrorCode.ERROR_FOR_SIP_SENDING_FAILED.getCode(),
490 InviteErrorCode.ERROR_FOR_SIP_SENDING_FAILED.getMsg(), null); 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,7 +641,7 @@ public class PlayServiceImpl implements IPlayService {
626 641
627 @Override 642 @Override
628 public void playBack(String deviceId, String channelId, String startTime, 643 public void playBack(String deviceId, String channelId, String startTime,
629 - String endTime, ErrorCallback<Object> callback) { 644 + String endTime, ErrorCallback<Object> callback) {
630 Device device = storager.queryVideoDevice(deviceId); 645 Device device = storager.queryVideoDevice(deviceId);
631 if (device == null) { 646 if (device == null) {
632 logger.warn("[录像回放] 未找到设备 deviceId: {},channelId:{}", deviceId, channelId); 647 logger.warn("[录像回放] 未找到设备 deviceId: {},channelId:{}", deviceId, channelId);
@@ -651,8 +666,8 @@ public class PlayServiceImpl implements IPlayService { @@ -651,8 +666,8 @@ public class PlayServiceImpl implements IPlayService {
651 666
652 @Override 667 @Override
653 public void playBack(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, 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 if (mediaServerItem == null || ssrcInfo == null) { 671 if (mediaServerItem == null || ssrcInfo == null) {
657 callback.run(InviteErrorCode.ERROR_FOR_PARAMETER_ERROR.getCode(), 672 callback.run(InviteErrorCode.ERROR_FOR_PARAMETER_ERROR.getCode(),
658 InviteErrorCode.ERROR_FOR_PARAMETER_ERROR.getMsg(), 673 InviteErrorCode.ERROR_FOR_PARAMETER_ERROR.getMsg(),
@@ -1548,16 +1563,16 @@ public class PlayServiceImpl implements IPlayService { @@ -1548,16 +1563,16 @@ public class PlayServiceImpl implements IPlayService {
1548 1563
1549 MediaServerItem newMediaServerItem = getNewMediaServerItem(device); 1564 MediaServerItem newMediaServerItem = getNewMediaServerItem(device);
1550 play(newMediaServerItem, deviceId, channelId, null, (code, msg, data)->{ 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,11 +20,11 @@ public interface DeviceChannelMapper {
20 @Insert("INSERT INTO wvp_device_channel (channel_id, device_id, name, manufacture, model, owner, civil_code, block, " + 20 @Insert("INSERT INTO wvp_device_channel (channel_id, device_id, name, manufacture, model, owner, civil_code, block, " +
21 "address, parental, parent_id, safety_way, register_way, cert_num, certifiable, err_code, secrecy, " + 21 "address, parental, parent_id, safety_way, register_way, cert_num, certifiable, err_code, secrecy, " +
22 "ip_address, port, password, ptz_type, status, stream_id, longitude, latitude, longitude_gcj02, latitude_gcj02, " + 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 "VALUES (#{channelId}, #{deviceId}, #{name}, #{manufacture}, #{model}, #{owner}, #{civilCode}, #{block}," + 24 "VALUES (#{channelId}, #{deviceId}, #{name}, #{manufacture}, #{model}, #{owner}, #{civilCode}, #{block}," +
25 "#{address}, #{parental}, #{parentId}, #{safetyWay}, #{registerWay}, #{certNum}, #{certifiable}, #{errCode}, #{secrecy}, " + 25 "#{address}, #{parental}, #{parentId}, #{safetyWay}, #{registerWay}, #{certNum}, #{certifiable}, #{errCode}, #{secrecy}, " +
26 "#{ipAddress}, #{port}, #{password}, #{PTZType}, #{status}, #{streamId}, #{longitude}, #{latitude}, #{longitudeGcj02}, " + 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 int add(DeviceChannel channel); 28 int add(DeviceChannel channel);
29 29
30 @Update(value = {" <script>" + 30 @Update(value = {" <script>" +
@@ -60,6 +60,7 @@ public interface DeviceChannelMapper { @@ -60,6 +60,7 @@ public interface DeviceChannelMapper {
60 "<if test='latitudeWgs84 != null'>, latitude_wgs84=#{latitudeWgs84}</if>" + 60 "<if test='latitudeWgs84 != null'>, latitude_wgs84=#{latitudeWgs84}</if>" +
61 "<if test='businessGroupId != null'>, business_group_id=#{businessGroupId}</if>" + 61 "<if test='businessGroupId != null'>, business_group_id=#{businessGroupId}</if>" +
62 "<if test='gpsTime != null'>, gps_time=#{gpsTime}</if>" + 62 "<if test='gpsTime != null'>, gps_time=#{gpsTime}</if>" +
  63 + "<if test='streamIdentification != null'>, stream_identification=#{streamIdentification}</if>" +
63 "WHERE device_id=#{deviceId} AND channel_id=#{channelId}"+ 64 "WHERE device_id=#{deviceId} AND channel_id=#{channelId}"+
64 " </script>"}) 65 " </script>"})
65 int update(DeviceChannel channel); 66 int update(DeviceChannel channel);
@@ -102,6 +103,7 @@ public interface DeviceChannelMapper { @@ -102,6 +103,7 @@ public interface DeviceChannelMapper {
102 "dc.longitude_wgs84, " + 103 "dc.longitude_wgs84, " +
103 "dc.latitude_wgs84, " + 104 "dc.latitude_wgs84, " +
104 "dc.business_group_id, " + 105 "dc.business_group_id, " +
  106 + "dc.stream_identification, " +
105 "dc.gps_time " + 107 "dc.gps_time " +
106 "from " + 108 "from " +
107 "wvp_device_channel dc " + 109 "wvp_device_channel dc " +
@@ -241,7 +243,7 @@ public interface DeviceChannelMapper { @@ -241,7 +243,7 @@ public interface DeviceChannelMapper {
241 "(channel_id, device_id, name, manufacture, model, owner, civil_code, block, sub_count, " + 243 "(channel_id, device_id, name, manufacture, model, owner, civil_code, block, sub_count, " +
242 " address, parental, parent_id, safety_way, register_way, cert_num, certifiable, err_code, secrecy, " + 244 " address, parental, parent_id, safety_way, register_way, cert_num, certifiable, err_code, secrecy, " +
243 " ip_address,port,password,ptz_type,status,stream_id,longitude,latitude,longitude_gcj02,latitude_gcj02,"+ 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 "values " + 247 "values " +
246 "<foreach collection='addChannels' index='index' item='item' separator=','> " + 248 "<foreach collection='addChannels' index='index' item='item' separator=','> " +
247 "(#{item.channelId}, #{item.deviceId}, #{item.name}, #{item.manufacture}, #{item.model}, " + 249 "(#{item.channelId}, #{item.deviceId}, #{item.name}, #{item.manufacture}, #{item.model}, " +
@@ -251,7 +253,7 @@ public interface DeviceChannelMapper { @@ -251,7 +253,7 @@ public interface DeviceChannelMapper {
251 "#{item.ipAddress}, #{item.port}, #{item.password}, #{item.PTZType}, #{item.status}, " + 253 "#{item.ipAddress}, #{item.port}, #{item.password}, #{item.PTZType}, #{item.status}, " +
252 "#{item.streamId}, #{item.longitude}, #{item.latitude},#{item.longitudeGcj02}, " + 254 "#{item.streamId}, #{item.longitude}, #{item.latitude},#{item.longitudeGcj02}, " +
253 "#{item.latitudeGcj02},#{item.longitudeWgs84}, #{item.latitudeWgs84}, #{item.hasAudio}, now(), now(), " + 255 "#{item.latitudeGcj02},#{item.longitudeWgs84}, #{item.latitudeWgs84}, #{item.hasAudio}, now(), now(), " +
254 - "#{item.businessGroupId}, #{item.gpsTime}) " + 256 + "#{item.businessGroupId}, #{item.gpsTime}, #{item.streamIdentification}) " +
255 "</foreach> " + 257 "</foreach> " +
256 "</script>") 258 "</script>")
257 int batchAdd(@Param("addChannels") List<DeviceChannel> addChannels); 259 int batchAdd(@Param("addChannels") List<DeviceChannel> addChannels);
@@ -349,6 +351,7 @@ public interface DeviceChannelMapper { @@ -349,6 +351,7 @@ public interface DeviceChannelMapper {
349 "<if test='item.latitudeWgs84 != null'>, latitude_wgs84=#{item.latitudeWgs84}</if>" + 351 "<if test='item.latitudeWgs84 != null'>, latitude_wgs84=#{item.latitudeWgs84}</if>" +
350 "<if test='item.businessGroupId != null'>, business_group_id=#{item.businessGroupId}</if>" + 352 "<if test='item.businessGroupId != null'>, business_group_id=#{item.businessGroupId}</if>" +
351 "<if test='item.gpsTime != null'>, gps_time=#{item.gpsTime}</if>" + 353 "<if test='item.gpsTime != null'>, gps_time=#{item.gpsTime}</if>" +
  354 + "<if test='item.streamIdentification != null'>, stream_identification=#{item.streamIdentification}</if>" +
352 "<if test='item.id > 0'>WHERE id=#{item.id}</if>" + 355 "<if test='item.id > 0'>WHERE id=#{item.id}</if>" +
353 "<if test='item.id == 0'>WHERE device_id=#{item.deviceId} AND channel_id=#{item.channelId}</if>" + 356 "<if test='item.id == 0'>WHERE device_id=#{item.deviceId} AND channel_id=#{item.channelId}</if>" +
354 "</foreach>" + 357 "</foreach>" +
@@ -542,4 +545,9 @@ public interface DeviceChannelMapper { @@ -542,4 +545,9 @@ public interface DeviceChannelMapper {
542 " </script>"}) 545 " </script>"})
543 List<DeviceChannel> getSubChannelsByDeviceId(@Param("deviceId") String deviceId, @Param("parentId") String parentId, @Param("onlyCatalog") boolean onlyCatalog); 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,7 +43,6 @@ public interface DeviceMapper {
43 "geo_coord_sys," + 43 "geo_coord_sys," +
44 "on_line," + 44 "on_line," +
45 "media_server_id," + 45 "media_server_id," +
46 - "switch_primary_sub_stream," +  
47 "broadcast_push_after_ack," + 46 "broadcast_push_after_ack," +
48 "(SELECT count(0) FROM wvp_device_channel WHERE device_id=wvp_device.device_id) as channel_count "+ 47 "(SELECT count(0) FROM wvp_device_channel WHERE device_id=wvp_device.device_id) as channel_count "+
49 " FROM wvp_device WHERE device_id = #{deviceId}") 48 " FROM wvp_device WHERE device_id = #{deviceId}")
@@ -163,7 +162,6 @@ public interface DeviceMapper { @@ -163,7 +162,6 @@ public interface DeviceMapper {
163 "geo_coord_sys,"+ 162 "geo_coord_sys,"+
164 "on_line,"+ 163 "on_line,"+
165 "media_server_id,"+ 164 "media_server_id,"+
166 - "switch_primary_sub_stream switchPrimarySubStream,"+  
167 "(SELECT count(0) FROM wvp_device_channel WHERE device_id=de.device_id) as channel_count " + 165 "(SELECT count(0) FROM wvp_device_channel WHERE device_id=de.device_id) as channel_count " +
168 "FROM wvp_device de" + 166 "FROM wvp_device de" +
169 "<if test=\"onLine != null\"> where on_line=${onLine}</if>"+ 167 "<if test=\"onLine != null\"> where on_line=${onLine}</if>"+
@@ -256,7 +254,6 @@ public interface DeviceMapper { @@ -256,7 +254,6 @@ public interface DeviceMapper {
256 "<if test=\"asMessageChannel != null\">, as_message_channel=#{asMessageChannel}</if>" + 254 "<if test=\"asMessageChannel != null\">, as_message_channel=#{asMessageChannel}</if>" +
257 "<if test=\"broadcastPushAfterAck != null\">, broadcast_push_after_ack=#{broadcastPushAfterAck}</if>" + 255 "<if test=\"broadcastPushAfterAck != null\">, broadcast_push_after_ack=#{broadcastPushAfterAck}</if>" +
258 "<if test=\"geoCoordSys != null\">, geo_coord_sys=#{geoCoordSys}</if>" + 256 "<if test=\"geoCoordSys != null\">, geo_coord_sys=#{geoCoordSys}</if>" +
259 - "<if test=\"switchPrimarySubStream != null\">, switch_primary_sub_stream=#{switchPrimarySubStream}</if>" +  
260 "<if test=\"mediaServerId != null\">, media_server_id=#{mediaServerId}</if>" + 257 "<if test=\"mediaServerId != null\">, media_server_id=#{mediaServerId}</if>" +
261 "WHERE device_id=#{deviceId}"+ 258 "WHERE device_id=#{deviceId}"+
262 " </script>"}) 259 " </script>"})
@@ -275,8 +272,7 @@ public interface DeviceMapper { @@ -275,8 +272,7 @@ public interface DeviceMapper {
275 "broadcastPushAfterAck,"+ 272 "broadcastPushAfterAck,"+
276 "geo_coord_sys,"+ 273 "geo_coord_sys,"+
277 "on_line,"+ 274 "on_line,"+
278 - "media_server_id,"+  
279 - "switch_primary_sub_stream"+ 275 + "media_server_id"+
280 ") VALUES (" + 276 ") VALUES (" +
281 "#{deviceId}," + 277 "#{deviceId}," +
282 "#{name}," + 278 "#{name}," +
@@ -290,8 +286,7 @@ public interface DeviceMapper { @@ -290,8 +286,7 @@ public interface DeviceMapper {
290 "#{broadcastPushAfterAck}," + 286 "#{broadcastPushAfterAck}," +
291 "#{geoCoordSys}," + 287 "#{geoCoordSys}," +
292 "#{onLine}," + 288 "#{onLine}," +
293 - "#{mediaServerId}," +  
294 - "#{switchPrimarySubStream}" + 289 + "#{mediaServerId}" +
295 ")") 290 ")")
296 void addCustomDevice(Device device); 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,10 +153,7 @@ public class MobilePositionController {
153 Device device = storager.queryVideoDevice(deviceId); 153 Device device = storager.queryVideoDevice(deviceId);
154 device.setSubscribeCycleForMobilePosition(Integer.parseInt(expires)); 154 device.setSubscribeCycleForMobilePosition(Integer.parseInt(expires));
155 device.setMobilePositionSubmissionInterval(Integer.parseInt(interval)); 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,7 +199,7 @@ public class DeviceQuery {
199 Runnable runnable = dynamicTask.get(key); 199 Runnable runnable = dynamicTask.get(key);
200 if (runnable instanceof ISubscribeTask) { 200 if (runnable instanceof ISubscribeTask) {
201 ISubscribeTask subscribeTask = (ISubscribeTask) runnable; 201 ISubscribeTask subscribeTask = (ISubscribeTask) runnable;
202 - subscribeTask.stop(); 202 + subscribeTask.stop(null);
203 } 203 }
204 dynamicTask.stop(key); 204 dynamicTask.stop(key);
205 } 205 }
@@ -264,6 +264,14 @@ public class DeviceQuery { @@ -264,6 +264,14 @@ public class DeviceQuery {
264 deviceChannelService.updateChannel(deviceId, channel); 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 * @param deviceId 设备id 277 * @param deviceId 设备id
web_src/src/components/channelList.vue
@@ -13,24 +13,30 @@ @@ -13,24 +13,30 @@
13 prefix-icon="el-icon-search" v-model="searchSrt" clearable></el-input> 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 default-first-option> 17 default-first-option>
18 <el-option label="全部" value=""></el-option> 18 <el-option label="全部" value=""></el-option>
19 <el-option label="设备" value="false"></el-option> 19 <el-option label="设备" value="false"></el-option>
20 <el-option label="子目录" value="true"></el-option> 20 <el-option label="子目录" value="true"></el-option>
21 </el-select> 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 default-first-option> 24 default-first-option>
25 <el-option label="全部" value=""></el-option> 25 <el-option label="全部" value=""></el-option>
26 <el-option label="在线" value="true"></el-option> 26 <el-option label="在线" value="true"></el-option>
27 <el-option label="离线" value="false"></el-option> 27 <el-option label="离线" value="false"></el-option>
28 </el-select> 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 </el-select> 40 </el-select>
35 </div> 41 </div>
36 <el-button icon="el-icon-refresh-right" circle size="mini" @click="refresh()"></el-button> 42 <el-button icon="el-icon-refresh-right" circle size="mini" @click="refresh()"></el-button>
@@ -46,11 +52,11 @@ @@ -46,11 +52,11 @@
46 <el-main style="padding: 5px;"> 52 <el-main style="padding: 5px;">
47 <el-table ref="channelListTable" :data="deviceChannelList" :height="winHeight" style="width: 100%" 53 <el-table ref="channelListTable" :data="deviceChannelList" :height="winHeight" style="width: 100%"
48 header-row-class-name="table-header"> 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 </el-table-column> 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 </el-table-column> 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 <template v-slot:default="scope"> 60 <template v-slot:default="scope">
55 <el-input 61 <el-input
56 v-show="scope.row.edit" 62 v-show="scope.row.edit"
@@ -63,7 +69,7 @@ @@ -63,7 +69,7 @@
63 <span v-show="!scope.row.edit">{{ scope.row.name }}</span> 69 <span v-show="!scope.row.edit">{{ scope.row.name }}</span>
64 </template> 70 </template>
65 </el-table-column> 71 </el-table-column>
66 - <el-table-column label="快照" min-width="120"> 72 + <el-table-column label="快照" min-width="100">
67 <template v-slot:default="scope"> 73 <template v-slot:default="scope">
68 <el-image 74 <el-image
69 :src="getSnap(scope.row)" 75 :src="getSnap(scope.row)"
@@ -77,11 +83,11 @@ @@ -77,11 +83,11 @@
77 </el-image> 83 </el-image>
78 </template> 84 </template>
79 </el-table-column> 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 </el-table-column> 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 </el-table-column> 89 </el-table-column>
84 - <el-table-column label="位置信息" min-width="200"> 90 + <el-table-column label="位置信息" min-width="120">
85 <template v-slot:default="scope"> 91 <template v-slot:default="scope">
86 <el-input 92 <el-input
87 v-show="scope.row.edit" 93 v-show="scope.row.edit"
@@ -94,7 +100,7 @@ @@ -94,7 +100,7 @@
94 <span v-show="!scope.row.edit">{{ scope.row.location }}</span> 100 <span v-show="!scope.row.edit">{{ scope.row.location }}</span>
95 </template> 101 </template>
96 </el-table-column> 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 <template v-slot:default="scope"> 104 <template v-slot:default="scope">
99 <el-select v-show="scope.row.edit" v-model="scope.row.PTZType" 105 <el-select v-show="scope.row.edit" v-model="scope.row.PTZType"
100 placeholder="云台类型" filterable> 106 placeholder="云台类型" filterable>
@@ -108,13 +114,28 @@ @@ -108,13 +114,28 @@
108 <div v-show="!scope.row.edit">{{ scope.row.PTZTypeText }}</div> 114 <div v-show="!scope.row.edit">{{ scope.row.PTZTypeText }}</div>
109 </template> 115 </template>
110 </el-table-column> 116 </el-table-column>
111 - <el-table-column label="开启音频" min-width="120"> 117 + <el-table-column label="开启音频" min-width="100">
112 <template slot-scope="scope"> 118 <template slot-scope="scope">
113 <el-switch @change="updateChannel(scope.row)" v-model="scope.row.hasAudio" active-color="#409EFF"> 119 <el-switch @change="updateChannel(scope.row)" v-model="scope.row.hasAudio" active-color="#409EFF">
114 </el-switch> 120 </el-switch>
115 </template> 121 </template>
116 </el-table-column> 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 <template slot-scope="scope"> 139 <template slot-scope="scope">
119 <div slot="reference" class="name-wrapper"> 140 <div slot="reference" class="name-wrapper">
120 <el-tag size="medium" v-if="scope.row.status === true">在线</el-tag> 141 <el-tag size="medium" v-if="scope.row.status === true">在线</el-tag>
@@ -122,8 +143,6 @@ @@ -122,8 +143,6 @@
122 </div> 143 </div>
123 </template> 144 </template>
124 </el-table-column> 145 </el-table-column>
125 -  
126 -  
127 <el-table-column label="操作" min-width="340" fixed="right"> 146 <el-table-column label="操作" min-width="340" fixed="right">
128 <template slot-scope="scope"> 147 <template slot-scope="scope">
129 <el-button size="medium" v-bind:disabled="device == null || device.online === 0" icon="el-icon-video-play" 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,7 +232,7 @@ export default {
213 searchSrt: "", 232 searchSrt: "",
214 channelType: "", 233 channelType: "",
215 online: "", 234 online: "",
216 - isSubStream: false, 235 + subStream: "",
217 winHeight: window.innerHeight - 200, 236 winHeight: window.innerHeight - 200,
218 currentPage: 1, 237 currentPage: 1,
219 count: 15, 238 count: 15,
@@ -495,6 +514,43 @@ export default { @@ -495,6 +514,43 @@ export default {
495 console.log(JSON.stringify(res)); 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 refresh: function () { 554 refresh: function () {
499 this.initData(); 555 this.initData();
500 }, 556 },
web_src/src/components/dialog/deviceEdit.vue
@@ -61,12 +61,6 @@ @@ -61,12 +61,6 @@
61 <el-form-item v-if="form.subscribeCycleForMobilePosition > 0" label="移动位置报送间隔" prop="subscribeCycleForCatalog" > 61 <el-form-item v-if="form.subscribeCycleForMobilePosition > 0" label="移动位置报送间隔" prop="subscribeCycleForCatalog" >
62 <el-input v-model="form.mobilePositionSubmissionInterval" clearable ></el-input> 62 <el-input v-model="form.mobilePositionSubmissionInterval" clearable ></el-input>
63 </el-form-item> 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 <el-form-item label="其他选项"> 64 <el-form-item label="其他选项">
71 <el-checkbox label="SSRC校验" v-model="form.ssrcCheck" style="float: left"></el-checkbox> 65 <el-checkbox label="SSRC校验" v-model="form.ssrcCheck" style="float: left"></el-checkbox>
72 <el-checkbox label="作为消息通道" v-model="form.asMessageChannel" style="float: left"></el-checkbox> 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 \ No newline at end of file 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 \ No newline at end of file 6 \ No newline at end of file