SceneFileBuildServiceImpl.java 55 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196
  1. package com.fdkankan.contro.service.impl;
  2. import cn.hutool.core.bean.BeanUtil;
  3. import cn.hutool.core.collection.CollUtil;
  4. import cn.hutool.core.date.DateUtil;
  5. import cn.hutool.core.io.FileUtil;
  6. import cn.hutool.core.thread.ThreadUtil;
  7. import cn.hutool.core.util.StrUtil;
  8. import cn.hutool.core.util.ZipUtil;
  9. import cn.hutool.http.HttpUtil;
  10. import com.alibaba.fastjson.JSON;
  11. import com.alibaba.fastjson.JSONObject;
  12. import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
  13. import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
  14. import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
  15. import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
  16. import com.fdkankan.common.constant.*;
  17. import com.fdkankan.common.exception.BusinessException;
  18. import com.fdkankan.common.util.DateExtUtil;
  19. import com.fdkankan.common.util.FileMd5Util;
  20. import com.fdkankan.common.util.FileUtils;
  21. import com.fdkankan.common.util.SnowflakeIdGenerator;
  22. import com.fdkankan.contro.bean.SendCallAlgorithmDetail;
  23. import com.fdkankan.contro.common.Result;
  24. import com.fdkankan.contro.constant.RedisConstants;
  25. import com.fdkankan.contro.entity.*;
  26. import com.fdkankan.contro.mapper.ISceneFileBuildMapper;
  27. import com.fdkankan.contro.service.*;
  28. import com.fdkankan.contro.vo.ResponseSceneFile;
  29. import com.fdkankan.contro.vo.ScenePlusVO;
  30. import com.fdkankan.contro.vo.SendCallAlgorithmParam;
  31. import com.fdkankan.fyun.config.FYunFileConfig;
  32. import com.fdkankan.fyun.face.FYunFileServiceInterface;
  33. import com.fdkankan.fyun.local.constant.LocalConstants;
  34. import com.fdkankan.model.constants.ConstantFilePath;
  35. import com.fdkankan.model.constants.UploadFilePath;
  36. import com.fdkankan.rabbitmq.bean.BuildSceneCallMessage;
  37. import com.fdkankan.rabbitmq.util.RabbitMqProducer;
  38. import com.fdkankan.redis.util.RedisLockUtil;
  39. import com.fdkankan.redis.util.RedisUtil;
  40. import com.fdkankan.web.response.ResultData;
  41. import com.fdkankan.web.util.RSAEncrypt;
  42. import lombok.extern.slf4j.Slf4j;
  43. import net.lingala.zip4j.core.ZipFile;
  44. import org.apache.commons.codec.binary.Base64;
  45. import org.apache.commons.lang3.StringUtils;
  46. import org.springframework.beans.factory.annotation.Autowired;
  47. import org.springframework.beans.factory.annotation.Value;
  48. import org.springframework.stereotype.Service;
  49. import org.springframework.util.ObjectUtils;
  50. import org.springframework.web.multipart.MultipartFile;
  51. import java.io.File;
  52. import java.io.IOException;
  53. import java.nio.charset.StandardCharsets;
  54. import java.util.*;
  55. import java.util.concurrent.CompletableFuture;
  56. import java.util.concurrent.ExecutorService;
  57. /**
  58. * <p>
  59. * 场景文件建模表 服务实现类
  60. * </p>
  61. *
  62. * @author dengsixing
  63. * @since 2021-12-23
  64. */
  65. @Slf4j
  66. @Service
  67. public class SceneFileBuildServiceImpl extends ServiceImpl<ISceneFileBuildMapper, SceneFileBuild> implements ISceneFileBuildService {
  68. private static final String SPLICE = "#";
  69. private static final String sendCallAlgorithmPath = "/mnt/sendCallAlgorithm/";
  70. private static final String zipPassword = "a3ad34136de359536af553f9e7f3cefd";
  71. @Value("${main.url}")
  72. private String mainUrl;
  73. @Value("${fyun.type}")
  74. private String fyunType;
  75. @Value("${scene.pro.new.url}")
  76. private String sceneProNewUrl;
  77. @Value("${queue.modeling.modeling-pre}")
  78. private String queueModelingPre;
  79. @Autowired
  80. private RedisUtil redisUtil;
  81. @Autowired
  82. private IScenePlusExtService scenePlusExtService;
  83. @Autowired
  84. private IScene3dNumService scene3dNumService;
  85. @Autowired
  86. private IScenePlusService scenePlusService;
  87. @Autowired
  88. private RabbitMqProducer rabbitMqProducer;
  89. @Autowired
  90. private ISceneEditInfoService sceneEditInfoService;
  91. @Autowired
  92. private ISceneEditControlsService sceneEditControlsService;
  93. @Autowired
  94. private ISceneEditInfoExtService sceneEditInfoExtService;
  95. @Autowired
  96. private ISceneCooperationService sceneCooperationService;
  97. @Autowired
  98. private ISceneResourceCameraService sceneResourceCameraService;
  99. @Autowired
  100. private ISceneResourceCooperationService sceneResourceCooperationService;
  101. @Autowired
  102. private ICameraService cameraService;
  103. @Autowired
  104. private ICameraDetailService cameraDetailService;
  105. @Autowired
  106. private IUserService userService;
  107. @Autowired
  108. private ISceneFileUploadService sceneFileUploadService;
  109. @Autowired
  110. private FYunFileServiceInterface fYunFileService;
  111. @Autowired
  112. private FYunFileConfig fYunFileConfig;
  113. @Autowired
  114. private RedisLockUtil redisLockUtil;
  115. @Autowired
  116. private IScenePreService scenePreService;
  117. @Autowired
  118. private ICompanyService companyService;
  119. @Override
  120. public SceneFileBuild findByFileId(String fileId) {
  121. List<SceneFileBuild> list = this.list(new LambdaQueryWrapper<SceneFileBuild>().eq(SceneFileBuild::getFileId, fileId)
  122. .orderByDesc(SceneFileBuild::getId));
  123. if(CollUtil.isEmpty(list)){
  124. return null;
  125. }
  126. return list.get(0);
  127. }
  128. @Override
  129. public ResponseSceneFile preUpload(String params) throws Exception {
  130. log.info("preUpload-params: "+params);
  131. if (StrUtil.isEmpty(params)){
  132. throw new BusinessException(ErrorCode.PARAM_REQUIRED);
  133. }
  134. params = params.replaceAll("%2B", "+");
  135. Base64 base64 = new Base64();
  136. String cipher = params;
  137. // 私钥解密过程
  138. byte[] res = RSAEncrypt.decrypt(RSAEncrypt.loadPrivateKeyByStr(RSAEncrypt.loadPrivateKeyByFile()),
  139. base64.decode(cipher));
  140. String restr = new String(res, "UTF-8");
  141. log.debug("preUpload-params解密结果:" + restr);
  142. String[] strArr = restr.split(SPLICE);
  143. if (strArr.length != 5) {
  144. throw new BusinessException(ErrorCode.PARAM_REQUIRED);
  145. }
  146. String mac = strArr[0];
  147. String totalPicNum = strArr[1];
  148. String chunks = strArr[2];
  149. String folderName = strArr[3];
  150. if (StrUtil.isEmpty(mac)){
  151. throw new BusinessException(ErrorCode.FAILURE_CODE_5044);
  152. }
  153. if (totalPicNum == null){
  154. throw new BusinessException(ErrorCode.FAILURE_CODE_5045);
  155. }
  156. if (chunks == null){
  157. throw new BusinessException(ErrorCode.FAILURE_CODE_5046);
  158. }
  159. if (folderName == null){
  160. throw new BusinessException(ErrorCode.FAILURE_CODE_5047);
  161. }
  162. log.info("mac:{} 准备上传文件,folderName:{}", mac, folderName);
  163. ResponseSceneFile responseSceneFile = new ResponseSceneFile();
  164. // 检测是否有生成
  165. String fileId = redisUtil.get(String.format(RedisConstants.FOLDER_FILEID_BUILD, folderName));
  166. if (!ObjectUtils.isEmpty(fileId)) {
  167. responseSceneFile.setFileId(fileId);
  168. return responseSceneFile;
  169. }
  170. SceneFileBuild sceneFileBuild = this.findByUnicode(folderName);
  171. if (sceneFileBuild != null) {
  172. fileId = sceneFileBuild.getFileId();
  173. responseSceneFile.setFileId(fileId);
  174. redisUtil.set(String.format(RedisConstants.FOLDER_FILEID_BUILD, folderName), fileId, 2 * 24 * 60 * 60);
  175. return responseSceneFile;
  176. }
  177. // 加锁
  178. long incr = redisUtil.incr(String.format(RedisConstants.FOLDER_LOCK_BUILD, folderName), 1);
  179. if (incr > 1) {
  180. throw new BusinessException(ErrorCode.FAILURE_CODE_5052);
  181. }
  182. redisUtil.expire(String.format(RedisConstants.FOLDER_LOCK_BUILD, folderName), 120);
  183. log.info("开始新生成build数据");
  184. fileId = new SnowflakeIdGenerator(0, 0).nextId() + "";
  185. log.info("新生成build数据,{}", fileId);
  186. sceneFileBuild = new SceneFileBuild();
  187. sceneFileBuild.setChildName(mac);
  188. sceneFileBuild.setFileId(fileId);
  189. sceneFileBuild.setUnicode(folderName);
  190. sceneFileBuild.setTotalPicNum(Integer.valueOf(totalPicNum));
  191. sceneFileBuild.setChunks(Integer.valueOf(chunks));
  192. this.save(sceneFileBuild);
  193. redisUtil.set(String.format(RedisConstants.FOLDER_FILEID_BUILD, folderName), fileId, 2 * 24 * 60 * 60);
  194. redisUtil.set(String.format(RedisConstants.FILEID_FOLDER_BUILD, fileId), folderName, 2 * 24 * 60 * 60);
  195. responseSceneFile.setFileId(fileId);
  196. return responseSceneFile;
  197. }
  198. public SceneFileBuild findByUnicode(String unicode) {
  199. List<SceneFileBuild> list = this.list(new QueryWrapper<SceneFileBuild>()
  200. .eq("unicode", unicode)
  201. .orderByDesc("id"));
  202. if(CollUtil.isEmpty(list))
  203. return null;
  204. return list.get(0);
  205. }
  206. public ScenePlusVO buildScene(String fileId, String prefix,JSONObject jsonObject,String buildType,long cameraType) throws Exception{
  207. //调用createScene方法生成scene数据和加入算法队列
  208. String sceneNum = "";
  209. String cameraName = jsonObject.getJSONObject("cam").getString("uuid");
  210. String unicode = jsonObject.getString("creator") + "_" + jsonObject.getString("uuidtime");
  211. Camera camera = cameraService.getByChildName(cameraName);
  212. if (camera == null) {
  213. throw new BusinessException(CameraConstant.FAILURE_6003);
  214. }
  215. CameraDetail cameraDetail = cameraDetailService.getByCameraId(camera.getId());
  216. if (cameraDetail == null) {
  217. log.error("该相机详情不存在:" + cameraName);
  218. throw new BusinessException(CameraConstant.FAILURE_6003);
  219. }
  220. //查看场景中的文件目录是否有改文件id,有则重新计算改场景,无则新建场景
  221. ScenePlus scenePlus = scenePlusService.getByFileId("/" + fileId + "/");
  222. int rebuild = 1;
  223. if (ObjectUtils.isEmpty(scenePlus)) {
  224. sceneNum = scene3dNumService.generateSceneNum(cameraDetail.getType());
  225. rebuild = 0;
  226. } else {
  227. sceneNum = scenePlus.getNum();
  228. if (scenePlus.getSceneStatus().equals(SceneStatus.wait.code())) {
  229. log.info(scenePlus.getNum() + ":场景处于计算中,不能再计算");
  230. return null;
  231. }
  232. }
  233. if (sceneNum == null) {
  234. log.error("大场景序号为空:" + sceneNum);
  235. throw new BusinessException(ErrorCode.FAILURE_CODE_5005);
  236. }
  237. String dataSource = cameraName.replace("4DKKPRO_", "").replace("-fdage", "").toLowerCase() + File.separator +
  238. fileId + File.separator + unicode;
  239. if (cameraType == 14) {
  240. dataSource = ConstantFilePath.BUILD_MODEL_LASER_PATH +dataSource;
  241. } else {
  242. dataSource = ConstantFilePath.BUILD_MODEL_PATH + dataSource;
  243. }
  244. String localDataPath = String.format(ConstantFilePath.DATABUFFER_FORMAT, sceneNum);
  245. String imgViewPath = String.format(UploadFilePath.IMG_VIEW_PATH, sceneNum);
  246. String dataViewPath = String.format(UploadFilePath.DATA_VIEW_PATH, sceneNum);
  247. String userName = null;
  248. if (!ObjectUtils.isEmpty(cameraDetail.getUserId())) {
  249. SSOUser user = userService.getSSOUserByUserId(cameraDetail.getUserId());
  250. userName = ObjectUtils.isEmpty(user) ? null : user.getUserName();
  251. }
  252. String icon = null;
  253. if (!ObjectUtils.isEmpty(jsonObject.getString("icon"))) {
  254. fYunFileService.copyFileInBucket(ConstantFilePath.OSS_PREFIX + prefix + jsonObject.getString("icon"),imgViewPath + jsonObject.getString("icon"));
  255. icon = fYunFileConfig.getHost() + imgViewPath + jsonObject.getString("icon");
  256. log.info("上传icon成功....");
  257. }
  258. JSONObject firmwareVersion = new JSONObject();
  259. if (!ObjectUtils.isEmpty(jsonObject.getString("camSoftwareVersion"))) {
  260. firmwareVersion.put("camSoftwareVersion", jsonObject.getString("camSoftwareVersion"));
  261. }
  262. if (!ObjectUtils.isEmpty(jsonObject.getString("version"))) {
  263. firmwareVersion.put("version", jsonObject.getString("version"));
  264. }
  265. String sceneUrl = "/" + sceneProNewUrl;
  266. //重算的场景,先移除该场景对应的容量
  267. if (rebuild == 1) {
  268. scenePlusService.resetSpace(sceneNum);
  269. //删除oss的houst_floor.json(国际版可能会卡住)
  270. fYunFileService.deleteFile(dataViewPath + "houst_floor.json");
  271. } else {
  272. //上传log-main.png
  273. fYunFileService.uploadFile(ConstantFilePath.LOGO_PATH + "logo-main.png", imgViewPath + "logo-main.png");
  274. fYunFileService.uploadFile(ConstantFilePath.LOGO_PATH + "logo-main-en.png", imgViewPath + "logo-main-en.png");
  275. }
  276. String algorithm = jsonObject.getString("location") != null && "1".equals(jsonObject.getString("location")) ? "sfm" : "slam";
  277. ScenePlusVO scenePlusVO = this.createScenePlus(sceneNum, camera.getId(), camera.getChildName(), jsonObject.getString("creator"),
  278. jsonObject.getString("pwd"), unicode,cameraType, dataSource, icon, cameraDetail.getUserId(), userName,algorithm,
  279. jsonObject.getJSONArray("points").size(), jsonObject.getString("name"), jsonObject.getString("info"),
  280. jsonObject.getInteger("scenetype"), jsonObject.getString("gps"), rebuild,
  281. jsonObject.getInteger("resolution"), firmwareVersion.toString(), sceneUrl, buildType, cameraDetail.getCooperationUser());
  282. if (Objects.nonNull(scenePlusVO)) {
  283. JSONObject statusJson = new JSONObject();
  284. //临时将-2改成1,app还没完全更新
  285. statusJson.put("status", scenePlusVO.getSceneStatus() == -2 ? 1 : scenePlusVO.getSceneStatus());
  286. statusJson.put("webSite", scenePlusVO.getWebSite());
  287. statusJson.put("sceneNum", scenePlusVO.getNum());
  288. statusJson.put("thumb", scenePlusVO.getThumb());
  289. statusJson.put("payStatus", 0);
  290. statusJson.put("recStatus", 'A');
  291. FileUtils.writeFile(localDataPath + "status.json", statusJson.toString());
  292. fYunFileService.uploadFile(localDataPath + "status.json", dataViewPath + "status.json");
  293. }
  294. BuildSceneCallMessage mqMessage = getBuildSceneMqMessage(sceneNum, cameraType, algorithm, jsonObject.getInteger("resolution"), buildType,
  295. scenePlusVO.getDataSource());
  296. rabbitMqProducer.sendByWorkQueue(queueModelingPre, mqMessage);
  297. return scenePlusVO;
  298. }
  299. @Override
  300. public ResultData uploadSuccessBuild(String params) throws Exception {
  301. log.info("uploadSuccessBuild-params: " + params);
  302. if (StringUtils.isEmpty(params)) {
  303. throw new BusinessException(ErrorCode.PARAM_REQUIRED);
  304. }
  305. params = params.replaceAll("%2B", "+");
  306. params = params.replaceAll(" ", "+");
  307. Base64 base64 = new Base64();
  308. String cipher = params;
  309. // 私钥解密过程
  310. byte[] res = RSAEncrypt.decrypt(RSAEncrypt.loadPrivateKeyByStr(RSAEncrypt.loadPrivateKeyByFile()), base64.decode(cipher));
  311. String restr = new String(res, "UTF-8");
  312. log.info("uploadSuccessBuild-params解密结果:" + restr);
  313. String[] strArr = restr.split(SPLICE);
  314. if (strArr.length != 3) {
  315. throw new BusinessException(ErrorCode.PARAM_REQUIRED);
  316. }
  317. String mac = strArr[0];
  318. String fileId = strArr[1];
  319. String folderName = redisUtil.get(String.format(RedisConstants.FILEID_FOLDER_BUILD, fileId));
  320. if(StringUtils.isEmpty(folderName)){
  321. SceneFileBuild fileBuild = findByFileId(fileId);
  322. if(ObjectUtils.isEmpty(fileBuild)){
  323. throw new BusinessException(ErrorCode.FAILURE_CODE_5012);
  324. }
  325. folderName = fileBuild.getUnicode();
  326. redisUtil.set(String.format(RedisConstants.FILEID_FOLDER_BUILD, fileId), folderName,2 * 24 * 60 * 60);
  327. }
  328. StringBuilder prefixBuffer = new StringBuilder(mac).append(File.separator).append(fileId).append(File.separator).append(folderName).append(File.separator);
  329. String buildType = "V2";
  330. Long cameraType = 10L;
  331. JSONObject fdageJson = JSONObject.parseObject(fYunFileService.getFileContent(ConstantFilePath.OSS_PREFIX + prefixBuffer + "data.fdage"));
  332. if(ObjectUtils.isEmpty(fdageJson)){
  333. log.info("data.fdage文件不存在");
  334. throw new BusinessException(CameraConstant.FAILURE_6009);
  335. }
  336. //根据videoVersion判断是V2还是V3版本的算法和页面
  337. if (fdageJson.containsKey("videoVersion") && StrUtil.isNotEmpty(fdageJson.getString("videoVersion"))) {
  338. if (fdageJson.getIntValue("videoVersion") >= 4) {
  339. buildType = "V3";
  340. cameraType = 11L;
  341. }
  342. }
  343. buildScene(fileId, prefixBuffer.toString(),fdageJson,buildType,cameraType);
  344. return ResultData.ok();
  345. }
  346. @Override
  347. public ResultData turntableUploadSuccess(String params) throws Exception {
  348. log.info("turntableUploadSuccess-params: " + params);
  349. if (StringUtils.isEmpty(params)) {
  350. throw new BusinessException(ErrorCode.PARAM_REQUIRED);
  351. }
  352. params = params.replaceAll("%2B", "+");
  353. params = params.replaceAll(" ", "+");
  354. Base64 base64 = new Base64();
  355. String cipher = params;
  356. // 私钥解密过程
  357. byte[] res = RSAEncrypt.decrypt(RSAEncrypt.loadPrivateKeyByStr(RSAEncrypt.loadPrivateKeyByFile()),
  358. base64.decode(cipher));
  359. String restr = new String(res, "UTF-8");
  360. log.info("turntableUploadSuccess-params:解密结果:" + restr);
  361. String[] strArr = restr.split(SPLICE);
  362. if (strArr.length != 3) {
  363. throw new BusinessException(ErrorCode.PARAM_REQUIRED);
  364. }
  365. String mac = strArr[0];
  366. String fileId = strArr[1];
  367. String folderName = redisUtil.get(String.format(RedisConstants.FILEID_FOLDER_BUILD, fileId));
  368. if(StringUtils.isEmpty(folderName)){
  369. SceneFileBuild fileBuild = findByFileId(fileId);
  370. if(ObjectUtils.isEmpty(fileBuild)){
  371. throw new BusinessException(ErrorCode.FAILURE_CODE_5012);
  372. }
  373. folderName = fileBuild.getUnicode();
  374. redisUtil.set(String.format(RedisConstants.FILEID_FOLDER_BUILD, fileId), folderName);
  375. }
  376. //云目录
  377. StringBuilder prefixBuffer = new StringBuilder(mac).append(File.separator).append(fileId).append(File.separator).append(folderName).append(File.separator);
  378. JSONObject fdageJson = JSONObject.parseObject(fYunFileService.getFileContent(ConstantFilePath.OSS_PREFIX + prefixBuffer + "data.fdage"));
  379. if(ObjectUtils.isEmpty(fdageJson)){
  380. log.info("data.fdage文件不存在");
  381. throw new BusinessException(CameraConstant.FAILURE_6009);
  382. }
  383. String buildType = "V3";
  384. //13表示转台
  385. Long cameraType = 13L;
  386. //激光转台 八目相机占用 10 和 11
  387. if(fdageJson.getJSONObject("cam").getIntValue("type") == 10){
  388. //激光转台
  389. cameraType = 14L;
  390. }
  391. buildScene(fileId, prefixBuffer.toString(), fdageJson, buildType, cameraType);
  392. return ResultData.ok();
  393. }
  394. public ScenePlusVO createScenePlus(String projectNum, Long cameraId, String cameraName, String phoneId, String sceneKey,
  395. String unicode, Long cameraType, String dataSource, String pic, Long userId, String userName,
  396. String algorithm, Integer sceneShootCount, String sceneName,
  397. String sceneDec, Integer sceneType, String gps,Integer type,
  398. Integer resolution, String firmwareVersion, String url, String buildType,
  399. Long cooperationUser)throws Exception{
  400. ScenePlusVO scenePlusVO = new ScenePlusVO();
  401. ScenePlus scenePlus = new ScenePlus();
  402. ScenePlusExt scenePlusExt = new ScenePlusExt();
  403. scenePlusExt.setWebSite(url+projectNum);
  404. scenePlus.setCameraId(cameraId);
  405. scenePlus.setPhoneId(phoneId);
  406. scenePlus.setNum(projectNum);
  407. scenePlus.setSceneSource(1);
  408. scenePlusExt.setDataSource(dataSource);
  409. if(resolution == null || resolution.intValue() == 0){
  410. scenePlusExt.setSceneScheme(cameraType.intValue());
  411. }else {
  412. scenePlusExt.setSceneScheme(4);
  413. }
  414. //转台相机用4k图
  415. if(cameraType.longValue() == 13 ){
  416. scenePlus.setSceneSource(3);
  417. scenePlusExt.setSceneScheme(10);
  418. }
  419. if (pic != null && pic.length() > 5) {
  420. scenePlusExt.setThumb(pic);
  421. } else {
  422. scenePlusExt.setThumb(ConstantUrl.DEFAULT_SCENE_PIC);
  423. }
  424. scenePlusExt.setThumb(scenePlusExt.getThumb().concat("?t=") + System.currentTimeMillis());
  425. scenePlus.setUserId(userId);
  426. if (sceneShootCount == null) {
  427. scenePlusExt.setShootCount(0);
  428. } else {
  429. scenePlusExt.setShootCount(sceneShootCount);
  430. }
  431. if (sceneName != null) {
  432. scenePlus.setTitle(sceneName);
  433. }
  434. if (sceneDec != null) {
  435. scenePlus.setDescription("<p>" + new String(sceneDec.getBytes("UTF-8")) + "</p>");
  436. }
  437. if (sceneType != null) {
  438. scenePlus.setSceneType(sceneType);
  439. }
  440. if (gps != null && !gps.trim().equals("")) {
  441. scenePlusExt.setGps(gps);
  442. }
  443. scenePlusExt.setAlgorithm(algorithm);
  444. if(!org.springframework.util.StringUtils.isEmpty(firmwareVersion)){
  445. scenePlusExt.setFirmwareVersion(firmwareVersion);
  446. }
  447. scenePlusExt.setBuildType(buildType);
  448. log.info("场景记录添加到数据库:"+projectNum);
  449. //type=0为新生成场景,其余为重新计算场景
  450. SceneEditInfo sceneEditInfo = new SceneEditInfo();
  451. SceneEditInfoExt sceneEditInfoExt = new SceneEditInfoExt();
  452. SceneEditControls sceneEditControls = new SceneEditControls();
  453. if(type == 0){
  454. scenePlus.setSceneStatus(SceneStatus.wait.code());
  455. scenePlusService.save(scenePlus);
  456. scenePlusExt.setPlusId(scenePlus.getId());
  457. scenePlusExtService.save(scenePlusExt);
  458. sceneEditInfo.setTitle(scenePlus.getTitle());
  459. sceneEditInfo.setDescription(scenePlus.getDescription());
  460. sceneEditInfo.setScenePlusId(scenePlus.getId());
  461. if(StrUtil.isNotBlank(sceneKey)) {
  462. sceneEditInfo.setScenePassword(sceneKey);
  463. sceneEditControls.setShowLock((int) CommonStatus.YES.code());
  464. }
  465. sceneEditInfoService.save(sceneEditInfo);
  466. sceneEditInfoExt.setScenePlusId(scenePlus.getId());
  467. sceneEditInfoExt.setEditInfoId(sceneEditInfo.getId());
  468. sceneEditInfoExtService.save(sceneEditInfoExt);
  469. sceneEditControls.setEditInfoId(sceneEditInfo.getId());
  470. sceneEditControlsService.save(sceneEditControls);
  471. //新增场景时,同时新增场景协作信息
  472. if(cooperationUser != null){
  473. SceneCooperation sceneCooperationEntity = new SceneCooperation();
  474. sceneCooperationEntity.setNum(projectNum);
  475. sceneCooperationEntity.setUserId(cooperationUser);
  476. sceneCooperationService.save(sceneCooperationEntity);
  477. List<SceneResourceCamera> resourceCameraList = sceneResourceCameraService.findListByCameraId(cameraId);
  478. SceneResourceCooperation sceneResourceCooperation = null;
  479. if(resourceCameraList != null && resourceCameraList.size() > 0){
  480. for (SceneResourceCamera sceneResourceCamera : resourceCameraList) {
  481. sceneResourceCooperation = new SceneResourceCooperation();
  482. sceneResourceCooperation.setSceneResourceId(sceneResourceCamera.getSceneResourceId());
  483. sceneResourceCooperation.setSceneCooperationId(sceneCooperationEntity.getId());
  484. sceneResourceCooperationService.save(sceneResourceCooperation);
  485. }
  486. }
  487. }
  488. }else {
  489. ScenePlus oldScene = scenePlusService.getScenePlusByNum(projectNum);
  490. scenePlus.setId(oldScene.getId());
  491. scenePlus.setSceneStatus(0);
  492. scenePlus.setRecStatus(RecStatus.VALID.code());
  493. scenePlus.setPayStatus(0);
  494. scenePlus.setCreateTime(Calendar.getInstance().getTime());
  495. ScenePlusExt oldSceneExt = scenePlusExtService.getScenePlusExtByPlusId(oldScene.getId());
  496. scenePlusExt.setSpace(oldSceneExt.getSpace());
  497. scenePlusExt.setEcs(oldSceneExt.getEcs());
  498. scenePlusExt.setViewCount(oldSceneExt.getViewCount());
  499. if(sceneName!=null) {
  500. scenePlus.setTitle(sceneName);
  501. }
  502. if(sceneType!=null) {
  503. scenePlus.setSceneType(sceneType);
  504. }
  505. scenePlusService.updateById(scenePlus);
  506. scenePlusExtService.updateById(scenePlusExt);
  507. SceneEditInfo oldSceneEditInfo = sceneEditInfoService.getByScenePlusId(oldScene.getId());
  508. SceneEditInfoExt oldSceneEditeIinfoExt = sceneEditInfoExtService.getByEditInfoId(oldSceneEditInfo.getId());
  509. if(StrUtil.isNotBlank(sceneKey)) {
  510. sceneEditInfo.setScenePassword(sceneKey);
  511. sceneEditControls.setShowLock((int) CommonStatus.YES.code());
  512. }else{
  513. sceneEditInfo.setScenePassword("");
  514. sceneEditControls.setShowLock((int)CommonStatus.NO.code());
  515. }
  516. sceneEditInfo.setTitle(scenePlus.getTitle());
  517. sceneEditInfo.setDescription(scenePlus.getDescription());
  518. sceneEditInfo.setId(oldSceneEditInfo.getId());
  519. sceneEditInfo.setScenePlusId(scenePlus.getId());
  520. sceneEditInfo.setFloorLogoSize(100);
  521. sceneEditInfo.setRecStatus(RecStatus.VALID.code());
  522. sceneEditInfo.setFloorPublishVer(oldSceneEditInfo.getFloorEditVer() + 1);
  523. sceneEditInfo.setFloorEditVer(oldSceneEditInfo.getFloorEditVer() + 1);
  524. sceneEditInfo.setVersion(oldSceneEditInfo.getVersion() + 1);
  525. sceneEditInfoService.updateById(sceneEditInfo);
  526. if(Objects.nonNull(oldSceneEditeIinfoExt)){
  527. sceneEditInfoExt.setId(oldSceneEditeIinfoExt.getId());
  528. sceneEditInfoExt.setEditInfoId(sceneEditInfo.getId());
  529. sceneEditInfoExt.setScenePlusId(scenePlus.getId());
  530. sceneEditInfoExtService.updateById(sceneEditInfoExt);
  531. }
  532. }
  533. BeanUtil.copyProperties(scenePlusExt, scenePlusVO);
  534. BeanUtil.copyProperties(scenePlus, scenePlusVO);
  535. return scenePlusVO;
  536. }
  537. public BuildSceneCallMessage getBuildSceneMqMessage(String projectNum,
  538. Long cameraType, String algorithm, Integer resolution,
  539. String buildType, String dataSource) {
  540. BuildSceneCallMessage mqMsg = new BuildSceneCallMessage();
  541. mqMsg.setSceneNum(projectNum);
  542. mqMsg.setCameraType(String.valueOf(cameraType));
  543. mqMsg.setAlgorithm(algorithm);
  544. mqMsg.setResolution(String.valueOf(resolution));
  545. mqMsg.setBuildType(buildType);
  546. mqMsg.setPath(dataSource);
  547. mqMsg.setCreateTime(DateUtil.format(Calendar.getInstance().getTime(), DateExtUtil.dateStyle));
  548. mqMsg.setExt(new HashMap<>());
  549. return mqMsg;
  550. }
  551. @Override
  552. public ResultData rebuildScene(String num,Boolean force) throws IOException {
  553. ScenePlus scenePlus = scenePlusService.getScenePlusByNum(num);
  554. if(Objects.isNull(scenePlus)){
  555. throw new BusinessException(ErrorCode.FAILURE_CODE_5005);
  556. }
  557. if (scenePlus.getSceneStatus() == 0 && (ObjectUtils.isEmpty(force) || !force)) {
  558. throw new BusinessException(ErrorCode.FAILURE_CODE_5033);
  559. }
  560. ScenePlusExt scenePlusExt = scenePlusExtService.getScenePlusExtByPlusId(scenePlus.getId());
  561. String path = scenePlusExt.getDataSource();
  562. Integer sceneSource = scenePlus.getSceneSource();
  563. String buildType = scenePlusExt.getBuildType();
  564. Integer sceneScheme = scenePlusExt.getSceneScheme();
  565. //重新计算时需要删除文件夹,否知使用缓存
  566. FileUtils.delAllFile(path + File.separator + "results");
  567. String dataFdageOssPath = ConstantFilePath.OSS_PREFIX+ path.replace(ConstantFilePath.BUILD_MODEL_PATH, "")
  568. .replace(ConstantFilePath.BUILD_MODEL_LASER_PATH, "") + "/data.fdage";
  569. JSONObject fdageData = JSONObject.parseObject(fYunFileService.getFileContent(dataFdageOssPath));
  570. if(ObjectUtils.isEmpty(fdageData)){
  571. log.error("data.fdage文件不存在");
  572. return ResultData.error(CameraConstant.FAILURE_6009.code(), CameraConstant.FAILURE_6009.message());
  573. }
  574. //重算的场景,先移除该场景对应的容量
  575. scenePlusService.resetSpace(num);
  576. String statusJsonOssPath = String.format(UploadFilePath.DATA_VIEW_PATH, num) + "status.json";
  577. JSONObject statusJson = JSONObject.parseObject(fYunFileService.getFileContent(String.format(UploadFilePath.DATA_VIEW_PATH, num) + "status.json"));
  578. //临时将-2改成1,app还没完全更新
  579. statusJson.put("status", SceneStatus.wait.code());
  580. fYunFileService.uploadFile(statusJson.toJSONString().getBytes(StandardCharsets.UTF_8),statusJsonOssPath);
  581. Long cameraType = (long)sceneScheme == 3 ? 12 : (long)sceneScheme;
  582. //判断是否转台相机
  583. if(sceneSource == 3){
  584. cameraType = 13L;
  585. }
  586. if(sceneSource == 4){
  587. cameraType = 14L;
  588. }
  589. if(sceneSource == 4){
  590. BuildSceneCallMessage buildSceneMqMessage = this.getBuildSceneMqMessage(
  591. num, cameraType,
  592. fdageData.getString("location") != null && "1".equals(fdageData.getString("location")) ? "sfm" : "slam",
  593. fdageData.getInteger("resolution"), buildType, path);
  594. rabbitMqProducer.sendByWorkQueue(queueModelingPre, buildSceneMqMessage);
  595. }else{
  596. BuildSceneCallMessage buildSceneMqMessage = this.getBuildSceneMqMessage(
  597. num, cameraType, fdageData.getString("location") != null && "1".equals(fdageData.getString("location")) ? "sfm" : "slam",
  598. fdageData.getInteger("resolution"), buildType,
  599. path);
  600. rabbitMqProducer.sendByWorkQueue(queueModelingPre, buildSceneMqMessage);
  601. }
  602. scenePlusService.update(new LambdaUpdateWrapper<ScenePlus>()
  603. .set(ScenePlus::getSceneStatus, SceneStatus.wait.code())
  604. .eq(ScenePlus::getNum, num));
  605. return ResultData.ok();
  606. }
  607. @Override
  608. public ResultData uploadFile(MultipartFile file, String params) throws Exception {
  609. log.info("upload-params: "+params);
  610. if (StringUtils.isEmpty(params)){
  611. throw new BusinessException(ErrorCode.PARAM_REQUIRED);
  612. }
  613. params = params.replaceAll("%2B", "+");
  614. Base64 base64 = new Base64();
  615. String cipher = params;
  616. // 私钥解密过程
  617. byte[] res = RSAEncrypt.decrypt(RSAEncrypt.loadPrivateKeyByStr(RSAEncrypt.loadPrivateKeyByFile()),
  618. base64.decode(cipher));
  619. String restr = new String(res, "UTF-8");
  620. log.info("upload-params解密结果:" + restr);
  621. String[] strArr = restr.split(SPLICE);
  622. if (strArr.length != 6) {
  623. throw new BusinessException(ErrorCode.PARAM_REQUIRED);
  624. }
  625. String mac = strArr[0];
  626. String fileId = strArr[1];
  627. String picNum = strArr[2];
  628. String md5 = strArr[3];
  629. String chunk = strArr[4];
  630. log.info("mac:{},fileId:{},picNum:{},md5:{},chunk:{}", mac, fileId, picNum, md5, chunk);
  631. ResultData result = null;
  632. if (file.isEmpty()){
  633. log.error("文件为空。");
  634. throw new BusinessException(ErrorCode.PARAM_REQUIRED.code(),"文件为空。");
  635. }
  636. if (StringUtils.isEmpty(fileId)){
  637. log.error("文件Id为空。");
  638. throw new BusinessException(ErrorCode.PARAM_REQUIRED.code(),"文件Id为空。");
  639. }
  640. if (picNum == null){
  641. log.error("照片数目为空。");
  642. throw new BusinessException(ErrorCode.PARAM_REQUIRED.code(),"照片数目为空。");
  643. }
  644. if (StringUtils.isEmpty(mac)){
  645. log.error("mac为空。");
  646. throw new BusinessException(ErrorCode.PARAM_REQUIRED.code(),"mac为空。");
  647. }
  648. if (StringUtils.isEmpty(md5)){
  649. log.error("md5为空。");
  650. throw new BusinessException(ErrorCode.PARAM_REQUIRED.code(),"md5为空。");
  651. }
  652. long size = file.getSize();
  653. log.info("mac:{}, fileId:{}, picNum:{}, md5:{}, chunk:{}", mac, fileId, picNum, md5, chunk);
  654. chunk = chunk.split(SPLICE)[0];
  655. // 获取文件名
  656. String fileName = file.getOriginalFilename();
  657. log.info("上传的文件名为:" + fileName);
  658. // 获取文件的后缀名
  659. String folderName = redisUtil.get(String.format(RedisConstants.FILEID_FOLDER_BUILD, fileId));
  660. if(StringUtils.isEmpty(folderName)){
  661. SceneFileBuild fileBuild = findByFileId(fileId);
  662. if(ObjectUtils.isEmpty(fileBuild)){
  663. log.error("数据不正常,fileBuild没找到");
  664. throw new BusinessException(ErrorCode.FAILURE_CODE_5012);
  665. }
  666. folderName = fileBuild.getUnicode();
  667. redisUtil.set(String.format(RedisConstants.FILEID_FOLDER_BUILD, fileId), folderName,2 * 24 * 60 * 60);
  668. }
  669. // 1. 判断该文件是否已经上传过
  670. // 2. 如果已经上传过,判断MD5值和文件大小是否相等。如果相等,更新数据记录。如果不相等,删除该文件,重新上传。
  671. // 3. 如果未上传过,需要上传。
  672. String filePath = mac.concat(File.separator).concat(fileId).concat(File.separator).concat(folderName);
  673. String yunFilePath = LocalConstants.BASE_PATH.concat(fYunFileConfig.getBucket()).concat(File.separator).concat(ConstantFilePath.OSS_PREFIX)
  674. .concat(filePath).concat(File.separator).concat(fileName);
  675. log.info("yunFilePath:{}", yunFilePath);
  676. boolean needUpload = false;
  677. File yunFile = new File(yunFilePath);
  678. if (yunFile.exists()){
  679. String fileMD5 = FileMd5Util.getFileMD5(yunFile);
  680. if (md5.equals(fileMD5) && yunFile.length() == size){
  681. log.info("文件已存在,MD5和文件大小一致。");
  682. SceneFileUpload uploadEntity = sceneFileUploadService.findByFileIdAndChunk(fileId, Integer.valueOf(chunk));
  683. if (uploadEntity != null){
  684. uploadEntity.setSize((int) size);
  685. uploadEntity.setMd5(md5);
  686. uploadEntity.setFilePath(yunFilePath);
  687. uploadEntity.setFileSourceName(fileName);
  688. uploadEntity.setUploadStatus(1);
  689. sceneFileUploadService.updateById(uploadEntity);
  690. }else{
  691. SceneFileUpload sceneFileUploadEntity = new SceneFileUpload();
  692. sceneFileUploadEntity.setSize((int) size);
  693. sceneFileUploadEntity.setMd5(md5);
  694. sceneFileUploadEntity.setFilePath(yunFilePath.toString());
  695. sceneFileUploadEntity.setFileSourceName(fileName);
  696. sceneFileUploadEntity.setUploadStatus(1);
  697. sceneFileUploadEntity.setFileId(fileId);
  698. sceneFileUploadEntity.setChunk(Integer.valueOf(chunk));
  699. sceneFileUploadService.save(sceneFileUploadEntity);
  700. }
  701. result = ResultData.ok();
  702. }else if (!md5.equals(fileMD5)) {
  703. log.error("文件已上传,上传MD5:"+md5+",服务器MD5:"+fileMD5+"。不一致。上传失败");
  704. FileUtils.delFile(yunFilePath.toString());
  705. needUpload = true;
  706. }else if (yunFile.length() != size){
  707. log.error("文件已上传,文件大小不一致。上传失败");
  708. FileUtils.delFile(yunFilePath);
  709. needUpload = true;
  710. }
  711. }else {
  712. log.error("文件不存在,需要重新上传");
  713. needUpload = true;
  714. }
  715. // 4. 上传成功后,校验MD5和文件大小是否相等
  716. // 5. 如果相等,更新数据记录。如果不相等,返回上传失败结果。
  717. try {
  718. if (needUpload){
  719. fYunFileService.uploadFile(file.getInputStream(),ConstantFilePath.OSS_PREFIX.concat(filePath).concat(File.separator).concat(fileName));
  720. File uploadFile = new File(yunFilePath);
  721. String fileMD5 = FileMd5Util.getFileMD5(uploadFile);
  722. SceneFileUpload sceneFileUploadEntity = new SceneFileUpload();
  723. sceneFileUploadEntity.setSize((int) size);
  724. sceneFileUploadEntity.setMd5(md5);
  725. sceneFileUploadEntity.setFilePath(yunFilePath);
  726. sceneFileUploadEntity.setFileSourceName(fileName);
  727. sceneFileUploadEntity.setFileId(fileId);
  728. sceneFileUploadEntity.setChunk(Integer.valueOf(chunk));
  729. if (md5.equals(fileMD5) && uploadFile.length() == size){
  730. log.info("文件已上传,MD5和文件大小一致。上传成功");
  731. sceneFileUploadEntity.setUploadStatus(1);
  732. sceneFileUploadService.save(sceneFileUploadEntity);
  733. result = ResultData.ok();
  734. }else if (!md5.equals(fileMD5)) {
  735. log.error("文件已上传,上传MD5:"+md5+",服务器MD5:"+fileMD5+"。不一致。上传失败");
  736. sceneFileUploadEntity.setUploadStatus(-1);
  737. sceneFileUploadService.save(sceneFileUploadEntity);
  738. result = ResultData.error(ErrorCode.SYSTEM_ERROR,"上传失败, 请重新上传。");
  739. }else if (uploadFile.length() != size){
  740. log.error("文件已上传,文件大小不一致。上传失败");
  741. sceneFileUploadEntity.setUploadStatus(-1);
  742. sceneFileUploadService.save(sceneFileUploadEntity);
  743. result = ResultData.error(ErrorCode.SYSTEM_ERROR,"上传失败, 请重新上传。");
  744. }
  745. }
  746. }catch (IllegalStateException | IOException e) {
  747. log.error("上传失败, 请重新上传,md5:{},chunk:{}", md5, chunk);
  748. log.error("上传失败", e);
  749. result = ResultData.error(ErrorCode.SYSTEM_ERROR,"上传失败, 请重新上传。");
  750. }
  751. return result;
  752. }
  753. @Override
  754. public ResultData sendCallAlgorithm(SendCallAlgorithmParam param) throws Exception {
  755. log.info("sendCallAlgorithm 参数为:{}", JSONObject.toJSONString(param));
  756. String filePath = param.getFilepath();
  757. String details = param.getDetails()
  758. .replace("base64_urlsafe:","")
  759. .replaceAll("-","+")
  760. .replaceAll("_","/")
  761. .concat("==");
  762. try {
  763. details = cn.hutool.core.codec.Base64.decodeStr(details);
  764. }catch (Exception e){
  765. log.error("details解密报错,details:{}", details);
  766. log.error("details解密报错", e);
  767. return ResultData.error(ErrorCode.PARAM_FORMAT_ERROR);
  768. }
  769. SendCallAlgorithmDetail detail = JSON.parseObject(details, SendCallAlgorithmDetail.class);
  770. Integer fileChunkSum = detail.getFileChunkSum();
  771. String uuid = detail.getUuid();
  772. String snCode = uuid.split("_")[0];
  773. String parentPath = sendCallAlgorithmPath.concat(uuid);
  774. // if(FileUtil.exist(parentPath)){
  775. // FileUtil.del(parentPath);
  776. // }
  777. Camera camera = cameraService.getByChildName(snCode);
  778. if(Objects.isNull(camera)){
  779. throw new BusinessException(ErrorCode.CAMERA_BIND_NO_EXIST.code(), "相机未入库");
  780. }
  781. String localFilePath = parentPath.concat(File.separator).concat(uuid).concat(".zip");
  782. try {
  783. String extName = FileUtil.extName(filePath);
  784. String subFilePath = parentPath.concat(File.separator).concat(uuid).concat(".").concat(extName);
  785. FileUtil.mkParentDirs(localFilePath);
  786. HttpUtil.downloadFile(filePath, subFilePath);
  787. }catch (Exception e){
  788. throw new BusinessException(ErrorCode.FAILURE_CODE_5063.code(), "原始资源压缩包下载失败");
  789. }
  790. //检测压缩包分卷是否与detail中的总数一样
  791. List<String> fileNames = FileUtil.listFileNames(parentPath);
  792. if(fileNames.size() != fileChunkSum){
  793. return ResultData.ok("压缩包分卷不完整,请继续上传剩余的分卷");
  794. }
  795. if(!FileUtil.exist(localFilePath)){
  796. throw new BusinessException(ErrorCode.FAILURE_CODE_5063.code(), "zip压缩包不存在");
  797. }
  798. ScenePre scenePre = new ScenePre();
  799. scenePre.setZipPath(parentPath);
  800. scenePre.setCreateTime(new Date());
  801. scenePre.setUpdateTime(new Date());
  802. scenePre.setStatus(0);
  803. scenePreService.save(scenePre);
  804. // 异步解压资源文件上传
  805. ExecutorService executor = ThreadUtil.newSingleExecutor();
  806. try {
  807. CompletableFuture.runAsync(() -> {
  808. try {
  809. log.info("开始异步解压文件");
  810. ZipFile zipFile = new ZipFile(new File(localFilePath));
  811. if (zipFile.isEncrypted()) {
  812. zipFile.setPassword(zipPassword);
  813. zipFile.extractAll(parentPath);
  814. } else {
  815. ZipUtil.unzip(localFilePath, parentPath);
  816. }
  817. List<String> filePathList = FileUtils.list(new File(parentPath));
  818. String configJsonPath = null;
  819. for (String item : filePathList) {
  820. if(!item.contains("config.json")){
  821. continue;
  822. }
  823. configJsonPath = item;
  824. }
  825. String dataPath = FileUtil.getParent(configJsonPath, 1);
  826. // 读取本地文件并校验文件
  827. // 读取config.json
  828. log.info("config.json路径:{}", configJsonPath);
  829. if(!FileUtil.exist(configJsonPath)){
  830. throw new RuntimeException("config.json 文件有误!");
  831. }
  832. JSONObject configJson = JSONObject.parseObject(FileUtils.readFile(configJsonPath));
  833. String folderName = configJson.getString("id");
  834. String customUserId = configJson.getString("customUserId");
  835. if(StrUtil.isBlank(folderName) || StrUtil.isBlank(snCode)){
  836. throw new RuntimeException("config.json 文件有误!");
  837. }
  838. // 检测是否有生成
  839. String fileId = getFileIdByFolderName(folderName);
  840. String subFolder = snCode.concat(File.separator).concat(fileId).concat(File.separator).concat(folderName);
  841. // 解压获取dataSource 并上传资源到OSS
  842. String dataSource = ConstantFilePath.BUILD_MODEL_PATH.concat(subFolder);
  843. log.info("dataSource 为:{}", dataSource);
  844. scenePre.setFileId(fileId);
  845. scenePre.setStatus(1);
  846. scenePre.setUpdateTime(new Date());
  847. scenePreService.updateById(scenePre);
  848. log.info("异步开始上传文件");
  849. // 上传oaas
  850. fYunFileService.uploadFileByCommand(dataPath, ConstantFilePath.OSS_PREFIX.concat(subFolder));
  851. //删除本地压缩包,防止补拍上传文件不一致
  852. FileUtil.del(parentPath);
  853. scenePre.setOssPath(ConstantFilePath.OSS_PREFIX.concat(subFolder));
  854. scenePre.setStatus(2);
  855. scenePre.setUpdateTime(new Date());
  856. scenePreService.updateById(scenePre);
  857. log.info("文件上传成功,开始通知计算");
  858. // 通知计算
  859. this.copyDataAndBuild(null, dataSource, "V4", null, customUserId);
  860. log.info("通知计算成功");
  861. scenePre.setStatus(3);
  862. scenePre.setUpdateTime(new Date());
  863. scenePreService.updateById(scenePre);
  864. } catch (Exception e) {
  865. log.error("上传失败", e);
  866. scenePre.setStatus(CommonSuccessStatus.Fail.code());
  867. scenePreService.updateById(scenePre);
  868. }
  869. }, executor);
  870. }finally {
  871. executor.shutdown();
  872. }
  873. return ResultData.ok();
  874. }
  875. public static void main(String[] args) {
  876. String details = "{\"camType\":\"kj\",\"uploadType\":\"log\",\"uuid\":\"90d95cdb5_202211141023024060\",\"fileChunkSum\":4,\"fileChunkNum\":0}";
  877. String encode = cn.hutool.core.codec.Base64.encode(details);
  878. System.out.println(encode);
  879. String details2 = "base64_urlsafe:".concat(encode.replaceAll("\\+", "-").replaceAll("/", "_").replaceAll("=", ""));
  880. System.out.println(details2);
  881. String details3 = details2.replace("base64_urlsafe:","").replaceAll("-","+").replaceAll("_","/");//.concat("==");
  882. System.out.println(details3);
  883. String s = cn.hutool.core.codec.Base64.decodeStr(details3);
  884. System.out.println(s);
  885. }
  886. private String getFileIdByFolderName(String folderName) {
  887. // 检测是否有生成
  888. String fileId = redisUtil.get(String.format(RedisConstants.FOLDER_FILEID_BUILD, folderName));
  889. if (!org.springframework.util.ObjectUtils.isEmpty(fileId)) {
  890. return fileId;
  891. }
  892. SceneFileBuild sceneFileBuild = this.findByUnicode(folderName);
  893. if (sceneFileBuild != null) {
  894. fileId = sceneFileBuild.getFileId();
  895. redisUtil.set(String.format(RedisConstants.FOLDER_FILEID_BUILD, folderName), fileId, 2 * 24 * 60 * 60);
  896. return fileId;
  897. }
  898. // 加锁
  899. boolean lock = redisLockUtil.lock(String.format(RedisConstants.FOLDER_LOCK_BUILD, folderName), 120);
  900. if (!lock) {
  901. throw new BusinessException(ErrorCode.FAILURE_CODE_5052);
  902. }
  903. String dataSource = scenePlusService.getDataSourceLikeUnicode("/" + folderName);
  904. if (!org.springframework.util.ObjectUtils.isEmpty(dataSource)) {
  905. log.info("从数据库中查到与 fileId:{} 匹配的路径为:{}", fileId, dataSource);
  906. int n = dataSource.split("/").length;
  907. if (n > 1) {
  908. fileId = dataSource.split("/")[n - 2];
  909. }
  910. }
  911. if (org.springframework.util.ObjectUtils.isEmpty(fileId)) {
  912. fileId = new SnowflakeIdGenerator(0, 0).nextId() + "";
  913. log.info("新生成build数据,{}", fileId);
  914. }
  915. sceneFileBuild = new SceneFileBuild();
  916. sceneFileBuild.setChildName(folderName.split("_")[0]);
  917. sceneFileBuild.setFileId(fileId);
  918. sceneFileBuild.setRecStatus("A");
  919. sceneFileBuild.setUnicode(folderName);
  920. sceneFileBuild.setCreateTime(new Date());
  921. this.save(sceneFileBuild);
  922. redisUtil.set(String.format(RedisConstants.FOLDER_FILEID_BUILD, folderName), fileId, 2 * 24 * 60 * 60);
  923. redisUtil.set(String.format(RedisConstants.FILEID_FOLDER_BUILD, fileId), folderName, 2 * 24 * 60 * 60);
  924. return fileId;
  925. }
  926. public ResultData copyDataAndBuild(String sourceBucet,String dataSource,String sceneVer,User user, String customUserId) throws Exception {
  927. if(!StringUtils.equals(sceneVer,"V3") && ! StringUtils.equals(sceneVer,"V4")){
  928. throw new BusinessException(ErrorCode.PARAM_FORMAT_ERROR.code(),"版本有误,请填写 V3 或者 V4");
  929. }
  930. String fYunPath = ConstantFilePath.OSS_PREFIX + dataSource.replace(ConstantFilePath.BUILD_MODEL_PATH, "")
  931. .replace(ConstantFilePath.BUILD_MODEL_LASER_PATH, "");
  932. if(!ObjectUtils.isEmpty(sourceBucet)){
  933. fYunFileService.copyFileBetweenBucket(sourceBucet,fYunPath,fYunFileConfig.getBucket(),fYunPath);
  934. }
  935. // 下载data.fdage
  936. JSONObject fdageData = JSONObject.parseObject(fYunFileService.getFileContent(fYunPath + "/data.fdage"));
  937. if(ObjectUtils.isEmpty(fdageData)){
  938. throw new BusinessException(ErrorCode.SYSTEM_ERROR.code(),"4dage 文件不存在");
  939. }
  940. String cameraName = fdageData.getJSONObject("cam").getString("uuid");
  941. Camera cameraEntity = cameraService.getByChildName(cameraName);
  942. if(cameraEntity == null){
  943. log.error("该相机不存在:" + cameraName);
  944. throw new BusinessException(ErrorCode.FAILURE_CODE_6003);
  945. }
  946. CameraDetail detailEntity = cameraDetailService.getByCameraId(cameraEntity.getId());
  947. if(detailEntity == null){
  948. log.error("该相机详情不存在:" + cameraName);
  949. throw new BusinessException(ErrorCode.FAILURE_CODE_6003);
  950. }
  951. Long cameraType = 11L;
  952. //判断是否转台相机
  953. if (detailEntity.getType() == 9) {
  954. cameraType = 13L;
  955. }
  956. if (detailEntity.getType() == 10) {
  957. cameraType = 14L;
  958. }
  959. String sceneNum = scene3dNumService.generateSceneNum(detailEntity.getType());
  960. String icon = null;
  961. String imgViewPath = null;
  962. switch (sceneVer) {
  963. case "V3":
  964. case "V4":
  965. int rebuild = 0;
  966. ScenePlus scenePlus = scenePlusService.getByFileId(dataSource);
  967. if (!ObjectUtils.isEmpty(scenePlus)) {
  968. log.info("该场景资源已存在,执行补拍逻辑!");
  969. rebuild = 1;
  970. sceneNum = scenePlus.getNum();
  971. }
  972. imgViewPath = String.format(UploadFilePath.IMG_VIEW_PATH, sceneNum);
  973. if(fdageData.containsKey("icon") && StringUtils.isNotEmpty(fdageData.getString("icon"))){
  974. String ossPath = ConstantFilePath.OSS_PREFIX + dataSource.replace(ConstantFilePath.BUILD_MODEL_PATH, "")
  975. .replace(ConstantFilePath.BUILD_MODEL_LASER_PATH, "");
  976. fYunFileService.copyFileInBucket(ossPath + File.separator + fdageData.getString("icon"),imgViewPath + fdageData.getString("icon"));
  977. icon = fYunFileConfig.getHost() + imgViewPath + fdageData.getString("icon");
  978. log.info("上传icon成功....");
  979. }
  980. buildScenePost(dataSource, fdageData, "V3", cameraType, sceneNum, cameraEntity, detailEntity, rebuild, icon, user, customUserId);
  981. break;
  982. }
  983. Map<String,Object> result = new HashMap<>();
  984. result.put("code",sceneNum);
  985. return ResultData.ok(result);
  986. }
  987. private ScenePlusVO buildScenePost(String dataSource, JSONObject jsonObject, String buildType, long cameraType,
  988. String sceneNum, Camera camera, CameraDetail cameraDetail, int rebuild,String icon,User user, String customUserId) throws Exception {
  989. String localDataPath = String.format(ConstantFilePath.DATABUFFER_FORMAT, sceneNum);
  990. String imgViewPath = String.format(UploadFilePath.IMG_VIEW_PATH, sceneNum);
  991. String dataViewPath = String.format(UploadFilePath.DATA_VIEW_PATH, sceneNum);
  992. JSONObject firmwareVersion = new JSONObject();
  993. if (!ObjectUtils.isEmpty(jsonObject.getString("camSoftwareVersion"))) {
  994. firmwareVersion.put("camSoftwareVersion", jsonObject.getString("camSoftwareVersion"));
  995. }
  996. if (!ObjectUtils.isEmpty(jsonObject.getString("version"))) {
  997. firmwareVersion.put("version", jsonObject.getString("version"));
  998. }
  999. String sceneUrl = "/" + sceneProNewUrl;
  1000. //重算的场景,先移除该场景对应的容量
  1001. if (rebuild == 1) {
  1002. scenePlusService.resetSpace(sceneNum);
  1003. //删除oss的houst_floor.json(国际版可能会卡住)
  1004. fYunFileService.deleteFile(dataViewPath + "houst_floor.json");
  1005. } else {
  1006. //上传log-main.png
  1007. fYunFileService.uploadFile(ConstantFilePath.LOGO_PATH + "logo-main.png", imgViewPath + "logo-main.png");
  1008. fYunFileService.uploadFile(ConstantFilePath.LOGO_PATH + "logo-main-en.png", imgViewPath + "logo-main-en.png");
  1009. }
  1010. String algorithm = jsonObject.getString("location") != null && "1".equals(jsonObject.getString("location")) ? "sfm" : "slam";
  1011. String unicode = jsonObject.getString("creator") + "_" + jsonObject.getString("uuidtime");
  1012. ScenePlusVO scenePlusVO = this.createScenePlus(sceneNum, camera.getId(), camera.getChildName(), jsonObject.getString("creator"),
  1013. jsonObject.getString("pwd"), unicode, cameraType, dataSource, icon, cameraDetail.getUserId() , null, algorithm,
  1014. jsonObject.getJSONArray("points").size(), jsonObject.getString("name"), jsonObject.getString("info"),
  1015. jsonObject.getInteger("scenetype"), jsonObject.getString("gps"), rebuild,
  1016. jsonObject.getInteger("resolution"), firmwareVersion.toString(), sceneUrl, buildType, cameraDetail.getCooperationUser());
  1017. if (Objects.nonNull(scenePlusVO)) {
  1018. JSONObject statusJson = new JSONObject();
  1019. //临时将-2改成1,app还没完全更新
  1020. statusJson.put("status", scenePlusVO.getSceneStatus() == -2 ? 1 : scenePlusVO.getSceneStatus());
  1021. statusJson.put("webSite", scenePlusVO.getWebSite());
  1022. statusJson.put("sceneNum", scenePlusVO.getNum());
  1023. statusJson.put("thumb", scenePlusVO.getThumb());
  1024. statusJson.put("payStatus", 0);
  1025. statusJson.put("recStatus", 'A');
  1026. FileUtils.writeFile(localDataPath + "status.json", statusJson.toString());
  1027. fYunFileService.uploadFile(localDataPath + "status.json", dataViewPath + "status.json");
  1028. }
  1029. BuildSceneCallMessage mqMessage = getBuildSceneMqMessage(sceneNum, cameraType, algorithm, jsonObject.getInteger("resolution"), buildType,
  1030. scenePlusVO.getDataSource());
  1031. if (cameraDetail.getCompanyId() != null) {
  1032. Company company = companyService.getById(cameraDetail.getCompanyId());
  1033. if (company != null && !ObjectUtils.isEmpty(company.getCalculateFlexibility()) && !company.getCalculateFlexibility()) {
  1034. mqMessage.setFlexibility(-1);
  1035. }
  1036. }
  1037. mqMessage.getExt().put("deleteExtras", true);
  1038. mqMessage.getExt().put("customUserId", customUserId);
  1039. mqMessage.getExt().put("gps", jsonObject.getString("gps"));
  1040. rabbitMqProducer.sendByWorkQueue(queueModelingPre, mqMessage);
  1041. return scenePlusVO;
  1042. }
  1043. }