Merge branch 'wvp-28181-2.0'
# Conflicts: # sql/update.sql # src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java # src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java # src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRTPServerFactory.java # src/main/java/com/genersoft/iot/vmp/service/impl/MediaServerServiceImpl.java # src/main/java/com/genersoft/iot/vmp/service/impl/MediaServiceImpl.java # src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
This commit is contained in:
@@ -0,0 +1,35 @@
|
||||
package com.genersoft.iot.vmp.service;
|
||||
|
||||
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 国标通道业务类
|
||||
* @author lin
|
||||
*/
|
||||
public interface IDeviceChannelService {
|
||||
|
||||
/**
|
||||
* 更新gps信息
|
||||
*/
|
||||
DeviceChannel updateGps(DeviceChannel deviceChannel, Device device);
|
||||
|
||||
/**
|
||||
* 添加设备通道
|
||||
*
|
||||
* @param deviceId 设备id
|
||||
* @param channel 通道
|
||||
*/
|
||||
void updateChannel(String deviceId, DeviceChannel channel);
|
||||
|
||||
/**
|
||||
* 批量添加设备通道
|
||||
*
|
||||
* @param deviceId 设备id
|
||||
* @param channels 多个通道
|
||||
*/
|
||||
int updateChannels(String deviceId, List<DeviceChannel> channels);
|
||||
|
||||
}
|
||||
@@ -18,7 +18,7 @@ public interface IGbStreamService {
|
||||
* @param count
|
||||
* @return
|
||||
*/
|
||||
PageInfo<GbStream> getAll(Integer page, Integer count, String platFormId, String catalogId,String query,Boolean pushing,String mediaServerId);
|
||||
PageInfo<GbStream> getAll(Integer page, Integer count, String platFormId, String catalogId,String query,String mediaServerId);
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@@ -47,6 +47,8 @@ public interface IMediaServerService {
|
||||
|
||||
SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId, String ssrc, boolean ssrcCheck, boolean isPlayback);
|
||||
|
||||
SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId, String ssrc, boolean ssrcCheck, boolean isPlayback, Integer port);
|
||||
|
||||
void closeRTPServer(String deviceId, String channelId, String ssrc);
|
||||
|
||||
void clearRTPServer(MediaServerItem mediaServerItem);
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.genersoft.iot.vmp.service;
|
||||
|
||||
import com.genersoft.iot.vmp.vmanager.gb28181.platform.bean.ChannelReduce;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 平台关联通道管理
|
||||
* @author lin
|
||||
*/
|
||||
public interface IPlatformChannelService {
|
||||
|
||||
/**
|
||||
* 更新目录下的通道
|
||||
* @param platformId 平台编号
|
||||
* @param channelReduces 通道信息
|
||||
* @param catalogId 目录编号
|
||||
* @return
|
||||
*/
|
||||
int updateChannelForGB(String platformId, List<ChannelReduce> channelReduces, String catalogId);
|
||||
|
||||
}
|
||||
@@ -101,4 +101,9 @@ public interface IStreamProxyService {
|
||||
void zlmServerOffline(String mediaServerId);
|
||||
|
||||
void clean();
|
||||
|
||||
/**
|
||||
* 更新代理流
|
||||
*/
|
||||
boolean updateStreamProxy(StreamProxyItem streamProxyItem);
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import com.genersoft.iot.vmp.media.zlm.ZLMServerConfig;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.MediaItem;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem;
|
||||
import com.genersoft.iot.vmp.service.bean.StreamPushItemFromRedis;
|
||||
import com.genersoft.iot.vmp.vmanager.bean.StreamPushExcelDto;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
|
||||
@@ -44,31 +45,59 @@ public interface IStreamPushService {
|
||||
* 停止一路推流
|
||||
* @param app 应用名
|
||||
* @param streamId 流ID
|
||||
* @return
|
||||
*/
|
||||
boolean stop(String app, String streamId);
|
||||
|
||||
/**
|
||||
* 新的节点加入
|
||||
* @param mediaServerId
|
||||
* @return
|
||||
*/
|
||||
void zlmServerOnline(String mediaServerId);
|
||||
|
||||
/**
|
||||
* 节点离线
|
||||
* @param mediaServerId
|
||||
* @return
|
||||
*/
|
||||
void zlmServerOffline(String mediaServerId);
|
||||
|
||||
/**
|
||||
* 清空
|
||||
*/
|
||||
void clean();
|
||||
|
||||
|
||||
boolean saveToRandomGB();
|
||||
|
||||
/**
|
||||
* 批量添加
|
||||
*/
|
||||
void batchAdd(List<StreamPushItem> streamPushExcelDtoList);
|
||||
|
||||
/**
|
||||
* 中止多个推流
|
||||
*/
|
||||
boolean batchStop(List<GbStream> streamPushItems);
|
||||
|
||||
/**
|
||||
* 导入时批量增加
|
||||
*/
|
||||
void batchAddForUpload(List<StreamPushItem> streamPushItems, Map<String, List<String[]>> streamPushItemsForAll);
|
||||
|
||||
/**
|
||||
* 全部离线
|
||||
*/
|
||||
void allStreamOffline();
|
||||
|
||||
/**
|
||||
* 推流离线
|
||||
*/
|
||||
void offline(List<StreamPushItemFromRedis> offlineStreams);
|
||||
|
||||
/**
|
||||
* 推流上线
|
||||
*/
|
||||
void online(List<StreamPushItemFromRedis> onlineStreams);
|
||||
|
||||
/**
|
||||
* 增加推流
|
||||
*/
|
||||
boolean add(StreamPushItem stream);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.genersoft.iot.vmp.service;
|
||||
|
||||
import com.genersoft.iot.vmp.storager.dao.dto.User;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -21,4 +22,8 @@ public interface IUserService {
|
||||
int updateUsers(User user);
|
||||
|
||||
boolean checkPushAuthority(String callId, String sign);
|
||||
|
||||
PageInfo<User> getUsers(int page, int count);
|
||||
|
||||
int changePushKey(int id, String pushKey);
|
||||
}
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
package com.genersoft.iot.vmp.service;
|
||||
|
||||
import com.genersoft.iot.vmp.service.bean.GPSMsgInfo;
|
||||
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
||||
import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* 定时查找redis中的GPS推送消息,并保存到对应的流中
|
||||
*/
|
||||
@Component
|
||||
public class StreamGPSSubscribeTask {
|
||||
|
||||
@Autowired
|
||||
private IRedisCatchStorage redisCatchStorage;
|
||||
|
||||
@Autowired
|
||||
private IVideoManagerStorage storager;
|
||||
|
||||
|
||||
@Scheduled(fixedRate = 30 * 1000) //每30秒执行一次
|
||||
public void execute(){
|
||||
List<GPSMsgInfo> gpsMsgInfo = redisCatchStorage.getAllGpsMsgInfo();
|
||||
if (gpsMsgInfo.size() > 0) {
|
||||
storager.updateStreamGPS(gpsMsgInfo);
|
||||
for (GPSMsgInfo msgInfo : gpsMsgInfo) {
|
||||
msgInfo.setStored(true);
|
||||
redisCatchStorage.updateGpsMsgInfo(msgInfo);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -17,7 +17,6 @@ public class DeviceAlarmServiceImpl implements IDeviceAlarmService {
|
||||
@Autowired
|
||||
private DeviceAlarmMapper deviceAlarmMapper;
|
||||
|
||||
|
||||
@Override
|
||||
public PageInfo<DeviceAlarm> getAllAlarm(int page, int count, String deviceId, String alarmPriority, String alarmMethod, String alarmType, String startTime, String endTime) {
|
||||
PageHelper.startPage(page, count);
|
||||
|
||||
@@ -0,0 +1,165 @@
|
||||
package com.genersoft.iot.vmp.service.impl;
|
||||
|
||||
import com.genersoft.iot.vmp.common.StreamInfo;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
|
||||
import com.genersoft.iot.vmp.gb28181.utils.Coordtransform;
|
||||
import com.genersoft.iot.vmp.service.IDeviceChannelService;
|
||||
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
||||
import com.genersoft.iot.vmp.storager.dao.DeviceChannelMapper;
|
||||
import com.genersoft.iot.vmp.storager.dao.DeviceMapper;
|
||||
import com.genersoft.iot.vmp.utils.DateUtil;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author lin
|
||||
*/
|
||||
@Service
|
||||
public class DeviceChannelServiceImpl implements IDeviceChannelService {
|
||||
|
||||
private final static Logger logger = LoggerFactory.getLogger(DeviceChannelServiceImpl.class);
|
||||
|
||||
@Autowired
|
||||
private IRedisCatchStorage redisCatchStorage;
|
||||
|
||||
@Autowired
|
||||
private DeviceChannelMapper channelMapper;
|
||||
|
||||
@Autowired
|
||||
private DeviceMapper deviceMapper;
|
||||
|
||||
@Override
|
||||
public DeviceChannel updateGps(DeviceChannel deviceChannel, Device device) {
|
||||
if (deviceChannel.getLongitude()*deviceChannel.getLatitude() > 0) {
|
||||
if (device == null) {
|
||||
device = deviceMapper.getDeviceByDeviceId(deviceChannel.getDeviceId());
|
||||
}
|
||||
|
||||
if ("WGS84".equals(device.getGeoCoordSys())) {
|
||||
deviceChannel.setLongitudeWgs84(deviceChannel.getLongitude());
|
||||
deviceChannel.setLatitudeWgs84(deviceChannel.getLatitude());
|
||||
Double[] position = Coordtransform.WGS84ToGCJ02(deviceChannel.getLongitude(), deviceChannel.getLatitude());
|
||||
deviceChannel.setLongitudeGcj02(position[0]);
|
||||
deviceChannel.setLatitudeGcj02(position[1]);
|
||||
}else if ("GCJ02".equals(device.getGeoCoordSys())) {
|
||||
deviceChannel.setLongitudeGcj02(deviceChannel.getLongitude());
|
||||
deviceChannel.setLatitudeGcj02(deviceChannel.getLatitude());
|
||||
Double[] position = Coordtransform.GCJ02ToWGS84(deviceChannel.getLongitude(), deviceChannel.getLatitude());
|
||||
deviceChannel.setLongitudeWgs84(position[0]);
|
||||
deviceChannel.setLatitudeWgs84(position[1]);
|
||||
}else {
|
||||
deviceChannel.setLongitudeGcj02(0.00);
|
||||
deviceChannel.setLatitudeGcj02(0.00);
|
||||
deviceChannel.setLongitudeWgs84(0.00);
|
||||
deviceChannel.setLatitudeWgs84(0.00);
|
||||
}
|
||||
}else {
|
||||
deviceChannel.setLongitudeGcj02(deviceChannel.getLongitude());
|
||||
deviceChannel.setLatitudeGcj02(deviceChannel.getLatitude());
|
||||
deviceChannel.setLongitudeWgs84(deviceChannel.getLongitude());
|
||||
deviceChannel.setLatitudeWgs84(deviceChannel.getLatitude());
|
||||
}
|
||||
return deviceChannel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateChannel(String deviceId, DeviceChannel channel) {
|
||||
String channelId = channel.getChannelId();
|
||||
channel.setDeviceId(deviceId);
|
||||
StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channelId);
|
||||
if (streamInfo != null) {
|
||||
channel.setStreamId(streamInfo.getStream());
|
||||
}
|
||||
String now = DateUtil.getNow();
|
||||
channel.setUpdateTime(now);
|
||||
DeviceChannel deviceChannel = channelMapper.queryChannel(deviceId, channelId);
|
||||
channel = updateGps(channel, null);
|
||||
if (deviceChannel == null) {
|
||||
channel.setCreateTime(now);
|
||||
channelMapper.add(channel);
|
||||
}else {
|
||||
channelMapper.update(channel);
|
||||
}
|
||||
channelMapper.updateChannelSubCount(deviceId,channel.getParentId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int updateChannels(String deviceId, List<DeviceChannel> channels) {
|
||||
List<DeviceChannel> addChannels = new ArrayList<>();
|
||||
List<DeviceChannel> updateChannels = new ArrayList<>();
|
||||
HashMap<String, DeviceChannel> channelsInStore = new HashMap<>();
|
||||
Device device = deviceMapper.getDeviceByDeviceId(deviceId);
|
||||
if (channels != null && channels.size() > 0) {
|
||||
List<DeviceChannel> channelList = channelMapper.queryChannels(deviceId, null, null, null, null);
|
||||
if (channelList.size() == 0) {
|
||||
for (DeviceChannel channel : channels) {
|
||||
channel.setDeviceId(deviceId);
|
||||
StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channel.getChannelId());
|
||||
if (streamInfo != null) {
|
||||
channel.setStreamId(streamInfo.getStream());
|
||||
}
|
||||
String now = DateUtil.getNow();
|
||||
channel.setUpdateTime(now);
|
||||
channel.setCreateTime(now);
|
||||
channel = updateGps(channel, device);
|
||||
addChannels.add(channel);
|
||||
}
|
||||
}else {
|
||||
for (DeviceChannel deviceChannel : channelList) {
|
||||
channelsInStore.put(deviceChannel.getChannelId(), deviceChannel);
|
||||
}
|
||||
for (DeviceChannel channel : channels) {
|
||||
channel.setDeviceId(deviceId);
|
||||
StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channel.getChannelId());
|
||||
if (streamInfo != null) {
|
||||
channel.setStreamId(streamInfo.getStream());
|
||||
}
|
||||
String now = DateUtil.getNow();
|
||||
channel.setUpdateTime(now);
|
||||
channel = updateGps(channel, device);
|
||||
if (channelsInStore.get(channel.getChannelId()) != null) {
|
||||
updateChannels.add(channel);
|
||||
}else {
|
||||
addChannels.add(channel);
|
||||
channel.setCreateTime(now);
|
||||
}
|
||||
}
|
||||
}
|
||||
int limitCount = 300;
|
||||
if (addChannels.size() > 0) {
|
||||
if (addChannels.size() > limitCount) {
|
||||
for (int i = 0; i < addChannels.size(); i += limitCount) {
|
||||
int toIndex = i + limitCount;
|
||||
if (i + limitCount > addChannels.size()) {
|
||||
toIndex = addChannels.size();
|
||||
}
|
||||
channelMapper.batchAdd(addChannels.subList(i, toIndex));
|
||||
}
|
||||
}else {
|
||||
channelMapper.batchAdd(addChannels);
|
||||
}
|
||||
}
|
||||
if (updateChannels.size() > 0) {
|
||||
if (updateChannels.size() > limitCount) {
|
||||
for (int i = 0; i < updateChannels.size(); i += limitCount) {
|
||||
int toIndex = i + limitCount;
|
||||
if (i + limitCount > updateChannels.size()) {
|
||||
toIndex = updateChannels.size();
|
||||
}
|
||||
channelMapper.batchUpdate(updateChannels.subList(i, toIndex));
|
||||
}
|
||||
}else {
|
||||
channelMapper.batchUpdate(updateChannels);
|
||||
}
|
||||
}
|
||||
}
|
||||
return addChannels.size() + updateChannels.size();
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,7 @@ import com.genersoft.iot.vmp.gb28181.task.ISubscribeTask;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.cmd.CatalogResponseMessageHandler;
|
||||
import com.genersoft.iot.vmp.gb28181.utils.Coordtransform;
|
||||
import com.genersoft.iot.vmp.service.IDeviceChannelService;
|
||||
import com.genersoft.iot.vmp.service.IDeviceService;
|
||||
import com.genersoft.iot.vmp.gb28181.task.impl.CatalogSubscribeTask;
|
||||
import com.genersoft.iot.vmp.gb28181.task.impl.MobilePositionSubscribeTask;
|
||||
@@ -55,6 +56,9 @@ public class DeviceServiceImpl implements IDeviceService {
|
||||
@Autowired
|
||||
private DeviceMapper deviceMapper;
|
||||
|
||||
@Autowired
|
||||
private IDeviceChannelService deviceChannelService;
|
||||
|
||||
@Autowired
|
||||
private DeviceChannelMapper deviceChannelMapper;
|
||||
|
||||
@@ -82,10 +86,10 @@ public class DeviceServiceImpl implements IDeviceService {
|
||||
redisCatchStorage.clearCatchByDeviceId(device.getDeviceId());
|
||||
}
|
||||
device.setUpdateTime(now);
|
||||
device.setOnline(1);
|
||||
|
||||
// 第一次上线
|
||||
// 第一次上线 或则设备之前是离线状态--进行通道同步和设备信息查询
|
||||
if (device.getCreateTime() == null) {
|
||||
device.setOnline(1);
|
||||
device.setCreateTime(now);
|
||||
logger.info("[设备上线,首次注册]: {},查询设备信息以及通道信息", device.getDeviceId());
|
||||
deviceMapper.add(device);
|
||||
@@ -93,8 +97,19 @@ public class DeviceServiceImpl implements IDeviceService {
|
||||
commander.deviceInfoQuery(device);
|
||||
sync(device);
|
||||
}else {
|
||||
deviceMapper.update(device);
|
||||
redisCatchStorage.updateDevice(device);
|
||||
if(device.getOnline() == 0){
|
||||
device.setOnline(1);
|
||||
device.setCreateTime(now);
|
||||
logger.info("[设备上线,离线状态下重新注册]: {},查询设备信息以及通道信息", device.getDeviceId());
|
||||
deviceMapper.update(device);
|
||||
redisCatchStorage.updateDevice(device);
|
||||
commander.deviceInfoQuery(device);
|
||||
sync(device);
|
||||
}else {
|
||||
deviceMapper.update(device);
|
||||
redisCatchStorage.updateDevice(device);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 上线添加订阅
|
||||
@@ -121,6 +136,8 @@ public class DeviceServiceImpl implements IDeviceService {
|
||||
device.setOnline(0);
|
||||
redisCatchStorage.updateDevice(device);
|
||||
deviceMapper.update(device);
|
||||
//进行通道离线
|
||||
deviceChannelMapper.offlineByDeviceId(deviceId);
|
||||
// 离线释放所有ssrc
|
||||
List<SsrcTransaction> ssrcTransactions = streamSession.getSsrcTransactionForAll(deviceId, null, null, null);
|
||||
if (ssrcTransactions != null && ssrcTransactions.size() > 0) {
|
||||
@@ -143,7 +160,7 @@ public class DeviceServiceImpl implements IDeviceService {
|
||||
logger.info("[添加目录订阅] 设备{}", device.getDeviceId());
|
||||
// 添加目录订阅
|
||||
CatalogSubscribeTask catalogSubscribeTask = new CatalogSubscribeTask(device, sipCommander, dynamicTask);
|
||||
// 提前开始刷新订阅
|
||||
// 刷新订阅
|
||||
int subscribeCycleForCatalog = Math.max(device.getSubscribeCycleForCatalog(),30);
|
||||
// 设置最小值为30
|
||||
dynamicTask.startCron(device.getDeviceId() + "catalog", catalogSubscribeTask, (subscribeCycleForCatalog -1) * 1000);
|
||||
@@ -178,8 +195,8 @@ public class DeviceServiceImpl implements IDeviceService {
|
||||
MobilePositionSubscribeTask mobilePositionSubscribeTask = new MobilePositionSubscribeTask(device, sipCommander, dynamicTask);
|
||||
// 设置最小值为30
|
||||
int subscribeCycleForCatalog = Math.max(device.getSubscribeCycleForMobilePosition(),30);
|
||||
// 提前开始刷新订阅
|
||||
dynamicTask.startCron(device.getDeviceId() + "mobile_position" , mobilePositionSubscribeTask, (subscribeCycleForCatalog -1 ) * 1000);
|
||||
// 刷新订阅
|
||||
dynamicTask.startCron(device.getDeviceId() + "mobile_position" , mobilePositionSubscribeTask, (subscribeCycleForCatalog) * 1000);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -324,23 +341,12 @@ public class DeviceServiceImpl implements IDeviceService {
|
||||
private void updateDeviceChannelGeoCoordSys(Device device) {
|
||||
List<DeviceChannel> deviceChannels = deviceChannelMapper.getAllChannelWithCoordinate(device.getDeviceId());
|
||||
if (deviceChannels.size() > 0) {
|
||||
List<DeviceChannel> deviceChannelsForStore = new ArrayList<>();
|
||||
for (DeviceChannel deviceChannel : deviceChannels) {
|
||||
if ("WGS84".equals(device.getGeoCoordSys())) {
|
||||
deviceChannel.setLongitudeWgs84(deviceChannel.getLongitude());
|
||||
deviceChannel.setLatitudeWgs84(deviceChannel.getLatitude());
|
||||
Double[] position = Coordtransform.WGS84ToGCJ02(deviceChannel.getLongitude(), deviceChannel.getLatitude());
|
||||
deviceChannel.setLongitudeGcj02(position[0]);
|
||||
deviceChannel.setLatitudeGcj02(position[1]);
|
||||
}else if ("GCJ02".equals(device.getGeoCoordSys())) {
|
||||
deviceChannel.setLongitudeGcj02(deviceChannel.getLongitude());
|
||||
deviceChannel.setLatitudeGcj02(deviceChannel.getLatitude());
|
||||
Double[] position = Coordtransform.GCJ02ToWGS84(deviceChannel.getLongitude(), deviceChannel.getLatitude());
|
||||
deviceChannel.setLongitudeWgs84(position[0]);
|
||||
deviceChannel.setLatitudeWgs84(position[1]);
|
||||
}
|
||||
deviceChannelsForStore.add(deviceChannelService.updateGps(deviceChannel, device));
|
||||
}
|
||||
deviceChannelService.updateChannels(device.getDeviceId(), deviceChannelsForStore);
|
||||
}
|
||||
storage.updateChannels(device.getDeviceId(), deviceChannels);
|
||||
}
|
||||
|
||||
|
||||
@@ -352,11 +358,11 @@ public class DeviceServiceImpl implements IDeviceService {
|
||||
}
|
||||
if (parentId == null || parentId.equals(deviceId)) {
|
||||
// 字根节点开始查询
|
||||
List<DeviceChannel> rootNodes = getRootNodes(deviceId, "CivilCode".equals(device.getTreeType()), true, !onlyCatalog);
|
||||
List<DeviceChannel> rootNodes = getRootNodes(deviceId, TreeType.CIVIL_CODE.equals(device.getTreeType()), true, !onlyCatalog);
|
||||
return transportChannelsToTree(rootNodes, "");
|
||||
}
|
||||
|
||||
if ("CivilCode".equals(device.getTreeType())) {
|
||||
if (TreeType.CIVIL_CODE.equals(device.getTreeType())) {
|
||||
if (parentId.length()%2 != 0) {
|
||||
return null;
|
||||
}
|
||||
@@ -386,7 +392,7 @@ public class DeviceServiceImpl implements IDeviceService {
|
||||
|
||||
}
|
||||
// 使用业务分组展示树
|
||||
if ("BusinessGroup".equals(device.getTreeType())) {
|
||||
if (TreeType.BUSINESS_GROUP.equals(device.getTreeType())) {
|
||||
if (parentId.length() < 14 ) {
|
||||
return null;
|
||||
}
|
||||
@@ -406,11 +412,11 @@ public class DeviceServiceImpl implements IDeviceService {
|
||||
}
|
||||
if (parentId == null || parentId.equals(deviceId)) {
|
||||
// 字根节点开始查询
|
||||
List<DeviceChannel> rootNodes = getRootNodes(deviceId, "CivilCode".equals(device.getTreeType()), false, true);
|
||||
List<DeviceChannel> rootNodes = getRootNodes(deviceId, TreeType.CIVIL_CODE.equals(device.getTreeType()), false, true);
|
||||
return rootNodes;
|
||||
}
|
||||
|
||||
if ("CivilCode".equals(device.getTreeType())) {
|
||||
if (TreeType.CIVIL_CODE.equals(device.getTreeType())) {
|
||||
if (parentId.length()%2 != 0) {
|
||||
return null;
|
||||
}
|
||||
@@ -431,7 +437,7 @@ public class DeviceServiceImpl implements IDeviceService {
|
||||
|
||||
}
|
||||
// 使用业务分组展示树
|
||||
if ("BusinessGroup".equals(device.getTreeType())) {
|
||||
if (TreeType.BUSINESS_GROUP.equals(device.getTreeType())) {
|
||||
if (parentId.length() < 14 ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
package com.genersoft.iot.vmp.service.impl;
|
||||
|
||||
import com.genersoft.iot.vmp.conf.SipConfig;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.GbStream;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
|
||||
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.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;
|
||||
@@ -46,15 +45,15 @@ public class GbStreamServiceImpl implements IGbStreamService {
|
||||
private ParentPlatformMapper platformMapper;
|
||||
|
||||
@Autowired
|
||||
private SipConfig sipConfig;
|
||||
private PlatformCatalogMapper catalogMapper;
|
||||
|
||||
@Autowired
|
||||
private EventPublisher eventPublisher;
|
||||
|
||||
@Override
|
||||
public PageInfo<GbStream> getAll(Integer page, Integer count, String platFormId, String catalogId, String query, Boolean pushing, String mediaServerId) {
|
||||
public PageInfo<GbStream> getAll(Integer page, Integer count, String platFormId, String catalogId, String query, String mediaServerId) {
|
||||
PageHelper.startPage(page, count);
|
||||
List<GbStream> all = gbStreamMapper.selectAll(platFormId, catalogId, query, pushing, mediaServerId);
|
||||
List<GbStream> all = gbStreamMapper.selectAll(platFormId, catalogId, query, mediaServerId);
|
||||
return new PageInfo<>(all);
|
||||
}
|
||||
|
||||
@@ -102,16 +101,25 @@ public class GbStreamServiceImpl implements IGbStreamService {
|
||||
deviceChannel.setLatitude(gbStream.getLatitude());
|
||||
deviceChannel.setDeviceId(platform.getDeviceGBId());
|
||||
deviceChannel.setManufacture("wvp-pro");
|
||||
// deviceChannel.setStatus(gbStream.isStatus()?1:0);
|
||||
deviceChannel.setStatus(1);
|
||||
deviceChannel.setParentId(catalogId ==null?gbStream.getCatalogId():catalogId);
|
||||
deviceChannel.setStatus(gbStream.isStatus()?1:0);
|
||||
|
||||
deviceChannel.setRegisterWay(1);
|
||||
if (catalogId.length() > 0 && catalogId.length() <= 10) {
|
||||
// 父节点是行政区划,则设置CivilCode使用此行政区划
|
||||
deviceChannel.setCivilCode(platform.getAdministrativeDivision());
|
||||
|
||||
if (platform.getTreeType().equals(TreeType.CIVIL_CODE)){
|
||||
deviceChannel.setCivilCode(catalogId);
|
||||
}else {
|
||||
deviceChannel.setCivilCode(platform.getAdministrativeDivision());
|
||||
}else if (platform.getTreeType().equals(TreeType.BUSINESS_GROUP)){
|
||||
PlatformCatalog catalog = catalogMapper.select(catalogId);
|
||||
if (catalog == null) {
|
||||
deviceChannel.setParentId(platform.getDeviceGBId());
|
||||
deviceChannel.setBusinessGroupId(null);
|
||||
}else {
|
||||
deviceChannel.setParentId(catalog.getId());
|
||||
deviceChannel.setBusinessGroupId(catalog.getBusinessGroupId());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
deviceChannel.setModel("live");
|
||||
deviceChannel.setOwner("wvp-pro");
|
||||
deviceChannel.setParental(0);
|
||||
|
||||
@@ -1,5 +1,26 @@
|
||||
package com.genersoft.iot.vmp.service.impl;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import com.genersoft.iot.vmp.media.zlm.ZLMRunner;
|
||||
import com.genersoft.iot.vmp.service.IStreamProxyService;
|
||||
import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.TransactionDefinition;
|
||||
import org.springframework.transaction.TransactionStatus;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
@@ -14,25 +35,16 @@ import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
|
||||
import com.genersoft.iot.vmp.media.zlm.ZLMServerConfig;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
||||
import com.genersoft.iot.vmp.service.IMediaServerService;
|
||||
import com.genersoft.iot.vmp.service.IStreamProxyService;
|
||||
import com.genersoft.iot.vmp.service.bean.SSRCInfo;
|
||||
import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
|
||||
import com.genersoft.iot.vmp.storager.dao.MediaServerMapper;
|
||||
import com.genersoft.iot.vmp.utils.DateUtil;
|
||||
import com.genersoft.iot.vmp.utils.redis.JedisUtil;
|
||||
import com.genersoft.iot.vmp.utils.redis.RedisUtil;
|
||||
import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
|
||||
import okhttp3.*;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.TransactionDefinition;
|
||||
import org.springframework.transaction.TransactionStatus;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.*;
|
||||
|
||||
@@ -47,6 +59,9 @@ public class MediaServerServiceImpl implements IMediaServerService {
|
||||
@Autowired
|
||||
private SipConfig sipConfig;
|
||||
|
||||
@Autowired
|
||||
private ZLMRunner zlmRunner;
|
||||
|
||||
@Value("${server.ssl.enabled:false}")
|
||||
private boolean sslEnabled;
|
||||
|
||||
@@ -120,7 +135,7 @@ public class MediaServerServiceImpl implements IMediaServerService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId, String presetSsrc, boolean ssrcCheck, boolean isPlayback) {
|
||||
public SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId, String presetSsrc, boolean ssrcCheck, boolean isPlayback, Integer port) {
|
||||
if (mediaServerItem == null || mediaServerItem.getId() == null) {
|
||||
return null;
|
||||
}
|
||||
@@ -148,13 +163,18 @@ public class MediaServerServiceImpl implements IMediaServerService {
|
||||
}
|
||||
int rtpServerPort = mediaServerItem.getRtpProxyPort();
|
||||
if (mediaServerItem.isRtpEnable()) {
|
||||
rtpServerPort = zlmrtpServerFactory.createRTPServer(mediaServerItem, streamId, ssrcCheck?Integer.parseInt(ssrc):0);
|
||||
rtpServerPort = zlmrtpServerFactory.createRTPServer(mediaServerItem, streamId, ssrcCheck?Integer.parseInt(ssrc):0, port);
|
||||
}
|
||||
redisUtil.set(key, mediaServerItem);
|
||||
return new SSRCInfo(rtpServerPort, ssrc, streamId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId, String ssrc, boolean ssrcCheck, boolean isPlayback) {
|
||||
return openRTPServer(mediaServerItem, streamId, ssrc, ssrcCheck, isPlayback, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void closeRTPServer(String deviceId, String channelId, String stream) {
|
||||
String mediaServerId = streamSession.getMediaServerId(deviceId, channelId, stream);
|
||||
@@ -271,7 +291,13 @@ public class MediaServerServiceImpl implements IMediaServerService {
|
||||
return null;
|
||||
}
|
||||
String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetting.getServerId() + "_" + mediaServerId;
|
||||
return (MediaServerItem)redisUtil.get(key);
|
||||
MediaServerItem serverItem=(MediaServerItem)redisUtil.get(key);
|
||||
if(null==serverItem){
|
||||
//zlm服务不在线,启动重连
|
||||
reloadZlm();
|
||||
serverItem=(MediaServerItem)redisUtil.get(key);
|
||||
}
|
||||
return serverItem;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -351,14 +377,15 @@ public class MediaServerServiceImpl implements IMediaServerService {
|
||||
*/
|
||||
@Override
|
||||
public void zlmServerOnline(ZLMServerConfig zlmServerConfig) {
|
||||
logger.info("[ZLM] 正在连接 : {} -> {}:{}",
|
||||
zlmServerConfig.getGeneralMediaServerId(), zlmServerConfig.getIp(), zlmServerConfig.getHttpPort());
|
||||
|
||||
MediaServerItem serverItem = mediaServerMapper.queryOne(zlmServerConfig.getGeneralMediaServerId());
|
||||
if (serverItem == null) {
|
||||
logger.warn("[未注册的zlm] 拒接接入:{}来自{}:{}", zlmServerConfig.getGeneralMediaServerId(), zlmServerConfig.getIp(),zlmServerConfig.getHttpPort() );
|
||||
logger.warn("请检查ZLM的<general.mediaServerId>配置是否与WVP的<media.id>一致");
|
||||
return;
|
||||
}else {
|
||||
logger.info("[ZLM] 正在连接 : {} -> {}:{}",
|
||||
zlmServerConfig.getGeneralMediaServerId(), zlmServerConfig.getIp(), zlmServerConfig.getHttpPort());
|
||||
}
|
||||
serverItem.setHookAliveInterval(zlmServerConfig.getHookAliveInterval());
|
||||
if (serverItem.getHttpPort() == 0) {
|
||||
@@ -463,8 +490,13 @@ public class MediaServerServiceImpl implements IMediaServerService {
|
||||
String key = VideoManagerConstants.MEDIA_SERVERS_ONLINE_PREFIX + userSetting.getServerId();
|
||||
|
||||
if (redisUtil.zSize(key) == null || redisUtil.zSize(key) == 0) {
|
||||
logger.info("获取负载最低的节点时无在线节点");
|
||||
return null;
|
||||
logger.info("获取负载最低的节点时无在线节点,启动重连机制");
|
||||
//启动重连
|
||||
reloadZlm();
|
||||
if (redisUtil.zSize(key) == null || redisUtil.zSize(key) == 0) {
|
||||
logger.info("获取负载最低的节点时无在线节点");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// 获取分数最低的,及并发最低的
|
||||
@@ -595,9 +627,6 @@ public class MediaServerServiceImpl implements IMediaServerService {
|
||||
boolean result = false;
|
||||
OkHttpClient client = new OkHttpClient();
|
||||
String url = String.format("http://%s:%s/index/api/record", ip, port);
|
||||
|
||||
FormBody.Builder builder = new FormBody.Builder();
|
||||
|
||||
Request request = new Request.Builder()
|
||||
.get()
|
||||
.url(url)
|
||||
@@ -629,9 +658,14 @@ public class MediaServerServiceImpl implements IMediaServerService {
|
||||
MediaServerItem mediaServerItem = getOne(mediaServerId);
|
||||
if (mediaServerItem == null) {
|
||||
// zlm连接重试
|
||||
|
||||
logger.warn("[更新ZLM 保活信息]失败,未找到流媒体信息");
|
||||
return;
|
||||
logger.warn("[更新ZLM 保活信息]失败,未找到流媒体信息,尝试重连zlm");
|
||||
reloadZlm();
|
||||
mediaServerItem = getOne(mediaServerId);
|
||||
if (mediaServerItem == null) {
|
||||
// zlm连接重试
|
||||
logger.warn("[更新ZLM 保活信息]失败,未找到流媒体信息");
|
||||
return;
|
||||
}
|
||||
}
|
||||
String key = VideoManagerConstants.MEDIA_SERVER_KEEPALIVE_PREFIX + userSetting.getServerId() + "_" + mediaServerId;
|
||||
int hookAliveInterval = mediaServerItem.getHookAliveInterval() + 2;
|
||||
@@ -648,10 +682,18 @@ public class MediaServerServiceImpl implements IMediaServerService {
|
||||
mediaServerItemMap.put(mediaServerItem.getId(), mediaServerItem);
|
||||
}
|
||||
for (MediaServerItem mediaServerItem : allInCatch) {
|
||||
if (mediaServerItemMap.get(mediaServerItem) == null) {
|
||||
if (!mediaServerItemMap.containsKey(mediaServerItem.getId())) {
|
||||
delete(mediaServerItem.getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void reloadZlm(){
|
||||
try {
|
||||
zlmRunner.run();
|
||||
Thread.sleep(500);//延迟0.5秒缓冲时间
|
||||
} catch (Exception e) {
|
||||
logger.warn("尝试重连zlm失败!",e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,9 +67,9 @@ public class MediaServiceImpl implements IMediaService {
|
||||
JSONObject mediaJSON = JSON.parseObject(JSON.toJSONString(data.get(0)), JSONObject.class);
|
||||
JSONArray tracks = mediaJSON.getJSONArray("tracks");
|
||||
if (authority) {
|
||||
streamInfo = getStreamInfoByAppAndStream(mediaInfo, app, stream, tracks, null, streamAuthorityInfo.getCallId(), true);
|
||||
streamInfo = getStreamInfoByAppAndStream(mediaInfo, app, stream, tracks, addr,streamAuthorityInfo.getCallId(), true);
|
||||
}else {
|
||||
streamInfo = getStreamInfoByAppAndStream(mediaInfo, app, stream, tracks, null);
|
||||
streamInfo = getStreamInfoByAppAndStream(mediaInfo, app, stream, tracks, addr,null);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,106 @@
|
||||
package com.genersoft.iot.vmp.service.impl;
|
||||
|
||||
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.PlatformCatalog;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.TreeType;
|
||||
import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
|
||||
import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent;
|
||||
import com.genersoft.iot.vmp.service.IPlatformChannelService;
|
||||
import com.genersoft.iot.vmp.storager.dao.DeviceChannelMapper;
|
||||
import com.genersoft.iot.vmp.storager.dao.ParentPlatformMapper;
|
||||
import com.genersoft.iot.vmp.storager.dao.PlatformCatalogMapper;
|
||||
import com.genersoft.iot.vmp.storager.dao.PlatformChannelMapper;
|
||||
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;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author lin
|
||||
*/
|
||||
@Service
|
||||
public class PlatformChannelServiceImpl implements IPlatformChannelService {
|
||||
|
||||
private final static Logger logger = LoggerFactory.getLogger(PlatformChannelServiceImpl.class);
|
||||
|
||||
@Autowired
|
||||
private PlatformChannelMapper platformChannelMapper;
|
||||
|
||||
@Autowired
|
||||
private DeviceChannelMapper deviceChannelMapper;
|
||||
|
||||
@Autowired
|
||||
private PlatformCatalogMapper catalogManager;
|
||||
|
||||
@Autowired
|
||||
private ParentPlatformMapper platformMapper;
|
||||
|
||||
@Autowired
|
||||
EventPublisher eventPublisher;
|
||||
|
||||
@Override
|
||||
public int updateChannelForGB(String platformId, List<ChannelReduce> channelReduces, String catalogId) {
|
||||
ParentPlatform platform = platformMapper.getParentPlatByServerGBId(platformId);
|
||||
if (platform == null) {
|
||||
logger.warn("更新级联通道信息时未找到平台{}的信息", platformId);
|
||||
return 0;
|
||||
}
|
||||
Map<Integer, ChannelReduce> deviceAndChannels = new HashMap<>();
|
||||
for (ChannelReduce channelReduce : channelReduces) {
|
||||
channelReduce.setCatalogId(catalogId);
|
||||
deviceAndChannels.put(channelReduce.getId(), channelReduce);
|
||||
}
|
||||
List<Integer> deviceAndChannelList = new ArrayList<>(deviceAndChannels.keySet());
|
||||
// 查询当前已经存在的
|
||||
List<Integer> channelIds = platformChannelMapper.findChannelRelatedPlatform(platformId, channelReduces);
|
||||
if (deviceAndChannelList != null) {
|
||||
deviceAndChannelList.removeAll(channelIds);
|
||||
}
|
||||
for (Integer channelId : channelIds) {
|
||||
deviceAndChannels.remove(channelId);
|
||||
}
|
||||
List<ChannelReduce> channelReducesToAdd = new ArrayList<>(deviceAndChannels.values());
|
||||
// 对剩下的数据进行存储
|
||||
int result = 0;
|
||||
if (channelReducesToAdd.size() > 0) {
|
||||
result = platformChannelMapper.addChannels(platformId, channelReducesToAdd);
|
||||
// TODO 后续给平台增加控制开关以控制是否响应目录订阅
|
||||
List<DeviceChannel> deviceChannelList = getDeviceChannelListByChannelReduceList(channelReducesToAdd, catalogId, platform);
|
||||
eventPublisher.catalogEventPublish(platformId, deviceChannelList, CatalogEvent.ADD);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private List<DeviceChannel> getDeviceChannelListByChannelReduceList(List<ChannelReduce> channelReduces, String catalogId, ParentPlatform platform) {
|
||||
List<DeviceChannel> deviceChannelList = new ArrayList<>();
|
||||
if (channelReduces.size() > 0){
|
||||
PlatformCatalog catalog = catalogManager.select(catalogId);
|
||||
if (catalog == null && !catalogId.equals(platform.getServerGBId())) {
|
||||
logger.warn("未查询到目录{}的信息", catalogId);
|
||||
return null;
|
||||
}
|
||||
for (ChannelReduce channelReduce : channelReduces) {
|
||||
DeviceChannel deviceChannel = deviceChannelMapper.queryChannel(channelReduce.getDeviceId(), channelReduce.getChannelId());
|
||||
deviceChannel.setParental(0);
|
||||
deviceChannelList.add(deviceChannel);
|
||||
if (platform.getTreeType().equals(TreeType.CIVIL_CODE)){
|
||||
deviceChannel.setCivilCode(catalogId);
|
||||
}else if (platform.getTreeType().equals(TreeType.BUSINESS_GROUP)){
|
||||
deviceChannel.setParentId(catalogId);
|
||||
if (catalog != null) {
|
||||
deviceChannel.setBusinessGroupId(catalog.getBusinessGroupId());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return deviceChannelList;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,21 @@
|
||||
package com.genersoft.iot.vmp.service.impl;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
|
||||
import javax.sip.ResponseEvent;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.context.request.async.DeferredResult;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
@@ -7,7 +23,13 @@ import com.genersoft.iot.vmp.common.StreamInfo;
|
||||
import com.genersoft.iot.vmp.conf.DynamicTask;
|
||||
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.bean.Device;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.InviteStreamCallback;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.InviteStreamInfo;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.SsrcTransaction;
|
||||
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
|
||||
import com.genersoft.iot.vmp.gb28181.session.AudioBroadcastManager;
|
||||
import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
|
||||
@@ -16,6 +38,9 @@ import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform;
|
||||
import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeFactory;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForStreamChange;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.HookType;
|
||||
import com.genersoft.iot.vmp.utils.DateUtil;
|
||||
import com.genersoft.iot.vmp.media.zlm.AssistRESTfulUtils;
|
||||
import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe;
|
||||
@@ -32,9 +57,11 @@ import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
||||
import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
|
||||
import com.genersoft.iot.vmp.utils.redis.RedisUtil;
|
||||
import com.genersoft.iot.vmp.vmanager.bean.AudioBroadcastResult;
|
||||
import com.genersoft.iot.vmp.utils.DateUtil;
|
||||
import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
|
||||
import com.genersoft.iot.vmp.vmanager.gb28181.play.bean.AudioBroadcastEvent;
|
||||
import com.genersoft.iot.vmp.vmanager.gb28181.play.bean.PlayResult;
|
||||
|
||||
import gov.nist.javax.sip.stack.SIPDialog;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -313,16 +340,10 @@ public class PlayServiceImpl implements IPlayService {
|
||||
// 单端口模式streamId也有变化,需要重新设置监听
|
||||
if (!mediaServerItem.isRtpEnable()) {
|
||||
// 添加订阅
|
||||
JSONObject subscribeKey = new JSONObject();
|
||||
subscribeKey.put("app", "rtp");
|
||||
subscribeKey.put("stream", stream);
|
||||
subscribeKey.put("regist", true);
|
||||
subscribeKey.put("schema", "rtmp");
|
||||
subscribeKey.put("mediaServerId", mediaServerItem.getId());
|
||||
subscribe.removeSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed,subscribeKey);
|
||||
subscribeKey.put("stream", String.format("%08x", Integer.parseInt(ssrcInResponse)).toUpperCase());
|
||||
subscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey,
|
||||
(MediaServerItem mediaServerItemInUse, JSONObject response)->{
|
||||
HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", stream, true, "rtmp", mediaServerItem.getId());
|
||||
subscribe.removeSubscribe(hookSubscribe);
|
||||
hookSubscribe.getContent().put("stream", String.format("%08x", Integer.parseInt(ssrcInResponse)).toUpperCase());
|
||||
subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, JSONObject response)->{
|
||||
logger.info("[ZLM HOOK] ssrc修正后收到订阅消息: " + response.toJSONString());
|
||||
dynamicTask.stop(timeOutTaskKey);
|
||||
// hook响应
|
||||
@@ -333,7 +354,7 @@ public class PlayServiceImpl implements IPlayService {
|
||||
// 关闭rtp server
|
||||
mediaServerService.closeRTPServer(device.getDeviceId(), channelId, finalSsrcInfo.getStream());
|
||||
// 重新开启ssrc server
|
||||
mediaServerService.openRTPServer(mediaServerItem, finalSsrcInfo.getStream(), ssrcInResponse, device.isSsrcCheck(), false);
|
||||
mediaServerService.openRTPServer(mediaServerItem, finalSsrcInfo.getStream(), ssrcInResponse, device.isSsrcCheck(), false, finalSsrcInfo.getPort());
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,9 @@ import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem;
|
||||
import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe;
|
||||
import com.genersoft.iot.vmp.media.zlm.ZLMMediaListManager;
|
||||
import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeFactory;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForStreamChange;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.HookType;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
||||
import com.genersoft.iot.vmp.service.IMediaServerService;
|
||||
import com.genersoft.iot.vmp.service.bean.*;
|
||||
@@ -270,14 +273,9 @@ public class RedisGbPlayMsgListener implements MessageListener {
|
||||
}, userSetting.getPlatformPlayTimeout());
|
||||
|
||||
// 添加订阅
|
||||
JSONObject subscribeKey = new JSONObject();
|
||||
subscribeKey.put("app", content.getApp());
|
||||
subscribeKey.put("stream", content.getStream());
|
||||
subscribeKey.put("regist", true);
|
||||
subscribeKey.put("schema", "rtmp");
|
||||
subscribeKey.put("mediaServerId", mediaServerItem.getId());
|
||||
subscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey,
|
||||
(MediaServerItem mediaServerItemInUse, JSONObject json)->{
|
||||
HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed(content.getApp(), content.getStream(), true, "rtmp", mediaServerItem.getId());
|
||||
|
||||
subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, JSONObject json)->{
|
||||
dynamicTask.stop(taskKey);
|
||||
responseSendItem(mediaServerItem, content, toId, serial);
|
||||
});
|
||||
|
||||
@@ -1,16 +1,24 @@
|
||||
package com.genersoft.iot.vmp.service.impl;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.HandlerCatchData;
|
||||
import com.genersoft.iot.vmp.service.bean.GPSMsgInfo;
|
||||
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
||||
import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.data.redis.connection.Message;
|
||||
import org.springframework.data.redis.connection.MessageListener;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
|
||||
/**
|
||||
* 接收来自redis的GPS更新通知
|
||||
* @author lin
|
||||
@@ -20,12 +28,50 @@ public class RedisGpsMsgListener implements MessageListener {
|
||||
|
||||
private final static Logger logger = LoggerFactory.getLogger(RedisGpsMsgListener.class);
|
||||
|
||||
private boolean taskQueueHandlerRun = false;
|
||||
|
||||
@Autowired
|
||||
private IRedisCatchStorage redisCatchStorage;
|
||||
|
||||
@Autowired
|
||||
private IVideoManagerStorage storager;
|
||||
|
||||
private final ConcurrentLinkedQueue<Message> taskQueue = new ConcurrentLinkedQueue<>();
|
||||
|
||||
@Qualifier("taskExecutor")
|
||||
@Autowired
|
||||
private ThreadPoolTaskExecutor taskExecutor;
|
||||
|
||||
|
||||
@Override
|
||||
public void onMessage(@NotNull Message message, byte[] bytes) {
|
||||
GPSMsgInfo gpsMsgInfo = JSON.parseObject(message.getBody(), GPSMsgInfo.class);
|
||||
redisCatchStorage.updateGpsMsgInfo(gpsMsgInfo);
|
||||
taskQueue.offer(message);
|
||||
if (!taskQueueHandlerRun) {
|
||||
taskQueueHandlerRun = true;
|
||||
taskExecutor.execute(() -> {
|
||||
while (!taskQueue.isEmpty()) {
|
||||
Message msg = taskQueue.poll();
|
||||
GPSMsgInfo gpsMsgInfo = JSON.parseObject(msg.getBody(), GPSMsgInfo.class);
|
||||
// 只是放入redis缓存起来
|
||||
redisCatchStorage.updateGpsMsgInfo(gpsMsgInfo);
|
||||
}
|
||||
taskQueueHandlerRun = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 定时将经纬度更新到数据库
|
||||
*/
|
||||
@Scheduled(fixedRate = 2 * 1000) //每2秒执行一次
|
||||
public void execute(){
|
||||
List<GPSMsgInfo> gpsMsgInfo = redisCatchStorage.getAllGpsMsgInfo();
|
||||
if (gpsMsgInfo.size() > 0) {
|
||||
storager.updateStreamGPS(gpsMsgInfo);
|
||||
for (GPSMsgInfo msgInfo : gpsMsgInfo) {
|
||||
msgInfo.setStored(true);
|
||||
redisCatchStorage.updateGpsMsgInfo(msgInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
package com.genersoft.iot.vmp.service.impl;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.genersoft.iot.vmp.common.VideoManagerConstants;
|
||||
import com.genersoft.iot.vmp.conf.DynamicTask;
|
||||
import com.genersoft.iot.vmp.conf.UserSetting;
|
||||
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.gb28181.transmit.cmd.ISIPCommander;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
|
||||
import com.genersoft.iot.vmp.media.zlm.ZLMMediaListManager;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.MediaItem;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem;
|
||||
import com.genersoft.iot.vmp.service.IStreamPushService;
|
||||
import com.genersoft.iot.vmp.service.bean.GPSMsgInfo;
|
||||
import com.genersoft.iot.vmp.service.bean.PushStreamStatusChangeFromRedisDto;
|
||||
import com.genersoft.iot.vmp.service.bean.StreamPushItemFromRedis;
|
||||
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
||||
import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.boot.ApplicationArguments;
|
||||
import org.springframework.boot.ApplicationRunner;
|
||||
import org.springframework.data.redis.connection.Message;
|
||||
import org.springframework.data.redis.connection.MessageListener;
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
|
||||
|
||||
/**
|
||||
* 接收redis发送的推流设备上线下线通知
|
||||
* @author lin
|
||||
*/
|
||||
@Component
|
||||
public class RedisPushStreamStatusMsgListener implements MessageListener, ApplicationRunner {
|
||||
|
||||
private final static Logger logger = LoggerFactory.getLogger(RedisPushStreamStatusMsgListener.class);
|
||||
|
||||
private boolean taskQueueHandlerRun = false;
|
||||
|
||||
@Autowired
|
||||
private IRedisCatchStorage redisCatchStorage;
|
||||
|
||||
@Autowired
|
||||
private IStreamPushService streamPushService;
|
||||
|
||||
@Autowired
|
||||
private DynamicTask dynamicTask;
|
||||
|
||||
|
||||
|
||||
private final ConcurrentLinkedQueue<Message> taskQueue = new ConcurrentLinkedQueue<>();
|
||||
|
||||
@Qualifier("taskExecutor")
|
||||
@Autowired
|
||||
private ThreadPoolTaskExecutor taskExecutor;
|
||||
|
||||
@Override
|
||||
public void onMessage(Message message, byte[] bytes) {
|
||||
// TODO 增加队列
|
||||
logger.warn("[REDIS消息-推流设备状态变化]: {}", new String(message.getBody()));
|
||||
taskQueue.offer(message);
|
||||
|
||||
if (!taskQueueHandlerRun) {
|
||||
taskQueueHandlerRun = true;
|
||||
taskExecutor.execute(() -> {
|
||||
while (!taskQueue.isEmpty()) {
|
||||
Message msg = taskQueue.poll();
|
||||
PushStreamStatusChangeFromRedisDto statusChangeFromPushStream = JSON.parseObject(msg.getBody(), PushStreamStatusChangeFromRedisDto.class);
|
||||
if (statusChangeFromPushStream == null) {
|
||||
logger.warn("[REDIS消息]推流设备状态变化消息解析失败");
|
||||
return;
|
||||
}
|
||||
// 取消定时任务
|
||||
dynamicTask.stop(VideoManagerConstants.VM_MSG_GET_ALL_ONLINE_REQUESTED);
|
||||
if (statusChangeFromPushStream.isSetAllOffline()) {
|
||||
// 所有设备离线
|
||||
streamPushService.allStreamOffline();
|
||||
}
|
||||
if (statusChangeFromPushStream.getOfflineStreams() != null
|
||||
&& statusChangeFromPushStream.getOfflineStreams().size() > 0) {
|
||||
// 更新部分设备离线
|
||||
streamPushService.offline(statusChangeFromPushStream.getOfflineStreams());
|
||||
}
|
||||
if (statusChangeFromPushStream.getOnlineStreams() != null &&
|
||||
statusChangeFromPushStream.getOnlineStreams().size() > 0) {
|
||||
// 更新部分设备上线
|
||||
streamPushService.online(statusChangeFromPushStream.getOnlineStreams());
|
||||
}
|
||||
}
|
||||
taskQueueHandlerRun = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run(ApplicationArguments args) throws Exception {
|
||||
// 启动时设置所有推流通道离线,发起查询请求
|
||||
redisCatchStorage.sendStreamPushRequestedMsgForStatus();
|
||||
dynamicTask.startDelay(VideoManagerConstants.VM_MSG_GET_ALL_ONLINE_REQUESTED, ()->{
|
||||
logger.info("[REDIS消息]未收到redis回复推流设备状态,执行推流设备离线");
|
||||
// 五秒收不到请求就设置通道离线,然后通知上级离线
|
||||
streamPushService.allStreamOffline();
|
||||
}, 5000);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -3,16 +3,12 @@ package com.genersoft.iot.vmp.service.impl;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.genersoft.iot.vmp.conf.UserSetting;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.AlarmChannelMessage;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.DeviceAlarm;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
|
||||
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
|
||||
import com.genersoft.iot.vmp.media.zlm.ZLMMediaListManager;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.MediaItem;
|
||||
import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
|
||||
import com.genersoft.iot.vmp.utils.DateUtil;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -22,6 +18,7 @@ import org.springframework.stereotype.Component;
|
||||
|
||||
|
||||
/**
|
||||
* 接收其他wvp发送流变化通知
|
||||
* @author lin
|
||||
*/
|
||||
@Component
|
||||
@@ -49,7 +46,7 @@ public class RedisStreamMsgListener implements MessageListener {
|
||||
|
||||
JSONObject steamMsgJson = JSON.parseObject(message.getBody(), JSONObject.class);
|
||||
if (steamMsgJson == null) {
|
||||
logger.warn("[REDIS的ALARM通知]消息解析失败");
|
||||
logger.warn("[收到redis 流变化]消息解析失败");
|
||||
return;
|
||||
}
|
||||
String serverId = steamMsgJson.getString("serverId");
|
||||
@@ -58,7 +55,7 @@ public class RedisStreamMsgListener implements MessageListener {
|
||||
// 自己发送的消息忽略即可
|
||||
return;
|
||||
}
|
||||
logger.info("[REDIS通知] 流变化: {}", new String(message.getBody()));
|
||||
logger.info("[收到redis 流变化]: {}", new String(message.getBody()));
|
||||
String app = steamMsgJson.getString("app");
|
||||
String stream = steamMsgJson.getString("stream");
|
||||
boolean register = steamMsgJson.getBoolean("register");
|
||||
@@ -75,9 +72,10 @@ public class RedisStreamMsgListener implements MessageListener {
|
||||
mediaItem.setOriginType(0);
|
||||
mediaItem.setOriginTypeStr("0");
|
||||
mediaItem.setOriginTypeStr("unknown");
|
||||
|
||||
zlmMediaListManager.addPush(mediaItem);
|
||||
|
||||
|
||||
if (register) {
|
||||
zlmMediaListManager.addPush(mediaItem);
|
||||
}else {
|
||||
zlmMediaListManager.removeMedia(app, stream);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,10 +3,10 @@ package com.genersoft.iot.vmp.service.impl;
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
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.GbStream;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.TreeType;
|
||||
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;
|
||||
@@ -23,14 +23,19 @@ 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.WVPResult;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.TransactionDefinition;
|
||||
import org.springframework.transaction.TransactionStatus;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
@@ -48,7 +53,7 @@ public class StreamProxyServiceImpl implements IStreamProxyService {
|
||||
private IMediaService mediaService;
|
||||
|
||||
@Autowired
|
||||
private ZLMRESTfulUtils zlmresTfulUtils;;
|
||||
private ZLMRESTfulUtils zlmresTfulUtils;
|
||||
|
||||
@Autowired
|
||||
private StreamProxyMapper streamProxyMapper;
|
||||
@@ -62,9 +67,6 @@ public class StreamProxyServiceImpl implements IStreamProxyService {
|
||||
@Autowired
|
||||
private UserSetting userSetting;
|
||||
|
||||
@Autowired
|
||||
private SipConfig sipConfig;
|
||||
|
||||
@Autowired
|
||||
private GbStreamMapper gbStreamMapper;
|
||||
|
||||
@@ -83,6 +85,12 @@ public class StreamProxyServiceImpl implements IStreamProxyService {
|
||||
@Autowired
|
||||
private IMediaServerService mediaServerService;
|
||||
|
||||
@Autowired
|
||||
DataSourceTransactionManager dataSourceTransactionManager;
|
||||
|
||||
@Autowired
|
||||
TransactionDefinition transactionDefinition;
|
||||
|
||||
|
||||
@Override
|
||||
public WVPResult<StreamInfo> save(StreamProxyItem param) {
|
||||
@@ -99,6 +107,7 @@ public class StreamProxyServiceImpl implements IStreamProxyService {
|
||||
wvpResult.setMsg("保存失败");
|
||||
return wvpResult;
|
||||
}
|
||||
|
||||
String dstUrl = String.format("rtmp://%s:%s/%s/%s", "127.0.0.1", mediaInfo.getRtmpPort(), param.getApp(),
|
||||
param.getStream() );
|
||||
param.setDst_url(dstUrl);
|
||||
@@ -108,9 +117,9 @@ public class StreamProxyServiceImpl implements IStreamProxyService {
|
||||
boolean saveResult;
|
||||
// 更新
|
||||
if (videoManagerStorager.queryStreamProxy(param.getApp(), param.getStream()) != null) {
|
||||
saveResult = videoManagerStorager.updateStreamProxy(param);
|
||||
saveResult = updateStreamProxy(param);
|
||||
}else { // 新增
|
||||
saveResult = videoManagerStorager.addStreamProxy(param);
|
||||
saveResult = addStreamProxy(param);
|
||||
}
|
||||
if (saveResult) {
|
||||
result.append("保存成功");
|
||||
@@ -124,7 +133,7 @@ public class StreamProxyServiceImpl implements IStreamProxyService {
|
||||
if (param.isEnable_remove_none_reader()) {
|
||||
del(param.getApp(), param.getStream());
|
||||
}else {
|
||||
videoManagerStorager.updateStreamProxy(param);
|
||||
updateStreamProxy(param);
|
||||
}
|
||||
|
||||
}else {
|
||||
@@ -147,27 +156,81 @@ public class StreamProxyServiceImpl implements IStreamProxyService {
|
||||
result.append(", 关联国标平台[ " + param.getPlatformGbId() + " ]失败");
|
||||
}
|
||||
}
|
||||
if (!StringUtils.isEmpty(param.getGbId())) {
|
||||
// 查找开启了全部直播流共享的上级平台
|
||||
List<ParentPlatform> parentPlatforms = parentPlatformMapper.selectAllAhareAllLiveStream();
|
||||
if (parentPlatforms.size() > 0) {
|
||||
for (ParentPlatform parentPlatform : parentPlatforms) {
|
||||
param.setPlatformId(parentPlatform.getServerGBId());
|
||||
param.setCatalogId(parentPlatform.getCatalogId());
|
||||
String stream = param.getStream();
|
||||
StreamProxyItem streamProxyItems = platformGbStreamMapper.selectOne(param.getApp(), stream, parentPlatform.getServerGBId());
|
||||
if (streamProxyItems == null) {
|
||||
platformGbStreamMapper.add(param);
|
||||
eventPublisher.catalogEventPublishForStream(parentPlatform.getServerGBId(), param, CatalogEvent.ADD);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
wvpResult.setMsg(result.toString());
|
||||
return wvpResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增代理流
|
||||
* @param streamProxyItem
|
||||
* @return
|
||||
*/
|
||||
private boolean addStreamProxy(StreamProxyItem streamProxyItem) {
|
||||
TransactionStatus transactionStatus = dataSourceTransactionManager.getTransaction(transactionDefinition);
|
||||
boolean result = false;
|
||||
streamProxyItem.setStreamType("proxy");
|
||||
streamProxyItem.setStatus(true);
|
||||
String now = DateUtil.getNow();
|
||||
streamProxyItem.setCreateTime(now);
|
||||
try {
|
||||
if (streamProxyMapper.add(streamProxyItem) > 0) {
|
||||
if (!StringUtils.isEmpty(streamProxyItem.getGbId())) {
|
||||
if (gbStreamMapper.add(streamProxyItem) < 0) {
|
||||
//事务回滚
|
||||
dataSourceTransactionManager.rollback(transactionStatus);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}else {
|
||||
//事务回滚
|
||||
dataSourceTransactionManager.rollback(transactionStatus);
|
||||
return false;
|
||||
}
|
||||
result = true;
|
||||
dataSourceTransactionManager.commit(transactionStatus); //手动提交
|
||||
}catch (Exception e) {
|
||||
logger.error("向数据库添加流代理失败:", e);
|
||||
dataSourceTransactionManager.rollback(transactionStatus);
|
||||
}
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新代理流
|
||||
* @param streamProxyItem
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public boolean updateStreamProxy(StreamProxyItem streamProxyItem) {
|
||||
TransactionStatus transactionStatus = dataSourceTransactionManager.getTransaction(transactionDefinition);
|
||||
boolean result = false;
|
||||
streamProxyItem.setStreamType("proxy");
|
||||
try {
|
||||
if (streamProxyMapper.update(streamProxyItem) > 0) {
|
||||
if (!StringUtils.isEmpty(streamProxyItem.getGbId())) {
|
||||
if (gbStreamMapper.updateByAppAndStream(streamProxyItem) == 0) {
|
||||
//事务回滚
|
||||
dataSourceTransactionManager.rollback(transactionStatus);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
//事务回滚
|
||||
dataSourceTransactionManager.rollback(transactionStatus);
|
||||
return false;
|
||||
}
|
||||
|
||||
dataSourceTransactionManager.commit(transactionStatus); //手动提交
|
||||
result = true;
|
||||
}catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
dataSourceTransactionManager.rollback(transactionStatus);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSONObject addStreamProxyToZlm(StreamProxyItem param) {
|
||||
JSONObject result = null;
|
||||
@@ -239,7 +302,7 @@ public class StreamProxyServiceImpl implements IStreamProxyService {
|
||||
if (jsonObject.getInteger("code") == 0) {
|
||||
result = true;
|
||||
streamProxy.setEnable(true);
|
||||
videoManagerStorager.updateStreamProxy(streamProxy);
|
||||
updateStreamProxy(streamProxy);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
@@ -253,7 +316,7 @@ public class StreamProxyServiceImpl implements IStreamProxyService {
|
||||
JSONObject jsonObject = removeStreamProxyFromZlm(streamProxyDto);
|
||||
if (jsonObject != null && jsonObject.getInteger("code") == 0) {
|
||||
streamProxyDto.setEnable(false);
|
||||
result = videoManagerStorager.updateStreamProxy(streamProxyDto);
|
||||
result = updateStreamProxy(streamProxyDto);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
||||
@@ -4,6 +4,7 @@ import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.alibaba.fastjson.TypeReference;
|
||||
import com.genersoft.iot.vmp.conf.MediaConfig;
|
||||
import com.genersoft.iot.vmp.conf.UserSetting;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.*;
|
||||
import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
|
||||
@@ -13,6 +14,7 @@ import com.genersoft.iot.vmp.media.zlm.dto.*;
|
||||
import com.genersoft.iot.vmp.service.IGbStreamService;
|
||||
import com.genersoft.iot.vmp.service.IMediaServerService;
|
||||
import com.genersoft.iot.vmp.service.IStreamPushService;
|
||||
import com.genersoft.iot.vmp.service.bean.StreamPushItemFromRedis;
|
||||
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
||||
import com.genersoft.iot.vmp.storager.dao.*;
|
||||
import com.genersoft.iot.vmp.utils.DateUtil;
|
||||
@@ -21,7 +23,10 @@ import com.github.pagehelper.PageInfo;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.TransactionDefinition;
|
||||
import org.springframework.transaction.TransactionStatus;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.util.*;
|
||||
@@ -68,6 +73,16 @@ public class StreamPushServiceImpl implements IStreamPushService {
|
||||
@Autowired
|
||||
private IMediaServerService mediaServerService;
|
||||
|
||||
@Autowired
|
||||
DataSourceTransactionManager dataSourceTransactionManager;
|
||||
|
||||
@Autowired
|
||||
TransactionDefinition transactionDefinition;
|
||||
|
||||
@Autowired
|
||||
private MediaConfig mediaConfig;
|
||||
|
||||
|
||||
@Override
|
||||
public List<StreamPushItem> handleJSON(String jsonData, MediaServerItem mediaServerItem) {
|
||||
if (jsonData == null) {
|
||||
@@ -132,30 +147,9 @@ public class StreamPushServiceImpl implements IStreamPushService {
|
||||
stream.setStreamType("push");
|
||||
stream.setStatus(true);
|
||||
stream.setCreateTime(DateUtil.getNow());
|
||||
stream.setStreamType("push");
|
||||
stream.setMediaServerId(mediaConfig.getId());
|
||||
int add = gbStreamMapper.add(stream);
|
||||
|
||||
// 查找开启了全部直播流共享的上级平台
|
||||
List<ParentPlatform> parentPlatforms = parentPlatformMapper.selectAllAhareAllLiveStream();
|
||||
if (parentPlatforms.size() > 0) {
|
||||
for (ParentPlatform parentPlatform : parentPlatforms) {
|
||||
stream.setCatalogId(parentPlatform.getCatalogId());
|
||||
stream.setPlatformId(parentPlatform.getServerGBId());
|
||||
String streamId = stream.getStream();
|
||||
StreamProxyItem streamProxyItem = platformGbStreamMapper.selectOne(stream.getApp(), streamId, parentPlatform.getServerGBId());
|
||||
if (streamProxyItem == null) {
|
||||
platformGbStreamMapper.add(stream);
|
||||
eventPublisher.catalogEventPublishForStream(parentPlatform.getServerGBId(), stream, CatalogEvent.ADD);
|
||||
}else {
|
||||
if (!streamProxyItem.getGbId().equals(stream.getGbId())) {
|
||||
// 此流使用另一个国标Id已经与该平台关联,移除此记录
|
||||
platformGbStreamMapper.delByAppAndStreamAndPlatform(stream.getApp(), streamId, parentPlatform.getServerGBId());
|
||||
platformGbStreamMapper.add(stream);
|
||||
eventPublisher.catalogEventPublishForStream(parentPlatform.getServerGBId(), stream, CatalogEvent.ADD);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return add > 0;
|
||||
}
|
||||
|
||||
@@ -181,7 +175,6 @@ public class StreamPushServiceImpl implements IStreamPushService {
|
||||
|
||||
@Override
|
||||
public StreamPushItem getPush(String app, String streamId) {
|
||||
|
||||
return streamPushMapper.selectOne(app, streamId);
|
||||
}
|
||||
|
||||
@@ -345,31 +338,6 @@ public class StreamPushServiceImpl implements IStreamPushService {
|
||||
public void batchAdd(List<StreamPushItem> streamPushItems) {
|
||||
streamPushMapper.addAll(streamPushItems);
|
||||
gbStreamMapper.batchAdd(streamPushItems);
|
||||
// 查找开启了全部直播流共享的上级平台
|
||||
List<ParentPlatform> parentPlatforms = parentPlatformMapper.selectAllAhareAllLiveStream();
|
||||
if (parentPlatforms.size() > 0) {
|
||||
for (StreamPushItem stream : streamPushItems) {
|
||||
for (ParentPlatform parentPlatform : parentPlatforms) {
|
||||
stream.setCatalogId(parentPlatform.getCatalogId());
|
||||
stream.setPlatformId(parentPlatform.getServerGBId());
|
||||
String streamId = stream.getStream();
|
||||
StreamProxyItem streamProxyItem = platformGbStreamMapper.selectOne(stream.getApp(), streamId, parentPlatform.getServerGBId());
|
||||
if (streamProxyItem == null) {
|
||||
platformGbStreamMapper.add(stream);
|
||||
eventPublisher.catalogEventPublishForStream(parentPlatform.getServerGBId(), stream, CatalogEvent.ADD);
|
||||
}else {
|
||||
if (!streamProxyItem.getGbId().equals(stream.getGbId())) {
|
||||
// 此流使用另一个国标Id已经与该平台关联,移除此记录
|
||||
platformGbStreamMapper.delByAppAndStreamAndPlatform(stream.getApp(), streamId, parentPlatform.getServerGBId());
|
||||
platformGbStreamMapper.add(stream);
|
||||
eventPublisher.catalogEventPublishForStream(parentPlatform.getServerGBId(), stream, CatalogEvent.ADD);
|
||||
stream.setGbId(streamProxyItem.getGbId());
|
||||
eventPublisher.catalogEventPublishForStream(parentPlatform.getServerGBId(), stream, CatalogEvent.DEL);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -481,4 +449,58 @@ public class StreamPushServiceImpl implements IStreamPushService {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void allStreamOffline() {
|
||||
List<GbStream> onlinePushers = streamPushMapper.getOnlinePusherForGb();
|
||||
if (onlinePushers.size() == 0) {
|
||||
return;
|
||||
}
|
||||
streamPushMapper.setAllStreamOffline();
|
||||
|
||||
// 发送通知
|
||||
eventPublisher.catalogEventPublishForStream(null, onlinePushers, CatalogEvent.OFF);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void offline(List<StreamPushItemFromRedis> offlineStreams) {
|
||||
// 更新部分设备离线
|
||||
List<GbStream> onlinePushers = streamPushMapper.getOnlinePusherForGbInList(offlineStreams);
|
||||
streamPushMapper.offline(offlineStreams);
|
||||
// 发送通知
|
||||
eventPublisher.catalogEventPublishForStream(null, onlinePushers, CatalogEvent.OFF);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void online(List<StreamPushItemFromRedis> onlineStreams) {
|
||||
// 更新部分设备上线streamPushService
|
||||
List<GbStream> onlinePushers = streamPushMapper.getOfflinePusherForGbInList(onlineStreams);
|
||||
streamPushMapper.online(onlineStreams);
|
||||
// 发送通知
|
||||
eventPublisher.catalogEventPublishForStream(null, onlinePushers, CatalogEvent.ON);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean add(StreamPushItem stream) {
|
||||
stream.setUpdateTime(DateUtil.getNow());
|
||||
stream.setCreateTime(DateUtil.getNow());
|
||||
stream.setServerId(userSetting.getServerId());
|
||||
|
||||
// 放在事务内执行
|
||||
boolean result = false;
|
||||
TransactionStatus transactionStatus = dataSourceTransactionManager.getTransaction(transactionDefinition);
|
||||
try {
|
||||
int addStreamResult = streamPushMapper.add(stream);
|
||||
if (!StringUtils.isEmpty(stream.getGbId())) {
|
||||
stream.setStreamType("push");
|
||||
gbStreamMapper.add(stream);
|
||||
}
|
||||
dataSourceTransactionManager.commit(transactionStatus);
|
||||
result = true;
|
||||
}catch (Exception e) {
|
||||
logger.error("批量移除流与平台的关系时错误", e);
|
||||
dataSourceTransactionManager.rollback(transactionStatus);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,38 +14,60 @@ import java.util.*;
|
||||
|
||||
public class StreamPushUploadFileHandler extends AnalysisEventListener<StreamPushExcelDto> {
|
||||
|
||||
// 错误数据的回调,用于将错误数据发送给页面
|
||||
/**
|
||||
* 错误数据的回调,用于将错误数据发送给页面
|
||||
*/
|
||||
private ErrorDataHandler errorDataHandler;
|
||||
|
||||
// 推流的业务类用于存储数据
|
||||
/**
|
||||
* 推流的业务类用于存储数据
|
||||
*/
|
||||
private IStreamPushService pushService;
|
||||
|
||||
// 默认流媒体节点ID
|
||||
/**
|
||||
* 默认流媒体节点ID
|
||||
*/
|
||||
private String defaultMediaServerId;
|
||||
|
||||
// 用于存储不加过滤的所有数据
|
||||
/**
|
||||
* 用于存储不加过滤的所有数据
|
||||
*/
|
||||
private List<StreamPushItem> streamPushItems = new ArrayList<>();
|
||||
|
||||
// 用于存储更具APP+Stream过滤后的数据,可以直接存入stream_push表与gb_stream表
|
||||
/**
|
||||
* 用于存储更具APP+Stream过滤后的数据,可以直接存入stream_push表与gb_stream表
|
||||
*/
|
||||
private Map<String,StreamPushItem> streamPushItemForSave = new HashMap<>();
|
||||
|
||||
// 用于存储按照APP+Stream为KEY, 平台ID+目录Id 为value的数据,用于存储到gb_stream表后获取app+Stream对应的平台与目录信息,然后存入关联表
|
||||
/**
|
||||
* 用于存储按照APP+Stream为KEY, 平台ID+目录Id 为value的数据,用于存储到gb_stream表后获取app+Stream对应的平台与目录信息,然后存入关联表
|
||||
*/
|
||||
private Map<String, List<String[]>> streamPushItemsForPlatform = new HashMap<>();
|
||||
|
||||
// 用于判断文件是否存在重复的app+Stream+平台ID
|
||||
/**
|
||||
* 用于判断文件是否存在重复的app+Stream+平台ID
|
||||
*/
|
||||
private Set<String> streamPushStreamSet = new HashSet<>();
|
||||
|
||||
// 用于存储APP+Stream->国标ID 的数据结构, 数据一一对应,全局判断APP+Stream->国标ID是否存在不对应
|
||||
/**
|
||||
* 用于存储APP+Stream->国标ID 的数据结构, 数据一一对应,全局判断APP+Stream->国标ID是否存在不对应
|
||||
*/
|
||||
private BiMap<String,String> gBMap = HashBiMap.create();
|
||||
|
||||
// 记录错误的APP+Stream
|
||||
/**
|
||||
* 记录错误的APP+Stream
|
||||
*/
|
||||
private List<String> errorStreamList = new ArrayList<>();
|
||||
|
||||
|
||||
// 记录错误的国标ID
|
||||
/**
|
||||
* 记录错误的国标ID
|
||||
*/
|
||||
private List<String> errorGBList = new ArrayList<>();
|
||||
|
||||
// 读取数量计数器
|
||||
/**
|
||||
* 读取数量计数器
|
||||
*/
|
||||
private int loadedSize = 0;
|
||||
|
||||
public StreamPushUploadFileHandler(IStreamPushService pushService, String defaultMediaServerId, ErrorDataHandler errorDataHandler) {
|
||||
|
||||
@@ -3,6 +3,8 @@ package com.genersoft.iot.vmp.service.impl;
|
||||
import com.genersoft.iot.vmp.service.IUserService;
|
||||
import com.genersoft.iot.vmp.storager.dao.UserMapper;
|
||||
import com.genersoft.iot.vmp.storager.dao.dto.User;
|
||||
import com.github.pagehelper.PageHelper;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.StringUtils;
|
||||
@@ -11,7 +13,7 @@ import java.util.List;
|
||||
|
||||
@Service
|
||||
public class UserServiceImpl implements IUserService {
|
||||
|
||||
|
||||
@Autowired
|
||||
private UserMapper userMapper;
|
||||
|
||||
@@ -64,4 +66,16 @@ public class UserServiceImpl implements IUserService {
|
||||
return userMapper.checkPushAuthorityByCallIdAndSign(callId, sign).size() > 0;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageInfo<User> getUsers(int page, int count) {
|
||||
PageHelper.startPage(page, count);
|
||||
List<User> users = userMapper.getUsers();
|
||||
return new PageInfo<>(users);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int changePushKey(int id, String pushKey) {
|
||||
return userMapper.changePushKey(id,pushKey);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user