BuildObjServiceImpl.java 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430
  1. package com.fdkankan.contro.mq.service.impl;
  2. import cn.hutool.core.collection.CollUtil;
  3. import cn.hutool.core.io.FileUtil;
  4. import com.alibaba.fastjson.JSONObject;
  5. import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
  6. import com.fdkankan.common.constant.CommonOperStatus;
  7. import com.fdkankan.common.constant.CommonStatus;
  8. import com.fdkankan.common.constant.ModelKind;
  9. import com.fdkankan.common.constant.SceneSource;
  10. import com.fdkankan.common.util.FileUtils;
  11. import com.fdkankan.contro.entity.*;
  12. import com.fdkankan.contro.mq.service.IBuildSceneService;
  13. import com.fdkankan.contro.service.*;
  14. import com.fdkankan.contro.service.impl.FdkkV4Service;
  15. import com.fdkankan.fyun.face.FYunFileServiceInterface;
  16. import com.fdkankan.model.constants.ConstantFileName;
  17. import com.fdkankan.model.constants.ConstantFilePath;
  18. import com.fdkankan.model.constants.UploadFilePath;
  19. import com.fdkankan.model.utils.CreateObjUtil;
  20. import com.fdkankan.rabbitmq.bean.BuildSceneCallMessage;
  21. import com.fdkankan.rabbitmq.bean.BuildSceneResultMqMessage;
  22. import com.fdkankan.rabbitmq.util.RabbitMqProducer;
  23. import com.fdkankan.redis.util.RedisUtil;
  24. import lombok.extern.slf4j.Slf4j;
  25. import org.springframework.beans.factory.annotation.Autowired;
  26. import org.springframework.beans.factory.annotation.Value;
  27. import org.springframework.cloud.context.config.annotation.RefreshScope;
  28. import org.springframework.stereotype.Service;
  29. import org.springframework.util.ObjectUtils;
  30. import javax.annotation.Resource;
  31. import java.io.File;
  32. import java.util.*;
  33. /**
  34. * <p>
  35. * </p>
  36. *
  37. * @author dengsixing
  38. * @since 2022/3/1
  39. **/
  40. @Slf4j
  41. @Service
  42. @RefreshScope
  43. public class BuildObjServiceImpl implements IBuildSceneService {
  44. @Value("${queue.modeling.modeling-call}")
  45. private String queueModelingCall;
  46. @Value("${queue.modeling.obj.modeling-post}")
  47. private String queueObjModelingPost;
  48. @Value("${queue.modeling.obj.modeling-pre}")
  49. private String queueObjModelingPre;
  50. @Value("${model.modelKind:3dtiles}")
  51. private String modelKind;
  52. @Value("#{'${model.3dtiles.sceneSource:}'.split(',')}")
  53. private List<Integer> sdTilesSceneSourceList;
  54. @Value("${env:gn}")
  55. private String env;
  56. @Autowired
  57. private RabbitMqProducer mqProducer;
  58. @Resource
  59. private FYunFileServiceInterface fYunFileService;
  60. @Autowired
  61. private ISceneProService sceneProService;
  62. @Autowired
  63. private IFdkkLaserService fdkkLaserService;
  64. @Autowired
  65. private FdkkV4Service fdkkV4Service;
  66. // @Autowired
  67. // private IBuildSceneDTService buildSceneDTService;
  68. @Autowired
  69. private ISceneProEditService sceneProEditService;
  70. @Autowired
  71. private IScenePlusService scenePlusService;
  72. @Autowired
  73. private ISceneBuildProcessLogService sceneBuildProcessLogService;
  74. @Autowired
  75. private ICommonService commonService;
  76. @Autowired
  77. private IScenePlusExtService scenePlusExtService;
  78. @Autowired
  79. private RedisUtil redisUtil;
  80. @Autowired
  81. private ICameraDetailService cameraDetailService;
  82. @Autowired
  83. private ICompanyService companyService;
  84. @Autowired
  85. private IJmgaService jmgaService;
  86. @Override
  87. public void buildScenePre(BuildSceneCallMessage message) throws Exception{
  88. boolean success = false;
  89. String num = message.getSceneNum();
  90. String path = message.getPath();
  91. String laserObjFilePath = path + "_laser_obj";
  92. try {
  93. //根据相机类型,组装资源路径
  94. log.info("开始准备生成OBJ场景资源,路径:{}", laserObjFilePath);
  95. FileUtils.delAllFile(laserObjFilePath);
  96. //获取解压后的资源的data.fdage中的数据
  97. File folderPath = new File(path);
  98. fYunFileService.downloadFile(ConstantFilePath.OSS_PREFIX + path.replace(ConstantFilePath.BUILD_MODEL_LASER_PATH, "") + "/data.fdage", laserObjFilePath + "/capture/data.fdage");
  99. JSONObject jsonObject = FileUtils.readJson(laserObjFilePath + File.separator + "capture" + File.separator + "data.fdage");
  100. if(ObjectUtils.isEmpty(jsonObject)){
  101. log.error("data.fdage文件不存在");
  102. return ;
  103. }
  104. //下载资源到本地
  105. this.downLoadSource(message, laserObjFilePath);
  106. if (!jsonObject.containsKey("exportMeshObj") || jsonObject.getIntValue("exportMeshObj") != 1) {
  107. // 写入data.fdage 防止重算
  108. jsonObject.put("exportMeshObj", 1);
  109. FileUtil.writeUtf8String(jsonObject.toJSONString(), laserObjFilePath + File.separator + "capture" + File.separator + "data.fdage");
  110. fYunFileService.uploadFile(laserObjFilePath + File.separator + "capture" + File.separator + "data.fdage",
  111. ConstantFilePath.OSS_PREFIX + path.replace(ConstantFilePath.BUILD_MODEL_LASER_PATH, "") + "/data.fdage");
  112. }
  113. // 重新构造datafdage文件,添加生成obt文件选项
  114. jsonObject.put("OnlyExportMeshObj",true);
  115. FileUtils.writeFile(laserObjFilePath + File.separator + "capture" + File.separator + "data.fdage", jsonObject.toJSONString());
  116. message.getBuildContext().put("previousPath",path);
  117. message.setCameraType("14");
  118. message.setResolution(jsonObject.getString("resolution"));
  119. message.setPath(laserObjFilePath);
  120. message.setResultReceiverMqName(queueObjModelingPost);
  121. Map<String, Object> param = new HashMap<>();
  122. try {
  123. JyUser jyUser = scenePlusService.getJyUserByNum(num);
  124. ScenePlus scenePlus = scenePlusService.getScenePlusByNum(num);
  125. param.put("event_type", "scene");
  126. param.put("event_content", "排队中");
  127. param.put("scene_num", num);
  128. param.put("event_time", new Date());
  129. if(Objects.nonNull(scenePlus)){
  130. param.put("scene_title", scenePlus.getTitle());
  131. }
  132. param.put("ryid", jyUser.getRyId());
  133. param.put("ryno", jyUser.getRyNo());
  134. param.put("nick_name", jyUser.getRyNickName());
  135. jmgaService.sendStatus(param);
  136. }catch (Exception ex){
  137. log.info("推送事件失败,param:{}", param);
  138. }
  139. //发送mq,就进行计算
  140. mqProducer.sendByWorkQueue(queueModelingCall, message);
  141. success = true;
  142. log.info("场景计算资源准备结束,场景码:{}", message.getSceneNum());
  143. }catch (Exception e){
  144. log.error("生成OBJ场景资源准备异常,num=" + num, e);
  145. Map<String, Object> param = new HashMap<>();
  146. try {
  147. JyUser jyUser = scenePlusService.getJyUserByNum(num);
  148. ScenePlus scenePlus = scenePlusService.getScenePlusByNum(num);
  149. param.put("event_type", "scene");
  150. param.put("event_content", "计算失败");
  151. param.put("scene_num", num);
  152. param.put("event_time", new Date());
  153. if(Objects.nonNull(scenePlus)){
  154. param.put("scene_title", scenePlus.getTitle());
  155. }
  156. param.put("ryid", jyUser.getRyId());
  157. param.put("ryno", jyUser.getRyNo());
  158. param.put("nick_name", jyUser.getRyNickName());
  159. jmgaService.sendStatus(param);
  160. }catch (Exception ex){
  161. log.info("推送事件失败,param:{}", param);
  162. }
  163. // buildSceneDTService.handBaseFail("生成OBJ场景资源准备异常", message.getPath(), message.getSceneNum(), "计算控制服务器");
  164. throw e;
  165. }finally {
  166. fdkkLaserService.pushBuildStatusToLaserSystem(num, laserObjFilePath + "/laserData/mesh", success ? CommonOperStatus.SUCCESS.code() : CommonOperStatus.FAILD.code());
  167. }
  168. }
  169. @Override
  170. public void downLoadSource(BuildSceneCallMessage message,String path) throws Exception{
  171. //下载原始资源文件
  172. String ossPath = commonService.getOssOrignPath(message.getPath());
  173. fYunFileService.downloadByCommand(path + File.separator + "capture", ossPath, true);
  174. //下载caches/image,算法会执行快一些
  175. String ossResultPath = String.format(UploadFilePath.scene_result_data_path, message.getSceneNum());
  176. fYunFileService.downloadByCommand(path + "/caches/images/", ossResultPath + "caches/images/", true);
  177. //下载点位校准文件
  178. fYunFileService.downloadByCommand(path + "/extras/", ossResultPath + "extras/", true);
  179. }
  180. @Override
  181. public void buildScenePost(BuildSceneResultMqMessage message) throws Exception {
  182. String path = message.getPath();
  183. String projectNum = message.getBuildContext().get("sceneNum").toString();
  184. String laserObjFilePath = path;
  185. boolean success = false;
  186. try {
  187. //上传计算日志
  188. String buildLogPath = String.format(UploadFilePath.BUILD_LOG_PATH, projectNum);
  189. fYunFileService.uploadFile(path + File.separator + "console.log", buildLogPath + "console.log");
  190. if (!message.getBuildSuccess()) {
  191. log.error("生成OBJ场景计算失败!");
  192. Map<String, Object> param = new HashMap<>();
  193. try {
  194. ScenePlus scenePlus = scenePlusService.getScenePlusByNum(projectNum);
  195. JyUser jyUser = scenePlusService.getJyUserByNum(projectNum);
  196. param.put("event_type", "scene");
  197. param.put("event_content", "计算失败");
  198. param.put("scene_num", projectNum);
  199. param.put("event_time", new Date());
  200. if(Objects.nonNull(scenePlus)){
  201. param.put("scene_title", scenePlus.getTitle());
  202. }
  203. param.put("ryid", jyUser.getRyId());
  204. param.put("ryno", jyUser.getRyNo());
  205. param.put("nick_name", jyUser.getRyNickName());
  206. jmgaService.sendStatus(param);
  207. }catch (Exception ex){
  208. log.info("推送事件失败,param:{}", param);
  209. }
  210. // 发送钉钉消息,计算失败
  211. // buildSceneDTService.handModelFail("生成OBJ场景计算失败!", message.getPath(), message.getBuildContext().get("sceneNum").toString(), message.getHostName());
  212. return;
  213. }
  214. ScenePro scenePro = sceneProService.getByNum(projectNum);
  215. String version = "v4";
  216. String ossImagePath = String.format(UploadFilePath.IMG_VIEW_PATH, projectNum);
  217. //如果是微服务上线之前的存量场景且未生成过obj(未升级过),需要上传到v3的目录,在函数最后调用升级接口进行文件拷贝
  218. if(Objects.nonNull(scenePro) && scenePro.getIsUpgrade() != CommonStatus.YES.code().intValue()){
  219. ossImagePath = String.format(ConstantFilePath.IMAGE_PATH_FORMAT, projectNum);
  220. version = "v3";
  221. }
  222. //上传obj
  223. String resultsPath = path + File.separator + "results" + File.separator;
  224. if(this.modelKind.equals(ModelKind.DAM.code())){
  225. CreateObjUtil.convertTxtToDam(path + File.separator + "results" + File.separator + "tex" + File.separator + "modeldata.txt", path + File.separator + "results" + File.separator + ConstantFileName.modelUUID + "_50k.dam");
  226. CreateObjUtil.convertDamToLzma(path + File.separator + "results/");
  227. CreateObjUtil.convertTxtToDam(path + File.separator + "results" + File.separator + "tex" + File.separator + "modeldata.txt", path + File.separator + "results" + File.separator + ConstantFileName.modelUUID + "_50k.dam");
  228. File file = new File(path + File.separator + "results" + File.separator + ConstantFileName.modelUUID + "_50k.dam.lzma");
  229. while (!file.exists()) {
  230. Thread.sleep(60000);
  231. }
  232. fYunFileService.uploadFile(path + File.separator + "results" + File.separator + ConstantFileName.modelUUID + "_50k.dam.lzma", ossImagePath + ConstantFileName.modelUUID + "_50k.dam.lzma");
  233. fYunFileService.uploadFile(path + File.separator + "results" + File.separator + ConstantFileName.modelUUID + "_50k.dam", ossImagePath + ConstantFileName.modelUUID + "_50k.dam");
  234. }
  235. if(this.modelKind.equals(ModelKind.THREE_D_TILE.code())
  236. && CollUtil.isNotEmpty(sdTilesSceneSourceList)
  237. && sdTilesSceneSourceList.contains(SceneSource.JG.code())){
  238. String threedtilesPath = resultsPath + ModelKind.THREE_D_TILE.code();
  239. String oss3dtilesPath = ossImagePath + ModelKind.THREE_D_TILE.code();
  240. List<String> list = FileUtils.list(new File(threedtilesPath));
  241. if(CollUtil.isEmpty(list)){
  242. log.error("3dtiles目录异常,3dtiles地址:{}", new File(path + File.separator + "results" + File.separator + ModelKind.THREE_D_TILE.code()));
  243. throw new Exception("3dtiles目录异常");
  244. }
  245. //先删除
  246. fYunFileService.deleteFolder(oss3dtilesPath);
  247. //上传3dtiles文件
  248. fYunFileService.uploadFileByCommand(threedtilesPath, oss3dtilesPath);
  249. }
  250. String texPath = laserObjFilePath + File.separator + "results" + File.separator + "tex";
  251. File texFile = new File(texPath);
  252. if(texFile.exists()){
  253. for (File textureFile : texFile.listFiles()) {
  254. if(textureFile.getName().endsWith(".jpg")){
  255. fYunFileService.uploadFile(textureFile.getAbsolutePath(),
  256. ossImagePath + ConstantFileName.modelUUID + "_50k_texture_jpg_high1/"+textureFile.getName());
  257. }
  258. }
  259. }
  260. fYunFileService.uploadFile(laserObjFilePath + File.separator + "results" + File.separator + "tex/texture1.jpg",
  261. ossImagePath + ConstantFileName.modelUUID + "_50k_texture_jpg_high1/texture1.jpg");
  262. // 拷贝结果
  263. log.info("开始拷贝obj文件");
  264. FileUtils.copyFolderAllFiles(laserObjFilePath + "/results/mesh", laserObjFilePath + "/laserData/mesh/", true);
  265. //先删除
  266. fYunFileService.deleteFolder(String.format(UploadFilePath.DATA_VIEW_PATH, projectNum) + "mesh");
  267. //上传mesh文件
  268. fYunFileService.uploadFileByCommand(laserObjFilePath + "/results/mesh", String.format(UploadFilePath.DATA_VIEW_PATH, projectNum) + "mesh");
  269. CreateObjUtil.convertTxtToVisionmodeldata(resultsPath + "vision.txt", resultsPath + "vision.modeldata");
  270. fYunFileService.uploadFile(resultsPath + "vision.txt", ossImagePath.concat("vision.txt"));
  271. fYunFileService.uploadFile(resultsPath + "vision.modeldata", ossImagePath.concat("vision.modeldata"));
  272. if(!ObjectUtils.isEmpty(scenePro)){
  273. LambdaUpdateWrapper<ScenePro> updateWrapper = new LambdaUpdateWrapper<ScenePro>()
  274. .set(ScenePro::getStatus, -2).eq(ScenePro::getNum, projectNum);
  275. sceneProService.update(updateWrapper);
  276. sceneProEditService.update(new LambdaUpdateWrapper<SceneProEdit>().set(SceneProEdit::getMapVisi,0)
  277. .eq(SceneProEdit::getProId,scenePro.getId()));
  278. }
  279. ScenePlus scenePlus = scenePlusService.getScenePlusByNum(projectNum);
  280. if(Objects.nonNull(scenePlus)){
  281. // //清除用户编辑业务数据
  282. // Set<String> bizs = new HashSet<>();
  283. // bizs.add(UserEditDataType.BOX_MODEL.message());
  284. // bizs.add(UserEditDataType.FLOORPLAN.message());
  285. // commonService.initUserEditData(projectNum, bizs, null);
  286. LambdaUpdateWrapper<ScenePlus> plusUpdateWrapper = new LambdaUpdateWrapper<ScenePlus>()
  287. .set(ScenePlus::getSceneStatus, -2).eq(ScenePlus::getNum, projectNum);
  288. scenePlusService.update(plusUpdateWrapper);
  289. ScenePlusExt scenePlusExt = scenePlusExtService.getScenePlusExtByPlusId(scenePlus.getId());
  290. scenePlusExt.setAlgorithmTime(Calendar.getInstance().getTime());
  291. //计算容量
  292. Long space = commonService.getSpace(projectNum);
  293. scenePlusExt.setSpace(space);
  294. Object[] editInfoArr = commonService.updateEditInfo(scenePlus);
  295. SceneEditInfo sceneEditInfo = (SceneEditInfo)editInfoArr[0];
  296. SceneEditInfoExt sceneEditInfoExt = (SceneEditInfoExt)editInfoArr[1];
  297. SceneEditControls sceneEditControls = (SceneEditControls)editInfoArr[2];
  298. if(this.modelKind.equals(ModelKind.THREE_D_TILE.code())
  299. && CollUtil.isNotEmpty(sdTilesSceneSourceList)
  300. && sdTilesSceneSourceList.contains(scenePlus.getSceneSource())){
  301. scenePlusExt.setModelKind(ModelKind.THREE_D_TILE.code());
  302. scenePlusExtService.updateById(scenePlusExt);
  303. }
  304. log.info("生成scene.json上传oss并设置缓存,num:{}", projectNum);
  305. CameraDetail cameraDetail = cameraDetailService.getByCameraId(scenePlus.getCameraId());
  306. Company company = !org.apache.commons.lang3.ObjectUtils.isEmpty(cameraDetail.getCompanyId()) ? companyService.getById(cameraDetail.getCompanyId()) : null;
  307. //写scene.json
  308. commonService.writeSceneJson(projectNum, new JSONObject(),sceneEditInfo, sceneEditInfoExt, sceneEditControls, scenePlus,scenePlusExt,company);
  309. }
  310. //重置异步操作记录
  311. commonService.removeSceneAsynOperLog(projectNum);
  312. Map<String, Object> param = new HashMap<>();
  313. try {
  314. JyUser jyUser = scenePlusService.getJyUserByNum(projectNum);
  315. param.put("event_type", "scene");
  316. param.put("event_content", "计算成功");
  317. param.put("scene_num", projectNum);
  318. param.put("event_time", new Date());
  319. if(Objects.nonNull(scenePlus)){
  320. param.put("scene_title", scenePlus.getTitle());
  321. }
  322. param.put("ryid", jyUser.getRyId());
  323. param.put("ryno", jyUser.getRyNo());
  324. param.put("nick_name", jyUser.getRyNickName());
  325. jmgaService.sendStatus(param);
  326. }catch (Exception ex){
  327. log.info("推送事件失败,param:{}", param);
  328. }
  329. // 如果未升级V4,则升级V4
  330. if("v3".equals(version)){
  331. fdkkV4Service.upgradeToV4(projectNum);
  332. }
  333. success = true;
  334. //国际环境需要发邮件通知
  335. if("eur".equals(env)){
  336. commonService.sendEmail(projectNum);
  337. }
  338. }catch (Exception e){
  339. log.error("生成OBJ场景计算结果处理异常,num=" + projectNum, e);
  340. // buildSceneDTService.handBaseFail("生成OBJ场景计算结果处理异常", message.getPath(), projectNum, "计算控制服务器");
  341. Map<String, Object> param = new HashMap<>();
  342. try {
  343. ScenePlus scenePlus = scenePlusService.getScenePlusByNum(projectNum);
  344. JyUser jyUser = scenePlusService.getJyUserByNum(projectNum);
  345. param.put("event_type", "scene");
  346. param.put("event_content", "计算失败");
  347. param.put("scene_num", projectNum);
  348. param.put("event_time", new Date());
  349. if(Objects.nonNull(scenePlus)){
  350. param.put("scene_title", scenePlus.getTitle());
  351. }
  352. param.put("ryid", jyUser.getRyId());
  353. param.put("ryno", jyUser.getRyNo());
  354. param.put("nick_name", jyUser.getRyNickName());
  355. jmgaService.sendStatus(param);
  356. }catch (Exception ex){
  357. log.info("推送事件失败,param:{}", param);
  358. }
  359. throw e;
  360. }finally {
  361. fdkkLaserService.pushBuildStatusToLaserSystem(projectNum, laserObjFilePath + "/laserData/mesh", success ? CommonOperStatus.SUCCESS.code() : CommonOperStatus.FAILD.code());
  362. }
  363. }
  364. }