BuildSceneReceiver.java 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677
  1. package com.fdkankan.modeling.receiver;
  2. import cn.hutool.core.date.DateUtil;
  3. import com.alibaba.fastjson.JSONArray;
  4. import com.alibaba.fastjson.JSONObject;
  5. import com.fdkankan.common.util.ComputerUtil;
  6. import com.fdkankan.common.util.UploadToOssUtil;
  7. import com.fdkankan.modeling.constants.RedisKey;
  8. import com.fdkankan.modeling.constants.SysConstants;
  9. import com.fdkankan.modeling.entity.SceneFileBuild;
  10. import com.fdkankan.modeling.entity.ScenePro;
  11. import com.fdkankan.modeling.entity.SceneProExt;
  12. import com.fdkankan.modeling.feign.UserFeign;
  13. import com.fdkankan.modeling.push.PushMessageConfig;
  14. import com.fdkankan.modeling.service.ISceneFileBuildService;
  15. import com.fdkankan.modeling.service.ISceneProExtService;
  16. import com.fdkankan.modeling.service.ISceneProService;
  17. import com.fdkankan.modeling.service.ISceneService;
  18. import com.fdkankan.modeling.utils.DingDingUtils;
  19. import com.fdkankan.modeling.utils.PushMsgUtil;
  20. import com.fdkankan.mq.message.BuildSceneMqMessage;
  21. import com.fdkankan.platform.api.vo.User;
  22. import com.fdkankan.redis.util.RedisUtil;
  23. import com.fdkankan.utils.constant.ConstantFilePath;
  24. import com.fdkankan.utils.constant.ConstantUrl;
  25. import com.fdkankan.utils.utils.CreateObjUtil;
  26. import com.fdkankan.utils.utils.FileUtil;
  27. import com.fdkankan.utils.utils.FileUtils;
  28. import com.taobao.api.ApiException;
  29. import lombok.extern.log4j.Log4j2;
  30. import org.apache.commons.lang3.StringUtils;
  31. import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext;
  32. import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus;
  33. import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently;
  34. import org.apache.rocketmq.common.message.MessageExt;
  35. import org.springframework.beans.factory.annotation.Autowired;
  36. import org.springframework.beans.factory.annotation.Value;
  37. import org.springframework.data.redis.core.RedisTemplate;
  38. import org.springframework.stereotype.Component;
  39. import org.springframework.util.CollectionUtils;
  40. import org.springframework.util.ObjectUtils;
  41. import org.springframework.web.client.RestTemplate;
  42. import javax.annotation.Resource;
  43. import java.io.*;
  44. import java.security.InvalidKeyException;
  45. import java.security.NoSuchAlgorithmException;
  46. import java.time.Duration;
  47. import java.time.temporal.ChronoUnit;
  48. import java.util.Date;
  49. import java.util.HashMap;
  50. import java.util.List;
  51. import java.util.Map;
  52. import java.util.concurrent.*;
  53. import static com.fdkankan.modeling.push.PushMessageConfig.*;
  54. @Log4j2
  55. @Component
  56. public class BuildSceneReceiver implements MessageListenerConcurrently {
  57. @Autowired
  58. private ISceneService sceneService;
  59. @Autowired
  60. private ISceneProService sceneProService;
  61. @Autowired
  62. private UserFeign userFeign;
  63. @Autowired
  64. private ISceneFileBuildService sceneFileBuildService;
  65. @Autowired
  66. private ISceneProExtService sceneProExtService;
  67. @Autowired
  68. RedisUtil redisUtil;
  69. @Autowired
  70. RedisTemplate redisTemplate;
  71. private RestTemplate restTemplate = new RestTemplate();
  72. @Value("${4dkk.laserService.host}")
  73. private String laserHost;
  74. @Value("${oss.type}")
  75. private String ossType;
  76. @Value("${prefix.ali}")
  77. private String prefixAli;
  78. @Resource
  79. private UploadToOssUtil uploadToOssUtil;
  80. @Override
  81. public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgExt,
  82. ConsumeConcurrentlyContext consumeConcurrentlyContext) {
  83. if (CollectionUtils.isEmpty(msgExt)) {
  84. log.error("消息内容为空,退出构建,当前服务器id:{}", SysConstants.hostName);
  85. return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
  86. }
  87. MessageExt messageExt = msgExt.get(0);
  88. BuildSceneMqMessage message = JSONObject.parseObject(messageExt.getBody(), BuildSceneMqMessage.class);
  89. log.info("开始处理消息,消息队列:{},消息内容:{}", consumeConcurrentlyContext.getMessageQueue().getTopic(),
  90. JSONObject.toJSONString(message));
  91. process(message);
  92. return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
  93. }
  94. public void process(BuildSceneMqMessage message) {
  95. final ExecutorService exec = Executors.newFixedThreadPool(1);
  96. Callable<String> call = (Callable<String>) () -> {
  97. //开始执行耗时操作
  98. try {
  99. String key = RedisKey.SCENE_BUILDING + message.getSceneNum();
  100. // 获取缓存锁,防止重复消费
  101. Long building = redisUtil.incr(key, 1);
  102. if (building.compareTo(1L) != 0) {
  103. log.error("场景正在构建中,退出构建,当前服务器id:{},参数:{}", SysConstants.hostName, JSONObject.toJSONString(message));
  104. } else {
  105. redisTemplate.expire(key, Duration.of(SysConstants.modelTimeOut, ChronoUnit.HOURS));
  106. }
  107. //休眠2秒等待数据入库
  108. Thread.sleep(2000L);
  109. try {
  110. FileUtils.writeFile("/opt/hosts/running.txt", DateUtil.formatDateTime(new Date()));
  111. String tomcatLog = "scenenum:" + message.getSceneNum() + "\ntime:" + DateUtil.formatDateTime(new Date()) +
  112. " action:create hostname:" + SysConstants.hostName;
  113. //打开一个写文件器,构造函数中的第二个参数true表示以追加形式写文件
  114. FileWriter writer = new FileWriter("/mnt/elastic_log/tomcat" + "_" + message.getSceneNum() + ".log", true);
  115. writer.write(tomcatLog);
  116. writer.close();
  117. } catch (Exception e) {
  118. e.printStackTrace();
  119. }
  120. buildScene(message);
  121. redisUtil.del(key);
  122. try {
  123. FileUtils.deleteFile("/opt/hosts/running.txt");
  124. String tomcatLog = "scenenum:" + message.getSceneNum() + "\ntime:" + DateUtil.formatDateTime(new Date()) +
  125. " action:delete hostname:" + SysConstants.hostName;
  126. //打开一个写文件器,构造函数中的第二个参数true表示以追加形式写文件
  127. FileWriter writer = new FileWriter("/mnt/elastic_log/tomcat" + "_" + message.getSceneNum() + "log", true);
  128. writer.write(tomcatLog);
  129. writer.close();
  130. } catch (Exception e) {
  131. e.printStackTrace();
  132. }
  133. } catch (Exception e) {
  134. e.printStackTrace();
  135. sceneService.updateStatus(message.getSceneNum(), -1);
  136. BuildSceneReceiver.this.handFail("计算失败", message);
  137. }
  138. log.info("场景生成好了***");
  139. return "success";
  140. };
  141. Future<String> future = exec.submit(call);
  142. try {
  143. future.get(SysConstants.modelTimeOut, TimeUnit.HOURS); //任务处理超时时间设为 24个小时
  144. } catch (TimeoutException ex) {
  145. ex.printStackTrace();
  146. StringWriter trace=new StringWriter();
  147. ex.printStackTrace(new PrintWriter(trace));
  148. log.error("超时了");
  149. log.error(trace.toString());
  150. FileUtils.deleteFile("/opt/hosts/running.txt");
  151. future.cancel(true);
  152. handFail("计算超时",message);
  153. } catch (Exception e) {
  154. e.printStackTrace();
  155. StringWriter trace=new StringWriter();
  156. e.printStackTrace(new PrintWriter(trace));
  157. log.error(trace.toString());
  158. FileUtils.deleteFile("/opt/hosts/running.txt");
  159. future.cancel(true);
  160. handFail("计算失败",message);
  161. }
  162. }
  163. private void buildScene(BuildSceneMqMessage message){
  164. String projectNum = null;
  165. SceneFileBuild sceneFileBuildEntity = null;
  166. ScenePro scene = null;
  167. SceneProExt sceneProExt = null;
  168. try{
  169. if(StringUtils.equals(message.getIsStandardization(),"1")){
  170. //表示标定算法
  171. ComputerUtil.computerCalibration(message.getPath());
  172. return;
  173. }
  174. String unicode = message.getUnicode();
  175. String path = message.getPath();
  176. String prefix = message.getPrefix();
  177. String imgsName = message.getImgsName();
  178. projectNum = message.getSceneNum();
  179. String userName = message.getUserName();
  180. //不同的相机不同的方法
  181. String cameraType = message.getCameraType();
  182. String algorithm = message.getAlgorithm();
  183. String fileId = message.getFileId();
  184. String cameraName = message.getCameraName();
  185. //0表示有4k图,1表示没有
  186. String resolution = message.getResolution();
  187. //判断调用V2还是V3版本的算法
  188. String buildType = ObjectUtils.isEmpty(message.getBuildType()) ? "V2" : message.getBuildType();
  189. log.info("执行数据库操作--前");
  190. sceneFileBuildEntity = sceneFileBuildService.findByFileId(fileId);
  191. log.info("执行数据库操作--后");
  192. Map<String, String> dataMap = ComputerUtil.getTypeString(cameraType, algorithm,
  193. resolution);
  194. String splitType = dataMap.get("splitType");
  195. String skyboxType = dataMap.get("skyboxType");
  196. String dataDescribe = dataMap.get("dataDescribe");
  197. log.info("用的算法是:"+algorithm);
  198. log.info("用的相机是:"+ (Integer.parseInt(cameraType) < 4 ? "单球目" : "双球目(八目)"));
  199. Map<String,String> map = new HashMap<>();
  200. //该场景使用的容量
  201. Long space = 0L;
  202. //支付状态
  203. int payStatus = 0;
  204. //4表示硬件部研发的双球目相机,其余为旧版本相机
  205. if(Integer.parseInt(cameraType) < 3){
  206. for(int i = 0;i<5;++i){
  207. try{
  208. FileUtils.downLoadFromUrl(prefix+imgsName+"?m="+new Date().getTime(), imgsName,
  209. path + File.separator + "capture");
  210. FileUtils.decompress(path + File.separator + "capture" +File.separator+imgsName,
  211. path + File.separator + "capture") ;
  212. break;
  213. }
  214. catch(Exception e){
  215. e.printStackTrace();
  216. StringWriter trace=new StringWriter();
  217. e.printStackTrace(new PrintWriter(trace));
  218. log.error(trace.toString());
  219. if(i<4)
  220. {
  221. FileUtils.deleteFile(path + File.separator + "capture" +File.separator+imgsName);
  222. FileUtils.delFolder(path + File.separator + "capture" +File.separator+"images");
  223. }
  224. Thread.sleep(10000);
  225. }
  226. }
  227. FileUtils.deleteFile(path + File.separator + "capture" +File.separator+"zip.Zip");
  228. String data = FileUtils.readFile(path + File.separator + "capture" +File.separator+"data.fdage");
  229. JSONObject dataJson = new JSONObject();
  230. if(data!=null){
  231. dataJson = JSONObject.parseObject(data);
  232. if(dataJson.containsKey("imgs")){
  233. splitType = "SPLIT_V4";
  234. }
  235. }
  236. //生成project.json和data.json供算法部使用
  237. ComputerUtil.createJson(path, splitType, skyboxType, dataDescribe, projectNum, path);
  238. //计算模型并返回需要上传oss的文件集合
  239. map = ComputerUtil.computer(projectNum, path, buildType);
  240. uploadToOssUtil.uploadMulFiles(map);
  241. log.info("双目上完oss结束修改数据:"+projectNum);
  242. sceneService.updateTime(projectNum, space, payStatus);
  243. } else {
  244. //休眠1秒,否则可能获取不到场景资源
  245. Thread.sleep(1000);
  246. scene = sceneProService.findBySceneNum(projectNum);
  247. sceneProExt = sceneProExtService.getBySceneProId(scene.getId());
  248. if(scene == null){
  249. log.info(projectNum + ":场景不存在");
  250. handFail("场景不存在",message);
  251. return;
  252. }
  253. long start = System.currentTimeMillis();
  254. //cameraType=5为新版本双目, cameraType=6为小红屋新版本双目
  255. if(Integer.parseInt(cameraType) == 5 || Integer.parseInt(cameraType) == 6){
  256. path = ConstantFilePath.BUILD_MODEL_PATH + unicode;
  257. //下载zip包,并解压
  258. FileUtils.downLoadFromUrl(prefix + "/" + imgsName + "?m=" + System.currentTimeMillis(), imgsName, path + File.separator + "capture");
  259. FileUtils.decompress(path + File.separator + "capture" + File.separator + imgsName,
  260. path + File.separator + "capture") ;
  261. FileUtil.delFile(path + File.separator + "capture" + File.separator + imgsName);
  262. }else if(Integer.parseInt(cameraType) == 14 ) {
  263. CreateObjUtil.ossUtilCp(ConstantFilePath.OSS_PREFIX + cameraName.replace("4DKKPRO_", "")
  264. .replace("-fdage", "").toLowerCase() + File.separator + fileId + File.separator
  265. + unicode + File.separator,
  266. ConstantFilePath.BUILD_MODEL_LASER_PATH + cameraName.replace("4DKKPRO_", "")
  267. .replace("-fdage", "").toLowerCase() + File.separator + fileId + File.separator
  268. + unicode + File.separator + "capture");
  269. path = ConstantFilePath.BUILD_MODEL_LASER_PATH + cameraName.replace("4DKKPRO_", "").replace("-fdage", "").toLowerCase() + File.separator + fileId + File.separator + unicode;
  270. } else if(Integer.parseInt(cameraType) >= 4 ) {
  271. CreateObjUtil.ossUtilCp(ConstantFilePath.OSS_PREFIX + cameraName.replace("4DKKPRO_", "")
  272. .replace("-fdage", "").toLowerCase() + File.separator + fileId + File.separator
  273. + unicode + File.separator,
  274. ConstantFilePath.BUILD_MODEL_PATH + cameraName.replace("4DKKPRO_", "")
  275. .replace("-fdage", "").toLowerCase() + File.separator + fileId + File.separator
  276. + unicode + File.separator + "capture");
  277. path = ConstantFilePath.BUILD_MODEL_PATH + cameraName.replace("4DKKPRO_", "").replace("-fdage", "").toLowerCase() + File.separator + fileId + File.separator + unicode;
  278. }
  279. String data = FileUtils.readFile(path + File.separator + "capture" +File.separator+"data.fdage");
  280. //获取data.fdage的内容
  281. JSONObject dataJson = new JSONObject();
  282. if(data!=null){
  283. dataJson = JSONObject.parseObject(data);
  284. }
  285. //判断是否计算过资源,若计算过删除缓存
  286. File caches = new File(path + File.separator + "caches");
  287. if(caches.exists()){
  288. for(File deleteFile : caches.listFiles()){
  289. if(new File(path + "_images").exists()){
  290. if(deleteFile.isDirectory()){
  291. FileUtils.delAllFile(deleteFile.getAbsolutePath());
  292. }else {
  293. FileUtils.deleteFile(deleteFile.getAbsolutePath());
  294. }
  295. }
  296. else if(!deleteFile.getAbsolutePath().contains("images")){
  297. if(deleteFile.isDirectory()){
  298. FileUtils.delAllFile(deleteFile.getAbsolutePath());
  299. }else {
  300. FileUtils.deleteFile(deleteFile.getAbsolutePath());
  301. }
  302. }
  303. }
  304. }
  305. if(new File(path + File.separator + "results").exists()){
  306. FileUtils.delAllFile(path + File.separator + "results");
  307. }
  308. //生成project.json和data.json供算法部使用
  309. log.info("path:" + path);
  310. if(dataJson.containsKey("videoVersion") && StringUtils.isNotEmpty(dataJson.getString("videoVersion")) && Integer.parseInt(dataJson.getString("videoVersion")) < 4){
  311. //v2版本使用4k算法
  312. skyboxType = "SKYBOX_V6";
  313. }
  314. ComputerUtil.createJson(path, splitType, skyboxType, dataDescribe, projectNum, path);
  315. //计算模型并返回需要上传oss的文件集合
  316. map = ComputerUtil.computer(projectNum, path, buildType);
  317. if(Integer.parseInt(cameraType) == 5 || Integer.parseInt(cameraType) == 6){
  318. map.put(path + File.separator + "capture/stitch_params.txt", "data/data" + projectNum + "/stitch_params.txt");
  319. }
  320. map.put(path + File.separator + "capture/Up.xml", "data/data" + projectNum + "/Up.xml");
  321. map.put(path + File.separator + "capture/Up2.xml", "data/data" + projectNum + "/Up2.xml");
  322. if(Integer.parseInt(cameraType) == 13){
  323. //转台相机
  324. map.put(path + File.separator + "capture/Up.txt", "data/data" + projectNum + "/Up.txt");
  325. map.put(path + File.separator + "capture/Up2.txt", "data/data" + projectNum + "/Up2.txt");
  326. }
  327. uploadToOssUtil.uploadMulFiles(map);
  328. payStatus = 1;
  329. File spaceFile = null;
  330. for (String key : map.keySet()) {
  331. spaceFile = new File(key);
  332. if(spaceFile.exists()){
  333. space += spaceFile.length();
  334. }
  335. }
  336. log.info("八目上完oss结束修改数据:"+projectNum);
  337. //获取upload中的video视频名称
  338. String uploadData = FileUtils.readFile(path + File.separator + "results" +File.separator+"upload.json");
  339. com.alibaba.fastjson.JSONObject uploadJson = null;
  340. JSONArray array = null;
  341. if(uploadData!=null) {
  342. uploadJson = com.alibaba.fastjson.JSONObject.parseObject(uploadData);
  343. array = uploadJson.getJSONArray("upload");
  344. }
  345. com.alibaba.fastjson.JSONObject fileJson = null;
  346. String fileName = "";
  347. //读取videos_hdr_param.json, 保存点位视频的value
  348. Map<String, Object> videoMap = new HashMap<>();
  349. String videosHdr = FileUtils.readFile(path + File.separator + "results/videos/videos_hdr_param.json");
  350. JSONArray videoArray = null;
  351. if(StringUtils.isNotEmpty(videosHdr)){
  352. videoArray = com.alibaba.fastjson.JSONObject.parseObject(videosHdr).getJSONArray("hdr_param");
  353. }
  354. if(videoArray != null){
  355. for(int i = 0, len = videoArray.size(); i < len; i++) {
  356. videoMap.put(videoArray.getJSONObject(i).getString("name"), videoArray.getJSONObject(i).getString("value"));
  357. if(videoArray.getJSONObject(i).containsKey("fov")){
  358. videoMap.put(videoArray.getJSONObject(i).getString("name") + "_fov", videoArray.getJSONObject(i).getString("fov"));
  359. }
  360. }
  361. }
  362. //计算ts文件的大小,并拼接成json格式
  363. JSONArray jsonArray = new JSONArray();
  364. com.alibaba.fastjson.JSONObject videoJson = null;
  365. com.alibaba.fastjson.JSONObject videosJson = new com.alibaba.fastjson.JSONObject();
  366. long videoSize = 0L;
  367. for(int i = 0, len = array.size(); i < len; i++) {
  368. fileJson = array.getJSONObject(i);
  369. fileName = fileJson.getString("file");
  370. if(fileJson.getIntValue("clazz") == 11 && fileName.contains(".mp4") && !fileName.contains("-ios.mp4")){
  371. videoJson = new com.alibaba.fastjson.JSONObject();
  372. videoJson.put("id", fileName.substring(
  373. 0, fileName.lastIndexOf(".")).replace("videos/", ""));
  374. //如果ts文件存在,就计算ts大小
  375. if(new File(path + File.separator + "results" +File.separator+ fileName.replace(".mp4", ".ts")).exists()){
  376. videoSize = new File(path + File.separator + "results" +File.separator+ fileName.replace(".mp4", ".ts")).length();
  377. videoJson.put("tsSize", videoSize);
  378. }
  379. if(videoMap.containsKey(videoJson.get("id"))){
  380. videoJson.put("value", videoMap.get(videoJson.get("id")));
  381. }
  382. if(videoMap.containsKey(videoJson.get("id") + "_fov")){
  383. videoJson.put("blend_fov", videoMap.get(videoJson.get("id") + "_fov"));
  384. }else {
  385. videoJson.put("blend_fov", 7);
  386. }
  387. jsonArray.add(videoJson);
  388. }
  389. }
  390. videosJson.put("data", jsonArray);
  391. if(dataJson.containsKey("videoVersion") && StringUtils.isNotEmpty(dataJson.getString("videoVersion")) && Integer.parseInt(dataJson.getString("videoVersion")) >= 4){
  392. videosJson.put("version", 3);
  393. if("oss".equals(ossType)){
  394. videosJson.put("upPath", prefixAli + "data/data" + projectNum + "/Up.xml");
  395. }
  396. if("s3".equals(ossType)){
  397. videosJson.put("upPath", ConstantUrl.PREFIX_AWS + "data/data" + projectNum + "/Up.xml");
  398. }
  399. if(Integer.parseInt(cameraType) == 13){
  400. //转台相机
  401. videosJson.put("upPath", videosJson.getString("upPath").replace(".xml", ".txt"));
  402. }
  403. }else {
  404. videosJson.put("version", 1);
  405. if("oss".equals(ossType)){
  406. videosJson.put("upPath", prefixAli + "data/data" + projectNum + "/Up2.xml");
  407. }
  408. if("s3".equals(ossType)){
  409. videosJson.put("upPath", ConstantUrl.PREFIX_AWS + "data/data" + projectNum + "/Up2.xml");
  410. }
  411. if(Integer.parseInt(cameraType) == 13){
  412. //转台相机
  413. videosJson.put("upPath", videosJson.getString("upPath").replace(".xml", ".txt"));
  414. }
  415. }
  416. if(Integer.parseInt(cameraType) == 5 || Integer.parseInt(cameraType) == 6){
  417. videosJson.put("version", 1);
  418. if("oss".equals(ossType)){
  419. videosJson.put("upPath", prefixAli + "data/data" + projectNum + "/stitch_params.txt");
  420. }
  421. if("s3".equals(ossType)){
  422. videosJson.put("upPath", ConstantUrl.PREFIX_AWS + "data/data" + projectNum + "/stitch_params.txt");
  423. }
  424. }
  425. long computeTime = (System.currentTimeMillis() - start) / 1000;
  426. sceneProService.updateTime(projectNum, space, payStatus, videosJson.toJSONString(), computeTime);
  427. //更新scene.json里面的video数据
  428. StringBuffer dataBuf = new StringBuffer()
  429. .append("data").append(File.separator)
  430. .append("data").append(projectNum)
  431. .append(File.separator);
  432. StringBuffer dataBuffer = new StringBuffer(ConstantFilePath.SCENE_PATH).append(dataBuf.toString());
  433. String strsceneInfos = FileUtils.readFile(dataBuffer.toString() + "scene.json");
  434. com.alibaba.fastjson.JSONObject scenejson = new com.alibaba.fastjson.JSONObject();
  435. if(strsceneInfos!=null){
  436. scenejson = com.alibaba.fastjson.JSONObject.parseObject(strsceneInfos);
  437. }
  438. scenejson.put("videos", videosJson.toJSONString());
  439. FileUtils.writeFile(dataBuffer.toString() + "scene.json", scenejson.toString());
  440. User userEntity = userFeign.findByUserName(userName);
  441. if(userEntity == null){
  442. userFeign.updateUserUsedSpaceBySceneNum(null, projectNum);
  443. }else {
  444. userFeign.updateUserUsedSpaceBySceneNum(userEntity.getId(), projectNum);
  445. }
  446. if (sceneFileBuildEntity != null){
  447. sceneFileBuildEntity.setBuildStatus(3);
  448. sceneFileBuildService.updateById(sceneFileBuildEntity);
  449. }
  450. //根据data.fdage推送计算完成的消息
  451. log.info("推送消息,渠道是 {}, 手机token是 {}", dataJson.get("pushChannel"), dataJson.get("pushToken"));
  452. if(dataJson.containsKey("pushChannel") && dataJson.containsKey("pushToken")){
  453. try{
  454. if(!"s3".equals(ossType)){
  455. PushMessageConfig demo = null;
  456. if(dataJson.getIntValue("pushChannel") == 0){
  457. if(Integer.parseInt(cameraType) == 10 || Integer.parseInt(cameraType) == 13){
  458. //ios
  459. log.info("IOS_KEY:{}, IOS_SECRET:{}", IOS_KEY_Z, IOS_SECRET_Z);
  460. demo = new PushMessageConfig(IOS_KEY_Z, IOS_SECRET_Z);
  461. demo.sendIOSUnicast(dataJson.getString("pushToken"),
  462. "四维看看Minion", scene.getSceneName() + "计算完成", "您上传的" + scene.getSceneName() + "计算完成,点击查看",
  463. scene.getWebSite());
  464. }else {
  465. //ios
  466. log.info("IOS_KEY:{}, IOS_SECRET:{}", IOS_KEY, IOS_SECRET);
  467. demo = new PushMessageConfig(IOS_KEY, IOS_SECRET);
  468. demo.sendIOSUnicast(dataJson.getString("pushToken"),
  469. "四维看看Pro", scene.getSceneName() + "计算完成", "您上传的" + scene.getSceneName() + "计算完成,点击查看",
  470. scene.getWebSite());
  471. }
  472. }else {
  473. if(Integer.parseInt(cameraType) == 10 || Integer.parseInt(cameraType) == 13){
  474. //ios
  475. //安卓
  476. log.info("ANDROID_KEY:{}, ANDROID_SECRET:{}", ANDROID_KEY_Z, ANDROID_SECRET_Z);
  477. demo = new PushMessageConfig(ANDROID_KEY_Z, ANDROID_SECRET_Z);
  478. demo.sendAndroidUnicast2(dataJson.getString("pushToken"),
  479. "四维看看Minion", scene.getSceneName() + "计算完成", "您上传的" + scene.getSceneName() + "计算完成,点击查看",
  480. scene.getWebSite());
  481. }else {
  482. //安卓
  483. log.info("ANDROID_KEY:{}, ANDROID_SECRET:{}", ANDROID_KEY, ANDROID_SECRET);
  484. demo = new PushMessageConfig(ANDROID_KEY, ANDROID_SECRET);
  485. demo.sendAndroidUnicast(dataJson.getString("pushToken"),
  486. "四维看看Pro", scene.getSceneName() + "计算完成", "您上传的" + scene.getSceneName() + "计算完成,点击查看",
  487. scene.getWebSite());
  488. }
  489. }
  490. }else {
  491. PushMsgUtil.googlePushMsg(dataJson.getString("pushToken"),
  492. scene.getSceneName() + "计算完成", "您上传的" + scene.getSceneName() + "计算完成,点击查看",
  493. scene.getWebSite());
  494. }
  495. log.info("消息推送结束!");
  496. }catch (Exception e){
  497. log.info("推送消息失败:");
  498. e.printStackTrace();
  499. }
  500. }
  501. //计算成功 激光转台相机推送
  502. log.info("激光转台相机 同步 请求 ");
  503. if(Integer.parseInt(cameraType) == 14){
  504. try {
  505. String title = "";
  506. if(StringUtils.isNotEmpty(scene.getSceneName())){
  507. title = scene.getSceneName();
  508. }
  509. String dataSource = sceneProExt.getDataSource();
  510. String jgPath = dataSource;
  511. //创建目录
  512. if(dataSource.lastIndexOf("/")!=-1){
  513. jgPath = jgPath + "_laserData";
  514. }else{
  515. jgPath = jgPath.substring(0,jgPath.length()-1) + "_laserData";
  516. }
  517. FileUtils.createDir(jgPath+"/extras");
  518. log.info("生成 激光相机目录 " + jgPath);
  519. //生成data.json
  520. JSONObject jgDataJson = new JSONObject();
  521. jgDataJson.put("split_type", "SPLIT_V15");
  522. jgDataJson.put("skybox_type", "SKYBOX_V5");
  523. jgDataJson.put("extras", null);
  524. FileUtils.writeFile(jgPath + File.separator + "data.json", jgDataJson.toString());
  525. CreateObjUtil.cpfile(dataSource + "/results/laserData/cover", jgPath+"/extras/");
  526. CreateObjUtil.cplaserfile(dataSource + "/results/laserData", jgPath+File.separator);
  527. //激光相机
  528. String url = laserHost+"/indoor/{sceneCode}/api/init?path="
  529. + jgPath + File.separator + "laserData" + "&title="+ title
  530. + "&childName=" + cameraName + "&createTime=" + scene.getCreateTime()
  531. + "&snCode="+ cameraName;
  532. if(scene.getUserId()!=null){
  533. url = url + "&userId=" + scene.getUserId();
  534. }
  535. if(StringUtils.isNotEmpty(userName)){
  536. url = url + "&phone=" + userName;
  537. }
  538. url = url.replace("{sceneCode}",scene.getSceneCode());
  539. log.info("激光转台相机 同步 :" + url);
  540. com.alibaba.fastjson.JSONObject hotListJson =
  541. com.alibaba.fastjson.JSONObject.parseObject(restTemplate.getForObject(url,String.class));
  542. log.info("激光转台相机 同步结束 :" + hotListJson);
  543. }catch (Exception e){
  544. e.printStackTrace();
  545. handFail("激光转台相机同步失败",message);
  546. }
  547. }
  548. }
  549. CreateObjUtil.deleteFile(path.replace(ConstantFilePath.BUILD_MODEL_PATH, "/") + "/capture");
  550. } catch(Exception e){
  551. log.error("计算大场景失败"+projectNum);
  552. sceneService.updateStatus(projectNum, -1);
  553. if (sceneFileBuildEntity != null){
  554. sceneFileBuildEntity.setBuildStatus(-1);
  555. sceneFileBuildService.updateById(sceneFileBuildEntity);
  556. }
  557. e.printStackTrace();
  558. StringWriter trace=new StringWriter();
  559. e.printStackTrace(new PrintWriter(trace));
  560. log.error(trace.toString());
  561. handFail("计算失败",message);
  562. }finally {
  563. try{
  564. scene = sceneProService.findBySceneNum(projectNum);
  565. if(scene != null){
  566. com.alibaba.fastjson.JSONObject statusJson = new com.alibaba.fastjson.JSONObject();
  567. //临时将-2改成1,app还没完全更新
  568. int status = sceneProExt.getSceneStatus();
  569. if(status == -2){
  570. status = 1;
  571. }else if(status == -1){
  572. // 失败状态不予显示到客户端
  573. status = 0;
  574. }
  575. statusJson.put("status", status);
  576. statusJson.put("webSite", scene.getWebSite());
  577. statusJson.put("sceneNum", scene.getSceneCode());
  578. statusJson.put("thumb", scene.getThumb());
  579. statusJson.put("payStatus", sceneProExt.getPayStatus());
  580. FileUtils.writeFile(ConstantFilePath.SCENE_PATH+"data/data"+projectNum+File.separator+"status.json", statusJson.toString());
  581. uploadToOssUtil.upload(ConstantFilePath.SCENE_PATH+"data/data"+projectNum+File.separator+"status.json",
  582. "data/data"+projectNum+File.separator+"status.json");
  583. //上送日志
  584. uploadToOssUtil.upload(sceneProExt.getDataSource()+File.separator+"console.log",
  585. "build_log/"+scene.getSceneCode()+File.separator+"console.log");
  586. }
  587. }catch (Exception e){
  588. e.printStackTrace();
  589. }
  590. }
  591. }
  592. private void handFail(String reason,BuildSceneMqMessage message){
  593. String serverPath = message.getPath().substring(0,message.getPath().lastIndexOf("/")+1).concat(message.getPrefix());
  594. handFail(reason,serverPath,message.getSceneNum());
  595. }
  596. private void handFail(String reason,String serverPath,String num){
  597. // 释放缓存锁
  598. redisTemplate.delete(RedisKey.SCENE_BUILDING + num);
  599. CompletableFuture.runAsync(() -> {
  600. try {
  601. DingDingUtils.sendMsgToDingRobot(reason,serverPath,num);
  602. } catch (ApiException | UnsupportedEncodingException | NoSuchAlgorithmException | InvalidKeyException apiException) {
  603. apiException.printStackTrace();
  604. }
  605. });
  606. }
  607. }