package com.fdkankan.contro.service.impl; import cn.hutool.core.io.FileUtil; import cn.hutool.core.util.StrUtil; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.fdkankan.common.util.CmdUtils; import com.fdkankan.contro.dto.UploadSceneDTO; import com.fdkankan.contro.entity.SceneOrigBd; import com.fdkankan.contro.entity.ScenePlus; import com.fdkankan.contro.httpclient.HaixinClient; import com.fdkankan.contro.service.IHaixinService; import com.fdkankan.contro.service.ISceneOrigBdService; import com.fdkankan.contro.service.IScenePlusService; import com.fdkankan.fyun.config.FYunFileConfig; import com.fdkankan.fyun.face.FYunFileServiceInterface; import com.fdkankan.model.constants.ConstantFilePath; import com.fdkankan.model.constants.UploadFilePath; import com.fdkankan.web.response.ResultData; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import javax.annotation.Resource; import java.io.File; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; @Slf4j @Service public class HaixinServiceImpl implements IHaixinService { private static final String API_FDFS_UPLOAD = "/fdfs/api/file/upload"; private static final String API_SUBMIT_RENDER_RESULT = "/ecs/api/panoramicImageService/submitRenderResult"; private static final String API_SYNC_RENDER_STATUS = "/ecs/api/panoramicImageService/syncRenderStatus"; private static final int WAIT_TIME = 10 * 60;//推送等待时间 private static final int PER_SHOOT_TIME = 5 * 60;//推送等待时间 @Value("${haixin.host:#{null}}") private String haixinHost; @Value("${haixin.syncRenderStatus:false}") private boolean haixinSyncRenderStatus; @Autowired private ISceneOrigBdService sceneOrigBdService; @Resource private FYunFileConfig fYunFileConfig; @Resource private FYunFileServiceInterface fileServiceInterface; @Autowired private IScenePlusService scenePlusService; @Resource private HaixinClient haixinClient; @Autowired private IHaixinService haixinService; @Override public ResultData uploadScene(UploadSceneDTO dto) { SceneOrigBd sceneOrigBd = new SceneOrigBd(); sceneOrigBd.setFileUrl(dto.getFileUrl()); sceneOrigBd.setTaskId(dto.getTaskId()); sceneOrigBd.setKNo(dto.getkNo()); sceneOrigBd.setRyId(dto.getRyId()); sceneOrigBd.setRyNo(dto.getRyNo()); sceneOrigBd.setPassword(dto.getPassword()); sceneOrigBd.setRyPhone(dto.getRyPhone()); sceneOrigBd.setRyCid(dto.getRyCid()); sceneOrigBd.setRyName(dto.getRyName()); sceneOrigBd.setShootCount(dto.getShootCount()); sceneOrigBd.setExpectedTime(this.getExpectedTime(dto.getShootCount())); sceneOrigBd.setTaskNo(dto.getTaskNo()); if(StrUtil.isNotEmpty(dto.getPushAddress()) && dto.getPushAddress().endsWith(File.separator)){ dto.setPushAddress(dto.getPushAddress().substring(0, dto.getPushAddress().length() - 1)); } sceneOrigBd.setPushAddress(dto.getPushAddress()); sceneOrigBd.setDistrictCode(dto.getDistrictCode()); sceneOrigBd.setDistrictName(dto.getDistrictName()); sceneOrigBdService.save(sceneOrigBd); //推送进度 haixinService.syncRenderStatus(sceneOrigBd.getId(), 0, this.getExpectedTime(sceneOrigBd), null); return ResultData.ok(); } private Integer getExpectedTime(Integer shootCount){ if(shootCount == null){ return null; } Integer waitTime = 10 * 60;//等待推送时间 Integer callTime = shootCount * PER_SHOOT_TIME;//算法预估耗时 Integer preTime = callTime/10;//前置处理耗时,约是算法时间的10% Integer postTime = (callTime/10) * 2;//后置处理耗时,约是算法时间的20% return waitTime + callTime + preTime + postTime; } private Integer getExpectedTime(SceneOrigBd sceneOrigBd){ if(sceneOrigBd.getExpectedTime() == null){ return null; } List list = sceneOrigBdService.list( new LambdaQueryWrapper() .in(SceneOrigBd::getStatus, 0, 1, 2) .ne(SceneOrigBd::getId, sceneOrigBd.getId()).isNotNull(SceneOrigBd::getExpectedTime)); int sum = list.stream().mapToInt(v -> v.getExpectedTime()).sum() + sceneOrigBd.getExpectedTime(); return sum; } @Override public void noticHaixin(String num, boolean buildSuccess) throws Exception { ScenePlus scenePlus = scenePlusService.getScenePlusByNum(num); String taskId = scenePlus.getTaskId(); String zipDir = String.format(ConstantFilePath.SCENE_USER_PATH_V4, num) + "haixin/"; String zipPath = zipDir + num + ".zip"; try { if(buildSuccess){//计算成功,把原始资源打压缩包 //复制scene_edit_data/num/data/mapping目录到view目录 String editMappingPath = "/oss/4dkankan/" + String.format(UploadFilePath.DATA_EDIT_PATH, num) + "mapping"; String viewMappingPath = "/oss/4dkankan/" + String.format(UploadFilePath.DATA_VIEW_PATH, num) + "mapping"; if(FileUtil.exist(editMappingPath)){ FileUtil.copyContent(new File(editMappingPath), new File(viewMappingPath), true); } String viewPath = "/oss/4dkankan/" + String.format(UploadFilePath.VIEW_PATH, num); //打压缩包 this.zip(viewPath, zipPath); //上传到fastdf String url = haixinHost.concat(API_FDFS_UPLOAD); List files = FileUtil.loopFiles(zipDir); List fileNameRemoteList = new ArrayList<>(); String finalUrl = url; files.stream().forEach(file->{ JSONObject jsonObject = haixinClient.uploadToFdfs(finalUrl, file.getAbsolutePath()); JSONObject data = jsonObject.getJSONObject("data"); fileNameRemoteList.add(data.getString("fileNameRemote")); }); //通知计算结果 StringBuilder sb = new StringBuilder(); for (String fileNameRemote : fileNameRemoteList) { sb.append(",").append(fileNameRemote); } this.sendResult(taskId, sb.substring(1)); }else{ this.sendResult(taskId, null); } }catch (Exception e){ log.warn("推送计算结果失败,taskId:{}", taskId, e); this.sendResult(taskId, null); }finally { FileUtil.del(zipDir); } } private void zip(String sourcePath, String zipPath) throws Exception { FileUtil.mkParentDirs(zipPath); String cmd = "cd " + sourcePath + " && zip -r -s 2048M " + zipPath + " *";//&& mv -f " + zipPath + " " + target CmdUtils.callLineSh(cmd, 200); } @Override public void sendResult(String taskId, String packetPath){ String url = haixinHost.concat(API_SUBMIT_RENDER_RESULT); Map params = new HashMap<>(); params.put("vendor","A0BF"); params.put("projectId", taskId); params.put("packetPath", packetPath); haixinClient.postJson(url, params); } @Override public void syncRenderStatus(Long sceneOirgBdId, Integer status, Integer expectedTime, String failReason) { SceneOrigBd sceneOrigBd = sceneOrigBdService.getById(sceneOirgBdId); sceneOrigBd.setStatus(status); sceneOrigBd.setReason(failReason); sceneOrigBdService.updateById(sceneOrigBd); if(!haixinSyncRenderStatus){ return; } String num = null; ScenePlus scenePlus = scenePlusService.getByTaskId(sceneOrigBd.getTaskId()); if(scenePlus != null){ num = scenePlus.getNum(); } if(expectedTime == null && sceneOrigBd.getExpectedTime() != null){//如果指定预测时间是空,证明开始进入计算前置流程,可以计算预测时间 if(status == 1){ expectedTime = sceneOrigBd.getExpectedTime() - WAIT_TIME; } if(status == 2){ expectedTime = sceneOrigBd.getExpectedTime() - WAIT_TIME - (sceneOrigBd.getShootCount() * PER_SHOOT_TIME); } if(status == -1 || status == 3 || status == 4){ expectedTime = 0; } } String url = haixinHost.concat(API_SYNC_RENDER_STATUS); if(StrUtil.isNotEmpty(sceneOrigBd.getPushAddress())){ url = sceneOrigBd.getPushAddress().concat(API_SYNC_RENDER_STATUS); } Map params = new HashMap<>(); params.put("taskNo",sceneOrigBd.getTaskNo()); params.put("projectId", sceneOrigBd.getTaskId()); params.put("kNo", sceneOrigBd.getKNo()); params.put("num", num); params.put("status", status); params.put("expectedTime", expectedTime == null ? 0 : expectedTime); haixinClient.postJson(url, params); } }