国标级联通道共享支持按照设备添加共享和移除共享

pull/1642/head
648540858 2024-08-29 11:08:42 +08:00
parent 1efb5fca0f
commit e55cd08b08
15 changed files with 179 additions and 146 deletions

View File

@ -41,8 +41,6 @@ public class SubscribeHolder {
// 添加任务处理订阅过期
dynamicTask.startDelay(taskOverdueKey, () -> removeCatalogSubscribe(subscribeInfo.getId()),
subscribeInfo.getExpires() * 1000);
// 发送目录订阅添加通知
eventPublisher.catalogSubscribePutEventPublish(platformId, subscribeInfo);
}
}

View File

@ -259,4 +259,24 @@ public class PlatformController {
Assert.notNull(id, "平台ID不可为空");
platformChannelService.pushChannel(id);
}
@Operation(summary = "添加通道-通过设备", security = @SecurityRequirement(name = JwtUtils.HEADER))
@PostMapping("/channel/device/add")
@ResponseBody
public void addChannelByDevice(@RequestBody UpdateChannelParam param) {
Assert.notNull(param.getPlatformId(), "平台ID不可为空");
Assert.notNull(param.getDeviceIds(), "设备ID不可为空");
Assert.notEmpty(param.getDeviceIds(), "设备ID不可为空");
platformChannelService.addChannelByDevice(param.getPlatformId(), param.getDeviceIds());
}
@Operation(summary = "移除通道-通过设备", security = @SecurityRequirement(name = JwtUtils.HEADER))
@PostMapping("/channel/device/remove")
@ResponseBody
public void removeChannelByDevice(@RequestBody UpdateChannelParam param) {
Assert.notNull(param.getPlatformId(), "平台ID不可为空");
Assert.notNull(param.getDeviceIds(), "设备ID不可为空");
Assert.notEmpty(param.getDeviceIds(), "设备ID不可为空");
platformChannelService.removeChannelByDevice(param.getPlatformId(), param.getDeviceIds());
}
}

View File

@ -18,4 +18,7 @@ public class UpdateChannelParam {
@Schema(description = "待关联的通道ID")
List<Integer> channelIds;
@Schema(description = "待关联的设备ID")
List<Integer> deviceIds;
}

View File

@ -309,6 +309,13 @@ public interface CommonGBChannelMapper {
@SelectProvider(type = ChannelProvider.class, method = "queryByGbDeviceIds")
List<CommonGBChannel> queryByGbDeviceIds(List<Integer> deviceIds);
@Select(value = {" <script>" +
" select id from wvp_device_channel " +
" where channel_type = 0 and device_db_id in "+
" <foreach collection='deviceIds' item='item' open='(' separator=',' close=')' > #{item}</foreach>" +
" </script>"})
List<Integer> queryByGbDeviceIdsForIds(List<Integer> deviceIds);
@SelectProvider(type = ChannelProvider.class, method = "queryByGroupList")
List<CommonGBChannel> queryByGroupList(List<Group> groupList);

View File

@ -63,7 +63,11 @@ public interface PlatformMapper {
int delete(@Param("id") Integer id);
@Select(" SELECT pp.*, " +
" (SELECT count(0) FROM wvp_platform_channel pc WHERE pc.platform_id = pp.id ) as channel_count" +
" ( (SELECT count(0) FROM wvp_platform_channel pc WHERE pc.platform_id = pp.id ) + " +
" (SELECT count(0) FROM wvp_platform_group pg WHERE pg.platform_id = pp.id ) * pp.catalog_with_group + " +
" (SELECT count(0) FROM wvp_platform_region pr WHERE pr.platform_id = pp.id ) * pp.catalog_with_region + " +
" pp.catalog_with_platform " +
" ) as channel_count" +
" FROM wvp_platform pp "
)
List<Platform> queryList();

View File

@ -5,7 +5,6 @@ import com.genersoft.iot.vmp.gb28181.event.alarm.AlarmEvent;
import com.genersoft.iot.vmp.gb28181.event.device.RequestTimeoutEvent;
import com.genersoft.iot.vmp.gb28181.event.record.RecordEndEvent;
import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent;
import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogSubscribePutEvent;
import com.genersoft.iot.vmp.gb28181.event.subscribe.mobilePosition.MobilePositionEvent;
import com.genersoft.iot.vmp.media.event.mediaServer.MediaServerOfflineEvent;
import com.genersoft.iot.vmp.media.event.mediaServer.MediaServerOnlineEvent;
@ -106,11 +105,4 @@ public class EventPublisher {
outEvent.setRecordInfo(recordInfo);
applicationEventPublisher.publishEvent(outEvent);
}
public void catalogSubscribePutEventPublish(String platformId, SubscribeInfo subscribeInfo) {
CatalogSubscribePutEvent event = new CatalogSubscribePutEvent(this);
event.setPlatformId(platformId);
event.setSubscribeInfo(subscribeInfo);
applicationEventPublisher.publishEvent(event);
}
}

View File

@ -1,21 +0,0 @@
package com.genersoft.iot.vmp.gb28181.event.subscribe.catalog;
import com.genersoft.iot.vmp.gb28181.bean.SubscribeInfo;
import lombok.Getter;
import lombok.Setter;
import org.springframework.context.ApplicationEvent;
public class CatalogSubscribePutEvent extends ApplicationEvent {
public CatalogSubscribePutEvent(Object source) {
super(source);
}
@Getter
@Setter
private SubscribeInfo subscribeInfo;
@Getter
@Setter
private String platformId;
}

View File

@ -1,41 +0,0 @@
package com.genersoft.iot.vmp.gb28181.event.subscribe.catalog;
import com.genersoft.iot.vmp.gb28181.bean.CommonGBChannel;
import com.genersoft.iot.vmp.gb28181.bean.Platform;
import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
import com.genersoft.iot.vmp.gb28181.service.IPlatformService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
@Slf4j
@Component
public class CatalogSubscribePutEventLister implements ApplicationListener<CatalogSubscribePutEvent> {
@Autowired
private IPlatformService platformService;
@Autowired
private EventPublisher eventPublisher;
@Override
public void onApplicationEvent(CatalogSubscribePutEvent event) {
Platform platform = platformService.queryPlatformByServerGBId(event.getPlatformId());
if (platform == null){
return;
}
CommonGBChannel channel = CommonGBChannel.build(platform);
// 发送消息
try {
// 发送catalog
eventPublisher.catalogEventPublish(platform.getId(), channel, CatalogEvent.ADD);
} catch (Exception e) {
log.warn("[推送平台信息] 发送失败,平台{}{}", platform.getName(), platform.getServerGBId(), e);
}
}
}

View File

@ -30,4 +30,8 @@ public interface IPlatformChannelService {
List<CommonGBChannel> queryByPlatform(Platform platform);
void pushChannel(Integer platformId);
void addChannelByDevice(Integer platformId, List<Integer> deviceIds);
void removeChannelByDevice(Integer platformId, List<Integer> deviceIds);
}

View File

@ -51,6 +51,8 @@ public class PlatformChannelServiceImpl implements IPlatformChannelService {
private ISIPCommanderForPlatform sipCommanderFroPlatform;
@Override
public PageInfo<PlatformChannel> queryChannelList(int page, int count, String query, Boolean online, Integer platformId, Boolean hasShare) {
PageHelper.startPage(page, count);
@ -58,48 +60,6 @@ public class PlatformChannelServiceImpl implements IPlatformChannelService {
return new PageInfo<>(all);
}
@Override
@Transactional
public int addAllChannel(Integer platformId) {
List<CommonGBChannel> channelListNotShare = platformChannelMapper.queryNotShare(platformId, null);
Assert.notEmpty(channelListNotShare, "所有通道已共享");
int result = platformChannelMapper.addChannels(platformId, channelListNotShare);
if (result > 0) {
// 查询通道相关的行政区划信息是否共享,如果没共享就添加
Set<Region> regionListNotShare = getRegionNotShareByChannelList(channelListNotShare, platformId);
if (!regionListNotShare.isEmpty()) {
int addGroupResult = platformChannelMapper.addPlatformRegion(new ArrayList<>(regionListNotShare), platformId);
if (addGroupResult > 0) {
for (Region region : regionListNotShare) {
// 分组信息排序时需要将顶层排在最后
channelListNotShare.add(0, CommonGBChannel.build(region));
}
}
}
// 查询通道相关的分组信息是否共享,如果没共享就添加
Set<Group> groupListNotShare = getGroupNotShareByChannelList(channelListNotShare, platformId);
if (!groupListNotShare.isEmpty()) {
int addGroupResult = platformChannelMapper.addPlatformGroup(new ArrayList<>(groupListNotShare), platformId);
if (addGroupResult > 0) {
for (Group group : groupListNotShare) {
// 分组信息排序时需要将顶层排在最后
channelListNotShare.add(0, CommonGBChannel.build(group));
}
}
}
// 发送消息
try {
// 发送catalog
eventPublisher.catalogEventPublish(platformId, channelListNotShare, CatalogEvent.ADD);
} catch (Exception e) {
log.warn("[关联全部通道] 发送失败,数量:{}", channelListNotShare.size(), e);
}
}
return result;
}
/**
* 使
*/
@ -231,33 +191,46 @@ public class PlatformChannelServiceImpl implements IPlatformChannelService {
return channelList;
}
@Override
@Transactional
public int addAllChannel(Integer platformId) {
List<CommonGBChannel> channelListNotShare = platformChannelMapper.queryNotShare(platformId, null);
Assert.notEmpty(channelListNotShare, "所有通道已共享");
return addChannelList(platformId, channelListNotShare);
}
@Override
@Transactional
public int addChannels(Integer platformId, List<Integer> channelIds) {
List<CommonGBChannel> channelListNotShare = platformChannelMapper.queryNotShare(platformId, channelIds);
Assert.notEmpty(channelListNotShare, "通道已共享");
int result = platformChannelMapper.addChannels(platformId, channelListNotShare);
return addChannelList(platformId, channelListNotShare);
}
@Transactional
public int addChannelList(Integer platformId, List<CommonGBChannel> channelList) {
int result = platformChannelMapper.addChannels(platformId, channelList);
if (result > 0) {
// 查询通道相关的行政区划信息是否共享,如果没共享就添加
Set<Region> regionListNotShare = getRegionNotShareByChannelList(channelListNotShare, platformId);
Set<Region> regionListNotShare = getRegionNotShareByChannelList(channelList, platformId);
if (!regionListNotShare.isEmpty()) {
int addGroupResult = platformChannelMapper.addPlatformRegion(new ArrayList<>(regionListNotShare), platformId);
if (addGroupResult > 0) {
for (Region region : regionListNotShare) {
// 分组信息排序时需要将顶层排在最后
channelListNotShare.add(0, CommonGBChannel.build(region));
channelList.add(0, CommonGBChannel.build(region));
}
}
}
// 查询通道相关的分组信息是否共享,如果没共享就添加
Set<Group> groupListNotShare = getGroupNotShareByChannelList(channelListNotShare, platformId);
Set<Group> groupListNotShare = getGroupNotShareByChannelList(channelList, platformId);
if (!groupListNotShare.isEmpty()) {
int addGroupResult = platformChannelMapper.addPlatformGroup(new ArrayList<>(groupListNotShare), platformId);
if (addGroupResult > 0) {
for (Group group : groupListNotShare) {
// 分组信息排序时需要将顶层排在最后
channelListNotShare.add(0, CommonGBChannel.build(group));
channelList.add(0, CommonGBChannel.build(group));
}
}
}
@ -265,9 +238,9 @@ public class PlatformChannelServiceImpl implements IPlatformChannelService {
// 发送消息
try {
// 发送catalog
eventPublisher.catalogEventPublish(platformId, channelListNotShare, CatalogEvent.ADD);
eventPublisher.catalogEventPublish(platformId, channelList, CatalogEvent.ADD);
} catch (Exception e) {
log.warn("[关联通道] 发送失败,数量:{}", channelListNotShare.size(), e);
log.warn("[关联通道] 发送失败,数量:{}", channelList.size(), e);
}
}
return result;
@ -309,9 +282,20 @@ public class PlatformChannelServiceImpl implements IPlatformChannelService {
@Override
@Transactional
public int removeChannels(Integer platformId, List<Integer> channelIds) {
List<CommonGBChannel> channelList = platformChannelMapper.queryShare(platformId, channelIds);
Assert.notEmpty(channelList, "所选通道未共享");
public void addChannelByDevice(Integer platformId, List<Integer> deviceIds) {
List<Integer> channelList = commonGBChannelMapper.queryByGbDeviceIdsForIds(deviceIds);
addChannels(platformId, channelList);
}
@Override
@Transactional
public void removeChannelByDevice(Integer platformId, List<Integer> deviceIds) {
List<Integer> channelList = commonGBChannelMapper.queryByGbDeviceIdsForIds(deviceIds);
removeChannels(platformId, channelList);
}
@Transactional
public int removeChannelList(Integer platformId, List<CommonGBChannel> channelList) {
int result = platformChannelMapper.removeChannelsWithPlatform(platformId, channelList);
if (result > 0) {
// 查询通道相关的分组信息
@ -342,6 +326,14 @@ public class PlatformChannelServiceImpl implements IPlatformChannelService {
return result;
}
@Override
@Transactional
public int removeChannels(Integer platformId, List<Integer> channelIds) {
List<CommonGBChannel> channelList = platformChannelMapper.queryShare(platformId, channelIds);
Assert.notEmpty(channelList, "所选通道未共享");
return removeChannelList(platformId, channelList);
}
@Override
@Transactional
public void removeChannels(List<Integer> ids) {
@ -356,12 +348,12 @@ public class PlatformChannelServiceImpl implements IPlatformChannelService {
}
@Override
@Transactional
public void removeChannel(int channelId) {
List<Platform> platformList = platformChannelMapper.queryPlatFormListByChannelId(channelId);
if (platformList.isEmpty()) {
return;
}
for (Platform platform : platformList) {
ArrayList<Integer> ids = new ArrayList<>();
ids.add(channelId);

View File

@ -1,14 +1,15 @@
package com.genersoft.iot.vmp.gb28181.service.impl;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.genersoft.iot.vmp.common.*;
import com.genersoft.iot.vmp.common.InviteInfo;
import com.genersoft.iot.vmp.common.*;
import com.genersoft.iot.vmp.conf.DynamicTask;
import com.genersoft.iot.vmp.conf.UserSetting;
import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException;
import com.genersoft.iot.vmp.gb28181.bean.*;
import com.genersoft.iot.vmp.gb28181.dao.PlatformChannelMapper;
import com.genersoft.iot.vmp.gb28181.dao.PlatformMapper;
import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
import com.genersoft.iot.vmp.gb28181.service.IInviteStreamService;
import com.genersoft.iot.vmp.gb28181.service.IPlatformService;
@ -96,6 +97,8 @@ public class PlatformServiceImpl implements IPlatformService {
@Autowired
private PlatformChannelMapper platformChannelMapper;
@Autowired
private EventPublisher eventPublisher;
/**
*
@ -147,7 +150,6 @@ public class PlatformServiceImpl implements IPlatformService {
}
}
@Override
public Platform queryPlatformByServerGBId(String platformGbId) {
return platformMapper.getParentPlatByServerGBId(platformGbId);

View File

@ -12,6 +12,7 @@ import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
/**
@ -48,12 +49,15 @@ public class StreamProxyPlayServiceImpl implements IStreamProxyPlayService {
mediaServer = mediaServerService.getMediaServerForMinimumLoad(null);
}else {
mediaServer = mediaServerService.getOne(mediaServerId);
if (mediaServer == null) {
mediaServer = mediaServerService.getMediaServerForMinimumLoad(null);
}
}
if (mediaServer == null) {
throw new ControllerException(ErrorCode.ERROR100.getCode(), "未找到可用的媒体节点");
}
StreamInfo streamInfo = mediaServerService.startProxy(mediaServer, streamProxy);
if (mediaServerId == null) {
if (mediaServerId == null || !mediaServerId.equals(mediaServer.getId())) {
streamProxy.setMediaServerId(mediaServer.getId());
streamProxyMapper.update(streamProxy);
}
@ -72,15 +76,12 @@ public class StreamProxyPlayServiceImpl implements IStreamProxyPlayService {
@Override
public void stopProxy(StreamProxy streamProxy){
MediaServer mediaServer;
String mediaServerId = streamProxy.getMediaServerId();
if (mediaServerId == null) {
mediaServer = mediaServerService.getMediaServerForMinimumLoad(null);
}else {
mediaServer = mediaServerService.getOne(mediaServerId);
}
Assert.notNull(mediaServerId, "代理节点不存在");
MediaServer mediaServer = mediaServerService.getOne(mediaServerId);
if (mediaServer == null) {
throw new ControllerException(ErrorCode.ERROR100.getCode(), "未找到可用的媒体节点");
throw new ControllerException(ErrorCode.ERROR100.getCode(), "媒体节点不存在");
}
if (ObjectUtils.isEmpty(streamProxy.getStreamKey())) {
mediaServerService.closeStreams(mediaServer, streamProxy.getApp(), streamProxy.getStream());

View File

@ -19,12 +19,12 @@
:value="item.id">
</el-option>
</el-select>
流状态:
流状态:
<el-select size="mini" style="margin-right: 1rem;" @change="getStreamProxyList" v-model="pulling" placeholder="请选择"
default-first-option>
<el-option label="全部" value=""></el-option>
<el-option label="正在拉流" value="true"></el-option>
<el-option label="拉流未进行" value="false"></el-option>
<el-option label="尚未拉流" value="false"></el-option>
</el-select>
<el-button icon="el-icon-plus" size="mini" style="margin-right: 1rem;" type="primary" @click="addStreamProxy"></el-button>
<el-button v-if="false" icon="el-icon-search" size="mini" style="margin-right: 1rem;" type="primary" @click="addOnvif">ONVIF</el-button>
@ -58,8 +58,8 @@
<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.pulling">线</el-tag>
<el-tag size="medium" type="info" v-if="!scope.row.pulling">线</el-tag>
<el-tag size="medium" v-if="scope.row.pulling"></el-tag>
<el-tag size="medium" type="info" v-if="!scope.row.pulling"></el-tag>
</div>
</template>
</el-table-column>
@ -72,7 +72,7 @@
</template>
</el-table-column>
<el-table-column prop="createTime" label="创建时间" min-width="150" show-overflow-tooltip/>
<el-table-column label="操作" width="360" fixed="right">
<el-table-column label="操作" width="400" fixed="right">
<template slot-scope="scope">
<el-button size="medium" icon="el-icon-video-play" type="text" @click="play(scope.row)"></el-button>
<el-divider direction="vertical"></el-divider>

View File

@ -7,6 +7,7 @@
:close-on-click-modal="false"
:visible.sync="showDialog"
:destroy-on-close="true"
append-to-body
@close="close()"
>
<div class="page-header" style="width: 100%">

View File

@ -35,6 +35,8 @@
<el-button v-if="hasShare ==='true'" size="mini" type="danger" @click="remove()">
移除
</el-button>
<el-button size="mini" @click="addByDevice()"></el-button>
<el-button size="mini" @click="removeByDevice()"></el-button>
<el-button size="mini" @click="addAll()"></el-button>
<el-button size="mini" @click="removeAll()"></el-button>
<el-button size="mini" @click="getChannelList()"></el-button>
@ -87,15 +89,17 @@
layout="total, sizes, prev, pager, next"
:total="total">
</el-pagination>
<gbDeviceSelect ref="gbDeviceSelect"></gbDeviceSelect>
</div>
</template>
<script>
import gbDeviceSelect from "./GbDeviceSelect.vue";
export default {
name: 'shareChannelAdd',
components: {},
components: {gbDeviceSelect},
props: [ 'platformId'],
data() {
return {
@ -254,11 +258,78 @@ export default {
});
}).catch(() => {
});
},
addByDevice: function (row) {
this.$refs.gbDeviceSelect.openDialog((rows)=>{
let deviceIds = []
for (let i = 0; i < rows.length; i++) {
deviceIds.push(rows[i].id)
}
this.$axios({
method: 'post',
url: `/api/platform/channel/device/add`,
data: {
platformId: this.platformId,
deviceIds: deviceIds,
}
}).then((res)=> {
if (res.data.code === 0) {
this.$message.success({
showClose: true,
message: "保存成功"
})
this.initData()
}else {
this.$message.error({
showClose: true,
message: res.data.msg
})
}
}).catch((error)=> {
this.$message.error({
showClose: true,
message: error
})
this.loading = false
});
})
},
removeByDevice: function (row) {
this.$refs.gbDeviceSelect.openDialog((rows)=>{
let deviceIds = []
for (let i = 0; i < rows.length; i++) {
deviceIds.push(rows[i].id)
}
this.$axios({
method: 'post',
url: `/api/platform/channel/device/remove`,
data: {
platformId: this.platformId,
deviceIds: deviceIds,
}
}).then((res)=> {
if (res.data.code === 0) {
this.$message.success({
showClose: true,
message: "保存成功"
})
this.initData()
}else {
this.$message.error({
showClose: true,
message: res.data.msg
})
}
}).catch((error)=> {
this.$message.error({
showClose: true,
message: error
})
this.loading = false
});
})
},
remove: function (row) {
let channels = []