Browse Source

Merge branch 'wvp-28181-2.0'

# Conflicts:
#	src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/PlayController.java
648540858 2 years ago
parent
commit
12fa3b4c8d
35 changed files with 404 additions and 263 deletions
  1. 10 10
      doc/README.md
  2. 1 1
      sql/mysql.sql
  3. 5 0
      sql/update.sql
  4. 5 5
      src/main/java/com/genersoft/iot/vmp/conf/GlobalExceptionHandler.java
  5. 10 0
      src/main/java/com/genersoft/iot/vmp/conf/UserSetting.java
  6. 5 6
      src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java
  7. 1 0
      src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java
  8. 3 9
      src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRESTfulUtils.java
  9. 12 21
      src/main/java/com/genersoft/iot/vmp/media/zlm/dto/StreamProxyItem.java
  10. 8 0
      src/main/java/com/genersoft/iot/vmp/service/IDeviceChannelService.java
  11. 14 0
      src/main/java/com/genersoft/iot/vmp/service/IGbStreamService.java
  12. 7 0
      src/main/java/com/genersoft/iot/vmp/service/IPlatformChannelService.java
  13. 9 0
      src/main/java/com/genersoft/iot/vmp/service/impl/DeviceChannelServiceImpl.java
  14. 11 9
      src/main/java/com/genersoft/iot/vmp/service/impl/DeviceServiceImpl.java
  15. 32 2
      src/main/java/com/genersoft/iot/vmp/service/impl/GbStreamServiceImpl.java
  16. 23 0
      src/main/java/com/genersoft/iot/vmp/service/impl/PlatformChannelServiceImpl.java
  17. 10 24
      src/main/java/com/genersoft/iot/vmp/service/impl/StreamProxyServiceImpl.java
  18. 0 1
      src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceChannelMapper.java
  19. 1 1
      src/main/java/com/genersoft/iot/vmp/storager/dao/GbStreamMapper.java
  20. 8 0
      src/main/java/com/genersoft/iot/vmp/storager/dao/PlatformChannelMapper.java
  21. 3 0
      src/main/java/com/genersoft/iot/vmp/storager/dao/PlatformGbStreamMapper.java
  22. 3 3
      src/main/java/com/genersoft/iot/vmp/storager/dao/StreamProxyMapper.java
  23. 0 15
      src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStorageImpl.java
  24. 17 10
      src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/gbStream/GbStreamController.java
  25. 11 0
      src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/gbStream/bean/GbStreamParam.java
  26. 26 5
      src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/platform/PlatformController.java
  27. 11 0
      src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/platform/bean/UpdateChannelParam.java
  28. 1 4
      src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/PlayController.java
  29. 0 1
      src/main/java/com/genersoft/iot/vmp/vmanager/streamProxy/StreamProxyController.java
  30. 2 0
      src/main/resources/all-application.yml
  31. 31 38
      web_src/src/components/StreamProxyList.vue
  32. 40 40
      web_src/src/components/dialog/StreamProxyEdit.vue
  33. 20 28
      web_src/src/components/dialog/SyncChannelProgress.vue
  34. 33 16
      web_src/src/components/dialog/chooseChannelForGb.vue
  35. 31 14
      web_src/src/components/dialog/chooseChannelForStream.vue

+ 10 - 10
doc/README.md

@@ -21,22 +21,22 @@
 - [X] 实时视音频点播
 - [X] 设备控制
   - [X] 云台控制
-  - [ ] 远程启动
-  - [ ] 录像控制
-  - [ ] 报警布防/撤防
-  - [ ] 报警复位
+  - [X] 远程启动
+  - [X] 录像控制
+  - [X] 报警布防/撤防
+  - [X] 报警复位
   - [X] 强制关键帧
-  - [ ] 拉框放大
-  - [ ] 拉框缩小
-  - [ ] 看守位控制
-  - [ ] 设备配置
+  - [X] 拉框放大
+  - [X] 拉框缩小
+  - [X] 看守位控制
+  - [X] 设备配置
 - [X] 报警事件通知和分发
 - [X] 设备目录订阅
 - [X] 网络设备信息查询
   - [X] 设备目录查询
   - [X] 设备状态查询
-  - [ ] 设备配置查询
-  - [ ] 设备预置位查询
+  - [X] 设备配置查询
+  - [X] 设备预置位查询
 - [X] 状态信息报送
 - [X] 设备视音频文件检索
 - [X] 历史视音频的回放

+ 1 - 1
sql/mysql.sql

@@ -446,7 +446,7 @@ CREATE TABLE `stream_proxy` (
                                 `ffmpeg_cmd_key` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
                                 `rtp_type` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
                                 `mediaServerId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
-                                `enable_hls` bit(1) DEFAULT NULL,
+                                `enable_audio` bit(1) DEFAULT NULL,
                                 `enable_mp4` bit(1) DEFAULT NULL,
                                 `enable` bit(1) NOT NULL,
                                 `status` bit(1) NOT NULL,

+ 5 - 0
sql/update.sql

@@ -36,3 +36,8 @@ alter table device
 
 alter table device
     modify hostAddress varchar(50) null;
+
+alter table stream_proxy
+    change enable_hls enable_audio bit null;
+
+

+ 5 - 5
src/main/java/com/genersoft/iot/vmp/conf/GlobalExceptionHandler.java

@@ -1,12 +1,12 @@
 package com.genersoft.iot.vmp.conf;
 
 import com.genersoft.iot.vmp.conf.exception.ControllerException;
-import com.genersoft.iot.vmp.gb28181.event.alarm.AlarmEventListener;
 import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
 import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
 import org.springframework.security.authentication.BadCredentialsException;
 import org.springframework.web.bind.annotation.ExceptionHandler;
 import org.springframework.web.bind.annotation.ResponseStatus;
@@ -40,8 +40,8 @@ public class GlobalExceptionHandler {
      */
     @ExceptionHandler(ControllerException.class)
     @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
-    public WVPResult<String> exceptionHandler(ControllerException e) {
-        return WVPResult.fail(e.getCode(), e.getMsg());
+    public ResponseEntity<WVPResult<String>> exceptionHandler(ControllerException e) {
+        return new ResponseEntity<>(WVPResult.fail(e.getCode(), e.getMsg()), HttpStatus.OK);
     }
 
     /**
@@ -51,7 +51,7 @@ public class GlobalExceptionHandler {
      */
     @ExceptionHandler(BadCredentialsException.class)
     @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
-    public WVPResult<String> exceptionHandler(BadCredentialsException e) {
-        return WVPResult.fail(ErrorCode.ERROR100.getCode(), e.getMessage());
+    public ResponseEntity<WVPResult<String>> exceptionHandler(BadCredentialsException e) {
+        return new ResponseEntity<>(WVPResult.fail(ErrorCode.ERROR100.getCode(), e.getMessage()), HttpStatus.OK);
     }
 }

+ 10 - 0
src/main/java/com/genersoft/iot/vmp/conf/UserSetting.java

@@ -41,6 +41,8 @@ public class UserSetting {
 
     private Boolean gbSendStreamStrict = Boolean.FALSE;
 
+    private Boolean syncChannelOnDeviceOnline = Boolean.FALSE;
+
     private String serverId = "000000";
 
     private String thirdPartyGBIdReg = "[\\s\\S]*";
@@ -186,4 +188,12 @@ public class UserSetting {
     public void setGbSendStreamStrict(Boolean gbSendStreamStrict) {
         this.gbSendStreamStrict = gbSendStreamStrict;
     }
+
+    public Boolean getSyncChannelOnDeviceOnline() {
+        return syncChannelOnDeviceOnline;
+    }
+
+    public void setSyncChannelOnDeviceOnline(Boolean syncChannelOnDeviceOnline) {
+        this.syncChannelOnDeviceOnline = syncChannelOnDeviceOnline;
+    }
 }

+ 5 - 6
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java

@@ -2,7 +2,9 @@ package com.genersoft.iot.vmp.gb28181.transmit.cmd;
 
 import com.genersoft.iot.vmp.common.StreamInfo;
 import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException;
-import com.genersoft.iot.vmp.gb28181.bean.*;
+import com.genersoft.iot.vmp.gb28181.bean.Device;
+import com.genersoft.iot.vmp.gb28181.bean.DeviceAlarm;
+import com.genersoft.iot.vmp.gb28181.bean.InviteStreamCallback;
 import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
 import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe;
 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
@@ -10,10 +12,7 @@ import com.genersoft.iot.vmp.service.bean.SSRCInfo;
 import gov.nist.javax.sip.message.SIPRequest;
 
 import javax.sip.InvalidArgumentException;
-import javax.sip.PeerUnavailableException;
 import javax.sip.SipException;
-import javax.sip.message.Message;
-import javax.sip.message.Request;
 import java.text.ParseException;
 import javax.sip.message.Message;
 import javax.sip.message.Request;
@@ -234,7 +233,7 @@ public interface ISIPCommander {
 	 */
 	void deviceConfigCmd(Device device);
 	
-		/**
+	/**
 	 * 设备配置命令:basicParam
 	 * 
 	 * @param device  			视频设备
@@ -245,7 +244,7 @@ public interface ISIPCommander {
 	 * @param heartBeatCount	心跳超时次数(可选)
 	 */  
 	void deviceBasicConfigCmd(Device device, String channelId, String name, String expiration, String heartBeatInterval, String heartBeatCount, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
-	
+
 	/**
 	 * 查询设备状态
 	 * 

+ 1 - 0
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java

@@ -646,6 +646,7 @@ public class ZLMHttpHookListener {
 					// 修改数据
 					streamProxyService.stop(param.getApp(), param.getStream());
 				}else {
+					// 无人观看不做处理
 					ret.put("close", false);
 				}
 				return ret;

+ 3 - 9
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRESTfulUtils.java

@@ -239,14 +239,13 @@ public class ZLMRESTfulUtils {
     }
 
     public JSONObject addFFmpegSource(MediaServerItem mediaServerItem, String src_url, String dst_url, String timeout_ms,
-                                      boolean enable_hls, boolean enable_mp4, String ffmpeg_cmd_key){
+                                      boolean enable_audio, boolean enable_mp4, String ffmpeg_cmd_key){
         logger.info(src_url);
         logger.info(dst_url);
         Map<String, Object> param = new HashMap<>();
         param.put("src_url", src_url);
         param.put("dst_url", dst_url);
         param.put("timeout_ms", timeout_ms);
-        param.put("enable_hls", enable_hls);
         param.put("enable_mp4", enable_mp4);
         param.put("ffmpeg_cmd_key", ffmpeg_cmd_key);
         return sendPost(mediaServerItem, "addFFmpegSource",param, null);
@@ -294,19 +293,14 @@ public class ZLMRESTfulUtils {
         return sendPost(mediaServerItem, "restartServer",null, null);
     }
 
-    public JSONObject addStreamProxy(MediaServerItem mediaServerItem, String app, String stream, String url, boolean enable_hls, boolean enable_mp4, String rtp_type) {
+    public JSONObject addStreamProxy(MediaServerItem mediaServerItem, String app, String stream, String url, boolean enable_audio, boolean enable_mp4, String rtp_type) {
         Map<String, Object> param = new HashMap<>();
         param.put("vhost", "__defaultVhost__");
         param.put("app", app);
         param.put("stream", stream);
         param.put("url", url);
-        param.put("enable_hls", enable_hls?1:0);
         param.put("enable_mp4", enable_mp4?1:0);
-        param.put("enable_rtmp", 1);
-        param.put("enable_fmp4", 1);
-        param.put("enable_audio", 1);
-        param.put("enable_rtsp", 1);
-        param.put("add_mute_audio", 1);
+        param.put("enable_audio", enable_audio?1:0);
         param.put("rtp_type", rtp_type);
         return sendPost(mediaServerItem, "addStreamProxy",param, null);
     }

+ 12 - 21
src/main/java/com/genersoft/iot/vmp/media/zlm/dto/StreamProxyItem.java

@@ -31,8 +31,8 @@ public class StreamProxyItem extends GbStream {
     private String rtp_type;
     @Schema(description = "是否启用")
     private boolean enable;
-    @Schema(description = "是否启用HLS")
-    private boolean enable_hls;
+    @Schema(description = "是否启用音频")
+    private boolean enable_audio;
     @Schema(description = "是否启用MP4")
     private boolean enable_mp4;
     @Schema(description = "是否 无人观看时删除")
@@ -40,8 +40,6 @@ public class StreamProxyItem extends GbStream {
 
     @Schema(description = "是否 无人观看时自动停用")
     private boolean enable_disable_none_reader;
-    @Schema(description = "上级平台国标ID")
-    private String platformGbId;
     @Schema(description = "创建时间")
     private String createTime;
 
@@ -139,14 +137,6 @@ public class StreamProxyItem extends GbStream {
         this.enable = enable;
     }
 
-    public boolean isEnable_hls() {
-        return enable_hls;
-    }
-
-    public void setEnable_hls(boolean enable_hls) {
-        this.enable_hls = enable_hls;
-    }
-
     public boolean isEnable_mp4() {
         return enable_mp4;
     }
@@ -155,19 +145,12 @@ public class StreamProxyItem extends GbStream {
         this.enable_mp4 = enable_mp4;
     }
 
-
-    public String getPlatformGbId() {
-        return platformGbId;
-    }
-
-    public void setPlatformGbId(String platformGbId) {
-        this.platformGbId = platformGbId;
-    }
-
+    @Override
     public String getCreateTime() {
         return createTime;
     }
 
+    @Override
     public void setCreateTime(String createTime) {
         this.createTime = createTime;
     }
@@ -187,4 +170,12 @@ public class StreamProxyItem extends GbStream {
     public void setEnable_disable_none_reader(boolean enable_disable_none_reader) {
         this.enable_disable_none_reader = enable_disable_none_reader;
     }
+
+    public boolean isEnable_audio() {
+        return enable_audio;
+    }
+
+    public void setEnable_audio(boolean enable_audio) {
+        this.enable_audio = enable_audio;
+    }
 }

+ 8 - 0
src/main/java/com/genersoft/iot/vmp/service/IDeviceChannelService.java

@@ -3,6 +3,7 @@ package com.genersoft.iot.vmp.service;
 import com.genersoft.iot.vmp.gb28181.bean.Device;
 import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
 import com.genersoft.iot.vmp.vmanager.bean.ResourceBaceInfo;
+import com.genersoft.iot.vmp.vmanager.gb28181.platform.bean.ChannelReduce;
 
 import java.util.List;
 
@@ -38,4 +39,11 @@ public interface IDeviceChannelService {
      * @return
      */
     ResourceBaceInfo getOverview();
+
+    /**
+     * 查询所有未分配的通道
+     * @param platformId
+     * @return
+     */
+    List<ChannelReduce> queryAllChannelList(String platformId);
 }

+ 14 - 0
src/main/java/com/genersoft/iot/vmp/service/IGbStreamService.java

@@ -55,4 +55,18 @@ public interface IGbStreamService {
     int updateGbIdOrName(List<StreamPushItem> streamPushItemForUpdate);
 
     DeviceChannel getDeviceChannelListByStreamWithStatus(GbStream gbStream, String catalogId, ParentPlatform platform);
+
+    /**
+     * 查询所有未分配的通道
+     * @param platformId
+     * @return
+     */
+    List<GbStream> getAllGBChannels(String platformId);
+
+    /**
+     * 移除所有关联的通道
+     * @param platformId
+     * @param catalogId
+     */
+    void delAllPlatformInfo(String platformId, String catalogId);
 }

+ 7 - 0
src/main/java/com/genersoft/iot/vmp/service/IPlatformChannelService.java

@@ -19,4 +19,11 @@ public interface IPlatformChannelService {
      */
     int updateChannelForGB(String platformId, List<ChannelReduce> channelReduces, String catalogId);
 
+    /**
+     * 移除目录下的所有通道
+     * @param platformId
+     * @param catalogId
+     * @return
+     */
+    int delAllChannelForGB(String platformId, String catalogId);
 }

+ 9 - 0
src/main/java/com/genersoft/iot/vmp/service/impl/DeviceChannelServiceImpl.java

@@ -10,6 +10,7 @@ import com.genersoft.iot.vmp.storager.dao.DeviceChannelMapper;
 import com.genersoft.iot.vmp.storager.dao.DeviceMapper;
 import com.genersoft.iot.vmp.utils.DateUtil;
 import com.genersoft.iot.vmp.vmanager.bean.ResourceBaceInfo;
+import com.genersoft.iot.vmp.vmanager.gb28181.platform.bean.ChannelReduce;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -168,4 +169,12 @@ public class DeviceChannelServiceImpl implements IDeviceChannelService {
     public ResourceBaceInfo getOverview() {
         return channelMapper.getOverview();
     }
+
+
+    @Override
+    public List<ChannelReduce> queryAllChannelList(String platformId) {
+        return channelMapper.queryChannelListInAll(null, null, null, platformId, null);
+    }
+
+
 }

+ 11 - 9
src/main/java/com/genersoft/iot/vmp/service/impl/DeviceServiceImpl.java

@@ -1,6 +1,7 @@
 package com.genersoft.iot.vmp.service.impl;
 
 import com.genersoft.iot.vmp.conf.DynamicTask;
+import com.genersoft.iot.vmp.conf.UserSetting;
 import com.genersoft.iot.vmp.gb28181.bean.*;
 import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
 import com.genersoft.iot.vmp.gb28181.task.ISubscribeTask;
@@ -12,7 +13,6 @@ import com.genersoft.iot.vmp.service.IDeviceChannelService;
 import com.genersoft.iot.vmp.service.IDeviceService;
 import com.genersoft.iot.vmp.service.IMediaServerService;
 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
-import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
 import com.genersoft.iot.vmp.storager.dao.DeviceChannelMapper;
 import com.genersoft.iot.vmp.storager.dao.DeviceMapper;
 import com.genersoft.iot.vmp.storager.dao.PlatformChannelMapper;
@@ -78,7 +78,7 @@ public class DeviceServiceImpl implements IDeviceService {
     TransactionDefinition transactionDefinition;
 
     @Autowired
-    private IVideoManagerStorage storage;
+    private UserSetting userSetting;
 
     @Autowired
     private ISIPCommander commander;
@@ -120,16 +120,18 @@ public class DeviceServiceImpl implements IDeviceService {
             if(device.getOnline() == 0){
                 device.setOnline(1);
                 device.setCreateTime(now);
-                logger.info("[设备上线,离线状态下重新注册]: {},查询设备信息以及通道信息", device.getDeviceId());
                 deviceMapper.update(device);
                 redisCatchStorage.updateDevice(device);
-                try {
-                    commander.deviceInfoQuery(device);
-                } catch (InvalidArgumentException | SipException | ParseException e) {
-                    logger.error("[命令发送失败] 查询设备信息: {}", e.getMessage());
+                if (userSetting.getSyncChannelOnDeviceOnline()) {
+                    logger.info("[设备上线,离线状态下重新注册]: {},查询设备信息以及通道信息", device.getDeviceId());
+                    try {
+                        commander.deviceInfoQuery(device);
+                    } catch (InvalidArgumentException | SipException | ParseException e) {
+                        logger.error("[命令发送失败] 查询设备信息: {}", e.getMessage());
+                    }
+                    sync(device);
+                    // TODO 如果设备下的通道级联到了其他平台,那么需要发送事件或者notify给上级平台
                 }
-                sync(device);
-                // TODO 如果设备下的通道级联到了其他平台,那么需要发送事件或者notify给上级平台
             }else {
                 if (deviceChannelMapper.queryAllChannels(device.getDeviceId()).size() == 0) {
                     logger.info("[设备上线]: {},通道数为0,查询通道信息", device.getDeviceId());

+ 32 - 2
src/main/java/com/genersoft/iot/vmp/service/impl/GbStreamServiceImpl.java

@@ -4,11 +4,11 @@ import com.genersoft.iot.vmp.gb28181.bean.*;
 import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
 import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent;
 import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem;
+import com.genersoft.iot.vmp.service.IGbStreamService;
 import com.genersoft.iot.vmp.storager.dao.GbStreamMapper;
 import com.genersoft.iot.vmp.storager.dao.ParentPlatformMapper;
 import com.genersoft.iot.vmp.storager.dao.PlatformCatalogMapper;
 import com.genersoft.iot.vmp.storager.dao.PlatformGbStreamMapper;
-import com.genersoft.iot.vmp.service.IGbStreamService;
 import com.github.pagehelper.PageHelper;
 import com.github.pagehelper.PageInfo;
 import org.slf4j.Logger;
@@ -19,7 +19,6 @@ import org.springframework.stereotype.Service;
 import org.springframework.transaction.TransactionDefinition;
 import org.springframework.transaction.TransactionStatus;
 import org.springframework.util.ObjectUtils;
-import org.springframework.util.StringUtils;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -230,4 +229,35 @@ public class GbStreamServiceImpl implements IGbStreamService {
         deviceChannel.setSecrecy("0");
         return deviceChannel;
     }
+
+    @Override
+    public List<GbStream> getAllGBChannels(String platformId) {
+
+        return gbStreamMapper.selectAll(platformId, null, null, null);
+
+    }
+
+    @Override
+    public void delAllPlatformInfo(String platformId, String catalogId) {
+        if (platformId == null) {
+            return ;
+        }
+        ParentPlatform platform = platformMapper.getParentPlatByServerGBId(platformId);
+        if (platform == null) {
+            return ;
+        }
+        if (ObjectUtils.isEmpty(catalogId)) {
+            catalogId = platform.getDeviceGBId();
+        }
+        if (platformGbStreamMapper.delByPlatformAndCatalogId(platformId, catalogId) > 0) {
+            List<GbStream> gbStreams = platformGbStreamMapper.queryChannelInParentPlatformAndCatalog(platformId, catalogId);
+            List<DeviceChannel> deviceChannelList = new ArrayList<>();
+            for (GbStream gbStream : gbStreams) {
+                DeviceChannel deviceChannel = new DeviceChannel();
+                deviceChannel.setChannelId(gbStream.getGbId());
+                deviceChannelList.add(deviceChannel);
+            }
+            eventPublisher.catalogEventPublish(platformId, deviceChannelList, CatalogEvent.DEL);
+        }
+    }
 }

+ 23 - 0
src/main/java/com/genersoft/iot/vmp/service/impl/PlatformChannelServiceImpl.java

@@ -16,6 +16,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
+import org.springframework.util.ObjectUtils;
 
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -105,4 +106,26 @@ public class PlatformChannelServiceImpl implements IPlatformChannelService {
         }
         return deviceChannelList;
     }
+
+    @Override
+    public int delAllChannelForGB(String platformId, String catalogId) {
+
+        int result;
+        if (platformId == null) {
+            return 0;
+        }
+        ParentPlatform platform = platformMapper.getParentPlatByServerGBId(platformId);
+        if (platform == null) {
+            return 0;
+        }
+        if (ObjectUtils.isEmpty(catalogId)) {
+           catalogId = platform.getDeviceGBId();
+        }
+
+        if ((result = platformChannelMapper.delChannelForGBByCatalogId(platformId, catalogId)) > 0) {
+            List<DeviceChannel> deviceChannels = platformChannelMapper.queryAllChannelInCatalog(platformId, catalogId);
+            eventPublisher.catalogEventPublish(platformId, deviceChannels, CatalogEvent.DEL);
+        }
+        return result;
+    }
 }

+ 10 - 24
src/main/java/com/genersoft/iot/vmp/service/impl/StreamProxyServiceImpl.java

@@ -5,23 +5,22 @@ import com.alibaba.fastjson2.JSONObject;
 import com.genersoft.iot.vmp.common.StreamInfo;
 import com.genersoft.iot.vmp.conf.UserSetting;
 import com.genersoft.iot.vmp.conf.exception.ControllerException;
-import com.genersoft.iot.vmp.gb28181.bean.GbStream;
 import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
 import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent;
 import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
-import com.genersoft.iot.vmp.media.zlm.dto.hook.OnStreamChangedHookParam;
 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
 import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem;
+import com.genersoft.iot.vmp.media.zlm.dto.hook.OnStreamChangedHookParam;
 import com.genersoft.iot.vmp.service.IGbStreamService;
 import com.genersoft.iot.vmp.service.IMediaServerService;
 import com.genersoft.iot.vmp.service.IMediaService;
+import com.genersoft.iot.vmp.service.IStreamProxyService;
 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
 import com.genersoft.iot.vmp.storager.dao.GbStreamMapper;
 import com.genersoft.iot.vmp.storager.dao.ParentPlatformMapper;
 import com.genersoft.iot.vmp.storager.dao.PlatformGbStreamMapper;
 import com.genersoft.iot.vmp.storager.dao.StreamProxyMapper;
-import com.genersoft.iot.vmp.service.IStreamProxyService;
 import com.genersoft.iot.vmp.utils.DateUtil;
 import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
 import com.genersoft.iot.vmp.vmanager.bean.ResourceBaceInfo;
@@ -35,7 +34,9 @@ import org.springframework.transaction.TransactionDefinition;
 import org.springframework.transaction.TransactionStatus;
 import org.springframework.util.ObjectUtils;
 
-import java.util.*;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
 
 /**
  * 视频代理业务
@@ -101,7 +102,6 @@ public class StreamProxyServiceImpl implements IStreamProxyService {
                 param.getStream() );
         param.setDst_url(dstUrl);
         StringBuffer resultMsg = new StringBuffer();
-        boolean streamLive = false;
         param.setMediaServerId(mediaInfo.getId());
         boolean saveResult;
         // 更新
@@ -118,7 +118,6 @@ public class StreamProxyServiceImpl implements IStreamProxyService {
         if (param.isEnable()) {
             JSONObject jsonObject = addStreamProxyToZlm(param);
             if (jsonObject == null || jsonObject.getInteger("code") != 0) {
-                streamLive = false;
                 resultMsg.append(", 但是启用失败,请检查流地址是否可用");
                 param.setEnable(false);
                 // 直接移除
@@ -128,28 +127,12 @@ public class StreamProxyServiceImpl implements IStreamProxyService {
                     updateStreamProxy(param);
                 }
 
-
             }else {
-                streamLive = true;
                 resultForStreamInfo = mediaService.getStreamInfoByAppAndStream(
                         mediaInfo, param.getApp(), param.getStream(), null, null);
 
             }
         }
-        if ( !ObjectUtils.isEmpty(param.getPlatformGbId()) && streamLive) {
-            List<GbStream> gbStreams = new ArrayList<>();
-            gbStreams.add(param);
-            if (gbStreamService.addPlatformInfo(gbStreams, param.getPlatformGbId(), param.getCatalogId())){
-                return resultForStreamInfo;
-            }else {
-                resultMsg.append(",  关联国标平台[ " + param.getPlatformGbId() + " ]失败");
-                throw new ControllerException(ErrorCode.ERROR100.getCode(), resultMsg.toString());
-            }
-        }else {
-            if (!streamLive) {
-                throw new ControllerException(ErrorCode.ERROR100.getCode(), resultMsg.toString());
-            }
-        }
         return resultForStreamInfo;
     }
 
@@ -239,10 +222,10 @@ public class StreamProxyServiceImpl implements IStreamProxyService {
         }
         if ("default".equals(param.getType())){
             result = zlmresTfulUtils.addStreamProxy(mediaServerItem, param.getApp(), param.getStream(), param.getUrl(),
-                    param.isEnable_hls(), param.isEnable_mp4(), param.getRtp_type());
+                    param.isEnable_audio(), param.isEnable_mp4(), param.getRtp_type());
         }else if ("ffmpeg".equals(param.getType())) {
             result = zlmresTfulUtils.addFFmpegSource(mediaServerItem, param.getSrc_url(), param.getDst_url(),
-                    param.getTimeout_ms() + "", param.isEnable_hls(), param.isEnable_mp4(),
+                    param.getTimeout_ms() + "", param.isEnable_audio(), param.isEnable_mp4(),
                     param.getFfmpeg_cmd_key());
         }
         return result;
@@ -295,6 +278,9 @@ public class StreamProxyServiceImpl implements IStreamProxyService {
                 result = true;
                 streamProxy.setEnable(true);
                 updateStreamProxy(streamProxy);
+            }else {
+                logger.info("启用代理失败: {}/{}->{}({})", app, stream, jsonObject.getString("msg"),
+                        streamProxy.getSrc_url() == null? streamProxy.getUrl():streamProxy.getSrc_url());
             }
         }
         return result;

+ 0 - 1
src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceChannelMapper.java

@@ -1,6 +1,5 @@
 package com.genersoft.iot.vmp.storager.dao;
 
-import com.genersoft.iot.vmp.gb28181.bean.Device;
 import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
 import com.genersoft.iot.vmp.gb28181.bean.DeviceChannelInPlatform;
 import com.genersoft.iot.vmp.vmanager.bean.ResourceBaceInfo;

+ 1 - 1
src/main/java/com/genersoft/iot/vmp/storager/dao/GbStreamMapper.java

@@ -5,7 +5,6 @@ import com.genersoft.iot.vmp.gb28181.bean.GbStream;
 import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem;
 import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem;
 import com.genersoft.iot.vmp.service.bean.GPSMsgInfo;
-import com.genersoft.iot.vmp.vmanager.bean.StreamPushExcelDto;
 import org.apache.ibatis.annotations.*;
 import org.springframework.stereotype.Repository;
 
@@ -169,4 +168,5 @@ public interface GbStreamMapper {
 
     @Select("SELECT status FROM stream_push WHERE app=#{app} AND stream=#{stream}")
     Boolean selectStatusForPush(String app, String stream);
+
 }

+ 8 - 0
src/main/java/com/genersoft/iot/vmp/storager/dao/PlatformChannelMapper.java

@@ -57,6 +57,9 @@ public interface PlatformChannelMapper {
     @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}'")
     List<DeviceChannel> queryChannelInParentPlatform(String platformId, String channelId);
 
+    @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}")
+    List<DeviceChannel> queryAllChannelInCatalog(String platformId, String catalogId);
+
     @Select(" select dc.channelId as id, dc.name as name, pgc.platformId as platformId, pgc.catalogId as parentId, 0 as childrenCount, 1 as type " +
             " from device_channel dc left join platform_gb_channel pgc on dc.id = pgc.deviceChannelId " +
             " where pgc.platformId=#{platformId} and pgc.catalogId=#{catalogId}")
@@ -99,4 +102,9 @@ public interface PlatformChannelMapper {
            "DELETE FROM platform_gb_channel WHERE platformId=#{serverGBId}"  +
            "</script>")
     void delByPlatformId(String serverGBId);
+
+    @Delete("<script> " +
+            "DELETE FROM platform_gb_channel WHERE platformId=#{platformId} and catalogId=#{catalogId}"  +
+            "</script>")
+    int delChannelForGBByCatalogId(String platformId, String catalogId);
 }

+ 3 - 0
src/main/java/com/genersoft/iot/vmp/storager/dao/PlatformGbStreamMapper.java

@@ -105,4 +105,7 @@ public interface PlatformGbStreamMapper {
             "</foreach>" +
             "</script>")
     void delByAppAndStreamsByPlatformId(List<GbStream> gbStreams, String platformId);
+
+    @Delete("DELETE FROM platform_gb_stream WHERE platformId=#{platformId} and catalogId=#{catalogId}")
+    int delByPlatformAndCatalogId(String platformId, String catalogId);
 }

+ 3 - 3
src/main/java/com/genersoft/iot/vmp/storager/dao/StreamProxyMapper.java

@@ -12,9 +12,9 @@ import java.util.List;
 public interface StreamProxyMapper {
 
     @Insert("INSERT INTO stream_proxy (type, name, app, stream,mediaServerId, url, src_url, dst_url, " +
-            "timeout_ms, ffmpeg_cmd_key, rtp_type, enable_hls, enable_mp4, enable, status, enable_remove_none_reader, enable_disable_none_reader, createTime) VALUES" +
+            "timeout_ms, ffmpeg_cmd_key, rtp_type, enable_audio, enable_mp4, enable, status, enable_remove_none_reader, enable_disable_none_reader, createTime) VALUES" +
             "('${type}','${name}', '${app}', '${stream}', '${mediaServerId}','${url}', '${src_url}', '${dst_url}', " +
-            "'${timeout_ms}', '${ffmpeg_cmd_key}', '${rtp_type}', ${enable_hls}, ${enable_mp4}, ${enable}, ${status}, " +
+            "'${timeout_ms}', '${ffmpeg_cmd_key}', '${rtp_type}', ${enable_audio}, ${enable_mp4}, ${enable}, ${status}, " +
             "${enable_remove_none_reader}, ${enable_disable_none_reader}, '${createTime}' )")
     int add(StreamProxyItem streamProxyDto);
 
@@ -30,7 +30,7 @@ public interface StreamProxyMapper {
             "timeout_ms=#{timeout_ms}, " +
             "ffmpeg_cmd_key=#{ffmpeg_cmd_key}, " +
             "rtp_type=#{rtp_type}, " +
-            "enable_hls=#{enable_hls}, " +
+            "enable_audio=#{enable_audio}, " +
             "enable=#{enable}, " +
             "status=#{status}, " +
             "enable_remove_none_reader=#{enable_remove_none_reader}, " +

+ 0 - 15
src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStorageImpl.java

@@ -1,13 +1,11 @@
 package com.genersoft.iot.vmp.storager.impl;
 
-import com.genersoft.iot.vmp.common.StreamInfo;
 import com.genersoft.iot.vmp.conf.SipConfig;
 import com.genersoft.iot.vmp.conf.UserSetting;
 import com.genersoft.iot.vmp.gb28181.bean.*;
 import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
 import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent;
 import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem;
-import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem;
 import com.genersoft.iot.vmp.service.IGbStreamService;
 import com.genersoft.iot.vmp.service.bean.GPSMsgInfo;
 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
@@ -28,7 +26,6 @@ import org.springframework.transaction.TransactionStatus;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.util.CollectionUtils;
 import org.springframework.util.ObjectUtils;
-import org.springframework.util.StringUtils;
 
 import java.util.*;
 import java.util.concurrent.ConcurrentHashMap;
@@ -761,18 +758,6 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage {
 		return gbStreamMapper.updateStreamGPS(gpsMsgInfos);
 	}
 
-	private List<DeviceChannel> getDeviceChannelListByChannelReduceList(List<ChannelReduce> channelReduces, String catalogId) {
-		List<DeviceChannel> deviceChannelList = new ArrayList<>();
-		if (channelReduces.size() > 0){
-			for (ChannelReduce channelReduce : channelReduces) {
-				DeviceChannel deviceChannel = queryChannel(channelReduce.getDeviceId(), channelReduce.getChannelId());
-				deviceChannel.setParental(1);
-				deviceChannel.setParentId(catalogId);
-				deviceChannelList.add(deviceChannel);
-			}
-		}
-		return deviceChannelList;
-	}
 
 	private DeviceChannel getDeviceChannelByCatalog(PlatformCatalog catalog) {
 		ParentPlatform platform = platformMapper.getParentPlatByServerGBId(catalog.getPlatformId());

+ 17 - 10
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/gbStream/GbStreamController.java

@@ -1,9 +1,9 @@
 package com.genersoft.iot.vmp.vmanager.gb28181.gbStream;
 
 import com.genersoft.iot.vmp.gb28181.bean.GbStream;
+import com.genersoft.iot.vmp.service.IGbStreamService;
 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
 import com.genersoft.iot.vmp.vmanager.gb28181.gbStream.bean.GbStreamParam;
-import com.genersoft.iot.vmp.service.IGbStreamService;
 import com.github.pagehelper.PageInfo;
 import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.Parameter;
@@ -12,9 +12,10 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.util.ObjectUtils;
-import org.springframework.util.StringUtils;
 import org.springframework.web.bind.annotation.*;
 
+import java.util.List;
+
 @Tag(name  = "视频流关联到级联平台")
 @CrossOrigin
 @RestController
@@ -76,11 +77,14 @@ public class GbStreamController {
     @Operation(summary = "移除国标关联")
     @DeleteMapping(value = "/del")
     @ResponseBody
-    public Object del(@RequestBody GbStreamParam gbStreamParam){
-        if (gbStreamService.delPlatformInfo(gbStreamParam.getPlatformId(), gbStreamParam.getGbStreams())) {
-            return "success";
+    public void del(@RequestBody GbStreamParam gbStreamParam){
+
+        if (gbStreamParam.getGbStreams() == null || gbStreamParam.getGbStreams().size() == 0) {
+            if (gbStreamParam.isAll()) {
+                gbStreamService.delAllPlatformInfo(gbStreamParam.getPlatformId(), gbStreamParam.getCatalogId());
+            }
         }else {
-            return "fail";
+            gbStreamService.delPlatformInfo(gbStreamParam.getPlatformId(), gbStreamParam.getGbStreams());
         }
 
     }
@@ -93,11 +97,14 @@ public class GbStreamController {
     @Operation(summary = "保存国标关联")
     @PostMapping(value = "/add")
     @ResponseBody
-    public Object add(@RequestBody GbStreamParam gbStreamParam){
-        if (gbStreamService.addPlatformInfo(gbStreamParam.getGbStreams(), gbStreamParam.getPlatformId(), gbStreamParam.getCatalogId())) {
-            return "success";
+    public void add(@RequestBody GbStreamParam gbStreamParam){
+        if (gbStreamParam.getGbStreams() == null || gbStreamParam.getGbStreams().size() == 0) {
+            if (gbStreamParam.isAll()) {
+                List<GbStream> allGBChannels = gbStreamService.getAllGBChannels(gbStreamParam.getPlatformId());
+                gbStreamService.addPlatformInfo(allGBChannels, gbStreamParam.getPlatformId(), gbStreamParam.getCatalogId());
+            }
         }else {
-            return "fail";
+            gbStreamService.addPlatformInfo(gbStreamParam.getGbStreams(), gbStreamParam.getPlatformId(), gbStreamParam.getCatalogId());
         }
     }
 }

+ 11 - 0
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/gbStream/bean/GbStreamParam.java

@@ -14,6 +14,9 @@ public class GbStreamParam {
     @Schema(description = "目录ID")
     private String catalogId;
 
+    @Schema(description = "关联所有通道")
+    private boolean all;
+
     @Schema(description = "流国标信息列表")
     private List<GbStream> gbStreams;
 
@@ -40,4 +43,12 @@ public class GbStreamParam {
     public void setGbStreams(List<GbStream> gbStreams) {
         this.gbStreams = gbStreams;
     }
+
+    public boolean isAll() {
+        return all;
+    }
+
+    public void setAll(boolean all) {
+        this.all = all;
+    }
 }

+ 26 - 5
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/platform/PlatformController.java

@@ -10,8 +10,7 @@ import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
 import com.genersoft.iot.vmp.gb28181.bean.PlatformCatalog;
 import com.genersoft.iot.vmp.gb28181.bean.SubscribeHolder;
 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
-import com.genersoft.iot.vmp.service.IPlatformChannelService;
-import com.genersoft.iot.vmp.service.IPlatformService;
+import com.genersoft.iot.vmp.service.*;
 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
 import com.genersoft.iot.vmp.utils.DateUtil;
@@ -72,6 +71,12 @@ public class PlatformController {
 	@Autowired
 	private IPlatformService platformService;
 
+	@Autowired
+	private IDeviceChannelService deviceChannelService;
+
+	@Autowired
+	private IGbStreamService gbStreamService;
+
     /**
      * 获取国标服务的配置
      *
@@ -379,7 +384,16 @@ public class PlatformController {
         if (logger.isDebugEnabled()) {
             logger.debug("给上级平台添加国标通道API调用");
         }
-        int result = platformChannelService.updateChannelForGB(param.getPlatformId(), param.getChannelReduces(), param.getCatalogId());
+        int result = 0;
+        if (param.getChannelReduces() == null || param.getChannelReduces().size() == 0) {
+            if (param.isAll()) {
+                logger.info("[国标级联]添加所有通道到上级平台, {}", param.getPlatformId());
+                List<ChannelReduce> allChannelForDevice = deviceChannelService.queryAllChannelList(param.getPlatformId());
+                result = platformChannelService.updateChannelForGB(param.getPlatformId(), allChannelForDevice, param.getCatalogId());
+            }
+        }else {
+            result = platformChannelService.updateChannelForGB(param.getPlatformId(), param.getChannelReduces(), param.getCatalogId());
+        }
         if (result <= 0) {
             throw new ControllerException(ErrorCode.ERROR100);
         }
@@ -399,8 +413,15 @@ public class PlatformController {
         if (logger.isDebugEnabled()) {
             logger.debug("给上级平台删除国标通道API调用");
         }
-        int result = storager.delChannelForGB(param.getPlatformId(), param.getChannelReduces());
-
+        int result = 0;
+        if (param.getChannelReduces() == null || param.getChannelReduces().size() == 0) {
+            if (param.isAll()) {
+                logger.info("[国标级联]移除所有通道,上级平台, {}", param.getPlatformId());
+                result = platformChannelService.delAllChannelForGB(param.getPlatformId(), param.getCatalogId());
+            }
+        }else {
+            result = storager.delChannelForGB(param.getPlatformId(), param.getChannelReduces());
+        }
         if (result <= 0) {
             throw new ControllerException(ErrorCode.ERROR100);
         }

+ 11 - 0
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/platform/bean/UpdateChannelParam.java

@@ -17,6 +17,9 @@ public class UpdateChannelParam {
     @Schema(description = "目录的国标编号")
     private String catalogId;
 
+    @Schema(description = "处理所有通道")
+    private boolean all;
+
     @Schema(description = "")
     private List<ChannelReduce> channelReduces;
 
@@ -43,4 +46,12 @@ public class UpdateChannelParam {
     public void setCatalogId(String catalogId) {
         this.catalogId = catalogId;
     }
+
+    public boolean isAll() {
+        return all;
+    }
+
+    public void setAll(boolean all) {
+        this.all = all;
+    }
 }

+ 1 - 4
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/PlayController.java

@@ -111,7 +111,7 @@ public class PlayController {
 			resultHolder.invokeResult(msg);
 		});
 
-		if (userSetting.isUsePushingAsStatus()) {
+		if (userSetting.getUseSourceIpAsStreamIp()) {
 			// TODO 在点播未成功的情况下在此调用接口点播会导致返回的流地址ip错误
 			deferredResultEx.setFilter(result1 -> {
 				WVPResult<StreamInfo> wvpResult1 = (WVPResult<StreamInfo>)result1;
@@ -130,7 +130,6 @@ public class PlayController {
 			});
 		}
 
-
 		// 录像查询以channelId作为deviceId查询
 		resultHolder.put(key, uuid, deferredResultEx);
 
@@ -140,7 +139,6 @@ public class PlayController {
 		return result;
 	}
 
-
 	@Operation(summary = "停止点播")
 	@Parameter(name = "deviceId", description = "设备国标编号", required = true)
 	@Parameter(name = "channelId", description = "通道国标编号", required = true)
@@ -177,7 +175,6 @@ public class PlayController {
 		json.put("deviceId", deviceId);
 		json.put("channelId", channelId);
 		return json;
-
 	}
 
 	/**

+ 0 - 1
src/main/java/com/genersoft/iot/vmp/vmanager/streamProxy/StreamProxyController.java

@@ -109,7 +109,6 @@ public class StreamProxyController {
         logger.info("启用代理: " + app + "/" + stream);
         boolean result = streamProxyService.start(app, stream);
         if (!result) {
-            logger.info("启用代理失败: " + app + "/" + stream);
             throw new ControllerException(ErrorCode.ERROR100);
         }
     }

+ 2 - 0
src/main/resources/all-application.yml

@@ -195,6 +195,8 @@ user-settings:
     # 国标级联发流严格模式,严格模式会使用与sdp信息中一致的端口发流,端口共享media.rtp.port-range,这会损失一些性能,
     # 非严格模式使用随机端口发流,性能更好, 默认关闭
     gb-send-stream-strict: false
+    # 设备上线时是否自动同步通道
+    sync-channel-on-device-online: false
 
 # 关闭在线文档(生产环境建议关闭)
 springdoc:

+ 31 - 38
web_src/src/components/StreamProxyList.vue

@@ -32,7 +32,7 @@
       <el-table-column label="类型" width="100" >
         <template slot-scope="scope">
           <div slot="reference" class="name-wrapper">
-            <el-tag size="medium">{{scope.row.type}}</el-tag>
+            <el-tag size="medium">{{scope.row.type === "default"? "直接代理":"FFMPEG代理"}}</el-tag>
           </div>
         </template>
       </el-table-column>
@@ -55,15 +55,15 @@
         </template>
       </el-table-column>
       <el-table-column prop="createTime" label="创建时间"  min-width="150" show-overflow-tooltip/>
-      <el-table-column label="转HLS" min-width="120" >
+      <el-table-column label="音频" min-width="120" >
         <template slot-scope="scope">
           <div slot="reference" class="name-wrapper">
-            <el-tag size="medium" v-if="scope.row.enable_hls">已启用</el-tag>
-            <el-tag size="medium" type="info" v-if="!scope.row.enable_hls">未启用</el-tag>
+            <el-tag size="medium" v-if="scope.row.enable_audio">已启用</el-tag>
+            <el-tag size="medium" type="info" v-if="!scope.row.enable_audio">未启用</el-tag>
           </div>
         </template>
       </el-table-column>
-      <el-table-column label="MP4录制" min-width="120" >
+      <el-table-column label="录制" min-width="120" >
         <template slot-scope="scope">
           <div slot="reference" class="name-wrapper">
             <el-tag size="medium" v-if="scope.row.enable_mp4">已启用</el-tag>
@@ -71,11 +71,12 @@
           </div>
         </template>
       </el-table-column>
-      <el-table-column label="无人观看自动删除" min-width="160" >
+      <el-table-column label="无人观看" min-width="160" >
         <template slot-scope="scope">
           <div slot="reference" class="name-wrapper">
-            <el-tag size="medium" v-if="scope.row.enable_remove_none_reader">已启用</el-tag>
-            <el-tag size="medium" type="info" v-if="!scope.row.enable_remove_none_reader">未启用</el-tag>
+            <el-tag size="medium" v-if="scope.row.enable_remove_none_reader">移除</el-tag>
+            <el-tag size="medium" v-if="scope.row.enable_disable_none_reader">停用</el-tag>
+            <el-tag size="medium" type="info" v-if="!scope.row.enable_remove_none_reader && !scope.row.enable_disable_none_reader">不做处理</el-tag>
           </div>
         </template>
       </el-table-column>
@@ -131,7 +132,6 @@
 				currentPage:1,
 				count:15,
 				total:0,
-				getListLoading: false,
         startBtnLoading: false
 			};
 		},
@@ -139,7 +139,7 @@
 		},
 		mounted() {
 			this.initData();
-			this.updateLooper = setInterval(this.initData, 1000);
+			this.startUpdateList()
 		},
 		destroyed() {
 			this.$destroy('videojs');
@@ -149,6 +149,12 @@
 			initData: function() {
 				this.getStreamProxyList();
 			},
+      stopUpdateList: function (){
+        window.clearInterval(this.updateLooper)
+      },
+      startUpdateList: function (){
+        this.updateLooper = setInterval(this.initData, 1000);
+      },
 			currentChange: function(val){
 				this.currentPage = val;
 				this.getStreamProxyList();
@@ -159,7 +165,6 @@
 			},
 			getStreamProxyList: function() {
 				let that = this;
-				this.getListLoading = true;
 				this.$axios({
 					method: 'get',
 					url:`/api/proxy/list`,
@@ -175,23 +180,18 @@
             }
             that.streamProxyList = res.data.data.list;
           }
-          that.getListLoading = false;
 				}).catch(function (error) {
 					console.log(error);
-					that.getListLoading = false;
 				});
 			},
 			addStreamProxy: function(){
 				this.$refs.streamProxyEdit.openDialog(null, this.initData)
 			},
       addOnvif: function(){
-        this.getListLoading = true;
-        this.getListLoading = true;
         this.$axios({
           method: 'get',
           url:`/api/onvif/search?timeout=3000`,
         }).then((res) =>{
-          this.getListLoading = false;
           if (res.data.code === 0 ){
             if (res.data.data.length > 0) {
               this.$refs.onvifEdit.openDialog(res.data.data, (url)=>{
@@ -208,7 +208,6 @@
           }
 
         }).catch((error)=> {
-          this.getListLoading = false;
           this.$message.error(error.response.data.msg);
         });
 
@@ -217,7 +216,6 @@
 			},
 			play: function(row){
 				let that = this;
-				this.getListLoading = true;
 				this.$axios({
 					method: 'get',
 					url:`/api/push/getPlayUrl`,
@@ -227,7 +225,6 @@
             mediaServerId: row.mediaServerId
 					}
 				}).then(function (res) {
-					that.getListLoading = false;
 					if (res.data.code === 0) {
             that.$refs.devicePlayer.openDialog("streamPlay", null, null, {
               streamInfo: res.data.data,
@@ -243,13 +240,11 @@
 
 				}).catch(function (error) {
 					console.log(error);
-					that.getListLoading = false;
 				});
 
 			},
 			deleteStreamProxy: function(row){
 				let that = this;
-				this.getListLoading = true;
 				that.$axios({
                     method:"delete",
                     url:"/api/proxy/del",
@@ -258,16 +253,13 @@
                       stream: row.stream
                     }
                 }).then((res)=>{
-                    that.getListLoading = false;
 					          that.initData()
                 }).catch(function (error) {
                     console.log(error);
-					          that.getListLoading = false;
                 });
 			},
 			start: function(row){
-				let that = this;
-				this.getListLoading = true;
+        this.stopUpdateList()
         this.$set(row, 'startBtnLoading', true)
 				this.$axios({
 					method: 'get',
@@ -276,28 +268,31 @@
 						app: row.app,
 						stream: row.stream
 					}
-				}).then(function (res) {
-          that.getListLoading = false;
-          that.$set(row, 'startBtnLoading', false)
+				}).then((res)=> {
 				  if (res.data.code === 0){
-            that.initData()
+            this.initData()
           }else {
-            that.$message({
+            this.$message({
               showClose: true,
-              message: "保存失败,请检查地址是否可用!",
+              message: "启动失败,请检查地址是否可用!",
               type: "error",
             });
           }
-
-				}).catch(function (error) {
+          this.$set(row, 'startBtnLoading', false)
+          this.startUpdateList()
+				}).catch((error)=> {
 					console.log(error);
-					that.getListLoading = false;
-          that.$set(row, 'startBtnLoading', false)
+          this.$message({
+            showClose: true,
+            message: "启动失败,请检查地址是否可用!",
+            type: "error",
+          });
+          this.$set(row, 'startBtnLoading', false)
+          this.startUpdateList()
 				});
 			},
 			stop: function(row){
 				let that = this;
-				this.getListLoading = true;
 				this.$axios({
 					method: 'get',
 					url:`/api/proxy/stop`,
@@ -306,11 +301,9 @@
 						stream: row.stream
 					}
 				}).then(function (res) {
-					that.getListLoading = false;
 					that.initData()
 				}).catch(function (error) {
 					console.log(error);
-					that.getListLoading = false;
 				});
 			},
       refresh: function (){

+ 40 - 40
web_src/src/components/dialog/StreamProxyEdit.vue

@@ -83,31 +83,23 @@
                   <el-option label="组播" value="2"></el-option>
                 </el-select>
               </el-form-item>
-
-              <el-form-item label="国标平台">
-                <el-select
-                  v-model="proxyParam.platformGbId"
-                  style="width: 100%"
-                  placeholder="请选择国标平台"
-                >
-                  <el-option
-                    v-for="item in platformList"
-                    :key="item.name"
-                    :label="item.name"
-                    :value="item.serverGBId">
-                    <span style="float: left">{{ item.name }}</span>
-                    <span style="float: right; color: #8492a6; font-size: 13px">{{ item.serverGBId }}</span>
-                  </el-option>
-                </el-select>
-              </el-form-item>
+            <el-form-item label="无人观看" prop="rtp_type" >
+              <el-select
+                @change="noneReaderHandler"
+                v-model="proxyParam.none_reader"
+                style="width: 100%"
+                placeholder="请选择无人观看的处理方式"
+              >
+                <el-option label="不做处理" value="0"></el-option>
+                <el-option label="停用" value="1"></el-option>
+                <el-option label="移除" value="2"></el-option>
+              </el-select>
+            </el-form-item>
               <el-form-item label="其他选项">
                 <div style="float: left;">
                   <el-checkbox label="启用" v-model="proxyParam.enable" ></el-checkbox>
-                  <el-checkbox label="转HLS" v-model="proxyParam.enable_hls" ></el-checkbox>
-                  <el-checkbox label="MP4录制" v-model="proxyParam.enable_mp4" ></el-checkbox>
-                  <el-checkbox label="无人观看自动删除" v-model="proxyParam.enable_remove_none_reader" @change="removeNoneReader"></el-checkbox>
-                  <el-checkbox label="无人观看停止拉流" v-model="proxyParam.enable_disable_none_reader" @change="disableNoneReaderHandType"></el-checkbox>
-
+                  <el-checkbox label="开启音频" v-model="proxyParam.enable_audio" ></el-checkbox>
+                  <el-checkbox label="录制" v-model="proxyParam.enable_mp4" ></el-checkbox>
                 </div>
 
               </el-form-item>
@@ -169,10 +161,11 @@ export default {
           gbId: null,
           rtp_type: null,
           enable: true,
-          enable_hls: true,
+          enable_audio: true,
           enable_mp4: false,
+          none_reader: null,
           enable_remove_none_reader: false,
-          enable_disable_none_reader: true,
+          enable_disable_none_reader: false,
           platformGbId: null,
           mediaServerId: null,
       },
@@ -196,6 +189,7 @@ export default {
       this.listChangeCallback = callback;
       if (proxyParam != null) {
         this.proxyParam = proxyParam;
+        this.proxyParam.none_reader = null;
       }
 
       let that = this;
@@ -233,26 +227,26 @@ export default {
     },
     onSubmit: function () {
       this.dialogLoading = true;
-      var that = this;
-      that.$axios({
+      this.noneReaderHandler();
+      this.$axios({
         method: 'post',
         url:`/api/proxy/save`,
-        data: that.proxyParam
-      }).then(function (res) {
-        that.dialogLoading = false;
+        data: this.proxyParam
+      }).then((res)=> {
+        this.dialogLoading = false;
         if (typeof (res.data.code) != "undefined" && res.data.code === 0) {
-          that.$message({
+          this.$message({
             showClose: true,
             message: res.data.msg,
             type: "success",
           });
-          that.showDialog = false;
-          if (that.listChangeCallback != null) {
-            that.listChangeCallback();
-            that.dialogLoading = false;
+          this.showDialog = false;
+          if (this.listChangeCallback != null) {
+            this.listChangeCallback();
+            this.dialogLoading = false;
           }
         }
-      }).catch(function (error) {
+      }).catch((error) =>{
         console.log(error);
         this.dialogLoading = false;
       });
@@ -280,12 +274,18 @@ export default {
         this.platform.expires = "300";
       }
     },
-    removeNoneReader: function(checked) {
-      this.proxyParam.enable_disable_none_reader = !checked;
+    noneReaderHandler: function() {
+      if (this.proxyParam.none_reader === null || this.proxyParam.none_reader === "0") {
+        this.proxyParam.enable_disable_none_reader = false;
+        this.proxyParam.enable_remove_none_reader = false;
+      }else if (this.proxyParam.none_reader === "1"){
+        this.proxyParam.enable_disable_none_reader = true;
+        this.proxyParam.enable_remove_none_reader = false;
+      }else if (this.proxyParam.none_reader ==="2"){
+        this.proxyParam.enable_disable_none_reader = false;
+        this.proxyParam.enable_remove_none_reader = true;
+      }
     },
-    disableNoneReaderHandType: function(checked) {
-      this.proxyParam.enable_remove_none_reader = !checked;
-    }
   },
 };
 </script>

+ 20 - 28
web_src/src/components/dialog/SyncChannelProgress.vue

@@ -63,37 +63,29 @@ export default {
           }
 
           if (res.data.data != null) {
-            if (res.data.syncIng) {
+            if (res.data.data.syncIng) {
               if (res.data.data.total == 0) {
-                if (res.data.data.errorMsg !== null ){
-                  this.msg = res.data.data.errorMsg;
-                  this.syncStatus = "exception"
-                }else {
-                  this.msg = `等待同步中`;
-                  this.timmer = setTimeout(this.getProgress, 300)
-                }
-              }else  {
-                if (res.data.data.total == res.data.data.current) {
-                  this.syncStatus = "success"
-                  this.percentage = 100;
-                  this.msg = '同步成功';
-                }else {
-                  if (res.data.data.errorMsg !== null ){
-                    this.msg = res.data.data.errorMsg;
-                    this.syncStatus = "exception"
-                  }else {
-                    this.total = res.data.data.total;
-                    this.current = res.data.data.current;
-                    this.percentage = Math.floor(Number(res.data.data.current)/Number(res.data.data.total)* 10000)/100;
-                    this.msg = `同步中...[${res.data.data.current}/${res.data.data.total}]`;
-                    this.timmer = setTimeout(this.getProgress, 300)
-                  }
-                }
+                this.msg = `等待同步中`;
+                this.timmer = setTimeout(this.getProgress, 300)
+              }else {
+                this.total = res.data.data.total;
+                this.current = res.data.data.current;
+                this.percentage = Math.floor(Number(res.data.data.current)/Number(res.data.data.total)* 10000)/100;
+                this.msg = `同步中...[${res.data.data.current}/${res.data.data.total}]`;
+                this.timmer = setTimeout(this.getProgress, 300)
               }
             }else {
-              this.syncStatus = "success"
-              this.percentage = 100;
-              this.msg = '同步成功';
+              if (res.data.data.errorMsg){
+                this.msg = res.data.data.errorMsg;
+                this.syncStatus = "exception"
+              }else {
+                this.syncStatus = "success"
+                this.percentage = 100;
+                this.msg = '同步成功';
+                setTimeout(()=>{
+                  this.showDialog = false;
+                }, 3000)
+              }
             }
           }
         }else {

+ 33 - 16
web_src/src/components/dialog/chooseChannelForGb.vue

@@ -18,8 +18,10 @@
             <el-option label="在线" value="true"></el-option>
             <el-option label="离线" value="false"></el-option>
         </el-select>
-     <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>
-     <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>
+     <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>
+     <el-button v-if="catalogId === null" icon="el-icon-plus" size="mini" :disabled="gbChannels.length === 0 || multipleSelection.length === 0" @click="batchAdd">批量添加</el-button>
+     <el-button v-if="catalogId === null" icon="el-icon-plus" size="mini" @click="add()">全部添加</el-button>
+     <el-button v-if="catalogId !== null" type="danger" icon="el-icon-delete" size="mini" @click="remove()">全部移除</el-button>
     </div>
 
     <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 {
             this.initData();
         },
         add: function (row) {
+          let all = typeof(row) === "undefined"
           this.getCatalogFromUser((catalogId)=> {
             this.$axios({
               method:"post",
               url:"/api/platform/update_channel_for_gb",
               data:{
                 platformId:  this.platformId,
-                channelReduces: [row],
+                all: all,
+                channelReduces: all?[]:[row],
                 catalogId: catalogId
               }
             }).then((res)=>{
@@ -134,21 +138,34 @@ export default {
 
         },
         remove: function (row) {
-          console.log(row)
+          let all = typeof(row) === "undefined"
+          this.$confirm(`确定移除${all?"所有通道":""}吗?`, '提示', {
+            dangerouslyUseHTMLString: true,
+            confirmButtonText: '确定',
+            cancelButtonText: '取消',
+            type: 'warning'
+          }).then(() => {
+            console.log(row)
+
+            this.$axios({
+              method:"delete",
+              url:"/api/platform/del_channel_for_gb",
+              data:{
+                platformId:  this.platformId,
+                all: all,
+                channelReduces: all?[]:[row],
+              }
+            }).then((res)=>{
+              console.log("移除成功")
+              this.getChannelList();
+            }).catch(function (error) {
+              console.log(error);
+            });
+          }).catch(() => {
 
-          this.$axios({
-            method:"delete",
-            url:"/api/platform/del_channel_for_gb",
-            data:{
-              platformId:  this.platformId,
-              channelReduces: [row]
-            }
-          }).then((res)=>{
-            console.log("移除成功")
-            this.getChannelList();
-          }).catch(function (error) {
-            console.log(error);
           });
+
+
         },
         // checkedChange: function (val) {
         //     let that = this;

+ 31 - 14
web_src/src/components/dialog/chooseChannelForStream.vue

@@ -24,6 +24,8 @@
       </el-select>
       <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>
       <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>
+      <el-button v-if="catalogId === null"  icon="el-icon-plus" size="mini" style="margin-right: 1rem;" @click="add()">全部添加</el-button>
+      <el-button v-if="catalogId !== null" type="danger" icon="el-icon-delete" size="mini" style="margin-right: 1rem;" @click="remove()">全部移除</el-button>
     </div>
     <el-table ref="gbStreamsTable" :data="gbStreams" border style="width: 100%" :height="winHeight" :row-key="(row)=> row.app + row.stream" @selection-change="handleSelectionChange">
         <el-table-column align="center" type="selection" :reserve-selection="true" width="55">
@@ -128,6 +130,7 @@ export default {
 
         },
         add: function (row, scope) {
+          let all = typeof(row) === "undefined"
           this.getCatalogFromUser((catalogId)=>{
             this.$axios({
               method:"post",
@@ -135,7 +138,8 @@ export default {
               data:{
                 platformId: this.platformId,
                 catalogId: catalogId,
-                gbStreams:  [row],
+                all: all,
+                gbStreams: all?[]:[row],
               }
             }).then((res)=>{
               console.log("保存成功")
@@ -149,20 +153,33 @@ export default {
 
         },
         remove: function (row, scope) {
-          this.$axios({
-            method:"delete",
-            url:"/api/gbStream/del",
-            data:{
-              platformId: this.platformId,
-              gbStreams:  [row],
-            }
-          }).then((res)=>{
-            console.log("移除成功")
-            // this.gbStreams.splice(scope.$index,1)
-            this.getChannelList();
-          }).catch(function (error) {
-            console.log(error);
+          let all = typeof(row) === "undefined"
+          this.$confirm(`确定移除${all?"所有通道":""}吗?`, '提示', {
+            dangerouslyUseHTMLString: true,
+            confirmButtonText: '确定',
+            cancelButtonText: '取消',
+            type: 'warning'
+          }).then(() => {
+
+            this.$axios({
+              method:"delete",
+              url:"/api/gbStream/del",
+              data:{
+                platformId: this.platformId,
+                all: all,
+                gbStreams: all?[]:[row],
+              }
+            }).then((res)=>{
+              console.log("移除成功")
+              // this.gbStreams.splice(scope.$index,1)
+              this.getChannelList();
+            }).catch(function (error) {
+              console.log(error);
+            });
+          }).catch(() => {
+
           });
+
         },
         getChannelList: function () {
             let that = this;