123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513 |
- package com.fdkankan.extend.service.impl;
- import cn.hutool.core.collection.CollUtil;
- import cn.hutool.core.date.DateUtil;
- import cn.hutool.core.exceptions.ExceptionUtil;
- import cn.hutool.core.io.FileUtil;
- import cn.hutool.core.util.StrUtil;
- import cn.hutool.core.util.ZipUtil;
- import cn.hutool.crypto.SecureUtil;
- import cn.hutool.crypto.symmetric.AES;
- import cn.hutool.http.HttpStatus;
- import cn.hutool.http.HttpUtil;
- import cn.hutool.jwt.signers.AlgorithmUtil;
- import com.alibaba.fastjson.JSON;
- import com.alibaba.fastjson.JSONArray;
- import com.alibaba.fastjson.JSONObject;
- import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
- import com.fdkankan.common.constant.CommonSuccessStatus;
- import com.fdkankan.common.constant.ErrorCode;
- import com.fdkankan.common.constant.SceneStatus;
- import com.fdkankan.common.exception.BusinessException;
- import com.fdkankan.common.util.AesUtil;
- import com.fdkankan.common.util.DateExtUtil;
- import com.fdkankan.extend.bean.TowerSceneBean;
- import com.fdkankan.extend.entity.Camera;
- import com.fdkankan.extend.entity.CameraDetail;
- import com.fdkankan.extend.entity.ScenePlus;
- import com.fdkankan.extend.httpclient.HttpClient;
- import com.fdkankan.extend.service.*;
- import com.fdkankan.extend.util.RsaCryptTools;
- import com.fdkankan.fyun.face.FYunFileServiceInterface;
- import com.fdkankan.model.constants.UploadFilePath;
- import com.fdkankan.model.utils.SceneUtil;
- import com.fdkankan.rabbitmq.util.RabbitMqProducer;
- import com.fdkankan.redis.constant.RedisKey;
- import com.fdkankan.redis.util.RedisUtil;
- import com.fdkankan.web.response.ResultData;
- import lombok.extern.slf4j.Slf4j;
- import org.springframework.amqp.rabbit.core.RabbitTemplate;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.beans.factory.annotation.Value;
- import org.springframework.stereotype.Service;
- import org.springframework.web.multipart.MultipartFile;
- import javax.annotation.Resource;
- import javax.crypto.KeyGenerator;
- import javax.crypto.SecretKey;
- import java.io.File;
- import java.io.IOException;
- import java.util.*;
- import java.util.stream.Collectors;
- @Slf4j
- @Service
- public class TowerServiceImpl implements ITowerService {
- private static String parentPath = "/home/backend/4dkankan_v4/modeling-extend/download/";
- private static String ossParentPath = "customer-projects/china-tower/";
- private static String ossScenePoolFilePath = ossParentPath.concat("scene.txt");
- private static String ossCameraPoolFilePath = ossParentPath.concat("camera.txt");
- private static String pushLogPath = parentPath.concat("log.txt");
- public static final String TIE_TA_SCENE_PUSH_CALLBACK_QUEUE = "tie_ta_scene_push_callback_queue";
- /** 场景推送回调交换机*/
- public static final String TIE_TA_SCENE_PUSH_CALLBACK_EXCHANGE = "tie_ta_scene_push_callback_exchange";
- /** 场景推送回调交换机路由*/
- public static final String TIE_TA_SCENE_PUSH_CALLBACK_ROUTING = "tie_ta_scene_push_callback_routing";
- @Value("${tower.manufact}")
- private String manufact;
- @Value("${tower.private-key}")
- private String privateKey;
- @Value("${tower.url}")
- private String url;
- @Autowired
- private FYunFileServiceInterface fYunFileService;
- @Autowired
- private RedisUtil redisUtil;
- @Autowired
- private ICameraDetailService cameraDetailService;
- @Autowired
- private IScenePlusService scenePlusService;
- @Autowired
- private ITowerService towerService;
- @Autowired
- private ICameraService cameraService;
- @Autowired
- private ISsoService ssoService;
- @Resource
- private HttpClient httpClient;
- @Autowired
- private RabbitMqProducer rabbitMqProducer;
- @Autowired
- private RabbitTemplate rabbitTemplate;
- @Override
- public String packSceneDataHandler(String num, String title, String logId) throws Exception {
- //校验场景名称是否正确
- String sceneStr = fYunFileService.getFileContent(ossScenePoolFilePath);
- List<TowerSceneBean> towerSceneBeans = JSON.parseArray(sceneStr, TowerSceneBean.class);
- if(CollUtil.isEmpty(towerSceneBeans)){
- return null;
- }
- TowerSceneBean towerSceneBean = towerSceneBeans.stream().filter(bean -> title.equals(bean.getName())).findFirst().get();
- if(Objects.isNull(towerSceneBean)){
- return null;
- }
- log.info("开始下载:{}", num);
- //场景本地数据父目录
- String scenePath = parentPath.concat(num).concat("/");
- String sceneSourcePath = scenePath.concat(towerSceneBean.getSceneId()).concat("_").concat(towerSceneBean.getRoomId());
- String zipPath = sceneSourcePath.concat(".zip");
- //data数据下载
- String dataPath = sceneSourcePath + "/data/";
- String ossDataPath = String.format(UploadFilePath.DATA_VIEW_PATH, num);
- //下载floorplan.json
- fYunFileService.downloadFile(ossDataPath.concat("floorplan.json"), dataPath.concat("floorplan.json"));
- //下载scene.json
- String sceneJsonPath = dataPath.concat("scene.json");
- String sceneJson = redisUtil.get(String.format(RedisKey.SCENE_JSON, num));
- if(StrUtil.isEmpty(sceneJson)){
- sceneJson = fYunFileService.getFileContent(ossDataPath.concat("scene.json"));
- }
- JSONObject sceneJsonObj = JSON.parseObject(sceneJson);
- sceneJsonObj.put("sceneKind", "pano");
- FileUtil.writeUtf8String(sceneJsonObj.toJSONString(), sceneJsonPath);
- //下载mesh
- FileUtil.mkdir(dataPath.concat("mesh/"));
- List<String> meshList = fYunFileService.listRemoteFiles(ossDataPath.concat("mesh"));
- meshList.parallelStream().forEach(key -> fYunFileService.downloadFile(key, dataPath.concat("mesh/")));
- //images数据下载
- String imagesPath = sceneSourcePath + "/images/";
- String ossImagesPath = String.format(UploadFilePath.IMG_VIEW_PATH, num);
- //下载high图
- List<String> highList = fYunFileService.listRemoteFiles(ossImagesPath.concat("pan/high/"));
- FileUtil.mkdir(imagesPath.concat("4k/"));
- highList.parallelStream().forEach(key -> fYunFileService.downloadFile(key, imagesPath.concat("4k/")));
- //下载low图
- FileUtil.mkdir(imagesPath.concat("512/"));
- List<String> lowList = fYunFileService.listRemoteFiles(ossImagesPath.concat("pan/low/"));
- lowList.parallelStream().forEach(key -> fYunFileService.downloadFile(key, imagesPath.concat("512/")));
- //下载vision.txt
- fYunFileService.downloadFile(ossImagesPath.concat("vision.txt"), imagesPath.concat("vision.txt"));
- //下载caches/images
- List<String> panoramaImageList = SceneUtil.getPanoramaImageList(imagesPath.concat("vision.txt"));
- log.info(JSON.toJSONString(panoramaImageList));
- List<String> imageList = fYunFileService.listRemoteFiles(String.format(UploadFilePath.scene_result_data_path, num).concat("caches/images/"));
- if(CollUtil.isNotEmpty(imageList)){
- imageList.stream().forEach(key->{
- if(panoramaImageList.contains(key.substring(key.lastIndexOf("/") + 1))){
- if(!FileUtil.exist(imagesPath.concat("8K"))){
- FileUtil.mkdir(imagesPath.concat("8K"));
- }
- fYunFileService.downloadFile(key, imagesPath.concat("8K"));
- }
- });
- // //移除非必须文件
- // List<String> fileNames = FileUtil.listFileNames(imagesPath.concat("8K/"));
- // fileNames.stream().forEach(name->{
- // if(!panoramaImageList.contains(name)){
- // FileUtil.del(imagesPath.concat("8K/") + name);
- // }
- // });
- }
- this.convertVisable(imagesPath.concat("vision.txt"));
- //打包
- ZipUtil.zip(sceneSourcePath, zipPath, true);
- log.info("结束下载,开始推送:{}", num);
- try {
- this.dataPush(num, towerSceneBean.getSceneId(), towerSceneBean.getRoomId(), zipPath);
- }finally {
- FileUtil.del(scenePath);
- }
- return zipPath;
- }
- private void convertVisable(String visionPath){
- String visionStr = FileUtil.readUtf8String(visionPath);
- JSONObject visionObj = JSON.parseObject(visionStr);
- JSONArray array = visionObj.getJSONArray("sweepLocations");
- Map<Integer, String> uuidMap = new HashMap<>();
- for(int i = 0; i < array.size(); i++){
- JSONObject o = (JSONObject)array.get(i);
- uuidMap.put(i, o.getString("uuid"));
- }
- for(int i = 0; i < array.size(); i++){
- JSONObject o = (JSONObject)array.get(i);
- JSONArray visibles = o.getJSONArray("visibles");
- o.put("visibles", this.convertVisableHandler(visibles,uuidMap));
- JSONArray visibles2 = o.getJSONArray("visibles2");
- o.put("visibles2", this.convertVisableHandler(visibles2,uuidMap));
- JSONArray visibles3 = o.getJSONArray("visibles3");
- o.put("visibles3", this.convertVisableHandler(visibles3,uuidMap));
- }
- FileUtil.writeUtf8String(JSON.toJSONString(visionObj), visionPath);
- }
- private String[] convertVisableHandler(JSONArray visibles, Map<Integer, String> uuidMap){
- int size = visibles.size();
- String[] visibleArr = new String[size];
- for(int j = 0; j < size; j++){
- int index = (Integer)visibles.get(j);
- String uuid = uuidMap.get(index);
- visibleArr[j] = uuid;
- }
- return visibleArr;
- }
- @Override
- public void packSceneData(Long companyId, List<String> nums) {
- String key = "tower:scene:data:download";
- List<ScenePlus> scenePlusList = null;
- if(Objects.nonNull(companyId)){
- //根据客户企业id查出所有相机
- List<CameraDetail> cameraDetailList = cameraDetailService.getByCompanyId(companyId);
- if(CollUtil.isEmpty(cameraDetailList)){
- return;
- }
- Set<Long> cameraIds = cameraDetailList.stream().map(detail -> detail.getCameraId()).collect(Collectors.toSet());
- //根据相机id查出所有待下载场景
- scenePlusList = scenePlusService.getByCameraIds(cameraIds);
- }else if(CollUtil.isNotEmpty(nums)){
- scenePlusList = scenePlusService.list(new LambdaQueryWrapper<ScenePlus>().in(ScenePlus::getNum, nums));
- }else{
- String snCodeStr = fYunFileService.getFileContent(ossCameraPoolFilePath);
- List<String> snCodeList = Arrays.asList(snCodeStr.split(","));
- String sceneStr = fYunFileService.getFileContent(ossScenePoolFilePath);
- List<TowerSceneBean> towerSceneBeans = JSON.parseArray(sceneStr, TowerSceneBean.class);
- List<String> titleList = towerSceneBeans.stream().map(TowerSceneBean::getName).collect(Collectors.toList());
- scenePlusList = scenePlusService.list(new LambdaQueryWrapper<ScenePlus>().in(ScenePlus::getTitle, titleList));
- List<String> dbTitleList = scenePlusList.stream().map(ScenePlus::getTitle).collect(Collectors.toList());
- List<String> notFindList = titleList.stream().filter(title -> {
- if (dbTitleList.contains(title)) {
- return false;
- }else{
- return true;
- }
- }).collect(Collectors.toList());
- if(CollUtil.isNotEmpty(notFindList)){
- fYunFileService.uploadFile(JSON.toJSONString(notFindList).getBytes(),
- ossParentPath.concat("notFind")
- .concat("-")
- .concat(DateExtUtil.format(new Date(), DateExtUtil.dateStyle7))
- .concat(".txt"));
- }
- }
- if(CollUtil.isEmpty(scenePlusList)){
- return;
- }
- String id = DateExtUtil.format(Calendar.getInstance().getTime(), "yyyyMMddHHmmss");
- //遍历场景列表开始下载
- scenePlusList.stream().forEach(plus -> {
- JSONObject jsonObject = new JSONObject();
- try {
- jsonObject = new JSONObject();
- jsonObject.put("title", plus.getTitle());
- jsonObject.put("num", plus.getNum());
- String zipPath = towerService.packSceneDataHandler(plus.getNum(), plus.getTitle(), id);
- jsonObject.put("status", CommonSuccessStatus.SUCCESS.code());
- jsonObject.put("zipPath", zipPath);
- redisUtil.hset(key, plus.getNum(), JSON.toJSONString(jsonObject));
- }catch (Exception e){
- log.error("推送失败,num:{},title:{}", plus.getNum(), plus.getTitle(), e);
- jsonObject.put("status", CommonSuccessStatus.FAIL.code());
- jsonObject.put("error", ExceptionUtil.stacktraceToString(e, 3000));
- redisUtil.hset(key, plus.getNum(), JSON.toJSONString(jsonObject));
- }
- });
- }
- @Override
- public JSONObject dataPush(String num, String sceneId, String roomId, String zipPath) throws Exception {
- JSONObject jsonObject = null;
- log.info("开始组装参数");
- String fileMd5 = com.fdkankan.extend.util.FileUtil.getMulFileMD5(FileUtil.getInputStream(zipPath));
- String compose = sceneId.concat("+").concat(roomId).concat("+").concat(fileMd5);
- String encrypt = RsaCryptTools.encryptData(compose, privateKey);
- Map<String, Object> params = new HashMap<>();
- params.put("stationCode", sceneId);
- params.put("roomEntityID", roomId);
- params.put("file", FileUtil.file(zipPath));
- params.put("manufact", manufact);
- params.put("encrypt", encrypt);
- params.put("upUserAcct", "xxx");
- log.info("private-key:{}", privateKey);
- log.info("manufact:{}", manufact);
- log.info("compose:{}", compose);
- log.info("encrypt:{}", encrypt);
- log.info("开始推送");
- try {
- String post = HttpUtil.post(url, params, 60*60*1000);
- jsonObject = JSON.parseObject(post);
- if(!jsonObject.containsKey("resultCode")){
- throw new RuntimeException("铁塔接口出参错误");
- }
- return jsonObject;
- }catch (Exception e){
- log.error("调用铁塔接口出错,场景:{}", num, e);
- jsonObject = new JSONObject();
- jsonObject.put("resultCode", -2);
- jsonObject.put("resultMsg", "调用铁塔接口出错");
- return jsonObject;
- }
- }
- private void dataPushLog(String num, String title, String resultCode, String resultMsg, String logId){
- Map<String, Object> log = new HashMap<>();
- log.put("num", num);
- log.put("title", title);
- log.put("resultCode", resultCode);
- log.put("resultMsg", resultMsg);
- String content = JSON.toJSONString(log).concat("\r\n");
- FileUtil.appendUtf8String(content, parentPath.concat("download").concat("-").concat(logId).concat(".log"));
- }
- public static void main(String[] args) {
- // System.out.println(AlgorithmUtil.getId("AES"));
- }
- @Override
- public ResultData sceneBatchMove(MultipartFile file, String origSnCode, String snCode) throws IOException {
- if(file.isEmpty()){
- throw new BusinessException(-1, "文件为空");
- }
- String origPath = "/home/backend/4dkankan_v4/modeling-extend/move/";
- String move_url = "https://www.4dkankan.com/service/manage/scene/move";
- String orgFileId = DateUtil.format(Calendar.getInstance().getTime(), DateExtUtil.dateStyle11);
- String orgFilePath = origPath.concat(orgFileId).concat(".txt");
- FileUtil.mkParentDirs(orgFilePath);
- file.transferTo(new File(orgFilePath));
- List<String> nums = FileUtil.readUtf8Lines(orgFilePath);
- if(CollUtil.isEmpty(nums)){
- throw new BusinessException(-1, "文件为空");
- }
- Camera camera = cameraService.findByChildName(origSnCode);
- if(Objects.isNull(camera)){
- throw new BusinessException(ErrorCode.CAMERA_BIND_NO_EXIST);
- }
- List<String> notExists = new ArrayList<>();
- for (String num : nums) {
- ScenePlus byCameraIdAndNum = scenePlusService.getByCameraIdAndNum(num, camera.getId());
- if(Objects.isNull(byCameraIdAndNum)){
- notExists.add(num);
- }
- }
- if(CollUtil.isNotEmpty(notExists)){
- throw new BusinessException(-1, "在原始相机下查询不到场景,请核查:".concat(JSON.toJSONString(notExists)));
- }
- //模拟登录
- Map<String, Object> headers = new HashMap<>();
- try {
- String token = ssoService.login("zhongwentong", "4Dage168");
- headers.put("token", token);
- }catch (Exception e){
- return ResultData.error(-1, "登录失败");
- }
- List<Map<String, Object>> result = new ArrayList<>();
- for (String num : nums) {
- Map<String, Object> param = new HashMap<>();
- param.put("num", num);
- param.put("snCode", snCode);
- ResultData<Map<String, Object>> resultData = httpClient.post(move_url, headers, param);
- Map<String, Object> item = new HashMap<>();
- item.put("num", num);
- item.put("code", resultData.getCode());
- item.put("message", resultData.getMessage());
- result.add(item);
- }
- return ResultData.ok(result);
- }
- @Override
- public void pushScene(TowerSceneBean towerSceneBean) throws Exception {
- JSONObject pushResult = null;
- String num = towerSceneBean.getNum();
- Map<String, Object> noticeContent = new HashMap<>();
- noticeContent.put("num", num);
- String scenePath = parentPath.concat(num).concat("/");
- try {
- //场景本地数据父目录
- String sceneSourcePath = scenePath.concat(towerSceneBean.getSceneId()).concat("_").concat(towerSceneBean.getRoomId());
- String zipPath = sceneSourcePath.concat(".zip");
- log.info("开始下载:{}", num);
- ScenePlus scenePlus = scenePlusService.getByNum(num);
- if(Objects.isNull(scenePlus)){
- throw new RuntimeException("查询不到此场景");
- }
- if(scenePlus.getSceneStatus() != SceneStatus.SUCCESS.code() && scenePlus.getSceneStatus() != SceneStatus.NO_DISPLAY.code()){
- throw new RuntimeException("场景计算中");
- }
- //data数据下载
- String dataPath = sceneSourcePath + "/data/";
- String ossDataPath = String.format(UploadFilePath.DATA_VIEW_PATH, num);
- //下载floorplan.json
- fYunFileService.downloadFile(ossDataPath.concat("floorplan.json"), dataPath.concat("floorplan.json"));
- // //下载scene.json
- String sceneJsonPath = dataPath.concat("scene.json");
- String sceneJson = fYunFileService.getFileContent(ossDataPath.concat("scene.json"));
- JSONObject sceneJsonObj = JSON.parseObject(sceneJson);
- sceneJsonObj.put("sceneKind", "pano");
- FileUtil.writeUtf8String(sceneJsonObj.toJSONString(), sceneJsonPath);
- //下载mesh
- FileUtil.mkdir(dataPath.concat("mesh/"));
- List<String> meshList = fYunFileService.listRemoteFiles(ossDataPath.concat("mesh"));
- meshList.parallelStream().forEach(key -> fYunFileService.downloadFile(key, dataPath.concat("mesh/")));
- //images数据下载
- String imagesPath = sceneSourcePath + "/images/";
- String ossImagesPath = String.format(UploadFilePath.IMG_VIEW_PATH, num);
- //下载high图
- List<String> highList = fYunFileService.listRemoteFiles(ossImagesPath.concat("pan/high/"));
- FileUtil.mkdir(imagesPath.concat("4k/"));
- highList.parallelStream().forEach(key -> fYunFileService.downloadFile(key, imagesPath.concat("4k/")));
- //下载low图
- FileUtil.mkdir(imagesPath.concat("512/"));
- List<String> lowList = fYunFileService.listRemoteFiles(ossImagesPath.concat("pan/low/"));
- lowList.parallelStream().forEach(key -> fYunFileService.downloadFile(key, imagesPath.concat("512/")));
- //下载vision.txt
- fYunFileService.downloadFile(ossImagesPath.concat("vision.txt"), imagesPath.concat("vision.txt"));
- //下载caches/images
- List<String> panoramaImageList = SceneUtil.getPanoramaImageList(imagesPath.concat("vision.txt"));
- log.info(JSON.toJSONString(panoramaImageList));
- List<String> imageList = fYunFileService.listRemoteFiles(String.format(UploadFilePath.scene_result_data_path, num).concat("caches/images/"));
- if(CollUtil.isNotEmpty(imageList)){
- imageList.stream().forEach(key->{
- if(panoramaImageList.contains(key.substring(key.lastIndexOf("/") + 1))){
- if(!FileUtil.exist(imagesPath.concat("8K"))){
- FileUtil.mkdir(imagesPath.concat("8K"));
- }
- fYunFileService.downloadFile(key, imagesPath.concat("8K"));
- }
- });
- }
- this.convertVisable(imagesPath.concat("vision.txt"));
- //打包
- ZipUtil.zip(sceneSourcePath, zipPath, true);
- log.info("打包成功,开始推送:{}", num);
- pushResult = this.dataPush(num, towerSceneBean.getSceneId(), towerSceneBean.getRoomId(), zipPath);
- }catch (Exception e){
- log.error("场景推送出错,未知异常", e);
- pushResult = new JSONObject();
- pushResult.put("resultCode", -3);
- pushResult.put("resultMsg", e.getMessage());
- } finally {
- noticeContent.put("result", pushResult);
- rabbitMqProducer.sendByWorkQueue(TIE_TA_SCENE_PUSH_CALLBACK_QUEUE, noticeContent);
- // rabbitTemplate.convertAndSend(TIE_TA_SCENE_PUSH_CALLBACK_EXCHANGE , TIE_TA_SCENE_PUSH_CALLBACK_ROUTING , noticeContent);
- FileUtil.del(scenePath);
- }
- }
- }
|