From f7b19e697ab9686106b68b48bdff2e8615b4d1bd Mon Sep 17 00:00:00 2001
From: linwei <872216696@qq.com>
Date: Mon, 09 Feb 2026 19:28:12 +0800
Subject: [PATCH] 同步机构
---
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/service/impl/GdManageDeviceServiceImpl.java | 203 ++++++++++++++++++++++++++++++++++++++++++++++++--
1 files changed, 194 insertions(+), 9 deletions(-)
diff --git a/drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/service/impl/GdManageDeviceServiceImpl.java b/drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/service/impl/GdManageDeviceServiceImpl.java
index 1c4b2d1..2500bf5 100644
--- a/drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/service/impl/GdManageDeviceServiceImpl.java
+++ b/drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/service/impl/GdManageDeviceServiceImpl.java
@@ -19,15 +19,17 @@
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.extern.slf4j.Slf4j;
-import org.springframework.scheduling.annotation.Async;
-import org.springframework.scheduling.annotation.Scheduled;
import org.sxkj.gd.utils.GdGeoAddressUtil;
import org.sxkj.gd.utils.GeomUtils;
import org.sxkj.gd.workorder.dto.GdXingtuAirportListDTO;
+import org.sxkj.gd.workorder.dto.GdXingtuPayloadListDTO;
import org.sxkj.gd.workorder.dto.GdXingtuPilotListDTO;
import org.sxkj.gd.workorder.entity.GdManageDeviceEntity;
+import org.sxkj.gd.workorder.entity.GdManageDevicePayloadEntity;
import org.sxkj.gd.workorder.param.GdManageDevicePageParam;
+import org.sxkj.gd.workorder.service.IGdManageDevicePayloadService;
import org.sxkj.gd.workorder.vo.GdManageDeviceVO;
import org.sxkj.gd.workorder.excel.GdManageDeviceExcel;
import org.sxkj.gd.workorder.mapper.GdManageDeviceMapper;
@@ -42,9 +44,8 @@
import org.springblade.core.tool.utils.StringUtil;
import java.text.SimpleDateFormat;
-import java.util.Collections;
-import java.util.Date;
-import java.util.List;
+import java.util.*;
+import java.util.stream.Collectors;
/**
* 设备信息 服务实现类
@@ -58,6 +59,7 @@
public class GdManageDeviceServiceImpl extends BaseServiceImpl<GdManageDeviceMapper, GdManageDeviceEntity> implements IGdManageDeviceService {
private final JianXingtuApiService jianXingtuApiService;
+ private final IGdManageDevicePayloadService iGdManageDevicePayloadService;
@Override
public IPage<GdManageDeviceVO> selectGdManageDevicePage(IPage<GdManageDeviceVO> page, GdManageDevicePageParam gdManageDevice) {
@@ -104,16 +106,21 @@
* @return 同步数量
*/
@Override
- @Async
- @Scheduled(cron = "0 0 0 * * ?")
public int syncXingtuDevice() throws Exception {
int total = 0;
- total += syncPilotDevices();
+ // 2.同步机巢设备
total += syncAirportDevices();
- log.info("更新或新增设备"+total);
+ // 1.同步无人机设备
+ total += syncPilotDevices();
+ log.info("更新或新增设备" + total);
return total;
}
+ /**
+ * 同步星图无人机设备并入库
+ *
+ * @return 新增或更新数量
+ */
private int syncPilotDevices() throws Exception {
R response = jianXingtuApiService.getDevicePilotList(null);
List<GdXingtuPilotListDTO> items = parseList(response, GdXingtuPilotListDTO.class);
@@ -127,12 +134,20 @@
continue;
}
if (saveOrUpdateByAirportId(entity)) {
+ // 同步负载设备
+ List<GdXingtuPayloadListDTO> loadList = item.getLoadList();
+ syncPayloadDevices(loadList);
count++;
}
}
return count;
}
+ /**
+ * 同步星图机巢设备并入库
+ *
+ * @return 新增或更新数量
+ */
private int syncAirportDevices() throws Exception {
R response = jianXingtuApiService.getDeviceAirportList(null);
List<GdXingtuAirportListDTO> items = parseList(response, GdXingtuAirportListDTO.class);
@@ -152,13 +167,118 @@
return count;
}
+ /**
+ * 同步负载设备
+ *
+ * @param loadList 负载设备列表
+ */
+ private void syncPayloadDevices(List<GdXingtuPayloadListDTO> loadList) throws Exception {
+ // 1. 收集所有负载设备的飞行员序列号,用于后续查询和删除操作
+ Set<String> allPilotSnCodes = new HashSet<>();
+ if (loadList != null && !loadList.isEmpty()) {
+ for (GdXingtuPayloadListDTO load : loadList) {
+ if (load.getPilotSnCode() != null) {
+ allPilotSnCodes.add(load.getPilotSnCode());
+ }
+ }
+ }
+
+ // 2. 获取当前数据库中这些飞行员序列号对应的所有负载设备
+ List<GdManageDevicePayloadEntity> existingPayloads = new ArrayList<>();
+ if (!allPilotSnCodes.isEmpty()) {
+ existingPayloads = iGdManageDevicePayloadService.list(
+ Wrappers.<GdManageDevicePayloadEntity>lambdaQuery().in(GdManageDevicePayloadEntity::getPilotSnCode, allPilotSnCodes)
+ );
+ }
+
+ // 3. 创建现有负载设备的序列号映射,用于快速查找
+ Map<String, GdManageDevicePayloadEntity> existingPayloadMap = new HashMap<>();
+ for (GdManageDevicePayloadEntity payload : existingPayloads) {
+ if (payload.getPilotSnCode() != null && payload.getSnCode() != null) {
+ existingPayloadMap.put(payload.getPilotSnCode() + "_" + payload.getSnCode() + "_" + payload.getName(), payload);
+ }
+ }
+
+ // 4. 处理负载设备列表
+ if (loadList != null && !loadList.isEmpty()) {
+ List<GdManageDevicePayloadEntity> toSaveOrUpdate = new ArrayList<>();
+ Set<String> currentPayloadKeys = new HashSet<>();
+
+ // 对负载设备列表进行去重处理,确保每个负载设备只被处理一次
+ Map<String, GdXingtuPayloadListDTO> uniqueLoadMap = new HashMap<>();
+ for (GdXingtuPayloadListDTO load : loadList) {
+ if (load.getSnCode() != null && load.getPilotSnCode() != null) {
+ String payloadKey = load.getPilotSnCode() + "_" + load.getSnCode() + "_" + load.getName();
+ uniqueLoadMap.put(payloadKey, load);
+ }
+ }
+
+ // 处理去重后的负载设备列表
+ for (GdXingtuPayloadListDTO load : uniqueLoadMap.values()) {
+ String snCode = load.getSnCode();
+ String pilotSnCode1 = load.getPilotSnCode();
+ String name = load.getName();
+ String payloadKey = pilotSnCode1 + "_" + snCode + "_" + name;
+ currentPayloadKeys.add(payloadKey);
+
+ // 检查是否已存在
+ GdManageDevicePayloadEntity existing = existingPayloadMap.remove(payloadKey);
+ if (existing != null) {
+ // 更新现有负载
+ existing.setName(load.getName());
+ existing.setType(load.getType());
+ toSaveOrUpdate.add(existing);
+ } else {
+ // 新增负载
+ GdManageDevicePayloadEntity newPayload = new GdManageDevicePayloadEntity();
+ newPayload.setName(load.getName());
+ newPayload.setType(load.getType());
+ newPayload.setSnCode(snCode);
+ newPayload.setPilotSnCode(pilotSnCode1);
+ // 可以根据需要设置区域编码等其他字段
+ toSaveOrUpdate.add(newPayload);
+ }
+ }
+
+ // 4. 批量保存或更新负载设备
+ if (!toSaveOrUpdate.isEmpty()) {
+ iGdManageDevicePayloadService.saveOrUpdateBatch(toSaveOrUpdate);
+ }
+
+ // 5. 删除数据库中存在但负载列表中不存在的负载设备
+ if (!existingPayloadMap.isEmpty()) {
+ List<Long> toDeleteIds = existingPayloadMap.values().stream()
+ .map(GdManageDevicePayloadEntity::getId)
+ .collect(Collectors.toList());
+ iGdManageDevicePayloadService.removeByIds(toDeleteIds);
+ }
+ } else {
+ // 如果负载列表为空,删除该飞行员序列号对应的所有负载设备
+ if (!existingPayloads.isEmpty()) {
+ List<Long> toDeleteIds = existingPayloads.stream()
+ .map(GdManageDevicePayloadEntity::getId)
+ .collect(Collectors.toList());
+ iGdManageDevicePayloadService.removeByIds(toDeleteIds);
+ }
+ }
+ }
+
+ /**
+ * 按机场ID保存或更新设备信息
+ *
+ * @param entity 设备信息
+ * @return 是否保存成功
+ */
private boolean saveOrUpdateByAirportId(GdManageDeviceEntity entity) throws Exception {
if (StringUtil.isBlank(entity.getAirportId())) {
return false;
}
+ // 获取设备信息
GdManageDeviceEntity exist = lambdaQuery()
.eq(GdManageDeviceEntity::getAirportId, entity.getAirportId())
.one();
+ // 获取父级设备信息
+ GdManageDeviceEntity parent = getOne(Wrappers.<GdManageDeviceEntity>lambdaQuery().eq(GdManageDeviceEntity::getChildSn, entity.getDeviceSn()));
if (exist != null) {
entity.setId(exist.getId());
if (entity.getLongitude() == null) {
@@ -170,10 +290,23 @@
if (entity.getInsureExpiredTime() == null) {
entity.setInsureExpiredTime(exist.getInsureExpiredTime());
}
+ // 获取父级设备位置信息
+ if (parent != null) {
+ entity.setLongitude(parent.getLongitude());
+ entity.setLatitude(parent.getLatitude());
+ entity.setHeight(parent.getHeight());
+ entity.setModeCode(Long.valueOf(parent.getStatus()));
+ }
}
return saveOrUpdateDevice(entity);
}
+ /**
+ * 从星图无人机数据构建设备实体
+ *
+ * @param item 星图无人机数据
+ * @return 设备实体
+ */
private GdManageDeviceEntity buildFromPilot(GdXingtuPilotListDTO item) {
if (item == null) {
return null;
@@ -190,9 +323,28 @@
entity.setModeCode(parseModeCode(item.getStatus()));
entity.setInsureExpiredTime(parseInsuranceDate(item.getInsuranceInfo()));
entity.setAreaCode(extractAreaCode(item.getRegionCode()));
+ entity.setIsWithDock(item.getIsWithDock());
+ entity.setCreateDept(item.getDeptId());
+ entity.setDevicePayload(
+ Optional.ofNullable(item.getLoadList())
+ .orElse(Collections.emptyList())
+ .stream()
+ .filter(Objects::nonNull)
+ .map(load -> load.getName())
+ .filter(Objects::nonNull)
+ .distinct() // 添加去重逻辑
+ .collect(Collectors.joining(","))
+ );
+
return entity;
}
+ /**
+ * 从星图机巢数据构建设备实体
+ *
+ * @param item 星图机巢数据
+ * @return 设备实体
+ */
private GdManageDeviceEntity buildFromAirport(GdXingtuAirportListDTO item) {
if (item == null) {
return null;
@@ -210,9 +362,17 @@
entity.setModeCode(parseModeCode(item.getStatus()));
entity.setInsureExpiredTime(parseInsuranceDate(item.getInsuranceInfo()));
entity.setAreaCode(extractAreaCode(item.getRegionCode()));
+ entity.setHeight(item.getHeight());
+ entity.setCreateDept(item.getDeptId());
return entity;
}
+ /**
+ * 将设备在线状态转换为模式码
+ *
+ * @param status 状态文本
+ * @return 模式码
+ */
private Long parseModeCode(String status) {
if ("在线".equals(status)) {
return 0L;
@@ -223,6 +383,12 @@
return null;
}
+ /**
+ * 安全解析字符串为 Double
+ *
+ * @param value 字符串值
+ * @return Double 或 null
+ */
private Double parseDouble(String value) {
if (StringUtil.isBlank(value)) {
return null;
@@ -234,6 +400,12 @@
}
}
+ /**
+ * 提取区域编码中的末级编码
+ *
+ * @param regionCode 区域编码
+ * @return 末级区域编码
+ */
private String extractAreaCode(String regionCode) {
if (StringUtil.isBlank(regionCode)) {
return null;
@@ -250,6 +422,12 @@
return regionCode;
}
+ /**
+ * 解析保险信息并获取最新保险日期
+ *
+ * @param insuranceInfo 保险信息JSON
+ * @return 保险日期
+ */
private Date parseInsuranceDate(String insuranceInfo) {
if (StringUtil.isBlank(insuranceInfo)) {
return null;
@@ -283,6 +461,13 @@
}
}
+ /**
+ * 解析星图接口返回的列表数据
+ *
+ * @param response 接口响应
+ * @param clazz 目标类型
+ * @return 列表数据
+ */
private <T> List<T> parseList(R response, Class<T> clazz) {
if (response == null || !response.isSuccess() || response.getData() == null) {
return Collections.emptyList();
--
Gitblit v1.9.3