package com.ard.device.channel.service.impl;
|
|
import com.ard.common.constant.UserConstants;
|
import com.ard.common.utils.uuid.IdUtils;
|
import com.ard.device.camera.domain.ArdCamera;
|
import com.ard.device.camera.service.IArdCameraService;
|
import com.ard.device.channel.domain.ArdChannel;
|
import com.ard.device.channel.mapper.ArdChannelMapper;
|
import com.ard.device.channel.service.IArdChannelService;
|
import com.ard.vtdu.config.MediamtxConfig;
|
import com.ard.vtdu.domain.ArdVtdu;
|
import com.ard.vtdu.service.IArdVtduService;
|
import lombok.extern.slf4j.Slf4j;
|
import org.springframework.scheduling.annotation.Scheduled;
|
import org.springframework.stereotype.Service;
|
import javax.annotation.Resource;
|
import java.util.*;
|
import java.util.stream.Collectors;
|
|
/**
|
* 通道管理Service业务层处理
|
*
|
* @author ard
|
* @date 2023-08-19
|
*/
|
@Slf4j
|
@Service
|
public class ArdChannelServiceImpl implements IArdChannelService {
|
@Resource
|
private IArdCameraService ardCameraService;
|
@Resource
|
private ArdChannelMapper ardChannelMapper;
|
@Resource
|
private IArdVtduService ardVtduService;
|
@Resource
|
private MediamtxConfig mediamtxConfig;
|
/**
|
* 查询通道管理
|
*
|
* @param id 通道管理主键
|
* @return 通道管理
|
*/
|
@Override
|
public ArdChannel selectArdChannelById(String id) {
|
return ardChannelMapper.selectArdChannelById(id);
|
}
|
|
/**
|
* 查询通道管理列表
|
*
|
* @param ardChannel 通道管理
|
* @return 通道管理
|
*/
|
@Override
|
public List<ArdChannel> selectArdChannelList(ArdChannel ardChannel) {
|
return ardChannelMapper.selectArdChannelList(ardChannel);
|
}
|
|
/**
|
* 新增通道管理
|
*
|
* @param ardChannel 通道管理
|
* @return 结果
|
*/
|
@Override
|
public int insertArdChannel(ArdChannel ardChannel) {
|
ardChannel.setId(IdUtils.simpleUUID());
|
return ardChannelMapper.insertArdChannel(ardChannel);
|
}
|
|
/**
|
* 修改通道管理
|
*
|
* @param ardChannel 通道管理
|
* @return 结果
|
*/
|
@Override
|
public int updateArdChannel(ArdChannel ardChannel) {
|
return ardChannelMapper.updateArdChannel(ardChannel);
|
}
|
|
/**
|
* 批量删除通道管理
|
*
|
* @param ids 需要删除的通道管理主键
|
* @return 结果
|
*/
|
@Override
|
public int deleteArdChannelByIds(String[] ids) {
|
return ardChannelMapper.deleteArdChannelByIds(ids);
|
}
|
|
/**
|
* 删除通道管理信息
|
*
|
* @param id 通道管理主键
|
* @return 结果
|
*/
|
@Override
|
public int deleteArdChannelById(String id) {
|
return ardChannelMapper.deleteArdChannelById(id);
|
}
|
|
/**
|
* 清空通道
|
*
|
* @author 刘苏义
|
* @date 2024/8/10 11:18
|
*/
|
@Override
|
public int clearArdChannel(){
|
return ardChannelMapper.clearArdChannel();
|
}
|
/**
|
* 删除通道管理信息
|
*
|
* @param deviceId 所属设备ID
|
* @return 结果
|
*/
|
@Override
|
public int deleteArdChannelByDeviceId(String deviceId) {
|
return ardChannelMapper.deleteArdChannelByDeviceId(deviceId);
|
}
|
/**
|
* 校验相机通道是否唯一
|
*
|
* @param channel 通道信息
|
* @return 结果
|
*/
|
@Override
|
public boolean checkArdChannelUnique(ArdChannel channel) {
|
ArdChannel info = ardChannelMapper.checkArdChannelUnique(channel);
|
if (info != null && !Objects.equals(info.getId(), channel.getId()))
|
{
|
return UserConstants.NOT_UNIQUE;
|
}
|
return UserConstants.UNIQUE;
|
}
|
|
|
@Scheduled(cron = "0/5 * * * * ?")
|
public void syncVtdu() {
|
log.debug("定时同步Vtdu任务");
|
List<ArdChannel> channels = this.selectArdChannelList(new ArdChannel());
|
if (channels == null || channels.isEmpty()) {
|
log.warn("没有获取到通道数据,退出同步");
|
return;
|
}
|
List<ArdVtdu> ardVtduList = ardVtduService.selectArdVtduList(new ArdVtdu());
|
|
Set<String> validNames = channels.stream()
|
.map(channel -> channel.getDeviceId() + "_" + channel.getChanNo())
|
.collect(Collectors.toSet());
|
// 2. 合并操作:增、删、改
|
channels.forEach(channel -> {
|
String name = channel.getDeviceId() + "_" + channel.getChanNo(); // 生成媒体表的 name
|
String cameraId = channel.getDeviceId(); // cameraId 就是通道的 deviceId
|
String rtspSourceUrl = getRtspSource(channel);
|
String rtspUrl = "rtsp://" + mediamtxConfig.getPlayHost() + ":8554" + "/" + name; // 拼接 webrtcUrl
|
String rtmpUrl = "rtmp://" + mediamtxConfig.getPlayHost() + ":1935" + "/" + name; // 拼接 webrtcUrl
|
String protocol = mediamtxConfig.isHttps() ? "https://" : "http://";
|
String webrtcUrl = protocol + mediamtxConfig.getPlayHost() + ":8889" + "/" + name; // 拼接 webrtcUrl
|
|
// 先检查媒体表是否已有此记录
|
Optional<ArdVtdu> existingMedia = ardVtduList.stream()
|
.filter(media -> media.getName().equals(name)) // 查找是否已有对应的媒体记录
|
.findFirst();
|
|
if (existingMedia.isPresent()) {
|
// 如果已有,更新现有记录
|
ArdVtdu vtdu = existingMedia.get();
|
// 更新前后内容相同则不进行更新
|
if (!vtdu.getRtspSource().equals(rtspSourceUrl) ||
|
!vtdu.getWebrtcUrl().equals(webrtcUrl) ||
|
!vtdu.getRtspUrl().equals(rtspUrl) ||
|
!vtdu.getRtmpUrl().equals(rtmpUrl)) {
|
vtdu.setRtspUrl(rtspUrl);
|
vtdu.setRtmpUrl(rtmpUrl);
|
vtdu.setWebrtcUrl(webrtcUrl);
|
ardVtduService.updateArdVtdu(vtdu);
|
log.info("更新媒体记录:{}", vtdu.getName());
|
}
|
} else {
|
// 如果没有,插入新的记录
|
ArdVtdu vtdu = new ArdVtdu();
|
vtdu.setName(name);
|
vtdu.setRtspSource(rtspSourceUrl);
|
vtdu.setCameraId(cameraId);
|
vtdu.setRtspUrl(rtspUrl);
|
vtdu.setRtmpUrl(rtmpUrl);
|
vtdu.setWebrtcUrl(webrtcUrl);
|
ardVtduService.insertArdVtdu(vtdu); // 保存到媒体表
|
log.info("插入新媒体记录:{}", vtdu.getName());
|
}
|
});
|
// 3. 删除操作:删除媒体表中多余的记录
|
List<String> invalidNames = ardVtduList.stream()
|
.filter(vtdu -> !validNames.contains(vtdu.getName()))
|
.filter(vtdu -> !"publisher".equalsIgnoreCase(vtdu.getRtspSource())) // 不是机场流
|
.map(ArdVtdu::getName)
|
.collect(Collectors.toList());
|
|
if (!invalidNames.isEmpty()) {
|
// 将 List<String> 转换为 String[]
|
String[] namesArray = invalidNames.toArray(new String[0]);
|
ardVtduService.deleteArdVtduByNames(namesArray); // 传递数组
|
log.info("删除不再存在的媒体记录:{}", Arrays.toString(namesArray));
|
}
|
|
}
|
|
// 根据通道信息获取rtsp源地址
|
private String getRtspSource(ArdChannel channel) {
|
String rtspSource = "";
|
ArdCamera ardCamera =ardCameraService.selectArdCameraById(channel.getDeviceId());
|
if (ardCamera != null) {
|
switch (ardCamera.getFactory()) {
|
case "1":
|
rtspSource =
|
"rtsp://" + ardCamera.getUsername() + ":" + ardCamera.getPassword() + "@" + ardCamera.getIp() + ":" + ardCamera.getRtspPort() + "/h264/ch" + channel.getChanNo() + "/main/av_stream";
|
break;
|
case "2":
|
rtspSource =
|
"rtsp://" + ardCamera.getUsername() + ":" + ardCamera.getPassword() + "@" + ardCamera.getIp() + ":" + ardCamera.getRtspPort() + "/cam/realmonitor?channel=" + channel.getChanNo() + "&subtype=0";
|
break;
|
}
|
}
|
return rtspSource;
|
}
|
}
|