|
@@ -4,6 +4,7 @@ import cn.hutool.core.bean.BeanUtil;
|
|
|
import cn.hutool.core.collection.CollUtil;
|
|
|
import cn.hutool.core.date.DateUtil;
|
|
|
import cn.hutool.core.util.StrUtil;
|
|
|
+import cn.hutool.core.util.ZipUtil;
|
|
|
import com.alibaba.fastjson.JSONObject;
|
|
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
|
@@ -29,24 +30,26 @@ import com.fdkankan.model.constants.ConstantFilePath;
|
|
|
import com.fdkankan.model.constants.UploadFilePath;
|
|
|
import com.fdkankan.rabbitmq.bean.BuildSceneCallMessage;
|
|
|
import com.fdkankan.rabbitmq.util.RabbitMqProducer;
|
|
|
+import com.fdkankan.redis.util.RedisLockUtil;
|
|
|
import com.fdkankan.redis.util.RedisUtil;
|
|
|
import com.fdkankan.web.response.ResultData;
|
|
|
import com.fdkankan.web.util.RSAEncrypt;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
+import net.lingala.zip4j.core.ZipFile;
|
|
|
import org.apache.commons.codec.binary.Base64;
|
|
|
import org.apache.commons.lang3.StringUtils;
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
import org.springframework.beans.factory.annotation.Value;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
import org.springframework.util.ObjectUtils;
|
|
|
+import org.springframework.web.bind.annotation.RequestBody;
|
|
|
import org.springframework.web.multipart.MultipartFile;
|
|
|
|
|
|
import java.io.File;
|
|
|
import java.io.IOException;
|
|
|
import java.nio.charset.StandardCharsets;
|
|
|
-import java.util.Calendar;
|
|
|
-import java.util.List;
|
|
|
-import java.util.Objects;
|
|
|
+import java.util.*;
|
|
|
+import java.util.concurrent.CompletableFuture;
|
|
|
|
|
|
/**
|
|
|
* <p>
|
|
@@ -121,6 +124,15 @@ public class SceneFileBuildServiceImpl extends ServiceImpl<ISceneFileBuildMapper
|
|
|
@Autowired
|
|
|
private FYunFileConfig fYunFileConfig;
|
|
|
|
|
|
+ @Autowired
|
|
|
+ private RedisLockUtil redisLockUtil;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private IScenePreService scenePreService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private ICompanyService companyService;
|
|
|
+
|
|
|
@Override
|
|
|
public SceneFileBuild findByFileId(String fileId) {
|
|
|
|
|
@@ -827,4 +839,274 @@ public class SceneFileBuildServiceImpl extends ServiceImpl<ISceneFileBuildMapper
|
|
|
}
|
|
|
return result;
|
|
|
}
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public ResultData sendCallAlgorithm(@RequestBody Map<String,String> params) throws Exception {
|
|
|
+ log.info("sendCallAlgorithm 参数为:{}", JSONObject.toJSONString(params));
|
|
|
+ String filePath = params.get("filePath");
|
|
|
+ String userName = params.get("userName");
|
|
|
+ if(org.apache.commons.lang3.ObjectUtils.isEmpty(filePath)){
|
|
|
+ throw new BusinessException(ErrorCode.FAILURE_CODE_3001);
|
|
|
+ }
|
|
|
+ if(!filePath.endsWith(File.separator)){
|
|
|
+ filePath = filePath.concat(File.separator);
|
|
|
+ }
|
|
|
+ // 读取本地文件并校验文件
|
|
|
+ // 读取config.json
|
|
|
+// if(!new File(filePath+"config.json").exists()){
|
|
|
+// throw new BusinessException(ErrorCode.FAILURE_CODE_4001,filePath+"config.json");
|
|
|
+// }
|
|
|
+
|
|
|
+ JSONObject configJson = JSONObject.parseObject(FileUtils.readFile(filePath + "config.json"));
|
|
|
+ String folderName = configJson.getString("id");
|
|
|
+ String sncode = configJson.getString("sn");
|
|
|
+ String zipFileName = configJson.getString("zipFileName");
|
|
|
+ if(org.apache.commons.lang3.ObjectUtils.isEmpty(folderName) || org.apache.commons.lang3.ObjectUtils.isEmpty(sncode) || org.apache.commons.lang3.ObjectUtils.isEmpty(zipFileName)){
|
|
|
+ throw new BusinessException(ErrorCode.PARAM_ERROR,"config.json 文件有误!");
|
|
|
+ }
|
|
|
+
|
|
|
+ ScenePre scenePre = new ScenePre();
|
|
|
+
|
|
|
+ // 检测是否有生成
|
|
|
+ String fileId = getFileIdByFolderName(folderName);
|
|
|
+ String subFolder = sncode.concat(File.separator).concat(fileId).concat(File.separator).concat(folderName);
|
|
|
+ // 解压获取dataSource 并上传资源到OSS
|
|
|
+ String dataSource = ConstantFilePath.BUILD_MODEL_PATH.concat(subFolder);
|
|
|
+ log.info("dataSource 为:{}", dataSource);
|
|
|
+
|
|
|
+ scenePre.setFileId(fileId);
|
|
|
+ scenePre.setUsername(userName);
|
|
|
+ scenePre.setZipPath(filePath);
|
|
|
+ scenePre.setCreateTime(new Date());
|
|
|
+ scenePre.setUpdateTime(new Date());
|
|
|
+ scenePre.setStatus(0);
|
|
|
+ scenePreService.save(scenePre);
|
|
|
+
|
|
|
+ // 异步解压资源文件上传
|
|
|
+ String finalFilePath = filePath;
|
|
|
+ CompletableFuture.runAsync(() -> {
|
|
|
+ try {
|
|
|
+ log.info("开始异步解压文件");
|
|
|
+ ZipFile zipFile = new ZipFile(new File(finalFilePath.concat(zipFileName)));
|
|
|
+ if (zipFile.isEncrypted()) {
|
|
|
+ String pwd = zipFileName.substring(0, 5).concat(zipFileName.substring(0, 5));
|
|
|
+ zipFile.setPassword(pwd);
|
|
|
+ zipFile.extractAll(finalFilePath);
|
|
|
+ } else {
|
|
|
+ ZipUtil.unzip(finalFilePath.concat(zipFileName), finalFilePath);
|
|
|
+ }
|
|
|
+
|
|
|
+ scenePre.setStatus(1);
|
|
|
+ scenePre.setUpdateTime(new Date());
|
|
|
+ scenePreService.updateById(scenePre);
|
|
|
+ log.info("异步开始上传文件");
|
|
|
+ // 上传oaas
|
|
|
+ fYunFileService.uploadFileByCommand(finalFilePath.concat(folderName), ConstantFilePath.OSS_PREFIX.concat(subFolder));
|
|
|
+
|
|
|
+ scenePre.setOssPath(ConstantFilePath.OSS_PREFIX.concat(subFolder));
|
|
|
+
|
|
|
+ scenePre.setStatus(2);
|
|
|
+ scenePre.setUpdateTime(new Date());
|
|
|
+ scenePreService.updateById(scenePre);
|
|
|
+ log.info("文件上传成功,开始通知计算");
|
|
|
+ // 通知计算
|
|
|
+ this.copyDataAndBuild(null, dataSource, "V4", null);
|
|
|
+ log.info("通知计算成功");
|
|
|
+
|
|
|
+ scenePre.setStatus(3);
|
|
|
+ scenePre.setUpdateTime(new Date());
|
|
|
+ scenePreService.updateById(scenePre);
|
|
|
+ } catch (Exception e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ log.error("上传失败", e);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ return ResultData.ok();
|
|
|
+ }
|
|
|
+
|
|
|
+ private String getFileIdByFolderName(String folderName) {
|
|
|
+ // 检测是否有生成
|
|
|
+ String fileId = redisUtil.get(String.format(RedisConstants.FOLDER_FILEID_BUILD, folderName));
|
|
|
+ if (!org.springframework.util.ObjectUtils.isEmpty(fileId)) {
|
|
|
+ return fileId;
|
|
|
+ }
|
|
|
+
|
|
|
+ SceneFileBuild sceneFileBuild = this.findByUnicode(folderName);
|
|
|
+ if (sceneFileBuild != null) {
|
|
|
+ fileId = sceneFileBuild.getFileId();
|
|
|
+ redisUtil.set(String.format(RedisConstants.FOLDER_FILEID_BUILD, folderName), fileId, 2 * 24 * 60 * 60);
|
|
|
+ return fileId;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 加锁
|
|
|
+ boolean lock = redisLockUtil.lock(String.format(RedisConstants.FOLDER_LOCK_BUILD, folderName), 120);
|
|
|
+ if (!lock) {
|
|
|
+ throw new BusinessException(ErrorCode.FAILURE_CODE_5052);
|
|
|
+ }
|
|
|
+
|
|
|
+ String dataSource = scenePlusService.getDataSourceLikeUnicode("/" + folderName);
|
|
|
+
|
|
|
+ if (!org.springframework.util.ObjectUtils.isEmpty(dataSource)) {
|
|
|
+ log.info("从数据库中查到与 fileId:{} 匹配的路径为:{}", fileId, dataSource);
|
|
|
+ int n = dataSource.split("/").length;
|
|
|
+ if (n > 1) {
|
|
|
+ fileId = dataSource.split("/")[n - 2];
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (org.springframework.util.ObjectUtils.isEmpty(fileId)) {
|
|
|
+ fileId = new SnowflakeIdGenerator(0, 0).nextId() + "";
|
|
|
+ log.info("新生成build数据,{}", fileId);
|
|
|
+ }
|
|
|
+
|
|
|
+ sceneFileBuild = new SceneFileBuild();
|
|
|
+ sceneFileBuild.setChildName(folderName.split("_")[0]);
|
|
|
+ sceneFileBuild.setFileId(fileId);
|
|
|
+ sceneFileBuild.setRecStatus("A");
|
|
|
+ sceneFileBuild.setUnicode(folderName);
|
|
|
+ sceneFileBuild.setCreateTime(new Date());
|
|
|
+ this.save(sceneFileBuild);
|
|
|
+ redisUtil.set(String.format(RedisConstants.FOLDER_FILEID_BUILD, folderName), fileId, 2 * 24 * 60 * 60);
|
|
|
+ redisUtil.set(String.format(RedisConstants.FILEID_FOLDER_BUILD, fileId), folderName, 2 * 24 * 60 * 60);
|
|
|
+ return fileId;
|
|
|
+ }
|
|
|
+
|
|
|
+ public ResultData copyDataAndBuild(String sourceBucet,String dataSource,String sceneVer,User user) throws Exception {
|
|
|
+ if(!StringUtils.equals(sceneVer,"V3") && ! StringUtils.equals(sceneVer,"V4")){
|
|
|
+ throw new BusinessException(ErrorCode.PARAM_FORMAT_ERROR.code(),"版本有误,请填写 V3 或者 V4");
|
|
|
+ }
|
|
|
+
|
|
|
+ String fYunPath = ConstantFilePath.OSS_PREFIX + dataSource.replace(ConstantFilePath.BUILD_MODEL_PATH, "")
|
|
|
+ .replace(ConstantFilePath.BUILD_MODEL_LASER_PATH, "");
|
|
|
+ if(!ObjectUtils.isEmpty(sourceBucet)){
|
|
|
+ fYunFileService.copyFileBetweenBucket(sourceBucet,fYunPath,fYunFileConfig.getBucket(),fYunPath);
|
|
|
+ }
|
|
|
+ // 下载data.fdage
|
|
|
+ JSONObject fdageData = JSONObject.parseObject(fYunFileService.getFileContent(fYunPath + "/data.fdage"));
|
|
|
+ if(ObjectUtils.isEmpty(fdageData)){
|
|
|
+ throw new BusinessException(ErrorCode.SYSTEM_ERROR.code(),"4dage 文件不存在");
|
|
|
+ }
|
|
|
+ String cameraName = fdageData.getJSONObject("cam").getString("uuid");
|
|
|
+ Camera cameraEntity = cameraService.getByChildName(cameraName);
|
|
|
+ if(cameraEntity == null){
|
|
|
+ log.error("该相机不存在:" + cameraName);
|
|
|
+ throw new BusinessException(ErrorCode.FAILURE_CODE_6003);
|
|
|
+ }
|
|
|
+
|
|
|
+ CameraDetail detailEntity = cameraDetailService.getByCameraId(cameraEntity.getId());
|
|
|
+ if(detailEntity == null){
|
|
|
+ log.error("该相机详情不存在:" + cameraName);
|
|
|
+ throw new BusinessException(ErrorCode.FAILURE_CODE_6003);
|
|
|
+ }
|
|
|
+
|
|
|
+ Long cameraType = 11L;
|
|
|
+ //判断是否转台相机
|
|
|
+ if (detailEntity.getType() == 9) {
|
|
|
+ cameraType = 13L;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (detailEntity.getType() == 10) {
|
|
|
+ cameraType = 14L;
|
|
|
+ }
|
|
|
+ String sceneNum = scene3dNumService.generateSceneNum(detailEntity.getType());
|
|
|
+
|
|
|
+ String icon = null;
|
|
|
+ String imgViewPath = null;
|
|
|
+ switch (sceneVer) {
|
|
|
+ case "V3":
|
|
|
+ case "V4":
|
|
|
+ int rebuild = 0;
|
|
|
+ ScenePlus scenePlus = scenePlusService.getByFileId(dataSource);
|
|
|
+ if (!ObjectUtils.isEmpty(scenePlus)) {
|
|
|
+ log.info("该场景资源已存在,执行补拍逻辑!");
|
|
|
+ rebuild = 1;
|
|
|
+ sceneNum = scenePlus.getNum();
|
|
|
+ }
|
|
|
+
|
|
|
+ imgViewPath = String.format(UploadFilePath.IMG_VIEW_PATH, sceneNum);
|
|
|
+ if(fdageData.containsKey("icon") && StringUtils.isNotEmpty(fdageData.getString("icon"))){
|
|
|
+ String ossPath = ConstantFilePath.OSS_PREFIX + dataSource.replace(ConstantFilePath.BUILD_MODEL_PATH, "")
|
|
|
+ .replace(ConstantFilePath.BUILD_MODEL_LASER_PATH, "");
|
|
|
+ fYunFileService.copyFileInBucket(ossPath + File.separator + fdageData.getString("icon"),imgViewPath + fdageData.getString("icon"));
|
|
|
+ icon = fYunFileConfig.getHost() + imgViewPath + fdageData.getString("icon");
|
|
|
+ log.info("上传icon成功....");
|
|
|
+ }
|
|
|
+ buildScenePost(dataSource, fdageData, "V3", cameraType, sceneNum, cameraEntity, detailEntity, rebuild, icon,user);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ Map<String,Object> result = new HashMap<>();
|
|
|
+ result.put("code",sceneNum);
|
|
|
+ return ResultData.ok(result);
|
|
|
+ }
|
|
|
+
|
|
|
+ private ScenePlusVO buildScenePost(String dataSource, JSONObject jsonObject, String buildType, long cameraType,
|
|
|
+ String sceneNum, Camera camera, CameraDetail cameraDetail, int rebuild,String icon,User user) throws Exception {
|
|
|
+ String localDataPath = String.format(ConstantFilePath.DATABUFFER_FORMAT, sceneNum);
|
|
|
+ String imgViewPath = String.format(UploadFilePath.IMG_VIEW_PATH, sceneNum);
|
|
|
+ String dataViewPath = String.format(UploadFilePath.DATA_VIEW_PATH, sceneNum);
|
|
|
+
|
|
|
+ JSONObject firmwareVersion = new JSONObject();
|
|
|
+ if (!ObjectUtils.isEmpty(jsonObject.getString("camSoftwareVersion"))) {
|
|
|
+ firmwareVersion.put("camSoftwareVersion", jsonObject.getString("camSoftwareVersion"));
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!ObjectUtils.isEmpty(jsonObject.getString("version"))) {
|
|
|
+ firmwareVersion.put("version", jsonObject.getString("version"));
|
|
|
+ }
|
|
|
+
|
|
|
+ String sceneUrl = mainUrl + "/" + sceneProNewUrl;
|
|
|
+
|
|
|
+ //重算的场景,先移除该场景对应的容量
|
|
|
+ if (rebuild == 1) {
|
|
|
+ scenePlusService.resetSpace(sceneNum);
|
|
|
+ //删除oss的houst_floor.json(国际版可能会卡住)
|
|
|
+ fYunFileService.deleteFile(dataViewPath + "houst_floor.json");
|
|
|
+ } else {
|
|
|
+ //上传log-main.png
|
|
|
+ fYunFileService.uploadFile(ConstantFilePath.LOGO_PATH + "logo-main.png", imgViewPath + "logo-main.png");
|
|
|
+ fYunFileService.uploadFile(ConstantFilePath.LOGO_PATH + "logo-main-en.png", imgViewPath + "logo-main-en.png");
|
|
|
+ }
|
|
|
+ String algorithm = jsonObject.getString("location") != null && "1".equals(jsonObject.getString("location")) ? "sfm" : "slam";
|
|
|
+ String unicode = jsonObject.getString("creator") + "_" + jsonObject.getString("uuidtime");
|
|
|
+
|
|
|
+ ScenePlusVO scenePlusVO = this.createScenePlus(sceneNum, camera.getId(), camera.getChildName(), jsonObject.getString("creator"),
|
|
|
+ jsonObject.getString("pwd"), unicode, cameraType, fileId, icon, cameraDetail.getUserId(), userName,algorithm,
|
|
|
+ jsonObject.getJSONArray("points").size(), jsonObject.getString("name"), jsonObject.getString("info"),
|
|
|
+ jsonObject.getInteger("scenetype"), jsonObject.getString("gps"), rebuild,
|
|
|
+ jsonObject.getInteger("resolution"), firmwareVersion.toString(), sceneUrl, buildType, cameraDetail.getCooperationUser());
|
|
|
+
|
|
|
+ ScenePlusVO scenePlusVO = this.createScenePlus(sceneNum, camera.getId(), camera.getChildName(), jsonObject.getString("creator"),
|
|
|
+ jsonObject.getString("pwd"), unicode, cameraType, dataSource, icon,user.getId() , user.getUserName(),algorithm,
|
|
|
+ jsonObject.getJSONArray("points").size(), jsonObject.getString("name"), jsonObject.getString("info"),
|
|
|
+ jsonObject.getInteger("scenetype"), jsonObject.getString("gps"), rebuild,
|
|
|
+ jsonObject.getInteger("resolution"), firmwareVersion.toString(), sceneUrl, buildType, cameraDetail.getCooperationUser());
|
|
|
+
|
|
|
+ if (Objects.nonNull(scenePlusVO)) {
|
|
|
+ JSONObject statusJson = new JSONObject();
|
|
|
+ //临时将-2改成1,app还没完全更新
|
|
|
+ statusJson.put("status", scenePlusVO.getSceneStatus() == -2 ? 1 : scenePlusVO.getSceneStatus());
|
|
|
+ statusJson.put("webSite", scenePlusVO.getWebSite());
|
|
|
+ statusJson.put("sceneNum", scenePlusVO.getNum());
|
|
|
+ statusJson.put("thumb", scenePlusVO.getThumb());
|
|
|
+ statusJson.put("payStatus", 0);
|
|
|
+ statusJson.put("recStatus", 'A');
|
|
|
+ FileUtils.writeFile(localDataPath + "status.json", statusJson.toString());
|
|
|
+ fYunFileService.uploadFile(localDataPath + "status.json", dataViewPath + "status.json");
|
|
|
+ }
|
|
|
+
|
|
|
+ BuildSceneCallMessage mqMessage = getBuildSceneMqMessage(sceneNum, cameraType, algorithm, jsonObject.getInteger("resolution"), buildType,
|
|
|
+ scenePlusVO.getDataSource());
|
|
|
+
|
|
|
+ if (cameraDetail.getCompanyId() != null) {
|
|
|
+ Company company = companyService.getById(cameraDetail.getCompanyId());
|
|
|
+ if (company != null && !ObjectUtils.isEmpty(company.getCalculateFlexibility()) && !company.getCalculateFlexibility()) {
|
|
|
+ mqMessage.setFlexibility(-1);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ mqMessage.getExt().put("deleteExtras", true);
|
|
|
+ rabbitMqProducer.sendByWorkQueue(queueModelingPre, mqMessage);
|
|
|
+
|
|
|
+ return scenePlusVO;
|
|
|
+ }
|
|
|
+
|
|
|
}
|