123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415 |
- package com.fdkankan.external.service.impl;
- import cn.hutool.core.bean.BeanUtil;
- import cn.hutool.core.collection.CollUtil;
- import cn.hutool.core.date.DateUtil;
- import cn.hutool.core.date.TimeInterval;
- import cn.hutool.core.io.FileUtil;
- import cn.hutool.core.lang.UUID;
- import cn.hutool.core.thread.ExecutorBuilder;
- import cn.hutool.core.util.RuntimeUtil;
- import cn.hutool.core.util.StrUtil;
- import cn.hutool.core.util.ZipUtil;
- import cn.hutool.http.HttpUtil;
- import com.alibaba.fastjson.JSON;
- import com.alibaba.fastjson.JSONObject;
- import com.fdkankan.common.constant.CommonStatus;
- import com.fdkankan.common.constant.CommonSuccessStatus;
- import com.fdkankan.common.constant.FileSizeUnitType;
- import com.fdkankan.common.constant.SceneSource;
- import com.fdkankan.common.util.DateExtUtil;
- import com.fdkankan.common.util.FileSizeUtil;
- import com.fdkankan.external.bean.DownloadProcessBean;
- import com.fdkankan.external.bean.LaserDownloadBean;
- import com.fdkankan.external.callback.ErrorCallback;
- import com.fdkankan.external.callback.SuccessCallback;
- import com.fdkankan.external.entity.*;
- import com.fdkankan.external.httpclient.HttpClient;
- import com.fdkankan.external.mapper.SceneOfflinePackagePushMapper;
- import com.fdkankan.external.service.*;
- import com.fdkankan.external.util.CmdUtils;
- import com.fdkankan.fyun.face.FYunFileServiceInterface;
- import com.fdkankan.redis.constant.RedisKey;
- import com.fdkankan.redis.util.RedisUtil;
- import com.fdkankan.web.response.Result;
- import com.fdkankan.web.response.ResultData;
- import com.mybatisflex.core.query.QueryWrapper;
- import com.mybatisflex.spring.service.impl.ServiceImpl;
- import lombok.extern.slf4j.Slf4j;
- import org.apache.commons.lang3.StringUtils;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.beans.factory.annotation.Value;
- import org.springframework.stereotype.Service;
- import javax.annotation.Resource;
- import java.io.File;
- import java.nio.charset.Charset;
- import java.util.*;
- import java.util.concurrent.ThreadPoolExecutor;
- import java.util.stream.Collectors;
- /**
- * 场景离线包推送表 服务层实现。
- *
- * @author dsx
- * @since 2023-12-07
- */
- @Slf4j
- @Service
- public class SceneOfflinePackagePushServiceImpl extends ServiceImpl<SceneOfflinePackagePushMapper, SceneOfflinePackagePush> implements ISceneOfflinePackagePushService {
- @Value("${host.4dkk.scene}")
- private String fdkkSceneHost;
- @Value("${host.laser}")
- private String laserHost;
- @Value("${oss.host.laser.old}")
- private String ossHostLaserOld;
- @Value("${oss.host.laser.new}")
- private String ossHostLaserNew;
- @Value("${oss.host.4dkk.old}")
- private String ossHost4dkkOld;
- @Value("${oss.host.4dkk.new}")
- private String ossHost4dkkNew;
- @Value("${api.4dkk.scene.getInfo}")
- private String getInfoUrl;
- @Value("${api.laser.downOfflineScene}")
- private String downOfflineSceneUrl;
- @Value("${file.offlineZip.dir}")
- private String offlineZipDir;
- private final static ThreadPoolExecutor threadPoolExecutor = ExecutorBuilder.create().setCorePoolSize(1).setMaxPoolSize(3).build();
- @Autowired
- private IDepartmentService departmentService;
- @Autowired
- private IDepartmentCameraService departmentCameraService;
- @Autowired
- private IScenePlusService scenePlusService;
- @Autowired
- private IScenePlusExtService scenePlusExtService;
- @Autowired
- private ISceneOfflinePackagePushService sceneOfflinePackagePushService;
- @Autowired
- private ISceneService sceneService;
- @Resource
- private HttpClient httpClient;
- @Autowired
- private ICameraService cameraService;
- @Resource
- private RedisUtil redisUtil;
- @Resource
- private FYunFileServiceInterface fYunFileService;
- @Override
- public void scenePushScheduleHandler(String departmentCode) {
- Department department = departmentService.getByCode(departmentCode);
- if(Objects.isNull(department)){
- return;
- }
- List<DepartmentCamera> departmentCameraList = departmentCameraService.listByDepartmentId(department.getId());
- if(CollUtil.isEmpty(departmentCameraList)){
- return;
- }
- List<String> snCodeList = departmentCameraList.stream().map(DepartmentCamera::getSnCode).collect(Collectors.toList());
- List<Camera> cameras = cameraService.listBySnCodeList(snCodeList);
- if(CollUtil.isEmpty(cameras)){
- return;
- }
- Map<Long, String> snCodeMap = cameras.stream().collect(Collectors.toMap(Camera::getId, Camera::getSnCode));
- List<Long> cameraIdList = cameras.stream().map(Camera::getId).collect(Collectors.toList());
- List<ScenePlus> scenePlusList = scenePlusService.listByCameraIdList(cameraIdList);
- if(CollUtil.isEmpty(scenePlusList)){
- return;
- }
- SceneOfflinePackagePush condition =
- SceneOfflinePackagePush.builder()
- .departmentId(department.getId())
- .pushStatus(CommonSuccessStatus.SUCCESS.code())
- .build();
- for (ScenePlus scenePlus : scenePlusList) {
- try {
- condition.setNum(scenePlus.getNum());
- SceneOfflinePackagePush commonPush =
- SceneOfflinePackagePush.builder()
- .departmentId(department.getId())
- .destUrl(department.getDestUrl())
- .storageType("oss")
- .snCode(snCodeMap.get(scenePlus.getCameraId()))
- .num(scenePlus.getNum()).build();
- ScenePlusExt scenePlusExt = null;
- //点云场景推送
- int isObj = CommonStatus.NO.code();
- if(scenePlus.getSceneSource() == SceneSource.JG.code() || scenePlus.getSceneSource() == SceneSource.SG.code()){
- condition.setZipType("laser");
- SceneOfflinePackagePush lastPush = sceneOfflinePackagePushService.getLastByCondition(condition);
- Scene scene = sceneService.getBySceneCode(scenePlus.getNum());
- if(Objects.isNull(scene)){
- throw new RuntimeException("未查询到激光系统场景信息,场景码:" + scenePlus.getNum());
- }
- //如果没有推送过或者推送过但是版本号不一致,就需要推送
- if(Objects.isNull(lastPush) || lastPush.getVersion() != scene.getOfflineVerForPush()){
- // threadPoolExecutor.submit(()->{
- SceneOfflinePackagePush push = BeanUtil.copyProperties(commonPush, SceneOfflinePackagePush.class);
- push.setZipType("laser");
- push.setVersion(scene.getOfflineVerForPush());
- try {
- sceneOfflinePackagePushService.scenePushHandler(push);
- }catch (Exception e){
- log.error("场景推送失败,num:{}",scenePlus.getNum(), e);
- }
- // });
- }
- scenePlusExt = scenePlusExtService.getByPlusId(scenePlus.getId());
- isObj = scenePlusExt.getIsObj();
- }
- //看看场景推送
- if(scenePlus.getSceneSource() == SceneSource.BM.code()
- || scenePlus.getSceneSource() == SceneSource.ZT.code()
- || isObj == CommonStatus.YES.code()){
- condition.setZipType("kankan");
- SceneOfflinePackagePush lastPush = sceneOfflinePackagePushService.getLastByCondition(condition);
- //查询版本号
- String sceneJsonStr = fYunFileService.getFileContent("scene_view_data/" + scenePlus.getNum() + "/data/scene.json");
- // String getInfo = fdkkSceneHost.concat(String.format(getInfoUrl, scenePlus.getNum()));
- // ResultData<Map<String, Object>> mapResultData = httpClient.get(getInfo, new HashMap<>(), new SuccessCallback(), new ErrorCallback());
- JSONObject sceneJson = JSON.parseObject(sceneJsonStr);
- int version = sceneJson.getIntValue("version");
- //如果没有推送过或者推送过但是版本号不一致,就需要推送
- if(Objects.isNull(lastPush) || lastPush.getVersion() != version){
- // threadPoolExecutor.submit(()->{
- SceneOfflinePackagePush push = BeanUtil.copyProperties(commonPush, SceneOfflinePackagePush.class);
- push.setZipType("kankan");
- push.setVersion(version);
- try {
- sceneOfflinePackagePushService.scenePushHandler(push);
- }catch (Exception e){
- log.error("场景推送失败,num:{}",scenePlus.getNum(), e);
- }
- // });
- }
- }
- }catch (Exception e){
- log.error("场景推送失败,num:{}",scenePlus.getNum(), e);
- }
- }
- }
- private String genZipUrl4Kankan(String num){
- String downloadUrl = null;
- String downloadTaskKey = RedisKey.SCENE_DOWNLOADS_TASK_V4;
- String progressKey = String.format(RedisKey.PREFIX_DOWNLOAD_PROGRESS_V4, num);
- TimeInterval timer = DateUtil.timer();
- Map<String,String> playod = new HashMap<>(2);
- playod.put("type","local");
- playod.put("num",num);
- redisUtil.del(progressKey);
- redisUtil.lRightPush(downloadTaskKey, JSONObject.toJSONString(playod));
- boolean exit = false;
- String progress = null;
- DownloadProcessBean downloadProcessBean = null;
- do {
- progress = redisUtil.get(progressKey);
- if(StringUtils.isEmpty(progress)){
- downloadProcessBean = new DownloadProcessBean();
- }else{
- downloadProcessBean = JSONObject.parseObject(progress, DownloadProcessBean.class);
- }
- Integer status = downloadProcessBean.getStatus();
- if (Objects.nonNull(status) && status == 1002) {
- downloadUrl = downloadProcessBean.getUrl();
- exit = true;
- }
- if (Objects.nonNull(status) && status == 1003) {
- log.error("下载失败,num:{}", num);
- throw new RuntimeException("下载失败,num:" + num);
- }
- if (timer.intervalMinute() > 8 * 60) {
- log.error("下载超时,num:{}", num);
- throw new RuntimeException("下载超时,num:" + num);
- }
- try {
- Thread.sleep(5000L);
- } catch (InterruptedException e) {
- throw new RuntimeException(e);
- }
- } while (!exit);
- return downloadUrl.replace(ossHost4dkkOld, ossHost4dkkNew);
- }
- private String genZipUrl4Laser(String num){
- String downloadUrl = null;
- TimeInterval timer = DateUtil.timer();
- boolean exit = false;
- //请求激光系统开始下载
- Map<String, Object> params = new HashMap<>();
- params.put("sceneCode", num);
- Result<LaserDownloadBean> resultData = httpClient.downOfflineScene(laserHost.concat(downOfflineSceneUrl), params, new SuccessCallback(), new ErrorCallback());
- LaserDownloadBean laserRes = resultData.getData();
- if(laserRes.getStatus() == 2){
- return laserRes.getUrl().replace(ossHostLaserOld, ossHostLaserNew);
- }
- do {
- resultData = httpClient.downOfflineScene(laserHost.concat(downOfflineSceneUrl), params, new SuccessCallback(), new ErrorCallback());
- laserRes = resultData.getData();
- Integer status = laserRes.getStatus();
- if (Objects.nonNull(status) && status == 2) {
- downloadUrl = laserRes.getUrl();
- exit = true;
- }
- if (Objects.nonNull(status) && status == -1) {
- log.error("下载失败,num:{}", num);
- throw new RuntimeException("下载失败,num:" + num);
- }
- if (timer.intervalMinute() > 8 * 60) {
- log.error("下载超时,num:{}", num);
- throw new RuntimeException("下载超时,num:" + num);
- }
- try {
- Thread.sleep(5000L);
- } catch (InterruptedException e) {
- throw new RuntimeException(e);
- }
- } while (!exit);
- return downloadUrl.replace(ossHostLaserOld, ossHostLaserNew);
- }
- @Override
- public SceneOfflinePackagePush getLastByCondition(SceneOfflinePackagePush condition) {
- QueryWrapper wrapper = new QueryWrapper();
- wrapper.eq(SceneOfflinePackagePush::getDepartmentId, condition.getDepartmentId());
- wrapper.eq(SceneOfflinePackagePush::getNum, condition.getNum());
- wrapper.orderBy(SceneOfflinePackagePush::getId, false);
- wrapper.limit(1);
- if(StrUtil.isNotEmpty(condition.getZipType())){
- wrapper.eq(SceneOfflinePackagePush::getZipType, condition.getZipType());
- }
- if(Objects.nonNull(condition.getPushStatus())){
- wrapper.eq(SceneOfflinePackagePush::getPushStatus, condition.getPushStatus());
- }
- return this.getOne(wrapper);
- }
- @Override
- public void scenePushHandler(SceneOfflinePackagePush push){
- String num = push.getNum();
- String zipType = push.getZipType();
- int version = push.getVersion();
- String downloadUrl = null;
- try {
- if("laser".equals(zipType)){
- downloadUrl = this.genZipUrl4Laser(num);
- }else{
- downloadUrl = this.genZipUrl4Kankan(num);
- }
- //开始推送到第三方服务
- if(StrUtil.isEmpty(downloadUrl)){
- throw new RuntimeException("场景下载失败,下载链接为空,场景码:" + num);
- }
- //下载到本地
- String zipPath = offlineZipDir.concat(num).concat(".zip");
- HttpUtil.downloadFile(downloadUrl, zipPath);
- String dirPath = null;
- String unzipPath = offlineZipDir.concat(num).concat("-").concat(zipType).concat("-").concat(String.valueOf(version));
- ZipUtil.unzip(zipPath, unzipPath, Charset.forName("GBK"));
- if("laser".equals(zipType)){
- dirPath = unzipPath.concat("/www");
- }else{
- dirPath = unzipPath.concat("/wwwroot/scene_view_data");
- }
- String zipDir = dirPath.concat("/zip/");
- FileUtil.del(zipDir);
- String volumeName = zipDir.concat(num).concat(".zip");
- FileUtil.mkParentDirs(volumeName);
- String cmd = "cd " + dirPath + " && zip -r " + volumeName + " " + num + " -s 500M";
- log.info("压缩命令:{}", cmd);
- CmdUtils.callLineSh(cmd, 200);
- log.info("分卷压缩完成");
- List<String> fileList = FileUtil.listFileNames(zipDir);
- if(CollUtil.isEmpty(fileList)){
- throw new RuntimeException("压缩包不存在");
- }
- String id = UUID.fastUUID().toString();
- int index = 1;
- for (String file : fileList) {
- Map<String, Object> params = new HashMap<>();
- params.put("id", id);
- params.put("action", "upload");
- params.put("fileName", file);
- params.put("file", FileUtil.file(zipDir.concat(file)));
- log.info("开发发送第{}个压缩包", index);
- String post = HttpUtil.post(push.getDestUrl(), params, 60 * 60 * 1000);
- log.info("第{}个场景推送成功,接收端返回结果:{}", index, post);
- ++index;
- }
- ScenePlus scenePlus = scenePlusService.getByNum(num);
- ScenePlusExt scenePlusExt = scenePlusExtService.getByPlusId(scenePlus.getId());
- String title = scenePlus.getTitle();
- if("laser".equals(zipType)){
- Scene scene = sceneService.getBySceneCode(scenePlus.getNum());
- title = scene.getTitle();
- }
- Map<String, Object> params = new HashMap<>();
- params.put("id", id);
- params.put("action", "save");
- params.put("fileName", num.concat(".zip"));
- params.put("num", num);
- params.put("title", title);
- params.put("zipType", zipType);
- params.put("downloadUrl", downloadUrl);
- params.put("version", push.getVersion());
- params.put("calcTime", DateExtUtil.format(scenePlusExt.getAlgorithmTime(), DateExtUtil.dateStyle8));
- String post = HttpUtil.post(push.getDestUrl(), params, 60 * 60 * 1000);
- log.info("场景推送成功,接收端返回结果:{}", post);
- push.setPushStatus(CommonSuccessStatus.SUCCESS.code());
- }catch (Exception e){
- log.error("场景推送失败,num:{}", num, e);
- push.setPushStatus(CommonSuccessStatus.FAIL.code());
- }
- this.saveOrUpdate(push);
- }
- public static void main(String[] args) throws Exception {
- // Map<String, Object> params = new HashMap<>();
- // params.put("num", "KJ-t-WypZvHxCR4X");
- // params.put("title", "123");
- // params.put("zipType", "kankan");
- // params.put("version", 1);
- // params.put("calcTime", DateExtUtil.format(new Date(), DateExtUtil.dateStyle8));
- // params.put("file", FileUtil.file("D:\\mnt\\external\\temp\\KJ-t-WypZvHxCR4X.zip"));
- // final String post = HttpUtil.post("http://localhost:8080/scene/receive2", params, 60 * 60 * 1000);
- // System.out.println(post);
- }
- }
|