Browse Source

场景同步接口

dengsixing 3 năm trước cách đây
mục cha
commit
6302125b85

+ 44 - 0
4dkankan-center-scene/src/main/java/com/fdkankan/scene/controller/SceneEditController.java

@@ -737,11 +737,31 @@ public class SceneEditController extends BaseController {
         return sceneEditInfoService.deleteVideoBox(param);
     }
 
+    /**
+     * <p>
+        下载视频
+     * </p>
+     * @author dengsixing
+     * @date 2022/2/23
+     * @param param
+     * @return com.fdkankan.scene.vo.DownloadVO
+     **/
     @PostMapping(value = "downloadBallScreenVideo")
     public DownloadVO downloadBallScreenVideo(@RequestBody @Validated BallScreenVideoParamVO param){
         return sceneEditInfoService.downloadBallScreenVideo(param);
     }
 
+    /**
+     * <p>
+            上传视频
+     * </p>
+     * @author dengsixing
+     * @date 2022/2/23
+     * @param num
+     * @param fileName
+     * @param file
+     * @return com.fdkankan.common.response.ResultData
+     **/
     @PostMapping(value = "uploadBallScreenVideo")
     public ResultData uploadBallScreenVideo(
             @RequestParam("num") String num,
@@ -769,11 +789,35 @@ public class SceneEditController extends BaseController {
         return sceneUploadService.uploads(base64,fileName,bizType,files,num,type,getToken());
     }
 
+    /**
+     * <p>
+            删除文件
+     * </p>
+     * @author dengsixing
+     * @date 2022/2/23
+     * @param paramVO
+     * @return com.fdkankan.common.response.ResultData
+     **/
     @PostMapping("/delete/file")
     public ResultData delete(@RequestBody @Validated DeleteFileParamVO paramVO) throws Exception{
         return sceneUploadService.delete(paramVO);
     }
 
+    /**
+     * 场景同步
+     */
+    @PostMapping(value = "/sceneSync")
+    public ResultData sceneSync(
+        @RequestParam("num") String num,
+        @RequestParam(value = "type", defaultValue = "ajk") String type,
+        @RequestParam("floorPlanJson") String floorPlanJson,
+        @RequestParam("ajkJson") String ajkJson,
+        @RequestParam("cameraJson") String cameraJson,
+        @RequestParam("files") MultipartFile[] files) throws Exception{
+        return sceneEditInfoService.sceneSync(num, type, floorPlanJson, ajkJson, cameraJson, files);
+    }
+
+
 
 
 

+ 20 - 3
4dkankan-center-scene/src/main/java/com/fdkankan/scene/controller/TestController.java

@@ -5,6 +5,7 @@ import com.alibaba.csp.sentinel.annotation.SentinelResource;
 import com.alibaba.druid.pool.DruidDataSource;
 import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.fdkankan.common.constant.ConstantFilePath;
 import com.fdkankan.common.exception.BusinessException;
 import com.fdkankan.common.response.ResultData;
@@ -18,7 +19,9 @@ import com.fdkankan.platform.api.feign.PlatformUserClient;
 import com.fdkankan.platform.api.vo.Camera;
 import com.fdkankan.platform.api.vo.Company;
 import com.fdkankan.platform.api.vo.User;
+import com.fdkankan.redis.constant.RedisKey;
 import com.fdkankan.redis.constant.RedisLockKey;
+import com.fdkankan.redis.util.RedisLockUtil;
 import com.fdkankan.redis.util.RedisUtil;
 import com.fdkankan.scene.entity.Folder;
 import com.fdkankan.scene.listener.TestListener;
@@ -27,10 +30,12 @@ import com.fdkankan.scene.service.IScene3dNumService;
 import com.fdkankan.scene.service.ISceneService;
 import com.fdkankan.scene.vo.SceneVO;
 import com.google.common.collect.Lists;
+import java.util.concurrent.TimeUnit;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.cloud.context.config.annotation.RefreshScope;
+import org.springframework.data.redis.core.RedisTemplate;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
@@ -76,12 +81,18 @@ public class TestController {
     @Autowired
     private IScene3dNumService scene3dNumService;
 
+    @Autowired
+    RedisTemplate redisTemplate;
+
+    @Autowired
+    RedisLockUtil redisLockUtil;
+
 
     @GetMapping("/test")
     public String test() throws Exception {
 
 
-        List<Folder> list = folderService.list(new LambdaQueryWrapper<Folder>().eq(Folder::getId, 1));
+//        List<Folder> list = folderService.list(new LambdaQueryWrapper<Folder>().eq(Folder::getId, 1));
 //        for (int i = 0; i< 10; i++){
 //            rocketMQProducer.syncSend("qwe",i+"",  "消息体"+i);
 //        }
@@ -109,10 +120,16 @@ public class TestController {
 
 //        System.out.println("gghhjjkkllll");
 
-        TestListener bean = SpringUtil.getBean(TestListener.class);
+//        TestListener bean = SpringUtil.getBean(TestListener.class);
 
+//        folderService.update(new LambdaUpdateWrapper<Folder>().eq(Folder::getId, 1L).set(Folder::getFolderName, "hahaha"));
+//        Folder byId = folderService.getById(1L);
+//        folderService.updateById(byId);
 
-        return bean.getBuildSceneResultTopic();
+//        this.redisTemplate.opsForValue().setIfAbsent("test:lock:123", "123", (long)100000, TimeUnit.MILLISECONDS);
+        String key = String.format(RedisLockKey.LOCK_SCENE_SYNC, "123");
+        redisLockUtil.lock(key, 100000);
+        return "123123";
 
     }
 

+ 4 - 2
4dkankan-center-scene/src/main/java/com/fdkankan/scene/service/ISceneEditInfoService.java

@@ -6,6 +6,7 @@ import com.baomidou.mybatisplus.extension.service.IService;
 import com.fdkankan.scene.vo.*;
 import java.io.IOException;
 import java.util.List;
+import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.multipart.MultipartFile;
 
 /**
@@ -46,8 +47,9 @@ public interface ISceneEditInfoService extends IService<SceneEditInfo> {
 
     DownloadVO downloadBallScreenVideo(BallScreenVideoParamVO param);
 
-    ResultData uploadBallScreenVideo(String num,String fileName,MultipartFile file)
-        throws IOException;
+    ResultData uploadBallScreenVideo(String num,String fileName,MultipartFile file) throws IOException;
+
+    ResultData sceneSync(String num, String type, String floorPlanJson, String ajkJson, String cameraJson, MultipartFile[] files) throws Exception;
 
 
 

+ 176 - 0
4dkankan-center-scene/src/main/java/com/fdkankan/scene/service/impl/SceneEditInfoServiceImpl.java

@@ -14,21 +14,27 @@ import com.fdkankan.common.constant.*;
 import com.fdkankan.common.exception.BusinessException;
 import com.fdkankan.common.response.ResultData;
 import com.fdkankan.common.util.CreateObjUtil;
+import com.fdkankan.common.util.FileMd5Util;
 import com.fdkankan.common.util.FileUtil;
 import com.fdkankan.common.util.FileUtils;
 import com.fdkankan.fyun.constant.StorageType;
 import com.fdkankan.fyun.oss.UploadToOssUtil;
 import com.fdkankan.redis.constant.RedisKey;
+import com.fdkankan.redis.constant.RedisLockKey;
+import com.fdkankan.redis.util.RedisLockUtil;
 import com.fdkankan.redis.util.RedisUtil;
 import com.fdkankan.scene.bean.SceneJsonBean;
+import com.fdkankan.scene.entity.SceneDataDownload;
 import com.fdkankan.scene.entity.SceneEditControls;
 import com.fdkankan.scene.entity.SceneEditInfo;
 import com.fdkankan.scene.entity.ScenePro;
+import com.fdkankan.scene.entity.SceneProEdit;
 import com.fdkankan.scene.entity.SceneProExt;
 import com.fdkankan.scene.factory.FloorLogoHandlerFactory;
 import com.fdkankan.scene.factory.MusicHandlerFactory;
 import com.fdkankan.scene.factory.ScreenshotHandlerFactory;
 import com.fdkankan.scene.mapper.ISceneEditInfoMapper;
+import com.fdkankan.scene.service.ISceneDataDownloadService;
 import com.fdkankan.scene.service.ISceneEditControlsService;
 import com.fdkankan.scene.service.ISceneEditInfoService;
 import com.fdkankan.scene.service.ISceneProExtService;
@@ -41,6 +47,7 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
+import java.util.UUID;
 import java.util.stream.Collectors;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -64,6 +71,8 @@ import org.springframework.web.multipart.MultipartFile;
 @Service
 public class SceneEditInfoServiceImpl extends ServiceImpl<ISceneEditInfoMapper, SceneEditInfo> implements ISceneEditInfoService {
 
+    @Value("${oss.prefix.ali}")
+    private String prefixAli;
     @Value("${oss.prefix.url}")
     private String ossUrlPrefix;
     @Value("${upload.type}")
@@ -82,6 +91,10 @@ public class SceneEditInfoServiceImpl extends ServiceImpl<ISceneEditInfoMapper,
     RedisUtil redisUtil;
     @Autowired
     private ISceneProExtService sceneProExtService;
+    @Autowired
+    private RedisLockUtil redisLockUtil;
+    @Autowired
+    ISceneDataDownloadService sceneDataDownloadService;
 
 
     @Override
@@ -756,6 +769,169 @@ public class SceneEditInfoServiceImpl extends ServiceImpl<ISceneEditInfoMapper,
         return ResultData.ok();
     }
 
+    @Override
+    public ResultData sceneSync(String num, String type, String floorPlanJson, String ajkJson, String cameraJson,
+        MultipartFile[] files) throws Exception {
+
+        String lockKey = String.format(RedisLockKey.LOCK_SCENE_SYNC, num);
+        Boolean lock = redisLockUtil.lock(lockKey, RedisKey.EXPIRE_TIME_2_HOUR);
+        if(!lock){
+            throw new BusinessException(ErrorCode.FAILURE_CODE_5036);
+        }
+        try {
+
+            ScenePro scenePro = sceneProService.findBySceneNum(num);
+            if(scenePro == null){
+                throw new BusinessException(ErrorCode.FAILURE_CODE_5005);
+            }
+            SceneProExt sceneProExt = sceneProExtService.findBySceneProId(scenePro.getId());
+
+            //更新scene.json文件
+            String strsceneInfos = FileUtils.readFile(ConstantFilePath.SCENE_PATH + "data" + File.separator + "data" + num + File.separator + "scene.json");
+            if(strsceneInfos == null)
+                new File(ConstantFilePath.SCENE_PATH + "data" + File.separator + "data" + num + File.separator + "scene.json").createNewFile();
+
+            String path = sceneProExt.getDataSource();//   /mnt/data/0662c5389/831989883441512448/4898cab04f8c_202104141602356060/
+            if(path != null && !"".equals(path) && path.startsWith("http")){
+                path = ConstantFilePath.BUILD_MODEL_PATH + File.separator + path.split("/")[path.split("/").length - 2];
+            }
+            String target = path + "_ajk";   // /mnt/data/0662c5389/831989883441512448/4898cab04f8c_202104141602356060_ajk
+            File editPath = new File(target);
+            if(!editPath.exists()){
+                editPath.mkdirs();
+            }
+
+            //创建文件夹软连接并且复制data.json和project.json
+            if(new File(target + File.separator + "capture").exists()){
+                new File(target + File.separator + "capture").delete();
+            }
+            if(new File(target + File.separator + "caches").exists()){
+                //删除link
+                new File(target + File.separator + "caches" + File.separator + "images").delete();
+                //删除所有文件
+                FileUtils.delAllFile(target + File.separator + "caches");
+            }
+            if(new File(target + File.separator + "results").exists()){
+                FileUtils.delAllFile(target + File.separator + "results");
+            }
+            //创建文件夹,并link文件夹
+            new File(target + File.separator + "caches").mkdirs();
+            CreateObjUtil.createSoftConnection(path + File.separator + "capture", target + File.separator + "capture");
+            if(new File(path + File.separator + "caches" + File.separator + "images").exists()){
+                CreateObjUtil.createSoftConnection(path + File.separator + "caches" + File.separator + "images", target + File.separator + "caches" + File.separator + "images");
+            }
+
+            FileUtils.copyFile(path + File.separator + "data.json", target + File.separator+"data.json", true);
+            FileUtils.copyFile(path + File.separator + "project.json", target + File.separator+"project.json", true);
+
+            //data.json增加extras为执行重建算法
+            String project = FileUtils.readFile(target + File.separator+"project.json");
+            if(project != null){
+                JSONObject projectJson = JSONObject.parseObject(project);
+                projectJson.put("parent", projectJson.get("uuid"));
+                projectJson.put("uuid", UUID.randomUUID().toString());
+                projectJson.put("time", System.currentTimeMillis());
+                FileUtils.writeFile(path + File.separator + "project.json", projectJson.toString());
+            }
+
+            String data = FileUtils.readFile(target + File.separator+"data.json");
+            if(data != null){
+                JSONObject floorplanJson = new JSONObject();
+                floorplanJson.put("has_floor_ajk_json", true);
+                floorplanJson.put("has_vision_txt", true);
+                floorplanJson.put("has_floorplan_json", true);
+
+                JSONObject dataJson = JSONObject.parseObject(data);
+                dataJson.put("extras", floorplanJson);
+                //V5表示不需要生成high,low文件
+                dataJson.put("skybox_type", "SKYBOX_V8");
+                dataJson.put("split_type", "SPLIT_V10");
+                FileUtils.writeFile(target + File.separator+"data.json", new String(dataJson.toString().getBytes(), "UTF-8"));
+            }
+
+            //文件上传的位置可以自定义
+            log.info("画墙重建模型开始");
+            File targetFile = new File(target + File.separator + "extras" + File.separator + "floor_ajk.json");
+            if(!targetFile.getParentFile().exists()){
+                targetFile.getParentFile().mkdirs();
+            }
+            if(targetFile.exists()){
+                FileUtils.deleteFile(target + File.separator + "extras" + File.separator + "floor_ajk.json");
+            }
+            // 保存
+            FileUtils.writeFile(target + File.separator + "extras" + File.separator + "floorplan.json", new String(floorPlanJson.getBytes(), "UTF-8"));
+
+            FileUtils.writeFile(target + File.separator + "extras" + File.separator + "floor_ajk.json", new String(ajkJson.getBytes(), "UTF-8"));
+            FileUtils.writeFile(ConstantFilePath.SCENE_PATH+"data"+File.separator+"data"+num + File.separator + "floor_ajk.json", new String(ajkJson.getBytes(), "UTF-8"));
+
+            FileUtils.writeFile(target + File.separator + "extras" + File.separator + "vision.txt", new String(cameraJson.getBytes(), "UTF-8"));
+            FileUtils.writeFile(ConstantFilePath.SCENE_PATH+"data"+File.separator+"data"+num + File.separator + "camera.json", new String(cameraJson.getBytes(), "UTF-8"));
+
+            for(int i = 0; i < files.length; i ++){
+
+                File cadImg = new File(target + File.separator + "extras" + File.separator + "Floorplans/" + files[i].getOriginalFilename());
+                if(!cadImg.getParentFile().exists()){
+                    cadImg.getParentFile().mkdirs();
+                }
+                if(cadImg.exists())
+                {
+                    cadImg.delete();
+                }
+
+                files[i].transferTo(cadImg);
+            }
+            //下载封面图
+            FileUtils.downLoadFromUrl(scenePro.getThumb() + "?t=" + System.currentTimeMillis(),
+                "Cover.png", target + File.separator + "extras" + File.separator + "CoverImage");
+            //转换成jpg
+            FileUtils.pngToJpg(target + File.separator + "extras" + File.separator + "CoverImage/Cover.png",
+                target + File.separator + "extras" + File.separator + "CoverImage/Cover.jpg");
+
+            //安居客算法运行
+            log.info("安居客算法:开始建模——"+num);
+            CreateObjUtil.build3dModel(target , "1");
+            if(!new File(target + File.separator + "results" + File.separator + "upload.json").exists()){
+                return ResultData.error(ErrorCode.FAILURE_CODE_5042);
+            }
+
+            String zipPath = target + File.separator + "results/" + num + ".zip";
+            new File(zipPath).delete();
+
+//            FileUtils.zipFile(zipPath, target + File.separator + "results/ajk/");
+            String command = "bash /opt/ossutil/gzip.sh " + zipPath.replace(".zip", "") + " " + target + File.separator + "results/ajk/";
+            log.info("压缩文件:" + command);
+            CreateObjUtil.callshell(command);
+
+            if(!new File(zipPath).exists()){
+                return  ResultData.error(ErrorCode.FAILURE_CODE_5043);
+            }
+            String fileMD5 = FileMd5Util.getFileMD5(new File(zipPath));
+
+            uploadToOssUtil.upload(zipPath, "data_download/" + num + ".zip");
+
+            SceneDataDownload sceneDataDownload = sceneDataDownloadService.findBySceneNum(num);
+            if(sceneDataDownload == null){
+                sceneDataDownload = new SceneDataDownload();
+                sceneDataDownload.setNum(num);
+                sceneDataDownload.setDownloadPath(prefixAli + "data_download/" + num + ".zip");
+                sceneDataDownload.setFileMd5(fileMD5);
+                sceneDataDownloadService.save(sceneDataDownload);
+                return ResultData.ok();
+            }
+
+            sceneDataDownload.setFileMd5(fileMD5);
+            sceneDataDownload.setUpdateTime(Calendar.getInstance().getTime());
+            sceneDataDownloadService.updateById(sceneDataDownload);
+        }catch (Exception e){
+            log.error("画墙重建模型失败...", e);
+            throw new BusinessException(ErrorCode.FAILURE_CODE_5039);
+        }finally {
+            redisLockUtil.unlockLua(lockKey);
+        }
+
+        return ResultData.ok();
+    }
+
     private void updateBoxVideos(SceneEditInfo sceneEditInfo, Long sceneProId, String boxVideos){
         if(StrUtil.isEmpty(boxVideos)){
             return;

+ 1 - 2
4dkankan-center-scene/src/main/java/com/fdkankan/scene/service/impl/SceneProAppServiceImpl.java

@@ -98,8 +98,7 @@ public class SceneProAppServiceImpl extends ServiceImpl<ISceneProMapper, ScenePr
     IFolderSceneService folderSceneService;
 
     @Override
-    public ResultData
-    saveInitialPage(SceneEditParamVO base) throws Exception {
+    public ResultData saveInitialPage(SceneEditParamVO base) throws Exception {
         if(StringUtils.isEmpty(base.getNum()) || StringUtils.isEmpty(base.getInitialPoint())){
             throw new BusinessException(ErrorCode.FAILURE_CODE_3001);
         }