package com.fdkankan.ucenter.service.impl;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fdkankan.common.constant.CommonStatus;
import com.fdkankan.common.constant.ErrorCode;
import com.fdkankan.common.constant.SceneVersionType;
import com.fdkankan.common.exception.BusinessException;
import com.fdkankan.fyun.face.FYunFileServiceInterface;
import com.fdkankan.model.utils.CreateObjUtil;
import com.fdkankan.ucenter.common.PageInfo;
import com.fdkankan.ucenter.common.RedisKeyUtil;
import com.fdkankan.ucenter.common.Result;
import com.fdkankan.ucenter.common.constants.ConstantFilePath;
import com.fdkankan.ucenter.common.constants.ResultCodeMsg;
import com.fdkankan.ucenter.common.constants.UploadFilePath;
import com.fdkankan.redis.util.RedisUtil;
import com.fdkankan.ucenter.entity.*;
import com.fdkankan.ucenter.httpClient.service.LaserService;
import com.fdkankan.ucenter.mapper.IScenePlusMapper;
import com.fdkankan.ucenter.service.*;
import java.io.File;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.stream.Collectors;
import com.fdkankan.ucenter.util.RoamingPointUtil;
import com.fdkankan.ucenter.util.SceneResourcePath;
import com.fdkankan.ucenter.vo.request.RequestScene;
import com.fdkankan.ucenter.vo.response.SceneNumVo;
import com.fdkankan.ucenter.vo.response.SceneVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
/**
*
* 场景主表 服务实现类
*
*
* @author
* @since 2022-07-04
*/
@Service
@Slf4j
public class ScenePlusServiceImpl extends ServiceImpl implements IScenePlusService {
@Value("${fyun.host}")
private String fyunHost;
@Autowired
private IScenePlusExtService scenePlusExtService;
@Autowired
public SceneCommonService sceneCommonService;
@Autowired
private ISceneEditInfoService sceneEditInfoService;
@Autowired
private ISceneEditInfoExtService sceneEditInfoExtService;
@Autowired
private ISceneEditControlsService sceneEditControlsService;
@Autowired
private ICameraDetailService cameraDetailService;
@Autowired
private ISurveillanceService surveillanceService;
@Autowired
private ISceneProService sceneProService;
@Autowired
FYunFileServiceInterface fYunFileServiceInterface;
@Autowired
RedisUtil redisUtil;
@Autowired
LaserService laserService;
@Autowired
ISceneCopyLogService sceneCopyLogService;
@Autowired
private IUserService userService;
@Autowired
ICameraTypeService cameraTypeService;
@Override
public Long getCountByUserId(Long userId, List> sceneSourceList) {
LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>();
wrapper.eq(ScenePlus::getUserId, userId);
wrapper.in(ScenePlus::getSceneSource, sceneSourceList);
return this.count(wrapper);
}
@Override
public Long getCountByUserId(Long userId, Integer cameraType) {
return this.getBaseMapper().getCountByUserId(userId,cameraType);
}
@Override
public List getListByCameraId(Long cameraId) {
LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>();
wrapper.eq(ScenePlus::getCameraId,cameraId);
return this.list(wrapper);
}
@Override
public void bindOrUnCamera(List cameraIds, Long userId) {
if(cameraIds.size() >0){
LambdaUpdateWrapper wrapper = new LambdaUpdateWrapper<>();
wrapper.set(ScenePlus::getUserId,userId)
.in(ScenePlus::getCameraId,cameraIds);
this.update(wrapper);
}
}
@Override
public List getListByCameraIds(List cameraIds) {
if(cameraIds.size() >0){
LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>();
wrapper.in(ScenePlus::getCameraId,cameraIds);
return this.list(wrapper);
}
return new ArrayList<>();
}
@Override
public List getListByNums(List numList) {
LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>();
wrapper.in(ScenePlus::getNum,numList);
return this.list(wrapper);
}
@Override
public HashMap getMapByIds(List sceneIds) {
LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>();
wrapper.in(ScenePlus::getId,sceneIds);
List list = this.list(wrapper);
HashMap map = new HashMap<>();
list.forEach(entity -> map.put(entity.getId(),entity));
return map;
}
@Override
public ScenePlus getByNum(String sceneNum) {
LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>();
wrapper.eq(ScenePlus::getNum,sceneNum);
List list = this.list(wrapper);
if(list!=null && list.size() >0){
return list.get(0);
}
return null;
}
@Override
public List getByIds(List plusIds) {
LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>();
wrapper.in(ScenePlus::getId,plusIds);
return this.list(wrapper);
}
@Override
public Long copyV4Scene(ScenePlus scenePlus,String newNum ,CameraDetail cameraDetail,CameraType cameraType) {
String oldNum = scenePlus.getNum();
Long plusId = scenePlus.getId();
ScenePlusExt plusExt = scenePlusExtService.getByPlusId(plusId);
if(plusExt == null){
throw new BusinessException(ResultCodeMsg.FAILURE_CODE_400002, ResultCodeMsg.FAILURE_MSG_400002);
}
scenePlus.setNum(newNum);
scenePlus.setTitle(scenePlus.getTitle() +"(copy)");
scenePlus.setSceneStatus(0);
scenePlus.setId(null);
this.save(scenePlus);
ExecutorService executor = ThreadUtil.newSingleExecutor();
CompletableFuture.runAsync(() -> {
String oldDataSource = plusExt.getDataSource();
String newDataSource = sceneCommonService.getNewDataSource(oldDataSource);
log.info("sceneCopy-V4-oldNum:{},oldDataSource:{},newNum:{},newDataSource:{}",
oldNum,oldDataSource,newNum,newDataSource);
String newVideos = plusExt.getVideos();
if(StrUtil.isNotEmpty(newVideos)){
newVideos = plusExt.getVideos().replaceAll("/data/data" + oldNum, "/scene_view_data/" + newNum + "/data").replaceAll(oldNum, newNum);
}
plusExt.setId(null);
plusExt.setPlusId(scenePlus.getId());
plusExt.setDataSource(newDataSource);
plusExt.setWebSite(plusExt.getWebSite().replace(oldNum, newNum));
plusExt.setThumb(plusExt.getThumb().replace(oldNum, newNum));
plusExt.setVideos(newVideos);
plusExt.setViewCount(0);
scenePlusExtService.save(plusExt);
SceneEditInfo sceneEditInfo = sceneEditInfoService.getByScenePlusId(plusId);
Long sceneEditInfoId = sceneEditInfo.getId();
sceneEditInfo.setId(null);
sceneEditInfo.setScenePlusId(scenePlus.getId());
sceneEditInfo.setSceneProId(null);
sceneEditInfo.setTitle(scenePlus.getTitle());
sceneEditInfoService.save(sceneEditInfo);
SceneEditInfoExt sceneEditInfoExt = sceneEditInfoExtService.getByEditInfoId(sceneEditInfoId);
sceneEditInfoExt.setId(null);
sceneEditInfoExt.setEditInfoId(sceneEditInfo.getId());
sceneEditInfoExt.setScenePlusId(scenePlus.getId());
sceneEditInfoExt.setSceneProId(null);
sceneEditInfoExtService.save(sceneEditInfoExt);
SceneEditControls sceneEditControls = sceneEditControlsService.getBySceneEditId(sceneEditInfoId);
sceneEditControls.setId(null);
sceneEditControls.setEditInfoId(sceneEditInfo.getId());
sceneEditControlsService.save(sceneEditControls);
List list = surveillanceService.list(new LambdaQueryWrapper().eq(Surveillance::getNum, oldNum));
if (!Objects.isNull(list)) {
list.stream().forEach(item -> {
item.setNum(newNum);
item.setId(null);
surveillanceService.save(item);
});
}
if(scenePlus.getSceneSource() == 4 || scenePlus.getSceneSource() == 5){ //深时复制
laserService.copy(oldNum,newNum,newDataSource,true);
}else {
laserService.cloudPointBuild(oldNum,newNum);
}
try {
//重新生成编辑页基础设置二维码
sceneCommonService.createNewQrCode(SceneVersionType.V4.code(),sceneEditInfoExt.getShareLogoImg(),newNum,plusExt.getWebSite());
//copyDataSource
//cn.hutool.core.io.FileUtil.copyContent(new File(oldDataSource),new File(newDataSource),true);
this.copyOssAndNas(oldNum,newNum);
//修改 oss status.json ,nas scene.json
String targetData = String.format(SceneResourcePath.DATA_VIEW_PATH,newNum);
sceneCommonService.updateOssJson(targetData,oldNum,newNum,"status.json");
sceneCommonService.updateNasSceneJson(targetData,oldNum,newNum,scenePlus.getTitle(),"v4","scene.json");
if(scenePlus.getSceneSource() == 4 || scenePlus.getSceneSource() == 5){ //深时复制
laserService.copy(oldNum,newNum,newDataSource,false);
}
String redisKey = RedisKeyUtil.laserCopyLock + newNum;
long startTime = new Date().getTime();
long startTime2 = new Date().getTime();
while (redisUtil.hasKey(redisKey) ){ //深时场景复制同步锁
long waitTime = new Date().getTime();
if(waitTime - startTime2 >1000){
startTime2 = new Date().getTime();
log.info("等待激光复制业务结束----:{}",(waitTime - startTime) /1000);
}
}
scenePlus.setSceneStatus(-2);
this.updateById(scenePlus);
sceneCopyLogService.saveByNum(oldNum,newNum,scenePlus.getUserId());
String redisSceneLock = String.format(RedisKeyUtil.copySpaceLock,cameraDetail.getCameraId());
startTime = new Date().getTime();
startTime2 = new Date().getTime();
while(redisUtil.hasKey(redisSceneLock)){
long waitTime = new Date().getTime();
if(waitTime - startTime2 >1000){
startTime2 = new Date().getTime();
log.info("等待相机增加容量复制业务结束----:{},{}",(waitTime - startTime) /1000,cameraDetail.getCameraId());
}
}
redisUtil.set(redisSceneLock,"1",60*60);
Boolean checkSpace = cameraDetailService.checkSpace(cameraDetail.getCameraId(),cameraType);
if(!checkSpace){
List panoNumList = new ArrayList<>();
if(plusExt.getLocation() == 7){
panoNumList.add(scenePlus.getNum());
}
sceneProService.lockOrUnLockScenes(new ArrayList<>(),Arrays.asList(scenePlus.getNum()),-2,cameraType.getIsLaser(),panoNumList);
}
cameraDetailService.addUsedSpace(cameraDetail,plusExt.getSpace());
redisUtil.del(redisSceneLock);
}catch (Exception e){
log.error("复制场景失败-V4-sceneNum:{},error:{}",oldNum,e);
scenePlus.setSceneStatus(-1);
this.updateById(scenePlus);
throw new BusinessException(ResultCodeMsg.FAILURE_CODE_400006, ResultCodeMsg.FAILURE_MSG_400006);
}
}, executor).whenComplete((reslut, e) -> {
log.info("copy-success-");
});
return scenePlus.getId();
}
private void copyOssAndNas(String oldNum,String newNum){
// 拷贝场景编辑资源
String oldEditPath = String.format(SceneResourcePath.EDIT_PATH_v4, oldNum);
String newEditPath = String.format(SceneResourcePath.EDIT_PATH_v4, newNum);
fYunFileServiceInterface.copyFileInBucket(oldEditPath, newEditPath);
// 拷贝场景展示资源
String oldViewPath = String.format(SceneResourcePath.VIEW_PATH_v4, oldNum);
String newViewPath = String.format(SceneResourcePath.VIEW_PATH_v4, newNum);
fYunFileServiceInterface.copyFileInBucket(oldViewPath, newViewPath);
//复制计算结果文件
String oldResultPath = String.format(SceneResourcePath.SCENE_RESULT_DATA_PATH, oldNum);
String newResultPath = String.format(SceneResourcePath.SCENE_RESULT_DATA_PATH, newNum);
fYunFileServiceInterface.copyFileInBucket(oldResultPath, newResultPath);
// 拷贝本地资源
String oldPath = SceneResourcePath.nasBasePath + oldNum;
String newPath = SceneResourcePath.nasBasePath + newNum;
if(new File(oldPath).exists()){
FileUtil.copyContent(new File(oldPath), new File(newPath),true);
}
String oldPath_v4 = SceneResourcePath.nasBasePath_v4 + oldNum;
String newPath_v4 = SceneResourcePath.nasBasePath_v4 + newNum;
if(new File(oldPath_v4).exists()){
FileUtil.copyContent(new File(oldPath_v4), new File(newPath_v4),true);
}
}
@Override
public Result pageSceneWithHouseType(RequestScene param, String token) {
User ssoUser = userService.getByToken(token);
Page page = this.page(new Page<>(param.getPageNum(), param.getPageSize()),
new LambdaQueryWrapper().eq(ScenePlus::getUserId, ssoUser.getId()).eq(ScenePlus::getHouseType, CommonStatus.YES.code().intValue()));
List records = null;
if(page.getRecords().size() > 0){
records = page.getRecords().parallelStream().map(plus -> {
return SceneVo.builder().createTime(plus.getCreateTime())
.id(plus.getId()).roamingPointUrl(this.createRoamingPoint(plus.getNum())).sceneName(plus.getTitle())
.num(plus.getNum()).updateTime(plus.getUpdateTime()).userId(plus.getUserId()).build();
}).collect(Collectors.toList());
}
PageInfo pageInfo = PageInfo.PageInfo(page);
pageInfo.setList(records);
return Result.success(pageInfo);
}
@Override
public Result getArPathByNum(String num) {
ScenePro scenePro = sceneProService.getByNum(num);
if(Objects.nonNull(scenePro)){
return Result.success("成功", String.format("images/images%s/ar", num));
}
ScenePlus scenePlus = this.getByNum(num);
if(Objects.nonNull(scenePlus)){
return Result.success("成功", String.format(UploadFilePath.IMG_VIEW_PATH, num) + "ar");
}
return Result.failure(ErrorCode.FAILURE_CODE_5005.code(), ErrorCode.FAILURE_CODE_5005.message());
}
private String createRoamingPoint(String num){
String roamingPointOssPath = String.format(UploadFilePath.DATA_VIEW_PATH, num) + "roamingPoint.json";
String url = null;
try {
if(!fYunFileServiceInterface.fileExist(roamingPointOssPath)){
String visionModeldataPath = ConstantFilePath.SCENE_V4_PATH + num + File.separator + "vision.modeldata";
String visionModeldataOssPath = String.format(UploadFilePath.IMG_VIEW_PATH, num) + "vision.modeldata";
fYunFileServiceInterface.downloadFile(visionModeldataOssPath, visionModeldataPath);
String visionTxtLocalPath = ConstantFilePath.SCENE_V4_PATH + num + File.separator + "vision.txt";
CreateObjUtil.convertVisionmodeldataToTxt(visionModeldataPath, visionTxtLocalPath);
String roamingPoint = RoamingPointUtil.createRoamingPoint(num, visionTxtLocalPath);
if (StrUtil.isNotEmpty(roamingPoint)) {
fYunFileServiceInterface.uploadFile(roamingPoint.getBytes(StandardCharsets.UTF_8), roamingPointOssPath);
url = fyunHost + roamingPointOssPath;
}
}else{
url = fyunHost + roamingPointOssPath;
}
}catch (Exception e){
log.warn("生成roamingPointJson出错,num:" + num, e);
}
return url;
}
@Override
public Long getCountByCameraId(Long cameraId,Boolean status) {
LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>();
wrapper.eq(ScenePlus::getCameraId,cameraId);
if(status){
wrapper.eq(ScenePlus::getSceneStatus,-2);
}
return this.count(wrapper);
}
@Override
public Long getCountByCameraId(Long cameraId) {
LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>();
wrapper.eq(ScenePlus::getCameraId,cameraId);
wrapper.in(ScenePlus::getSceneStatus,0,-2);
return this.count(wrapper);
}
@Override
public Long getSpaceSumByCameraId(Long cameraId) {
return this.getBaseMapper().getSpaceSumByCameraId(cameraId);
}
@Override
public List getGroupBySceneSouceV4(Long userId) {
return this.getBaseMapper().getGroupBySceneSouceV4(userId);
}
@Override
public List getGroupBySceneSouceV3(Long userId) {
return this.getBaseMapper().getGroupBySceneSouceV3(userId);
}
@Override
public List getCountByUserIdAndSceneSource(Long userId, List sceneSourceList, Integer isObj) {
return this.getBaseMapper().getCountByUserIdAndSceneSource(userId,sceneSourceList,isObj);
}
}