Merge branch 'wvp-28181-2.0'

# Conflicts:
#	src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/PlayController.java
This commit is contained in:
648540858
2022-11-23 09:57:17 +08:00
35 changed files with 404 additions and 263 deletions

View File

@@ -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);
}
}

View File

@@ -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;
}
}

View File

@@ -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;
/**
* 查询设备状态
*

View File

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

View File

@@ -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);
}

View File

@@ -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;
}
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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);
}
}

View File

@@ -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());

View File

@@ -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);
}
}
}

View File

@@ -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;
}
}

View File

@@ -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;

View File

@@ -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;

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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}, " +

View File

@@ -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());

View File

@@ -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());
}
}
}

View File

@@ -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;
}
}

View File

@@ -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);
}

View File

@@ -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;
}
}

View File

@@ -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;
}
/**

View File

@@ -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);
}
}

View File

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