diff --git a/inspect-job/src/main/resources/logback.xml b/inspect-job/src/main/resources/logback.xml index e6cff4b..3b2cfcf 100644 --- a/inspect-job/src/main/resources/logback.xml +++ b/inspect-job/src/main/resources/logback.xml @@ -62,7 +62,7 @@ - + diff --git a/inspect-main/inspect-main-task/pom.xml b/inspect-main/inspect-main-task/pom.xml index 28181a5..a2f28dd 100644 --- a/inspect-main/inspect-main-task/pom.xml +++ b/inspect-main/inspect-main-task/pom.xml @@ -73,6 +73,11 @@ redisson 3.23.5 - + + + com.drewnoakes + metadata-extractor + 2.18.0 + \ No newline at end of file diff --git a/inspect-main/inspect-main-task/src/main/java/com/inspect/partrolresult/domain/AnalyseReqItem.java b/inspect-main/inspect-main-task/src/main/java/com/inspect/partrolresult/domain/AnalyseReqItem.java index a03a9f9..95f49d4 100644 --- a/inspect-main/inspect-main-task/src/main/java/com/inspect/partrolresult/domain/AnalyseReqItem.java +++ b/inspect-main/inspect-main-task/src/main/java/com/inspect/partrolresult/domain/AnalyseReqItem.java @@ -16,6 +16,7 @@ public class AnalyseReqItem implements Serializable { private String imageNormalUrlPath; private String[] typeList; private String[] imageUrlList; + private String[] dronePoseList; public AnalyseReqItem clone() { return JSONObject.parseObject(JSONObject.toJSONString(this), AnalyseReqItem.class); diff --git a/inspect-main/inspect-main-task/src/main/java/com/inspect/partrolresult/service/AnalyseRequestServiceImpl.java b/inspect-main/inspect-main-task/src/main/java/com/inspect/partrolresult/service/AnalyseRequestServiceImpl.java index fb39724..aa8c144 100644 --- a/inspect-main/inspect-main-task/src/main/java/com/inspect/partrolresult/service/AnalyseRequestServiceImpl.java +++ b/inspect-main/inspect-main-task/src/main/java/com/inspect/partrolresult/service/AnalyseRequestServiceImpl.java @@ -3,51 +3,136 @@ package com.inspect.partrolresult.service; import com.fasterxml.jackson.databind.ObjectMapper; import com.github.pagehelper.util.StringUtil; import com.inspect.analysis.constant.AnalyseConstants; - -import java.io.IOException; -import java.util.*; -import java.util.concurrent.TimeUnit; - import com.inspect.analysis.domain.AnalyseLog; import com.inspect.analysis.service.IAnalyseLogService; import com.inspect.base.core.constant.AlgConstants; import com.inspect.base.core.constant.RedisConst; +import com.inspect.base.core.sftp.SftpClient; import com.inspect.base.core.utils.DateUtils; import com.inspect.base.core.utils.HttpClientUtils; import com.inspect.base.core.utils.StringUtils; import com.inspect.base.redis.service.RedisService; import com.inspect.partrolresult.domain.AnalyseReqItem; import com.inspect.partrolresult.domain.AnalyseRequest; +import com.inspect.partrolresult.util.XmpUtil; import com.inspect.task.service.IPatrolTaskService; +import com.inspect.taskstatus.domain.PatrolTaskStatus; +import com.inspect.taskstatus.service.IPatrolTaskStatusService; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import javax.annotation.Resource; +import java.io.IOException; +import java.util.*; +import java.util.concurrent.TimeUnit; @Slf4j @Component public class AnalyseRequestServiceImpl implements IAnalyseRequestService { + private static final Set INFRARED_TYPES = new HashSet<>(Arrays.asList( + AlgConstants.INFRA_1800, + AlgConstants.INFRA_YU3, + AlgConstants.INFRA_CAMERA, + AlgConstants.INFRA_CAMERA_REVERSE + )); + private static final Set INFRARED_TYPES_2 = new HashSet<>(Arrays.asList( + + AlgConstants.INFRA_CAMERA_REVERSE + )); + private static final Set OLD_INFRARED_TYPES = new HashSet<>(Arrays.asList( + "infrared" + )); + private static final Set METER_TYPES = new HashSet<>(Arrays.asList( + AlgConstants.METER + )); @Resource private RedisService redisService; - @Value("${task.test-mode:false}") private boolean testMode; - @Value("${server.port}") private String port; - + @Value("${task.drone-xmp:false}") + private boolean droneXmpEnabled; @Resource private IPatrolTaskService patrolTaskService; - @Resource private AnalyseRequestRetryableDelegate retryDelegate; - @Resource private DelayQueueService delayQueueService; - @Resource private IAnalyseLogService analysisLogService; + @Resource + private IPatrolTaskStatusService patrolTaskStatusService; + @Resource + private SftpClient sftpClient; + + public static boolean checkInfraredType(String[] typeList) { + if (typeList == null) { + return false; + } + for (String type : typeList) { + if (INFRARED_TYPES.contains(type)) { + return true; + } + } + return false; + } + + public static boolean checkInfraredType2(String[] typeList) { + if (typeList == null) { + return false; + } + for (String type : typeList) { + if (INFRARED_TYPES_2.contains(type)) { + return true; + } + } + return false; + } + + public static boolean checkOldInfraredType(String[] typeList) { + if (typeList == null) { + return false; + } + for (String type : typeList) { + if (OLD_INFRARED_TYPES.contains(type)) { + return true; + } + } + return false; + } + + public static boolean checkMeterType(String[] typeList) { + if (typeList == null) { + return false; + } + for (String type : typeList) { + if (METER_TYPES.contains(type)) { + return true; + } + } + return false; + } + + public static void main(String[] args) { + try { + ObjectMapper mapper = new ObjectMapper(); + + AnalyseRequest r1 = new AnalyseRequest(); + r1.setRequestId("3177fe1c5d6f44f7bc527d5de8451ab9"); + String json = mapper.writeValueAsString(r1); + + AnalyseRequest r2 = mapper.readValue(json, AnalyseRequest.class); + boolean res = r1.equals(r2); + System.out.println(res); // 应为 true + boolean res2 = r1.hashCode() == r2.hashCode(); + System.out.println(res2); // 应为 true + } catch (Exception e) { + e.printStackTrace(); + } + + } //qinyl public void sendRequest(AnalyseRequest analyseReq, String[] typeList, boolean isFilter) throws IOException { @@ -148,6 +233,11 @@ public class AnalyseRequestServiceImpl implements IAnalyseRequestService { delayQueueService.submitRequest(AnalyseConstants.ALGORITHM_REQUEST_DELAY_QUEUE, analyseReq.getRequestId(), requestTimeout, TimeUnit.DAYS); } + // 读取无机人图片XMP位姿信息 + if (droneXmpEnabled) { + readDroneImageXmpInfo(analyseReq); + } + if (retryDelegate.callRemoteAnalyseService(analyseReq)) { log.info("CALL_REMOTE_ANALYSE SUCCESS, taskPatrolId: {}, requestId: {}", analyseReq.getTaskPatrolId(), @@ -181,108 +271,59 @@ public class AnalyseRequestServiceImpl implements IAnalyseRequestService { } } - public void sendCompensateRequest(AnalyseRequest request) { - final String defaultUrl = "http://localhost:" + this.port + AnalyseConstants.ANALYSE_RET_URI; - String[] typeList = request.getTypeList(); - if(typeList == null || typeList.length == 0) { - log.info("SEND_COMPENSATE_REQUEST typeList empty: {}", request); + public void readDroneImageXmpInfo(AnalyseRequest analyseReq) { + String taskPatrolId = analyseReq.getTaskPatrolId(); + PatrolTaskStatus taskStatus = patrolTaskStatusService.selectPatrolTaskStatusByTaskPatrolledId(taskPatrolId); + if (taskStatus == null || !"2".equals(taskStatus.getPosType())) { return; } + log.info("XMP reader, taskPatrolId:{}", taskPatrolId); - boolean containsInfrared = Arrays.asList(typeList).contains("infrared"); - log.info("SEND_COMPENSATE_REQUEST containsInfrared: {}, request: {}", containsInfrared, request); - if(containsInfrared) { - HttpClientUtils.sendPostAgain(defaultUrl, request.toInfraredResultStr()); - } else { - HttpClientUtils.sendPostAgain(defaultUrl, request.toErrorResultStr()); - } - } - - private static final Set INFRARED_TYPES = new HashSet<>(Arrays.asList( - AlgConstants.INFRA_1800, - AlgConstants.INFRA_YU3, - AlgConstants.INFRA_CAMERA, - AlgConstants.INFRA_CAMERA_REVERSE - )); - - private static final Set INFRARED_TYPES_2 = new HashSet<>(Arrays.asList( - - AlgConstants.INFRA_CAMERA_REVERSE - )); - - private static final Set OLD_INFRARED_TYPES = new HashSet<>(Arrays.asList( - "infrared" - )); - - private static final Set METER_TYPES = new HashSet<>(Arrays.asList( - AlgConstants.METER - )); - - public static boolean checkInfraredType(String[] typeList) { - if (typeList == null) { - return false; - } - for (String type : typeList) { - if (INFRARED_TYPES.contains(type)) { - return true; - } + List imgUrlList = analyseReq.getObjectList(); + if (imgUrlList == null) { + return; } - return false; - } - public static boolean checkInfraredType2(String[] typeList) { - if (typeList == null) { - return false; - } - for (String type : typeList) { - if (INFRARED_TYPES_2.contains(type)) { - return true; + for (AnalyseReqItem item : imgUrlList) { + if (item == null || item.getImageUrlList() == null) { + continue; } - } - return false; - } - public static boolean checkOldInfraredType(String[] typeList) { - if (typeList == null) { - return false; - } - for (String type : typeList) { - if (OLD_INFRARED_TYPES.contains(type)) { - return true; + String[] imageUrlList = item.getImageUrlList(); + String[] droneDataList = new String[imageUrlList.length]; + + for (int i = 0; i < imageUrlList.length; i++) { + try { + String imageUrl = imageUrlList[i]; + int finalI = i; + sftpClient.downLoad(imageUrl, (inputStream -> { + log.info("XMP imageUrl:{}", imageUrl); + String droneDataStr = XmpUtil.parseDrone(inputStream); + droneDataList[finalI] = droneDataStr; + })); + } catch (Exception e) { + log.error("读取XMP失败", e.getMessage()); + } } + item.setDronePoseList(droneDataList); } - return false; } - public static boolean checkMeterType(String[] typeList) { - if (typeList == null) { - return false; - } - for (String type : typeList) { - if (METER_TYPES.contains(type)) { - return true; - } + public void sendCompensateRequest(AnalyseRequest request) { + final String defaultUrl = "http://localhost:" + this.port + AnalyseConstants.ANALYSE_RET_URI; + String[] typeList = request.getTypeList(); + if (typeList == null || typeList.length == 0) { + log.info("SEND_COMPENSATE_REQUEST typeList empty: {}", request); + return; } - return false; - } - public static void main(String[] args) { - try { - ObjectMapper mapper = new ObjectMapper(); - - AnalyseRequest r1 = new AnalyseRequest(); - r1.setRequestId("3177fe1c5d6f44f7bc527d5de8451ab9"); - String json = mapper.writeValueAsString(r1); - - AnalyseRequest r2 = mapper.readValue(json, AnalyseRequest.class); - boolean res = r1.equals(r2); - System.out.println(res); // 应为 true - boolean res2 = r1.hashCode() == r2.hashCode(); - System.out.println(res2); // 应为 true - } catch (Exception e) { - e.printStackTrace(); + boolean containsInfrared = Arrays.asList(typeList).contains("infrared"); + log.info("SEND_COMPENSATE_REQUEST containsInfrared: {}, request: {}", containsInfrared, request); + if (containsInfrared) { + HttpClientUtils.sendPostAgain(defaultUrl, request.toInfraredResultStr()); + } else { + HttpClientUtils.sendPostAgain(defaultUrl, request.toErrorResultStr()); } - } } diff --git a/inspect-main/inspect-main-task/src/main/java/com/inspect/partrolresult/util/XmpUtil.java b/inspect-main/inspect-main-task/src/main/java/com/inspect/partrolresult/util/XmpUtil.java new file mode 100644 index 0000000..afe1ba8 --- /dev/null +++ b/inspect-main/inspect-main-task/src/main/java/com/inspect/partrolresult/util/XmpUtil.java @@ -0,0 +1,54 @@ +package com.inspect.partrolresult.util; + +import com.alibaba.fastjson.JSON; +import com.drew.imaging.ImageMetadataReader; +import com.drew.metadata.Metadata; +import com.drew.metadata.xmp.XmpDirectory; +import lombok.extern.slf4j.Slf4j; + +import java.io.InputStream; +import java.util.HashMap; +import java.util.Map; + +/** + * 解析图片的XMP信息 + */ +@Slf4j +public class XmpUtil { + private static final String DJI_XMP_FLAG = "drone-dji:"; + private static final String[] DJI_XMP_TAGS = { + "AbsoluteAltitude", "RelativeAltitude", "GpsLongitude", "GpsLatitude", + "GimbalPitchDegree", "GimbalRollDegree", "GimbalYawDegree", + "FlightPitchDegree", "FlightRollDegree", "FlightYawDegree" + }; + + /** + * 解析无人机图片的XMP信息 + * @return 位姿信息JSON字符串 + */ + public static String parseDrone(InputStream inputStream) { + try { + Metadata metadata = ImageMetadataReader.readMetadata(inputStream); + Map xmpMap = new HashMap<>(); + for (XmpDirectory xmpDir : metadata.getDirectoriesOfType(XmpDirectory.class)) { + Map props = xmpDir.getXmpProperties(); + getDjiTags(xmpMap, props); + } + String jsonStr = JSON.toJSONString(xmpMap); + log.info("Drone XMP info: {}", jsonStr); + return jsonStr; + } catch (Exception e) { + log.error("getXmpInfo error: {}", e.getMessage()); + } + return ""; + } + + private static void getDjiTags(Map xmpMap, Map props) { + for (String tag : DJI_XMP_TAGS) { + String val = props.get(DJI_XMP_FLAG + tag); + if (val != null) { + xmpMap.put(tag, val); + } + } + } +} diff --git a/inspect-main/inspect-main-task/src/main/java/com/inspect/task/controller/PatrolTaskController.java b/inspect-main/inspect-main-task/src/main/java/com/inspect/task/controller/PatrolTaskController.java index 4510c22..193993d 100644 --- a/inspect-main/inspect-main-task/src/main/java/com/inspect/task/controller/PatrolTaskController.java +++ b/inspect-main/inspect-main-task/src/main/java/com/inspect/task/controller/PatrolTaskController.java @@ -54,6 +54,8 @@ import org.apache.poi.ss.usermodel.*; import org.apache.poi.xssf.streaming.SXSSFSheet; import org.apache.poi.xssf.streaming.SXSSFWorkbook; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; @@ -2684,6 +2686,9 @@ public class PatrolTaskController extends BaseController { private void exportExcelV2(HttpServletResponse response, List dataList) throws Exception { response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); response.setHeader("Content-Disposition", "attachment; filename=\"task_export_" + System.currentTimeMillis() + ".xlsx\""); + response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); + response.setHeader("Pragma", "no-cache"); + response.setHeader("Expires", "0"); logger.info("[EXCEL]开始导出"); printMemoryInfo("开始导出"); @@ -2733,17 +2738,15 @@ public class PatrolTaskController extends BaseController { pathMap = null; } + response.setHeader("Transfer-Encoding", "chunked"); workbook.write(out); - // 清理临时文件 - workbook.dispose(); - printMemoryInfo("结束导出"); } catch (IOException e) { logger.error("导出异常:{}", e); printMemoryInfo("导出异常"); } finally { Path start = Paths.get(TEMP_DIR); Files.walk(start) - .filter(Files::isRegularFile) + .sorted(Comparator.reverseOrder()) .forEach(path -> { try { Files.deleteIfExists(path);