Bläddra i källkod

增加计算进度通知

dsx 2 år sedan
förälder
incheckning
f720eff2d5

+ 28 - 0
src/main/java/com/fdkankan/contro/controller/SceneFileController.java

@@ -1,6 +1,7 @@
 package com.fdkankan.contro.controller;
 
 import cn.hutool.core.util.ZipUtil;
+import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONObject;
 import com.fdkankan.common.constant.ErrorCode;
 import com.fdkankan.common.exception.BusinessException;
@@ -110,4 +111,31 @@ public class SceneFileController{
     public ResultData sendCallAlgorithm(@RequestBody Map<String,String> params) throws Exception {
         return sceneFileBuildService.sendCallAlgorithm(params);
     }
+
+    /**
+     * 本地上传相机原始资源压缩包,通知计算
+     * @param params
+     * @return
+     * @throws Exception
+     */
+    @PostMapping("test1")
+    public ResultData test1(@RequestBody Map<String,Object> params) throws Exception {
+        log.info("test1场景计算进度:{}", JSON.toJSONString(params));
+        return ResultData.ok();
+    }
+
+
+    /**
+     * 本地上传相机原始资源压缩包,通知计算
+     * @param params
+     * @return
+     * @throws Exception
+     */
+    @PostMapping("test2")
+    public ResultData test2(@RequestBody Map<String,Object> params) throws Exception {
+        log.info("test2场景计算进度:{}", JSON.toJSONString(params));
+        return ResultData.ok();
+    }
+
+
 }

+ 49 - 0
src/main/java/com/fdkankan/contro/mq/listener/BuildSceneProgressListener.java

@@ -0,0 +1,49 @@
+package com.fdkankan.contro.mq.listener;
+
+import com.alibaba.fastjson.JSONObject;
+import com.fdkankan.contro.mq.service.IBuildSceneProgressService;
+import com.fdkankan.contro.mq.service.impl.BuildSceneServiceImpl;
+import com.fdkankan.rabbitmq.bean.BuildSceneCallMessage;
+import com.rabbitmq.client.Channel;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.amqp.core.Message;
+import org.springframework.amqp.rabbit.annotation.Queue;
+import org.springframework.amqp.rabbit.annotation.RabbitListener;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+import java.nio.charset.StandardCharsets;
+
+@Slf4j
+@Component
+public class BuildSceneProgressListener{
+
+
+    @Autowired
+    private IBuildSceneProgressService buildSceneProgressService;
+
+    @Value("${queue.modeling.modeling-progress-notice}")
+    private String queueName;
+
+    /**
+     * 场景计算进度监听
+     * @param channel
+     * @param message
+     * @throws Exception
+     */
+    @RabbitListener(
+            queuesToDeclare = @Queue("${queue.modeling.modeling-progress-notice}")
+    )
+    public void buildSceneProgressHandler(Channel channel, Message message) throws Exception {
+        String messageId = message.getMessageProperties().getMessageId();
+        String msg = new String(message.getBody(), StandardCharsets.UTF_8);
+        log.info("开始推送场景计算进度,队列名:{},id:{},消息体:{}", queueName, messageId, msg);
+        BuildSceneCallMessage buildSceneMessage = JSONObject.parseObject(msg, BuildSceneCallMessage.class);
+        buildSceneProgressService.monitorProgress(buildSceneMessage);
+        channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
+        log.info("推送场景计算进度完成,队列名:{},id:{},消息体:{}", queueName, messageId, msg);
+
+    }
+
+}

+ 18 - 0
src/main/java/com/fdkankan/contro/mq/service/IBuildSceneProgressService.java

@@ -0,0 +1,18 @@
+package com.fdkankan.contro.mq.service;
+
+import com.fdkankan.rabbitmq.bean.BuildSceneCallMessage;
+import com.fdkankan.rabbitmq.bean.BuildSceneResultMqMessage;
+
+/**
+ * <p>
+ * TODO
+ * </p>
+ *
+ * @author dengsixing
+ * @since 2022/3/1
+ **/
+public interface IBuildSceneProgressService {
+
+    void monitorProgress(BuildSceneCallMessage buildSceneCallMessage);
+
+}

+ 133 - 0
src/main/java/com/fdkankan/contro/mq/service/impl/BuildSceneProgressServiceImpl.java

@@ -0,0 +1,133 @@
+package com.fdkankan.contro.mq.service.impl;
+
+import cn.hutool.core.io.FileUtil;
+import cn.hutool.core.io.watch.WatchMonitor;
+import cn.hutool.core.io.watch.Watcher;
+import cn.hutool.http.HttpUtil;
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import com.fdkankan.contro.entity.ScenePlus;
+import com.fdkankan.contro.entity.ScenePlusExt;
+import com.fdkankan.contro.mq.service.IBuildSceneProgressService;
+import com.fdkankan.contro.service.IScenePlusExtService;
+import com.fdkankan.contro.service.IScenePlusService;
+import com.fdkankan.rabbitmq.bean.BuildSceneCallMessage;
+import com.fdkankan.redis.constant.RedisKey;
+import com.fdkankan.redis.util.RedisUtil;
+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.stereotype.Service;
+
+import java.io.File;
+import java.math.BigDecimal;
+import java.nio.file.Path;
+import java.nio.file.WatchEvent;
+import java.util.HashMap;
+import java.util.Map;
+
+@RefreshScope
+@Slf4j
+@Service
+public class BuildSceneProgressServiceImpl implements IBuildSceneProgressService {
+
+    @Value("${build.progress.time:300}")
+    public Long buildProgressTime;
+    @Value("${build.progress.url}")
+    public String buildProgressUrl;
+    @Autowired
+    private RedisUtil redisUtil;
+
+    @Autowired
+    private IScenePlusService scenePlusService;
+    @Autowired
+    private IScenePlusExtService scenePlusExtService;
+
+    @Override
+    public void monitorProgress(BuildSceneCallMessage buildSceneCallMessage) {
+        String num = buildSceneCallMessage.getSceneNum();
+        String customUserId = (String)buildSceneCallMessage.getExt().get("customUserId");
+        String gps = (String)buildSceneCallMessage.getExt().get("gps");
+        String path = buildSceneCallMessage.getPath();
+
+        ScenePlus scenePlus = scenePlusService.getScenePlusByNum(num);
+        ScenePlusExt scenePlusExt = scenePlusExtService.getScenePlusExtByPlusId(scenePlus.getId());
+        String website = scenePlusExt.getWebSite();
+        String title = scenePlus.getTitle();
+
+        String projectJsonPath = path.concat(File.separator).concat("project.json");
+        File file = FileUtil.file(projectJsonPath);
+        WatchMonitor watchMonitor = WatchMonitor.create(file);
+        watchMonitor.setWatcher(new Watcher(){
+
+            boolean complete = false;
+            int mainProgress = 0;
+            Long totalTime = buildProgressTime;
+
+            @Override
+            public void onCreate(WatchEvent<?> event, Path currentPath) {
+                log.info("project.json文件创建完毕");
+                String projectJsonStr = FileUtil.readUtf8String(file);
+                JSONObject projectJson = JSON.parseObject(projectJsonStr);
+                JSONObject state = projectJson.getJSONObject("state");
+                Long expectTime = state.getLong("expect_time");
+                totalTime += expectTime;
+                redisUtil.set(String.format(RedisKey.SCENE_BUILD_EXPECT_TOTAL_TIME_NUM, num), String.valueOf(totalTime), RedisKey.CAMERA_EXPIRE_7_TIME);
+                Map<String, Object> params = new HashMap<>();
+                params.put("website", website);
+                params.put("title", title);
+                params.put("customUserId",customUserId);
+                params.put("gps", gps);
+                params.put("totalTime", totalTime);
+                params.put("progress", mainProgress);
+                HttpUtil.post(buildProgressUrl, JSON.toJSONString(params), 2000);
+
+            }
+
+            @Override
+            public void onModify(WatchEvent<?> event, Path currentPath) {
+                log.info("project.json文件发生了变化");
+                String projectJsonStr = FileUtil.readUtf8String(file);
+                JSONObject projectJson = JSON.parseObject(projectJsonStr);
+                JSONObject state = projectJson.getJSONObject("state");
+                complete = state.getBoolean("done");
+                if(complete){
+                    mainProgress = 90;
+                    Map<String, Object> params = new HashMap<>();
+                    params.put("website", website);
+                    params.put("title", title);
+                    params.put("customUserId",customUserId);
+                    params.put("gps", gps);
+                    params.put("totalTime", totalTime);
+                    params.put("progress", mainProgress);
+                    HttpUtil.post(buildProgressUrl, JSON.toJSONString(params), 2000);
+                    watchMonitor.interrupt();
+                }else{
+                    int progress = new BigDecimal(projectJson.getDouble("expect_time")).multiply(new BigDecimal(100)).intValue();
+                    if(progress - mainProgress >= 10){
+                        mainProgress = progress;
+                        Map<String, Object> params = new HashMap<>();
+                        params.put("website", website);
+                        params.put("title", title);
+                        params.put("customUserId",customUserId);
+                        params.put("gps", gps);
+                        params.put("totalTime", totalTime);
+                        params.put("progress", progress);
+                        HttpUtil.post(buildProgressUrl, JSON.toJSONString(params), 2000);
+                    }
+                }
+            }
+
+            @Override
+            public void onDelete(WatchEvent<?> event, Path currentPath) {
+            }
+
+            @Override
+            public void onOverflow(WatchEvent<?> event, Path currentPath) {
+            }
+        });
+        watchMonitor.start();
+
+    }
+}

+ 16 - 1
src/main/java/com/fdkankan/contro/mq/service/impl/BuildSceneServiceImpl.java

@@ -42,6 +42,7 @@ import org.apache.commons.lang3.ObjectUtils;
 import org.apache.commons.lang3.StringUtils;
 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.stereotype.Service;
 
 import java.io.File;
@@ -59,6 +60,7 @@ import java.util.stream.Collectors;
  * @author dengsixing
  * @since 2022/4/20
  **/
+@RefreshScope
 @Slf4j
 @Service
 public class BuildSceneServiceImpl implements IBuildSceneService {
@@ -72,6 +74,9 @@ public class BuildSceneServiceImpl implements IBuildSceneService {
     @Value("${model.type:#{null}}")
     private String modelType;
 
+    @Value("${build.progress.url}")
+    public String buildProgressUrl;
+
     @Autowired
     private RabbitMqProducer mqProducer;
 
@@ -260,10 +265,20 @@ public class BuildSceneServiceImpl implements IBuildSceneService {
 
             CreateObjUtil.deleteFile(path.replace(ConstantFilePath.BUILD_MODEL_PATH, "/") + "/capture");
 
+            Map<String, Object> ext = message.getExt();
+            Map<String, Object> params = new HashMap<>();
+            params.put("website", scenePlusExt.getWebSite());
+            params.put("title", scenePlus.getTitle());
+            params.put("customUserId", ext.get("customUserId"));
+            params.put("gps", ext.get("gps"));
+            params.put("totalTime", Integer.valueOf(redisUtil.get(String.format(RedisKey.SCENE_BUILD_EXPECT_TOTAL_TIME_NUM,sceneCode))));
+            params.put("progress", 100);
+            HttpUtil.post(buildProgressUrl, JSON.toJSONString(params), 2000);
+
             log.info("场景计算结果处理结束,场景码:{}", sceneCode);
 
         }catch (Exception e){
-            e.printStackTrace();
+            log.error("场景计算结果处理异常, num=" + sceneCode, e);
         }
     }
 

+ 82 - 73
src/main/java/com/fdkankan/contro/service/impl/SceneFileBuildServiceImpl.java

@@ -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.io.FileUtil;
+import cn.hutool.core.thread.ThreadUtil;
 import cn.hutool.core.util.StrUtil;
 import cn.hutool.core.util.ZipUtil;
 import cn.hutool.http.HttpUtil;
@@ -52,6 +53,7 @@ import java.io.IOException;
 import java.nio.charset.StandardCharsets;
 import java.util.*;
 import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutorService;
 
 /**
  * <p>
@@ -69,6 +71,8 @@ public class SceneFileBuildServiceImpl extends ServiceImpl<ISceneFileBuildMapper
 
     private static final String sendCallAlgorithmPath = "/mnt/sendCallAlgorithm/";
 
+    private static final String zipPassword = "a3ad34136de359536af553f9e7f3cefd";
+
     @Value("${main.url}")
     private String mainUrl;
     @Value("${fyun.type}")
@@ -885,82 +889,86 @@ public class SceneFileBuildServiceImpl extends ServiceImpl<ISceneFileBuildMapper
         scenePreService.save(scenePre);
 
         // 异步解压资源文件上传
-        CompletableFuture.runAsync(() -> {
-            try {
-                log.info("开始异步解压文件");
-                ZipFile zipFile = new ZipFile(new File(localFilePath));
-                if (zipFile.isEncrypted()) {
-                    String pwd = "948e2948e2";
-//                    String pwd = "916ed916ed";
-                    zipFile.setPassword(pwd);
-                    zipFile.extractAll(parentPath);
-                } else {
-                    ZipUtil.unzip(localFilePath, parentPath);
-                }
+        ExecutorService executor = ThreadUtil.newSingleExecutor();
+        try {
+            CompletableFuture.runAsync(() -> {
+                try {
+                    log.info("开始异步解压文件");
+                    ZipFile zipFile = new ZipFile(new File(localFilePath));
+                    if (zipFile.isEncrypted()) {
+                        zipFile.setPassword(zipPassword);
+                        zipFile.extractAll(parentPath);
+                    } else {
+                        ZipUtil.unzip(localFilePath, parentPath);
+                    }
 
-                List<String> filePathList = FileUtils.list(new File(parentPath));
-                String configJsonPath = null;
-                for (String item : filePathList) {
-                    if(!item.contains("config.json")){
-                        continue;
+                    List<String> filePathList = FileUtils.list(new File(parentPath));
+                    String configJsonPath = null;
+                    for (String item : filePathList) {
+                        if(!item.contains("config.json")){
+                            continue;
+                        }
+                        configJsonPath = item;
                     }
-                    configJsonPath = item;
-                }
-                String dataPath = FileUtil.getParent(configJsonPath, 1);
+                    String dataPath = FileUtil.getParent(configJsonPath, 1);
 
-                // 读取本地文件并校验文件
-                // 读取config.json
-                log.info("config.json路径:{}", configJsonPath);
-                if(!FileUtil.exist(configJsonPath)){
-                    throw new RuntimeException("config.json 文件有误!");
-                }
+                    // 读取本地文件并校验文件
+                    // 读取config.json
+                    log.info("config.json路径:{}", configJsonPath);
+                    if(!FileUtil.exist(configJsonPath)){
+                        throw new RuntimeException("config.json 文件有误!");
+                    }
 
-                JSONObject configJson = JSONObject.parseObject(FileUtils.readFile(configJsonPath));
-                String folderName = configJson.getString("id");
-                String sncode = configJson.getString("sn");
-                if(StrUtil.isBlank(folderName) || StrUtil.isBlank(sncode)){
-                    throw new RuntimeException("config.json 文件有误!");
-                }
+                    JSONObject configJson = JSONObject.parseObject(FileUtils.readFile(configJsonPath));
+                    String folderName = configJson.getString("id");
+                    String sncode = configJson.getString("sn");
+                    String customUserId = configJson.getString("customUserId");
+                    if(StrUtil.isBlank(folderName) || StrUtil.isBlank(sncode)){
+                        throw new RuntimeException("config.json 文件有误!");
+                    }
 
-                Camera camera = cameraService.getByChildName(sncode);
-                if(Objects.isNull(camera)){
-                    throw new BusinessException(ErrorCode.CAMERA_BIND_NO_EXIST.code(), "相机未入库");
-                }
+                    Camera camera = cameraService.getByChildName(sncode);
+                    if(Objects.isNull(camera)){
+                        throw new BusinessException(ErrorCode.CAMERA_BIND_NO_EXIST.code(), "相机未入库");
+                    }
 
-                // 检测是否有生成
-                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.setStatus(1);
-                scenePre.setUpdateTime(new Date());
-                scenePreService.updateById(scenePre);
-                log.info("异步开始上传文件");
-                // 上传oaas
-                fYunFileService.uploadFileByCommand(dataPath, 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) {
-                log.error("上传失败", e);
-                scenePre.setStatus(CommonSuccessStatus.Fail.code());
-                scenePreService.updateById(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.setStatus(1);
+                    scenePre.setUpdateTime(new Date());
+                    scenePreService.updateById(scenePre);
+                    log.info("异步开始上传文件");
+                    // 上传oaas
+                    fYunFileService.uploadFileByCommand(dataPath, 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, customUserId);
+                    log.info("通知计算成功");
+
+                    scenePre.setStatus(3);
+                    scenePre.setUpdateTime(new Date());
+                    scenePreService.updateById(scenePre);
+                } catch (Exception e) {
+                    log.error("上传失败", e);
+                    scenePre.setStatus(CommonSuccessStatus.Fail.code());
+                    scenePreService.updateById(scenePre);
+                }
+            }, executor);
+        }finally {
+            executor.shutdown();
+        }
         return ResultData.ok();
     }
 
@@ -1011,7 +1019,7 @@ public class SceneFileBuildServiceImpl extends ServiceImpl<ISceneFileBuildMapper
         return fileId;
     }
 
-    public ResultData copyDataAndBuild(String sourceBucet,String dataSource,String sceneVer,User user) throws Exception {
+    public ResultData copyDataAndBuild(String sourceBucet,String dataSource,String sceneVer,User user, String customUserId) throws Exception {
         if(!StringUtils.equals(sceneVer,"V3") && ! StringUtils.equals(sceneVer,"V4")){
             throw new BusinessException(ErrorCode.PARAM_FORMAT_ERROR.code(),"版本有误,请填写 V3 或者 V4");
         }
@@ -1071,7 +1079,7 @@ public class SceneFileBuildServiceImpl extends ServiceImpl<ISceneFileBuildMapper
                     icon = fYunFileConfig.getHost() + imgViewPath + fdageData.getString("icon");
                     log.info("上传icon成功....");
                 }
-                buildScenePost(dataSource, fdageData, "V3", cameraType, sceneNum, cameraEntity, detailEntity, rebuild, icon, user);
+                buildScenePost(dataSource, fdageData, "V3", cameraType, sceneNum, cameraEntity, detailEntity, rebuild, icon, user, customUserId);
                 break;
         }
         Map<String,Object> result = new HashMap<>();
@@ -1080,7 +1088,7 @@ public class SceneFileBuildServiceImpl extends ServiceImpl<ISceneFileBuildMapper
     }
 
     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 sceneNum, Camera camera, CameraDetail cameraDetail, int rebuild,String icon,User user, String customUserId) 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);
@@ -1138,6 +1146,7 @@ public class SceneFileBuildServiceImpl extends ServiceImpl<ISceneFileBuildMapper
             }
         }
         mqMessage.getExt().put("deleteExtras", true);
+        mqMessage.getExt().put("customUserId", customUserId);
         rabbitMqProducer.sendByWorkQueue(queueModelingPre, mqMessage);
 
         return scenePlusVO;