Commit 12fa3b4c8da2af13a710400d64c9fe6d5d6b1e5e

Authored by 648540858
2 parents 6b03568c 278264a2

Merge branch 'wvp-28181-2.0'

# Conflicts:
#	src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/PlayController.java
Showing 35 changed files with 404 additions and 263 deletions
doc/README.md
... ... @@ -21,22 +21,22 @@
21 21 - [X] 实时视音频点播
22 22 - [X] 设备控制
23 23 - [X] 云台控制
24   - - [ ] 远程启动
25   - - [ ] 录像控制
26   - - [ ] 报警布防/撤防
27   - - [ ] 报警复位
  24 + - [X] 远程启动
  25 + - [X] 录像控制
  26 + - [X] 报警布防/撤防
  27 + - [X] 报警复位
28 28 - [X] 强制关键帧
29   - - [ ] 拉框放大
30   - - [ ] 拉框缩小
31   - - [ ] 看守位控制
32   - - [ ] 设备配置
  29 + - [X] 拉框放大
  30 + - [X] 拉框缩小
  31 + - [X] 看守位控制
  32 + - [X] 设备配置
33 33 - [X] 报警事件通知和分发
34 34 - [X] 设备目录订阅
35 35 - [X] 网络设备信息查询
36 36 - [X] 设备目录查询
37 37 - [X] 设备状态查询
38   - - [ ] 设备配置查询
39   - - [ ] 设备预置位查询
  38 + - [X] 设备配置查询
  39 + - [X] 设备预置位查询
40 40 - [X] 状态信息报送
41 41 - [X] 设备视音频文件检索
42 42 - [X] 历史视音频的回放
... ...
sql/mysql.sql
... ... @@ -446,7 +446,7 @@ CREATE TABLE `stream_proxy` (
446 446 `ffmpeg_cmd_key` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
447 447 `rtp_type` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
448 448 `mediaServerId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
449   - `enable_hls` bit(1) DEFAULT NULL,
  449 + `enable_audio` bit(1) DEFAULT NULL,
450 450 `enable_mp4` bit(1) DEFAULT NULL,
451 451 `enable` bit(1) NOT NULL,
452 452 `status` bit(1) NOT NULL,
... ...
sql/update.sql
... ... @@ -36,3 +36,8 @@ alter table device
36 36  
37 37 alter table device
38 38 modify hostAddress varchar(50) null;
  39 +
  40 +alter table stream_proxy
  41 + change enable_hls enable_audio bit null;
  42 +
  43 +
... ...
src/main/java/com/genersoft/iot/vmp/conf/GlobalExceptionHandler.java
1 1 package com.genersoft.iot.vmp.conf;
2 2  
3 3 import com.genersoft.iot.vmp.conf.exception.ControllerException;
4   -import com.genersoft.iot.vmp.gb28181.event.alarm.AlarmEventListener;
5 4 import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
6 5 import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
7 6 import org.slf4j.Logger;
8 7 import org.slf4j.LoggerFactory;
9 8 import org.springframework.http.HttpStatus;
  9 +import org.springframework.http.ResponseEntity;
10 10 import org.springframework.security.authentication.BadCredentialsException;
11 11 import org.springframework.web.bind.annotation.ExceptionHandler;
12 12 import org.springframework.web.bind.annotation.ResponseStatus;
... ... @@ -40,8 +40,8 @@ public class GlobalExceptionHandler {
40 40 */
41 41 @ExceptionHandler(ControllerException.class)
42 42 @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
43   - public WVPResult<String> exceptionHandler(ControllerException e) {
44   - return WVPResult.fail(e.getCode(), e.getMsg());
  43 + public ResponseEntity<WVPResult<String>> exceptionHandler(ControllerException e) {
  44 + return new ResponseEntity<>(WVPResult.fail(e.getCode(), e.getMsg()), HttpStatus.OK);
45 45 }
46 46  
47 47 /**
... ... @@ -51,7 +51,7 @@ public class GlobalExceptionHandler {
51 51 */
52 52 @ExceptionHandler(BadCredentialsException.class)
53 53 @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
54   - public WVPResult<String> exceptionHandler(BadCredentialsException e) {
55   - return WVPResult.fail(ErrorCode.ERROR100.getCode(), e.getMessage());
  54 + public ResponseEntity<WVPResult<String>> exceptionHandler(BadCredentialsException e) {
  55 + return new ResponseEntity<>(WVPResult.fail(ErrorCode.ERROR100.getCode(), e.getMessage()), HttpStatus.OK);
56 56 }
57 57 }
... ...
src/main/java/com/genersoft/iot/vmp/conf/UserSetting.java
... ... @@ -41,6 +41,8 @@ public class UserSetting {
41 41  
42 42 private Boolean gbSendStreamStrict = Boolean.FALSE;
43 43  
  44 + private Boolean syncChannelOnDeviceOnline = Boolean.FALSE;
  45 +
44 46 private String serverId = "000000";
45 47  
46 48 private String thirdPartyGBIdReg = "[\\s\\S]*";
... ... @@ -186,4 +188,12 @@ public class UserSetting {
186 188 public void setGbSendStreamStrict(Boolean gbSendStreamStrict) {
187 189 this.gbSendStreamStrict = gbSendStreamStrict;
188 190 }
  191 +
  192 + public Boolean getSyncChannelOnDeviceOnline() {
  193 + return syncChannelOnDeviceOnline;
  194 + }
  195 +
  196 + public void setSyncChannelOnDeviceOnline(Boolean syncChannelOnDeviceOnline) {
  197 + this.syncChannelOnDeviceOnline = syncChannelOnDeviceOnline;
  198 + }
189 199 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java
... ... @@ -2,7 +2,9 @@ package com.genersoft.iot.vmp.gb28181.transmit.cmd;
2 2  
3 3 import com.genersoft.iot.vmp.common.StreamInfo;
4 4 import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException;
5   -import com.genersoft.iot.vmp.gb28181.bean.*;
  5 +import com.genersoft.iot.vmp.gb28181.bean.Device;
  6 +import com.genersoft.iot.vmp.gb28181.bean.DeviceAlarm;
  7 +import com.genersoft.iot.vmp.gb28181.bean.InviteStreamCallback;
6 8 import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
7 9 import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe;
8 10 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
... ... @@ -10,10 +12,7 @@ import com.genersoft.iot.vmp.service.bean.SSRCInfo;
10 12 import gov.nist.javax.sip.message.SIPRequest;
11 13  
12 14 import javax.sip.InvalidArgumentException;
13   -import javax.sip.PeerUnavailableException;
14 15 import javax.sip.SipException;
15   -import javax.sip.message.Message;
16   -import javax.sip.message.Request;
17 16 import java.text.ParseException;
18 17 import javax.sip.message.Message;
19 18 import javax.sip.message.Request;
... ... @@ -234,7 +233,7 @@ public interface ISIPCommander {
234 233 */
235 234 void deviceConfigCmd(Device device);
236 235  
237   - /**
  236 + /**
238 237 * 设备配置命令:basicParam
239 238 *
240 239 * @param device 视频设备
... ... @@ -245,7 +244,7 @@ public interface ISIPCommander {
245 244 * @param heartBeatCount 心跳超时次数(可选)
246 245 */
247 246 void deviceBasicConfigCmd(Device device, String channelId, String name, String expiration, String heartBeatInterval, String heartBeatCount, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
248   -
  247 +
249 248 /**
250 249 * 查询设备状态
251 250 *
... ...
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java
... ... @@ -646,6 +646,7 @@ public class ZLMHttpHookListener {
646 646 // 修改数据
647 647 streamProxyService.stop(param.getApp(), param.getStream());
648 648 }else {
  649 + // 无人观看不做处理
649 650 ret.put("close", false);
650 651 }
651 652 return ret;
... ...
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRESTfulUtils.java
... ... @@ -239,14 +239,13 @@ public class ZLMRESTfulUtils {
239 239 }
240 240  
241 241 public JSONObject addFFmpegSource(MediaServerItem mediaServerItem, String src_url, String dst_url, String timeout_ms,
242   - boolean enable_hls, boolean enable_mp4, String ffmpeg_cmd_key){
  242 + boolean enable_audio, boolean enable_mp4, String ffmpeg_cmd_key){
243 243 logger.info(src_url);
244 244 logger.info(dst_url);
245 245 Map<String, Object> param = new HashMap<>();
246 246 param.put("src_url", src_url);
247 247 param.put("dst_url", dst_url);
248 248 param.put("timeout_ms", timeout_ms);
249   - param.put("enable_hls", enable_hls);
250 249 param.put("enable_mp4", enable_mp4);
251 250 param.put("ffmpeg_cmd_key", ffmpeg_cmd_key);
252 251 return sendPost(mediaServerItem, "addFFmpegSource",param, null);
... ... @@ -294,19 +293,14 @@ public class ZLMRESTfulUtils {
294 293 return sendPost(mediaServerItem, "restartServer",null, null);
295 294 }
296 295  
297   - public JSONObject addStreamProxy(MediaServerItem mediaServerItem, String app, String stream, String url, boolean enable_hls, boolean enable_mp4, String rtp_type) {
  296 + public JSONObject addStreamProxy(MediaServerItem mediaServerItem, String app, String stream, String url, boolean enable_audio, boolean enable_mp4, String rtp_type) {
298 297 Map<String, Object> param = new HashMap<>();
299 298 param.put("vhost", "__defaultVhost__");
300 299 param.put("app", app);
301 300 param.put("stream", stream);
302 301 param.put("url", url);
303   - param.put("enable_hls", enable_hls?1:0);
304 302 param.put("enable_mp4", enable_mp4?1:0);
305   - param.put("enable_rtmp", 1);
306   - param.put("enable_fmp4", 1);
307   - param.put("enable_audio", 1);
308   - param.put("enable_rtsp", 1);
309   - param.put("add_mute_audio", 1);
  303 + param.put("enable_audio", enable_audio?1:0);
310 304 param.put("rtp_type", rtp_type);
311 305 return sendPost(mediaServerItem, "addStreamProxy",param, null);
312 306 }
... ...
src/main/java/com/genersoft/iot/vmp/media/zlm/dto/StreamProxyItem.java
... ... @@ -31,8 +31,8 @@ public class StreamProxyItem extends GbStream {
31 31 private String rtp_type;
32 32 @Schema(description = "是否启用")
33 33 private boolean enable;
34   - @Schema(description = "是否启用HLS")
35   - private boolean enable_hls;
  34 + @Schema(description = "是否启用音频")
  35 + private boolean enable_audio;
36 36 @Schema(description = "是否启用MP4")
37 37 private boolean enable_mp4;
38 38 @Schema(description = "是否 无人观看时删除")
... ... @@ -40,8 +40,6 @@ public class StreamProxyItem extends GbStream {
40 40  
41 41 @Schema(description = "是否 无人观看时自动停用")
42 42 private boolean enable_disable_none_reader;
43   - @Schema(description = "上级平台国标ID")
44   - private String platformGbId;
45 43 @Schema(description = "创建时间")
46 44 private String createTime;
47 45  
... ... @@ -139,14 +137,6 @@ public class StreamProxyItem extends GbStream {
139 137 this.enable = enable;
140 138 }
141 139  
142   - public boolean isEnable_hls() {
143   - return enable_hls;
144   - }
145   -
146   - public void setEnable_hls(boolean enable_hls) {
147   - this.enable_hls = enable_hls;
148   - }
149   -
150 140 public boolean isEnable_mp4() {
151 141 return enable_mp4;
152 142 }
... ... @@ -155,19 +145,12 @@ public class StreamProxyItem extends GbStream {
155 145 this.enable_mp4 = enable_mp4;
156 146 }
157 147  
158   -
159   - public String getPlatformGbId() {
160   - return platformGbId;
161   - }
162   -
163   - public void setPlatformGbId(String platformGbId) {
164   - this.platformGbId = platformGbId;
165   - }
166   -
  148 + @Override
167 149 public String getCreateTime() {
168 150 return createTime;
169 151 }
170 152  
  153 + @Override
171 154 public void setCreateTime(String createTime) {
172 155 this.createTime = createTime;
173 156 }
... ... @@ -187,4 +170,12 @@ public class StreamProxyItem extends GbStream {
187 170 public void setEnable_disable_none_reader(boolean enable_disable_none_reader) {
188 171 this.enable_disable_none_reader = enable_disable_none_reader;
189 172 }
  173 +
  174 + public boolean isEnable_audio() {
  175 + return enable_audio;
  176 + }
  177 +
  178 + public void setEnable_audio(boolean enable_audio) {
  179 + this.enable_audio = enable_audio;
  180 + }
190 181 }
... ...
src/main/java/com/genersoft/iot/vmp/service/IDeviceChannelService.java
... ... @@ -3,6 +3,7 @@ package com.genersoft.iot.vmp.service;
3 3 import com.genersoft.iot.vmp.gb28181.bean.Device;
4 4 import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
5 5 import com.genersoft.iot.vmp.vmanager.bean.ResourceBaceInfo;
  6 +import com.genersoft.iot.vmp.vmanager.gb28181.platform.bean.ChannelReduce;
6 7  
7 8 import java.util.List;
8 9  
... ... @@ -38,4 +39,11 @@ public interface IDeviceChannelService {
38 39 * @return
39 40 */
40 41 ResourceBaceInfo getOverview();
  42 +
  43 + /**
  44 + * 查询所有未分配的通道
  45 + * @param platformId
  46 + * @return
  47 + */
  48 + List<ChannelReduce> queryAllChannelList(String platformId);
41 49 }
... ...
src/main/java/com/genersoft/iot/vmp/service/IGbStreamService.java
... ... @@ -55,4 +55,18 @@ public interface IGbStreamService {
55 55 int updateGbIdOrName(List<StreamPushItem> streamPushItemForUpdate);
56 56  
57 57 DeviceChannel getDeviceChannelListByStreamWithStatus(GbStream gbStream, String catalogId, ParentPlatform platform);
  58 +
  59 + /**
  60 + * 查询所有未分配的通道
  61 + * @param platformId
  62 + * @return
  63 + */
  64 + List<GbStream> getAllGBChannels(String platformId);
  65 +
  66 + /**
  67 + * 移除所有关联的通道
  68 + * @param platformId
  69 + * @param catalogId
  70 + */
  71 + void delAllPlatformInfo(String platformId, String catalogId);
58 72 }
... ...
src/main/java/com/genersoft/iot/vmp/service/IPlatformChannelService.java
... ... @@ -19,4 +19,11 @@ public interface IPlatformChannelService {
19 19 */
20 20 int updateChannelForGB(String platformId, List<ChannelReduce> channelReduces, String catalogId);
21 21  
  22 + /**
  23 + * 移除目录下的所有通道
  24 + * @param platformId
  25 + * @param catalogId
  26 + * @return
  27 + */
  28 + int delAllChannelForGB(String platformId, String catalogId);
22 29 }
... ...
src/main/java/com/genersoft/iot/vmp/service/impl/DeviceChannelServiceImpl.java
... ... @@ -10,6 +10,7 @@ import com.genersoft.iot.vmp.storager.dao.DeviceChannelMapper;
10 10 import com.genersoft.iot.vmp.storager.dao.DeviceMapper;
11 11 import com.genersoft.iot.vmp.utils.DateUtil;
12 12 import com.genersoft.iot.vmp.vmanager.bean.ResourceBaceInfo;
  13 +import com.genersoft.iot.vmp.vmanager.gb28181.platform.bean.ChannelReduce;
13 14 import org.slf4j.Logger;
14 15 import org.slf4j.LoggerFactory;
15 16 import org.springframework.beans.factory.annotation.Autowired;
... ... @@ -168,4 +169,12 @@ public class DeviceChannelServiceImpl implements IDeviceChannelService {
168 169 public ResourceBaceInfo getOverview() {
169 170 return channelMapper.getOverview();
170 171 }
  172 +
  173 +
  174 + @Override
  175 + public List<ChannelReduce> queryAllChannelList(String platformId) {
  176 + return channelMapper.queryChannelListInAll(null, null, null, platformId, null);
  177 + }
  178 +
  179 +
171 180 }
... ...
src/main/java/com/genersoft/iot/vmp/service/impl/DeviceServiceImpl.java
1 1 package com.genersoft.iot.vmp.service.impl;
2 2  
3 3 import com.genersoft.iot.vmp.conf.DynamicTask;
  4 +import com.genersoft.iot.vmp.conf.UserSetting;
4 5 import com.genersoft.iot.vmp.gb28181.bean.*;
5 6 import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
6 7 import com.genersoft.iot.vmp.gb28181.task.ISubscribeTask;
... ... @@ -12,7 +13,6 @@ import com.genersoft.iot.vmp.service.IDeviceChannelService;
12 13 import com.genersoft.iot.vmp.service.IDeviceService;
13 14 import com.genersoft.iot.vmp.service.IMediaServerService;
14 15 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
15   -import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
16 16 import com.genersoft.iot.vmp.storager.dao.DeviceChannelMapper;
17 17 import com.genersoft.iot.vmp.storager.dao.DeviceMapper;
18 18 import com.genersoft.iot.vmp.storager.dao.PlatformChannelMapper;
... ... @@ -78,7 +78,7 @@ public class DeviceServiceImpl implements IDeviceService {
78 78 TransactionDefinition transactionDefinition;
79 79  
80 80 @Autowired
81   - private IVideoManagerStorage storage;
  81 + private UserSetting userSetting;
82 82  
83 83 @Autowired
84 84 private ISIPCommander commander;
... ... @@ -120,16 +120,18 @@ public class DeviceServiceImpl implements IDeviceService {
120 120 if(device.getOnline() == 0){
121 121 device.setOnline(1);
122 122 device.setCreateTime(now);
123   - logger.info("[设备上线,离线状态下重新注册]: {},查询设备信息以及通道信息", device.getDeviceId());
124 123 deviceMapper.update(device);
125 124 redisCatchStorage.updateDevice(device);
126   - try {
127   - commander.deviceInfoQuery(device);
128   - } catch (InvalidArgumentException | SipException | ParseException e) {
129   - logger.error("[命令发送失败] 查询设备信息: {}", e.getMessage());
  125 + if (userSetting.getSyncChannelOnDeviceOnline()) {
  126 + logger.info("[设备上线,离线状态下重新注册]: {},查询设备信息以及通道信息", device.getDeviceId());
  127 + try {
  128 + commander.deviceInfoQuery(device);
  129 + } catch (InvalidArgumentException | SipException | ParseException e) {
  130 + logger.error("[命令发送失败] 查询设备信息: {}", e.getMessage());
  131 + }
  132 + sync(device);
  133 + // TODO 如果设备下的通道级联到了其他平台,那么需要发送事件或者notify给上级平台
130 134 }
131   - sync(device);
132   - // TODO 如果设备下的通道级联到了其他平台,那么需要发送事件或者notify给上级平台
133 135 }else {
134 136 if (deviceChannelMapper.queryAllChannels(device.getDeviceId()).size() == 0) {
135 137 logger.info("[设备上线]: {},通道数为0,查询通道信息", device.getDeviceId());
... ...
src/main/java/com/genersoft/iot/vmp/service/impl/GbStreamServiceImpl.java
... ... @@ -4,11 +4,11 @@ import com.genersoft.iot.vmp.gb28181.bean.*;
4 4 import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
5 5 import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent;
6 6 import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem;
  7 +import com.genersoft.iot.vmp.service.IGbStreamService;
7 8 import com.genersoft.iot.vmp.storager.dao.GbStreamMapper;
8 9 import com.genersoft.iot.vmp.storager.dao.ParentPlatformMapper;
9 10 import com.genersoft.iot.vmp.storager.dao.PlatformCatalogMapper;
10 11 import com.genersoft.iot.vmp.storager.dao.PlatformGbStreamMapper;
11   -import com.genersoft.iot.vmp.service.IGbStreamService;
12 12 import com.github.pagehelper.PageHelper;
13 13 import com.github.pagehelper.PageInfo;
14 14 import org.slf4j.Logger;
... ... @@ -19,7 +19,6 @@ import org.springframework.stereotype.Service;
19 19 import org.springframework.transaction.TransactionDefinition;
20 20 import org.springframework.transaction.TransactionStatus;
21 21 import org.springframework.util.ObjectUtils;
22   -import org.springframework.util.StringUtils;
23 22  
24 23 import java.util.ArrayList;
25 24 import java.util.List;
... ... @@ -230,4 +229,35 @@ public class GbStreamServiceImpl implements IGbStreamService {
230 229 deviceChannel.setSecrecy("0");
231 230 return deviceChannel;
232 231 }
  232 +
  233 + @Override
  234 + public List<GbStream> getAllGBChannels(String platformId) {
  235 +
  236 + return gbStreamMapper.selectAll(platformId, null, null, null);
  237 +
  238 + }
  239 +
  240 + @Override
  241 + public void delAllPlatformInfo(String platformId, String catalogId) {
  242 + if (platformId == null) {
  243 + return ;
  244 + }
  245 + ParentPlatform platform = platformMapper.getParentPlatByServerGBId(platformId);
  246 + if (platform == null) {
  247 + return ;
  248 + }
  249 + if (ObjectUtils.isEmpty(catalogId)) {
  250 + catalogId = platform.getDeviceGBId();
  251 + }
  252 + if (platformGbStreamMapper.delByPlatformAndCatalogId(platformId, catalogId) > 0) {
  253 + List<GbStream> gbStreams = platformGbStreamMapper.queryChannelInParentPlatformAndCatalog(platformId, catalogId);
  254 + List<DeviceChannel> deviceChannelList = new ArrayList<>();
  255 + for (GbStream gbStream : gbStreams) {
  256 + DeviceChannel deviceChannel = new DeviceChannel();
  257 + deviceChannel.setChannelId(gbStream.getGbId());
  258 + deviceChannelList.add(deviceChannel);
  259 + }
  260 + eventPublisher.catalogEventPublish(platformId, deviceChannelList, CatalogEvent.DEL);
  261 + }
  262 + }
233 263 }
... ...
src/main/java/com/genersoft/iot/vmp/service/impl/PlatformChannelServiceImpl.java
... ... @@ -16,6 +16,7 @@ import org.slf4j.Logger;
16 16 import org.slf4j.LoggerFactory;
17 17 import org.springframework.beans.factory.annotation.Autowired;
18 18 import org.springframework.stereotype.Service;
  19 +import org.springframework.util.ObjectUtils;
19 20  
20 21 import java.util.ArrayList;
21 22 import java.util.HashMap;
... ... @@ -105,4 +106,26 @@ public class PlatformChannelServiceImpl implements IPlatformChannelService {
105 106 }
106 107 return deviceChannelList;
107 108 }
  109 +
  110 + @Override
  111 + public int delAllChannelForGB(String platformId, String catalogId) {
  112 +
  113 + int result;
  114 + if (platformId == null) {
  115 + return 0;
  116 + }
  117 + ParentPlatform platform = platformMapper.getParentPlatByServerGBId(platformId);
  118 + if (platform == null) {
  119 + return 0;
  120 + }
  121 + if (ObjectUtils.isEmpty(catalogId)) {
  122 + catalogId = platform.getDeviceGBId();
  123 + }
  124 +
  125 + if ((result = platformChannelMapper.delChannelForGBByCatalogId(platformId, catalogId)) > 0) {
  126 + List<DeviceChannel> deviceChannels = platformChannelMapper.queryAllChannelInCatalog(platformId, catalogId);
  127 + eventPublisher.catalogEventPublish(platformId, deviceChannels, CatalogEvent.DEL);
  128 + }
  129 + return result;
  130 + }
108 131 }
... ...
src/main/java/com/genersoft/iot/vmp/service/impl/StreamProxyServiceImpl.java
... ... @@ -5,23 +5,22 @@ import com.alibaba.fastjson2.JSONObject;
5 5 import com.genersoft.iot.vmp.common.StreamInfo;
6 6 import com.genersoft.iot.vmp.conf.UserSetting;
7 7 import com.genersoft.iot.vmp.conf.exception.ControllerException;
8   -import com.genersoft.iot.vmp.gb28181.bean.GbStream;
9 8 import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
10 9 import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent;
11 10 import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
12   -import com.genersoft.iot.vmp.media.zlm.dto.hook.OnStreamChangedHookParam;
13 11 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
14 12 import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem;
  13 +import com.genersoft.iot.vmp.media.zlm.dto.hook.OnStreamChangedHookParam;
15 14 import com.genersoft.iot.vmp.service.IGbStreamService;
16 15 import com.genersoft.iot.vmp.service.IMediaServerService;
17 16 import com.genersoft.iot.vmp.service.IMediaService;
  17 +import com.genersoft.iot.vmp.service.IStreamProxyService;
18 18 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
19 19 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
20 20 import com.genersoft.iot.vmp.storager.dao.GbStreamMapper;
21 21 import com.genersoft.iot.vmp.storager.dao.ParentPlatformMapper;
22 22 import com.genersoft.iot.vmp.storager.dao.PlatformGbStreamMapper;
23 23 import com.genersoft.iot.vmp.storager.dao.StreamProxyMapper;
24   -import com.genersoft.iot.vmp.service.IStreamProxyService;
25 24 import com.genersoft.iot.vmp.utils.DateUtil;
26 25 import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
27 26 import com.genersoft.iot.vmp.vmanager.bean.ResourceBaceInfo;
... ... @@ -35,7 +34,9 @@ import org.springframework.transaction.TransactionDefinition;
35 34 import org.springframework.transaction.TransactionStatus;
36 35 import org.springframework.util.ObjectUtils;
37 36  
38   -import java.util.*;
  37 +import java.util.HashMap;
  38 +import java.util.List;
  39 +import java.util.Map;
39 40  
40 41 /**
41 42 * 视频代理业务
... ... @@ -101,7 +102,6 @@ public class StreamProxyServiceImpl implements IStreamProxyService {
101 102 param.getStream() );
102 103 param.setDst_url(dstUrl);
103 104 StringBuffer resultMsg = new StringBuffer();
104   - boolean streamLive = false;
105 105 param.setMediaServerId(mediaInfo.getId());
106 106 boolean saveResult;
107 107 // 更新
... ... @@ -118,7 +118,6 @@ public class StreamProxyServiceImpl implements IStreamProxyService {
118 118 if (param.isEnable()) {
119 119 JSONObject jsonObject = addStreamProxyToZlm(param);
120 120 if (jsonObject == null || jsonObject.getInteger("code") != 0) {
121   - streamLive = false;
122 121 resultMsg.append(", 但是启用失败,请检查流地址是否可用");
123 122 param.setEnable(false);
124 123 // 直接移除
... ... @@ -128,28 +127,12 @@ public class StreamProxyServiceImpl implements IStreamProxyService {
128 127 updateStreamProxy(param);
129 128 }
130 129  
131   -
132 130 }else {
133   - streamLive = true;
134 131 resultForStreamInfo = mediaService.getStreamInfoByAppAndStream(
135 132 mediaInfo, param.getApp(), param.getStream(), null, null);
136 133  
137 134 }
138 135 }
139   - if ( !ObjectUtils.isEmpty(param.getPlatformGbId()) && streamLive) {
140   - List<GbStream> gbStreams = new ArrayList<>();
141   - gbStreams.add(param);
142   - if (gbStreamService.addPlatformInfo(gbStreams, param.getPlatformGbId(), param.getCatalogId())){
143   - return resultForStreamInfo;
144   - }else {
145   - resultMsg.append(", 关联国标平台[ " + param.getPlatformGbId() + " ]失败");
146   - throw new ControllerException(ErrorCode.ERROR100.getCode(), resultMsg.toString());
147   - }
148   - }else {
149   - if (!streamLive) {
150   - throw new ControllerException(ErrorCode.ERROR100.getCode(), resultMsg.toString());
151   - }
152   - }
153 136 return resultForStreamInfo;
154 137 }
155 138  
... ... @@ -239,10 +222,10 @@ public class StreamProxyServiceImpl implements IStreamProxyService {
239 222 }
240 223 if ("default".equals(param.getType())){
241 224 result = zlmresTfulUtils.addStreamProxy(mediaServerItem, param.getApp(), param.getStream(), param.getUrl(),
242   - param.isEnable_hls(), param.isEnable_mp4(), param.getRtp_type());
  225 + param.isEnable_audio(), param.isEnable_mp4(), param.getRtp_type());
243 226 }else if ("ffmpeg".equals(param.getType())) {
244 227 result = zlmresTfulUtils.addFFmpegSource(mediaServerItem, param.getSrc_url(), param.getDst_url(),
245   - param.getTimeout_ms() + "", param.isEnable_hls(), param.isEnable_mp4(),
  228 + param.getTimeout_ms() + "", param.isEnable_audio(), param.isEnable_mp4(),
246 229 param.getFfmpeg_cmd_key());
247 230 }
248 231 return result;
... ... @@ -295,6 +278,9 @@ public class StreamProxyServiceImpl implements IStreamProxyService {
295 278 result = true;
296 279 streamProxy.setEnable(true);
297 280 updateStreamProxy(streamProxy);
  281 + }else {
  282 + logger.info("启用代理失败: {}/{}->{}({})", app, stream, jsonObject.getString("msg"),
  283 + streamProxy.getSrc_url() == null? streamProxy.getUrl():streamProxy.getSrc_url());
298 284 }
299 285 }
300 286 return result;
... ...
src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceChannelMapper.java
1 1 package com.genersoft.iot.vmp.storager.dao;
2 2  
3   -import com.genersoft.iot.vmp.gb28181.bean.Device;
4 3 import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
5 4 import com.genersoft.iot.vmp.gb28181.bean.DeviceChannelInPlatform;
6 5 import com.genersoft.iot.vmp.vmanager.bean.ResourceBaceInfo;
... ...
src/main/java/com/genersoft/iot/vmp/storager/dao/GbStreamMapper.java
... ... @@ -5,7 +5,6 @@ import com.genersoft.iot.vmp.gb28181.bean.GbStream;
5 5 import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem;
6 6 import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem;
7 7 import com.genersoft.iot.vmp.service.bean.GPSMsgInfo;
8   -import com.genersoft.iot.vmp.vmanager.bean.StreamPushExcelDto;
9 8 import org.apache.ibatis.annotations.*;
10 9 import org.springframework.stereotype.Repository;
11 10  
... ... @@ -169,4 +168,5 @@ public interface GbStreamMapper {
169 168  
170 169 @Select("SELECT status FROM stream_push WHERE app=#{app} AND stream=#{stream}")
171 170 Boolean selectStatusForPush(String app, String stream);
  171 +
172 172 }
... ...
src/main/java/com/genersoft/iot/vmp/storager/dao/PlatformChannelMapper.java
... ... @@ -57,6 +57,9 @@ public interface PlatformChannelMapper {
57 57 @Select("SELECT dc.* FROM platform_gb_channel pgc left join device_channel dc on dc.id = pgc.deviceChannelId WHERE dc.channelId='${channelId}' and pgc.platformId='${platformId}'")
58 58 List<DeviceChannel> queryChannelInParentPlatform(String platformId, String channelId);
59 59  
  60 + @Select("SELECT dc.* FROM platform_gb_channel pgc left join device_channel dc on dc.id = pgc.deviceChannelId WHERE pgc.platformId='${platformId}' and pgc.catalogId=#{catalogId}")
  61 + List<DeviceChannel> queryAllChannelInCatalog(String platformId, String catalogId);
  62 +
60 63 @Select(" select dc.channelId as id, dc.name as name, pgc.platformId as platformId, pgc.catalogId as parentId, 0 as childrenCount, 1 as type " +
61 64 " from device_channel dc left join platform_gb_channel pgc on dc.id = pgc.deviceChannelId " +
62 65 " where pgc.platformId=#{platformId} and pgc.catalogId=#{catalogId}")
... ... @@ -99,4 +102,9 @@ public interface PlatformChannelMapper {
99 102 "DELETE FROM platform_gb_channel WHERE platformId=#{serverGBId}" +
100 103 "</script>")
101 104 void delByPlatformId(String serverGBId);
  105 +
  106 + @Delete("<script> " +
  107 + "DELETE FROM platform_gb_channel WHERE platformId=#{platformId} and catalogId=#{catalogId}" +
  108 + "</script>")
  109 + int delChannelForGBByCatalogId(String platformId, String catalogId);
102 110 }
... ...
src/main/java/com/genersoft/iot/vmp/storager/dao/PlatformGbStreamMapper.java
... ... @@ -105,4 +105,7 @@ public interface PlatformGbStreamMapper {
105 105 "</foreach>" +
106 106 "</script>")
107 107 void delByAppAndStreamsByPlatformId(List<GbStream> gbStreams, String platformId);
  108 +
  109 + @Delete("DELETE FROM platform_gb_stream WHERE platformId=#{platformId} and catalogId=#{catalogId}")
  110 + int delByPlatformAndCatalogId(String platformId, String catalogId);
108 111 }
... ...
src/main/java/com/genersoft/iot/vmp/storager/dao/StreamProxyMapper.java
... ... @@ -12,9 +12,9 @@ import java.util.List;
12 12 public interface StreamProxyMapper {
13 13  
14 14 @Insert("INSERT INTO stream_proxy (type, name, app, stream,mediaServerId, url, src_url, dst_url, " +
15   - "timeout_ms, ffmpeg_cmd_key, rtp_type, enable_hls, enable_mp4, enable, status, enable_remove_none_reader, enable_disable_none_reader, createTime) VALUES" +
  15 + "timeout_ms, ffmpeg_cmd_key, rtp_type, enable_audio, enable_mp4, enable, status, enable_remove_none_reader, enable_disable_none_reader, createTime) VALUES" +
16 16 "('${type}','${name}', '${app}', '${stream}', '${mediaServerId}','${url}', '${src_url}', '${dst_url}', " +
17   - "'${timeout_ms}', '${ffmpeg_cmd_key}', '${rtp_type}', ${enable_hls}, ${enable_mp4}, ${enable}, ${status}, " +
  17 + "'${timeout_ms}', '${ffmpeg_cmd_key}', '${rtp_type}', ${enable_audio}, ${enable_mp4}, ${enable}, ${status}, " +
18 18 "${enable_remove_none_reader}, ${enable_disable_none_reader}, '${createTime}' )")
19 19 int add(StreamProxyItem streamProxyDto);
20 20  
... ... @@ -30,7 +30,7 @@ public interface StreamProxyMapper {
30 30 "timeout_ms=#{timeout_ms}, " +
31 31 "ffmpeg_cmd_key=#{ffmpeg_cmd_key}, " +
32 32 "rtp_type=#{rtp_type}, " +
33   - "enable_hls=#{enable_hls}, " +
  33 + "enable_audio=#{enable_audio}, " +
34 34 "enable=#{enable}, " +
35 35 "status=#{status}, " +
36 36 "enable_remove_none_reader=#{enable_remove_none_reader}, " +
... ...
src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStorageImpl.java
1 1 package com.genersoft.iot.vmp.storager.impl;
2 2  
3   -import com.genersoft.iot.vmp.common.StreamInfo;
4 3 import com.genersoft.iot.vmp.conf.SipConfig;
5 4 import com.genersoft.iot.vmp.conf.UserSetting;
6 5 import com.genersoft.iot.vmp.gb28181.bean.*;
7 6 import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
8 7 import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent;
9 8 import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem;
10   -import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem;
11 9 import com.genersoft.iot.vmp.service.IGbStreamService;
12 10 import com.genersoft.iot.vmp.service.bean.GPSMsgInfo;
13 11 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
... ... @@ -28,7 +26,6 @@ import org.springframework.transaction.TransactionStatus;
28 26 import org.springframework.transaction.annotation.Transactional;
29 27 import org.springframework.util.CollectionUtils;
30 28 import org.springframework.util.ObjectUtils;
31   -import org.springframework.util.StringUtils;
32 29  
33 30 import java.util.*;
34 31 import java.util.concurrent.ConcurrentHashMap;
... ... @@ -761,18 +758,6 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage {
761 758 return gbStreamMapper.updateStreamGPS(gpsMsgInfos);
762 759 }
763 760  
764   - private List<DeviceChannel> getDeviceChannelListByChannelReduceList(List<ChannelReduce> channelReduces, String catalogId) {
765   - List<DeviceChannel> deviceChannelList = new ArrayList<>();
766   - if (channelReduces.size() > 0){
767   - for (ChannelReduce channelReduce : channelReduces) {
768   - DeviceChannel deviceChannel = queryChannel(channelReduce.getDeviceId(), channelReduce.getChannelId());
769   - deviceChannel.setParental(1);
770   - deviceChannel.setParentId(catalogId);
771   - deviceChannelList.add(deviceChannel);
772   - }
773   - }
774   - return deviceChannelList;
775   - }
776 761  
777 762 private DeviceChannel getDeviceChannelByCatalog(PlatformCatalog catalog) {
778 763 ParentPlatform platform = platformMapper.getParentPlatByServerGBId(catalog.getPlatformId());
... ...
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/gbStream/GbStreamController.java
1 1 package com.genersoft.iot.vmp.vmanager.gb28181.gbStream;
2 2  
3 3 import com.genersoft.iot.vmp.gb28181.bean.GbStream;
  4 +import com.genersoft.iot.vmp.service.IGbStreamService;
4 5 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
5 6 import com.genersoft.iot.vmp.vmanager.gb28181.gbStream.bean.GbStreamParam;
6   -import com.genersoft.iot.vmp.service.IGbStreamService;
7 7 import com.github.pagehelper.PageInfo;
8 8 import io.swagger.v3.oas.annotations.Operation;
9 9 import io.swagger.v3.oas.annotations.Parameter;
... ... @@ -12,9 +12,10 @@ import org.slf4j.Logger;
12 12 import org.slf4j.LoggerFactory;
13 13 import org.springframework.beans.factory.annotation.Autowired;
14 14 import org.springframework.util.ObjectUtils;
15   -import org.springframework.util.StringUtils;
16 15 import org.springframework.web.bind.annotation.*;
17 16  
  17 +import java.util.List;
  18 +
18 19 @Tag(name = "视频流关联到级联平台")
19 20 @CrossOrigin
20 21 @RestController
... ... @@ -76,11 +77,14 @@ public class GbStreamController {
76 77 @Operation(summary = "移除国标关联")
77 78 @DeleteMapping(value = "/del")
78 79 @ResponseBody
79   - public Object del(@RequestBody GbStreamParam gbStreamParam){
80   - if (gbStreamService.delPlatformInfo(gbStreamParam.getPlatformId(), gbStreamParam.getGbStreams())) {
81   - return "success";
  80 + public void del(@RequestBody GbStreamParam gbStreamParam){
  81 +
  82 + if (gbStreamParam.getGbStreams() == null || gbStreamParam.getGbStreams().size() == 0) {
  83 + if (gbStreamParam.isAll()) {
  84 + gbStreamService.delAllPlatformInfo(gbStreamParam.getPlatformId(), gbStreamParam.getCatalogId());
  85 + }
82 86 }else {
83   - return "fail";
  87 + gbStreamService.delPlatformInfo(gbStreamParam.getPlatformId(), gbStreamParam.getGbStreams());
84 88 }
85 89  
86 90 }
... ... @@ -93,11 +97,14 @@ public class GbStreamController {
93 97 @Operation(summary = "保存国标关联")
94 98 @PostMapping(value = "/add")
95 99 @ResponseBody
96   - public Object add(@RequestBody GbStreamParam gbStreamParam){
97   - if (gbStreamService.addPlatformInfo(gbStreamParam.getGbStreams(), gbStreamParam.getPlatformId(), gbStreamParam.getCatalogId())) {
98   - return "success";
  100 + public void add(@RequestBody GbStreamParam gbStreamParam){
  101 + if (gbStreamParam.getGbStreams() == null || gbStreamParam.getGbStreams().size() == 0) {
  102 + if (gbStreamParam.isAll()) {
  103 + List<GbStream> allGBChannels = gbStreamService.getAllGBChannels(gbStreamParam.getPlatformId());
  104 + gbStreamService.addPlatformInfo(allGBChannels, gbStreamParam.getPlatformId(), gbStreamParam.getCatalogId());
  105 + }
99 106 }else {
100   - return "fail";
  107 + gbStreamService.addPlatformInfo(gbStreamParam.getGbStreams(), gbStreamParam.getPlatformId(), gbStreamParam.getCatalogId());
101 108 }
102 109 }
103 110 }
... ...
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/gbStream/bean/GbStreamParam.java
... ... @@ -14,6 +14,9 @@ public class GbStreamParam {
14 14 @Schema(description = "目录ID")
15 15 private String catalogId;
16 16  
  17 + @Schema(description = "关联所有通道")
  18 + private boolean all;
  19 +
17 20 @Schema(description = "流国标信息列表")
18 21 private List<GbStream> gbStreams;
19 22  
... ... @@ -40,4 +43,12 @@ public class GbStreamParam {
40 43 public void setGbStreams(List<GbStream> gbStreams) {
41 44 this.gbStreams = gbStreams;
42 45 }
  46 +
  47 + public boolean isAll() {
  48 + return all;
  49 + }
  50 +
  51 + public void setAll(boolean all) {
  52 + this.all = all;
  53 + }
43 54 }
... ...
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/platform/PlatformController.java
... ... @@ -10,8 +10,7 @@ import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
10 10 import com.genersoft.iot.vmp.gb28181.bean.PlatformCatalog;
11 11 import com.genersoft.iot.vmp.gb28181.bean.SubscribeHolder;
12 12 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
13   -import com.genersoft.iot.vmp.service.IPlatformChannelService;
14   -import com.genersoft.iot.vmp.service.IPlatformService;
  13 +import com.genersoft.iot.vmp.service.*;
15 14 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
16 15 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
17 16 import com.genersoft.iot.vmp.utils.DateUtil;
... ... @@ -72,6 +71,12 @@ public class PlatformController {
72 71 @Autowired
73 72 private IPlatformService platformService;
74 73  
  74 + @Autowired
  75 + private IDeviceChannelService deviceChannelService;
  76 +
  77 + @Autowired
  78 + private IGbStreamService gbStreamService;
  79 +
75 80 /**
76 81 * 获取国标服务的配置
77 82 *
... ... @@ -379,7 +384,16 @@ public class PlatformController {
379 384 if (logger.isDebugEnabled()) {
380 385 logger.debug("给上级平台添加国标通道API调用");
381 386 }
382   - int result = platformChannelService.updateChannelForGB(param.getPlatformId(), param.getChannelReduces(), param.getCatalogId());
  387 + int result = 0;
  388 + if (param.getChannelReduces() == null || param.getChannelReduces().size() == 0) {
  389 + if (param.isAll()) {
  390 + logger.info("[国标级联]添加所有通道到上级平台, {}", param.getPlatformId());
  391 + List<ChannelReduce> allChannelForDevice = deviceChannelService.queryAllChannelList(param.getPlatformId());
  392 + result = platformChannelService.updateChannelForGB(param.getPlatformId(), allChannelForDevice, param.getCatalogId());
  393 + }
  394 + }else {
  395 + result = platformChannelService.updateChannelForGB(param.getPlatformId(), param.getChannelReduces(), param.getCatalogId());
  396 + }
383 397 if (result <= 0) {
384 398 throw new ControllerException(ErrorCode.ERROR100);
385 399 }
... ... @@ -399,8 +413,15 @@ public class PlatformController {
399 413 if (logger.isDebugEnabled()) {
400 414 logger.debug("给上级平台删除国标通道API调用");
401 415 }
402   - int result = storager.delChannelForGB(param.getPlatformId(), param.getChannelReduces());
403   -
  416 + int result = 0;
  417 + if (param.getChannelReduces() == null || param.getChannelReduces().size() == 0) {
  418 + if (param.isAll()) {
  419 + logger.info("[国标级联]移除所有通道,上级平台, {}", param.getPlatformId());
  420 + result = platformChannelService.delAllChannelForGB(param.getPlatformId(), param.getCatalogId());
  421 + }
  422 + }else {
  423 + result = storager.delChannelForGB(param.getPlatformId(), param.getChannelReduces());
  424 + }
404 425 if (result <= 0) {
405 426 throw new ControllerException(ErrorCode.ERROR100);
406 427 }
... ...
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/platform/bean/UpdateChannelParam.java
... ... @@ -17,6 +17,9 @@ public class UpdateChannelParam {
17 17 @Schema(description = "目录的国标编号")
18 18 private String catalogId;
19 19  
  20 + @Schema(description = "处理所有通道")
  21 + private boolean all;
  22 +
20 23 @Schema(description = "")
21 24 private List<ChannelReduce> channelReduces;
22 25  
... ... @@ -43,4 +46,12 @@ public class UpdateChannelParam {
43 46 public void setCatalogId(String catalogId) {
44 47 this.catalogId = catalogId;
45 48 }
  49 +
  50 + public boolean isAll() {
  51 + return all;
  52 + }
  53 +
  54 + public void setAll(boolean all) {
  55 + this.all = all;
  56 + }
46 57 }
... ...
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/PlayController.java
... ... @@ -111,7 +111,7 @@ public class PlayController {
111 111 resultHolder.invokeResult(msg);
112 112 });
113 113  
114   - if (userSetting.isUsePushingAsStatus()) {
  114 + if (userSetting.getUseSourceIpAsStreamIp()) {
115 115 // TODO 在点播未成功的情况下在此调用接口点播会导致返回的流地址ip错误
116 116 deferredResultEx.setFilter(result1 -> {
117 117 WVPResult<StreamInfo> wvpResult1 = (WVPResult<StreamInfo>)result1;
... ... @@ -130,7 +130,6 @@ public class PlayController {
130 130 });
131 131 }
132 132  
133   -
134 133 // 录像查询以channelId作为deviceId查询
135 134 resultHolder.put(key, uuid, deferredResultEx);
136 135  
... ... @@ -140,7 +139,6 @@ public class PlayController {
140 139 return result;
141 140 }
142 141  
143   -
144 142 @Operation(summary = "停止点播")
145 143 @Parameter(name = "deviceId", description = "设备国标编号", required = true)
146 144 @Parameter(name = "channelId", description = "通道国标编号", required = true)
... ... @@ -177,7 +175,6 @@ public class PlayController {
177 175 json.put("deviceId", deviceId);
178 176 json.put("channelId", channelId);
179 177 return json;
180   -
181 178 }
182 179  
183 180 /**
... ...
src/main/java/com/genersoft/iot/vmp/vmanager/streamProxy/StreamProxyController.java
... ... @@ -109,7 +109,6 @@ public class StreamProxyController {
109 109 logger.info("启用代理: " + app + "/" + stream);
110 110 boolean result = streamProxyService.start(app, stream);
111 111 if (!result) {
112   - logger.info("启用代理失败: " + app + "/" + stream);
113 112 throw new ControllerException(ErrorCode.ERROR100);
114 113 }
115 114 }
... ...
src/main/resources/all-application.yml
... ... @@ -195,6 +195,8 @@ user-settings:
195 195 # 国标级联发流严格模式,严格模式会使用与sdp信息中一致的端口发流,端口共享media.rtp.port-range,这会损失一些性能,
196 196 # 非严格模式使用随机端口发流,性能更好, 默认关闭
197 197 gb-send-stream-strict: false
  198 + # 设备上线时是否自动同步通道
  199 + sync-channel-on-device-online: false
198 200  
199 201 # 关闭在线文档(生产环境建议关闭)
200 202 springdoc:
... ...
web_src/src/components/StreamProxyList.vue
... ... @@ -32,7 +32,7 @@
32 32 <el-table-column label="类型" width="100" >
33 33 <template slot-scope="scope">
34 34 <div slot="reference" class="name-wrapper">
35   - <el-tag size="medium">{{scope.row.type}}</el-tag>
  35 + <el-tag size="medium">{{scope.row.type === "default"? "直接代理":"FFMPEG代理"}}</el-tag>
36 36 </div>
37 37 </template>
38 38 </el-table-column>
... ... @@ -55,15 +55,15 @@
55 55 </template>
56 56 </el-table-column>
57 57 <el-table-column prop="createTime" label="创建时间" min-width="150" show-overflow-tooltip/>
58   - <el-table-column label="转HLS" min-width="120" >
  58 + <el-table-column label="音频" min-width="120" >
59 59 <template slot-scope="scope">
60 60 <div slot="reference" class="name-wrapper">
61   - <el-tag size="medium" v-if="scope.row.enable_hls">已启用</el-tag>
62   - <el-tag size="medium" type="info" v-if="!scope.row.enable_hls">未启用</el-tag>
  61 + <el-tag size="medium" v-if="scope.row.enable_audio">已启用</el-tag>
  62 + <el-tag size="medium" type="info" v-if="!scope.row.enable_audio">未启用</el-tag>
63 63 </div>
64 64 </template>
65 65 </el-table-column>
66   - <el-table-column label="MP4录制" min-width="120" >
  66 + <el-table-column label="录制" min-width="120" >
67 67 <template slot-scope="scope">
68 68 <div slot="reference" class="name-wrapper">
69 69 <el-tag size="medium" v-if="scope.row.enable_mp4">已启用</el-tag>
... ... @@ -71,11 +71,12 @@
71 71 </div>
72 72 </template>
73 73 </el-table-column>
74   - <el-table-column label="无人观看自动删除" min-width="160" >
  74 + <el-table-column label="无人观看" min-width="160" >
75 75 <template slot-scope="scope">
76 76 <div slot="reference" class="name-wrapper">
77   - <el-tag size="medium" v-if="scope.row.enable_remove_none_reader">已启用</el-tag>
78   - <el-tag size="medium" type="info" v-if="!scope.row.enable_remove_none_reader">未启用</el-tag>
  77 + <el-tag size="medium" v-if="scope.row.enable_remove_none_reader">移除</el-tag>
  78 + <el-tag size="medium" v-if="scope.row.enable_disable_none_reader">停用</el-tag>
  79 + <el-tag size="medium" type="info" v-if="!scope.row.enable_remove_none_reader && !scope.row.enable_disable_none_reader">不做处理</el-tag>
79 80 </div>
80 81 </template>
81 82 </el-table-column>
... ... @@ -131,7 +132,6 @@
131 132 currentPage:1,
132 133 count:15,
133 134 total:0,
134   - getListLoading: false,
135 135 startBtnLoading: false
136 136 };
137 137 },
... ... @@ -139,7 +139,7 @@
139 139 },
140 140 mounted() {
141 141 this.initData();
142   - this.updateLooper = setInterval(this.initData, 1000);
  142 + this.startUpdateList()
143 143 },
144 144 destroyed() {
145 145 this.$destroy('videojs');
... ... @@ -149,6 +149,12 @@
149 149 initData: function() {
150 150 this.getStreamProxyList();
151 151 },
  152 + stopUpdateList: function (){
  153 + window.clearInterval(this.updateLooper)
  154 + },
  155 + startUpdateList: function (){
  156 + this.updateLooper = setInterval(this.initData, 1000);
  157 + },
152 158 currentChange: function(val){
153 159 this.currentPage = val;
154 160 this.getStreamProxyList();
... ... @@ -159,7 +165,6 @@
159 165 },
160 166 getStreamProxyList: function() {
161 167 let that = this;
162   - this.getListLoading = true;
163 168 this.$axios({
164 169 method: 'get',
165 170 url:`/api/proxy/list`,
... ... @@ -175,23 +180,18 @@
175 180 }
176 181 that.streamProxyList = res.data.data.list;
177 182 }
178   - that.getListLoading = false;
179 183 }).catch(function (error) {
180 184 console.log(error);
181   - that.getListLoading = false;
182 185 });
183 186 },
184 187 addStreamProxy: function(){
185 188 this.$refs.streamProxyEdit.openDialog(null, this.initData)
186 189 },
187 190 addOnvif: function(){
188   - this.getListLoading = true;
189   - this.getListLoading = true;
190 191 this.$axios({
191 192 method: 'get',
192 193 url:`/api/onvif/search?timeout=3000`,
193 194 }).then((res) =>{
194   - this.getListLoading = false;
195 195 if (res.data.code === 0 ){
196 196 if (res.data.data.length > 0) {
197 197 this.$refs.onvifEdit.openDialog(res.data.data, (url)=>{
... ... @@ -208,7 +208,6 @@
208 208 }
209 209  
210 210 }).catch((error)=> {
211   - this.getListLoading = false;
212 211 this.$message.error(error.response.data.msg);
213 212 });
214 213  
... ... @@ -217,7 +216,6 @@
217 216 },
218 217 play: function(row){
219 218 let that = this;
220   - this.getListLoading = true;
221 219 this.$axios({
222 220 method: 'get',
223 221 url:`/api/push/getPlayUrl`,
... ... @@ -227,7 +225,6 @@
227 225 mediaServerId: row.mediaServerId
228 226 }
229 227 }).then(function (res) {
230   - that.getListLoading = false;
231 228 if (res.data.code === 0) {
232 229 that.$refs.devicePlayer.openDialog("streamPlay", null, null, {
233 230 streamInfo: res.data.data,
... ... @@ -243,13 +240,11 @@
243 240  
244 241 }).catch(function (error) {
245 242 console.log(error);
246   - that.getListLoading = false;
247 243 });
248 244  
249 245 },
250 246 deleteStreamProxy: function(row){
251 247 let that = this;
252   - this.getListLoading = true;
253 248 that.$axios({
254 249 method:"delete",
255 250 url:"/api/proxy/del",
... ... @@ -258,16 +253,13 @@
258 253 stream: row.stream
259 254 }
260 255 }).then((res)=>{
261   - that.getListLoading = false;
262 256 that.initData()
263 257 }).catch(function (error) {
264 258 console.log(error);
265   - that.getListLoading = false;
266 259 });
267 260 },
268 261 start: function(row){
269   - let that = this;
270   - this.getListLoading = true;
  262 + this.stopUpdateList()
271 263 this.$set(row, 'startBtnLoading', true)
272 264 this.$axios({
273 265 method: 'get',
... ... @@ -276,28 +268,31 @@
276 268 app: row.app,
277 269 stream: row.stream
278 270 }
279   - }).then(function (res) {
280   - that.getListLoading = false;
281   - that.$set(row, 'startBtnLoading', false)
  271 + }).then((res)=> {
282 272 if (res.data.code === 0){
283   - that.initData()
  273 + this.initData()
284 274 }else {
285   - that.$message({
  275 + this.$message({
286 276 showClose: true,
287   - message: "保存失败,请检查地址是否可用!",
  277 + message: "启动失败,请检查地址是否可用!",
288 278 type: "error",
289 279 });
290 280 }
291   -
292   - }).catch(function (error) {
  281 + this.$set(row, 'startBtnLoading', false)
  282 + this.startUpdateList()
  283 + }).catch((error)=> {
293 284 console.log(error);
294   - that.getListLoading = false;
295   - that.$set(row, 'startBtnLoading', false)
  285 + this.$message({
  286 + showClose: true,
  287 + message: "启动失败,请检查地址是否可用!",
  288 + type: "error",
  289 + });
  290 + this.$set(row, 'startBtnLoading', false)
  291 + this.startUpdateList()
296 292 });
297 293 },
298 294 stop: function(row){
299 295 let that = this;
300   - this.getListLoading = true;
301 296 this.$axios({
302 297 method: 'get',
303 298 url:`/api/proxy/stop`,
... ... @@ -306,11 +301,9 @@
306 301 stream: row.stream
307 302 }
308 303 }).then(function (res) {
309   - that.getListLoading = false;
310 304 that.initData()
311 305 }).catch(function (error) {
312 306 console.log(error);
313   - that.getListLoading = false;
314 307 });
315 308 },
316 309 refresh: function (){
... ...
web_src/src/components/dialog/StreamProxyEdit.vue
... ... @@ -83,31 +83,23 @@
83 83 <el-option label="组播" value="2"></el-option>
84 84 </el-select>
85 85 </el-form-item>
86   -
87   - <el-form-item label="国标平台">
88   - <el-select
89   - v-model="proxyParam.platformGbId"
90   - style="width: 100%"
91   - placeholder="请选择国标平台"
92   - >
93   - <el-option
94   - v-for="item in platformList"
95   - :key="item.name"
96   - :label="item.name"
97   - :value="item.serverGBId">
98   - <span style="float: left">{{ item.name }}</span>
99   - <span style="float: right; color: #8492a6; font-size: 13px">{{ item.serverGBId }}</span>
100   - </el-option>
101   - </el-select>
102   - </el-form-item>
  86 + <el-form-item label="无人观看" prop="rtp_type" >
  87 + <el-select
  88 + @change="noneReaderHandler"
  89 + v-model="proxyParam.none_reader"
  90 + style="width: 100%"
  91 + placeholder="请选择无人观看的处理方式"
  92 + >
  93 + <el-option label="不做处理" value="0"></el-option>
  94 + <el-option label="停用" value="1"></el-option>
  95 + <el-option label="移除" value="2"></el-option>
  96 + </el-select>
  97 + </el-form-item>
103 98 <el-form-item label="其他选项">
104 99 <div style="float: left;">
105 100 <el-checkbox label="启用" v-model="proxyParam.enable" ></el-checkbox>
106   - <el-checkbox label="转HLS" v-model="proxyParam.enable_hls" ></el-checkbox>
107   - <el-checkbox label="MP4录制" v-model="proxyParam.enable_mp4" ></el-checkbox>
108   - <el-checkbox label="无人观看自动删除" v-model="proxyParam.enable_remove_none_reader" @change="removeNoneReader"></el-checkbox>
109   - <el-checkbox label="无人观看停止拉流" v-model="proxyParam.enable_disable_none_reader" @change="disableNoneReaderHandType"></el-checkbox>
110   -
  101 + <el-checkbox label="开启音频" v-model="proxyParam.enable_audio" ></el-checkbox>
  102 + <el-checkbox label="录制" v-model="proxyParam.enable_mp4" ></el-checkbox>
111 103 </div>
112 104  
113 105 </el-form-item>
... ... @@ -169,10 +161,11 @@ export default {
169 161 gbId: null,
170 162 rtp_type: null,
171 163 enable: true,
172   - enable_hls: true,
  164 + enable_audio: true,
173 165 enable_mp4: false,
  166 + none_reader: null,
174 167 enable_remove_none_reader: false,
175   - enable_disable_none_reader: true,
  168 + enable_disable_none_reader: false,
176 169 platformGbId: null,
177 170 mediaServerId: null,
178 171 },
... ... @@ -196,6 +189,7 @@ export default {
196 189 this.listChangeCallback = callback;
197 190 if (proxyParam != null) {
198 191 this.proxyParam = proxyParam;
  192 + this.proxyParam.none_reader = null;
199 193 }
200 194  
201 195 let that = this;
... ... @@ -233,26 +227,26 @@ export default {
233 227 },
234 228 onSubmit: function () {
235 229 this.dialogLoading = true;
236   - var that = this;
237   - that.$axios({
  230 + this.noneReaderHandler();
  231 + this.$axios({
238 232 method: 'post',
239 233 url:`/api/proxy/save`,
240   - data: that.proxyParam
241   - }).then(function (res) {
242   - that.dialogLoading = false;
  234 + data: this.proxyParam
  235 + }).then((res)=> {
  236 + this.dialogLoading = false;
243 237 if (typeof (res.data.code) != "undefined" && res.data.code === 0) {
244   - that.$message({
  238 + this.$message({
245 239 showClose: true,
246 240 message: res.data.msg,
247 241 type: "success",
248 242 });
249   - that.showDialog = false;
250   - if (that.listChangeCallback != null) {
251   - that.listChangeCallback();
252   - that.dialogLoading = false;
  243 + this.showDialog = false;
  244 + if (this.listChangeCallback != null) {
  245 + this.listChangeCallback();
  246 + this.dialogLoading = false;
253 247 }
254 248 }
255   - }).catch(function (error) {
  249 + }).catch((error) =>{
256 250 console.log(error);
257 251 this.dialogLoading = false;
258 252 });
... ... @@ -280,12 +274,18 @@ export default {
280 274 this.platform.expires = "300";
281 275 }
282 276 },
283   - removeNoneReader: function(checked) {
284   - this.proxyParam.enable_disable_none_reader = !checked;
  277 + noneReaderHandler: function() {
  278 + if (this.proxyParam.none_reader === null || this.proxyParam.none_reader === "0") {
  279 + this.proxyParam.enable_disable_none_reader = false;
  280 + this.proxyParam.enable_remove_none_reader = false;
  281 + }else if (this.proxyParam.none_reader === "1"){
  282 + this.proxyParam.enable_disable_none_reader = true;
  283 + this.proxyParam.enable_remove_none_reader = false;
  284 + }else if (this.proxyParam.none_reader ==="2"){
  285 + this.proxyParam.enable_disable_none_reader = false;
  286 + this.proxyParam.enable_remove_none_reader = true;
  287 + }
285 288 },
286   - disableNoneReaderHandType: function(checked) {
287   - this.proxyParam.enable_remove_none_reader = !checked;
288   - }
289 289 },
290 290 };
291 291 </script>
... ...
web_src/src/components/dialog/SyncChannelProgress.vue
... ... @@ -63,37 +63,29 @@ export default {
63 63 }
64 64  
65 65 if (res.data.data != null) {
66   - if (res.data.syncIng) {
  66 + if (res.data.data.syncIng) {
67 67 if (res.data.data.total == 0) {
68   - if (res.data.data.errorMsg !== null ){
69   - this.msg = res.data.data.errorMsg;
70   - this.syncStatus = "exception"
71   - }else {
72   - this.msg = `等待同步中`;
73   - this.timmer = setTimeout(this.getProgress, 300)
74   - }
75   - }else {
76   - if (res.data.data.total == res.data.data.current) {
77   - this.syncStatus = "success"
78   - this.percentage = 100;
79   - this.msg = '同步成功';
80   - }else {
81   - if (res.data.data.errorMsg !== null ){
82   - this.msg = res.data.data.errorMsg;
83   - this.syncStatus = "exception"
84   - }else {
85   - this.total = res.data.data.total;
86   - this.current = res.data.data.current;
87   - this.percentage = Math.floor(Number(res.data.data.current)/Number(res.data.data.total)* 10000)/100;
88   - this.msg = `同步中...[${res.data.data.current}/${res.data.data.total}]`;
89   - this.timmer = setTimeout(this.getProgress, 300)
90   - }
91   - }
  68 + this.msg = `等待同步中`;
  69 + this.timmer = setTimeout(this.getProgress, 300)
  70 + }else {
  71 + this.total = res.data.data.total;
  72 + this.current = res.data.data.current;
  73 + this.percentage = Math.floor(Number(res.data.data.current)/Number(res.data.data.total)* 10000)/100;
  74 + this.msg = `同步中...[${res.data.data.current}/${res.data.data.total}]`;
  75 + this.timmer = setTimeout(this.getProgress, 300)
92 76 }
93 77 }else {
94   - this.syncStatus = "success"
95   - this.percentage = 100;
96   - this.msg = '同步成功';
  78 + if (res.data.data.errorMsg){
  79 + this.msg = res.data.data.errorMsg;
  80 + this.syncStatus = "exception"
  81 + }else {
  82 + this.syncStatus = "success"
  83 + this.percentage = 100;
  84 + this.msg = '同步成功';
  85 + setTimeout(()=>{
  86 + this.showDialog = false;
  87 + }, 3000)
  88 + }
97 89 }
98 90 }
99 91 }else {
... ...
web_src/src/components/dialog/chooseChannelForGb.vue
... ... @@ -18,8 +18,10 @@
18 18 <el-option label="在线" value="true"></el-option>
19 19 <el-option label="离线" value="false"></el-option>
20 20 </el-select>
21   - <el-button v-if="catalogId !== null" icon="el-icon-delete" size="mini" style="margin-right: 1rem;" :disabled="gbChannels.length === 0 || multipleSelection.length === 0" type="danger" @click="batchDel">批量移除</el-button>
22   - <el-button v-if="catalogId === null" icon="el-icon-plus" size="mini" style="margin-right: 1rem;" :disabled="gbChannels.length === 0 || multipleSelection.length === 0" @click="batchAdd">批量添加</el-button>
  21 + <el-button v-if="catalogId !== null" icon="el-icon-delete" size="mini" :disabled="gbChannels.length === 0 || multipleSelection.length === 0" type="danger" @click="batchDel">批量移除</el-button>
  22 + <el-button v-if="catalogId === null" icon="el-icon-plus" size="mini" :disabled="gbChannels.length === 0 || multipleSelection.length === 0" @click="batchAdd">批量添加</el-button>
  23 + <el-button v-if="catalogId === null" icon="el-icon-plus" size="mini" @click="add()">全部添加</el-button>
  24 + <el-button v-if="catalogId !== null" type="danger" icon="el-icon-delete" size="mini" @click="remove()">全部移除</el-button>
23 25 </div>
24 26  
25 27 <el-table ref="gbChannelsTable" :data="gbChannels" border style="width: 100%" :height="winHeight" :row-key="(row)=> row.deviceId + row.channelId" @selection-change="handleSelectionChange">
... ... @@ -115,13 +117,15 @@ export default {
115 117 this.initData();
116 118 },
117 119 add: function (row) {
  120 + let all = typeof(row) === "undefined"
118 121 this.getCatalogFromUser((catalogId)=> {
119 122 this.$axios({
120 123 method:"post",
121 124 url:"/api/platform/update_channel_for_gb",
122 125 data:{
123 126 platformId: this.platformId,
124   - channelReduces: [row],
  127 + all: all,
  128 + channelReduces: all?[]:[row],
125 129 catalogId: catalogId
126 130 }
127 131 }).then((res)=>{
... ... @@ -134,21 +138,34 @@ export default {
134 138  
135 139 },
136 140 remove: function (row) {
137   - console.log(row)
  141 + let all = typeof(row) === "undefined"
  142 + this.$confirm(`确定移除${all?"所有通道":""}吗?`, '提示', {
  143 + dangerouslyUseHTMLString: true,
  144 + confirmButtonText: '确定',
  145 + cancelButtonText: '取消',
  146 + type: 'warning'
  147 + }).then(() => {
  148 + console.log(row)
  149 +
  150 + this.$axios({
  151 + method:"delete",
  152 + url:"/api/platform/del_channel_for_gb",
  153 + data:{
  154 + platformId: this.platformId,
  155 + all: all,
  156 + channelReduces: all?[]:[row],
  157 + }
  158 + }).then((res)=>{
  159 + console.log("移除成功")
  160 + this.getChannelList();
  161 + }).catch(function (error) {
  162 + console.log(error);
  163 + });
  164 + }).catch(() => {
138 165  
139   - this.$axios({
140   - method:"delete",
141   - url:"/api/platform/del_channel_for_gb",
142   - data:{
143   - platformId: this.platformId,
144   - channelReduces: [row]
145   - }
146   - }).then((res)=>{
147   - console.log("移除成功")
148   - this.getChannelList();
149   - }).catch(function (error) {
150   - console.log(error);
151 166 });
  167 +
  168 +
152 169 },
153 170 // checkedChange: function (val) {
154 171 // let that = this;
... ...
web_src/src/components/dialog/chooseChannelForStream.vue
... ... @@ -24,6 +24,8 @@
24 24 </el-select>
25 25 <el-button v-if="catalogId !== null" icon="el-icon-delete" size="mini" style="margin-right: 1rem;" :disabled="gbStreams.length === 0 || multipleSelection.length === 0" type="danger" @click="batchDel">批量移除</el-button>
26 26 <el-button v-if="catalogId === null" icon="el-icon-plus" size="mini" style="margin-right: 1rem;" :disabled="gbStreams.length === 0 || multipleSelection.length === 0" @click="batchAdd">批量添加</el-button>
  27 + <el-button v-if="catalogId === null" icon="el-icon-plus" size="mini" style="margin-right: 1rem;" @click="add()">全部添加</el-button>
  28 + <el-button v-if="catalogId !== null" type="danger" icon="el-icon-delete" size="mini" style="margin-right: 1rem;" @click="remove()">全部移除</el-button>
27 29 </div>
28 30 <el-table ref="gbStreamsTable" :data="gbStreams" border style="width: 100%" :height="winHeight" :row-key="(row)=> row.app + row.stream" @selection-change="handleSelectionChange">
29 31 <el-table-column align="center" type="selection" :reserve-selection="true" width="55">
... ... @@ -128,6 +130,7 @@ export default {
128 130  
129 131 },
130 132 add: function (row, scope) {
  133 + let all = typeof(row) === "undefined"
131 134 this.getCatalogFromUser((catalogId)=>{
132 135 this.$axios({
133 136 method:"post",
... ... @@ -135,7 +138,8 @@ export default {
135 138 data:{
136 139 platformId: this.platformId,
137 140 catalogId: catalogId,
138   - gbStreams: [row],
  141 + all: all,
  142 + gbStreams: all?[]:[row],
139 143 }
140 144 }).then((res)=>{
141 145 console.log("保存成功")
... ... @@ -149,20 +153,33 @@ export default {
149 153  
150 154 },
151 155 remove: function (row, scope) {
152   - this.$axios({
153   - method:"delete",
154   - url:"/api/gbStream/del",
155   - data:{
156   - platformId: this.platformId,
157   - gbStreams: [row],
158   - }
159   - }).then((res)=>{
160   - console.log("移除成功")
161   - // this.gbStreams.splice(scope.$index,1)
162   - this.getChannelList();
163   - }).catch(function (error) {
164   - console.log(error);
  156 + let all = typeof(row) === "undefined"
  157 + this.$confirm(`确定移除${all?"所有通道":""}吗?`, '提示', {
  158 + dangerouslyUseHTMLString: true,
  159 + confirmButtonText: '确定',
  160 + cancelButtonText: '取消',
  161 + type: 'warning'
  162 + }).then(() => {
  163 +
  164 + this.$axios({
  165 + method:"delete",
  166 + url:"/api/gbStream/del",
  167 + data:{
  168 + platformId: this.platformId,
  169 + all: all,
  170 + gbStreams: all?[]:[row],
  171 + }
  172 + }).then((res)=>{
  173 + console.log("移除成功")
  174 + // this.gbStreams.splice(scope.$index,1)
  175 + this.getChannelList();
  176 + }).catch(function (error) {
  177 + console.log(error);
  178 + });
  179 + }).catch(() => {
  180 +
165 181 });
  182 +
166 183 },
167 184 getChannelList: function () {
168 185 let that = this;
... ...