package com.dji.sample.droneairport.service.impl; import cn.hutool.json.JSONArray; import cn.hutool.json.JSONObject; //import com.alibaba.fastjson.JSON; import cn.hutool.json.JSONUtil; import com.alibaba.fastjson.JSON; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.dji.sample.common.model.ResponseResult; import com.dji.sample.component.redis.RedisOpsUtils; import com.dji.sample.droneairport.dao.DeviceExpanSionDao; import com.dji.sample.droneairport.model.Entity.DeviceExpanSionEntity; import com.dji.sample.droneairport.model.dto.*; import com.dji.sample.droneairport.model.param.ReturnTaskParam; import com.dji.sample.droneairport.service.RegistService; import com.dji.sample.droneairport.utils.AuthUtil; import com.dji.sample.droneairport.utils.SM2.Utils; import com.dji.sample.droneairport.utils.SM4Util; import com.dji.sample.manage.dao.IDeviceMapper; import com.dji.sample.manage.model.entity.DeviceEntity; import com.dji.sample.manage.model.receiver.OsdSubDeviceReceiver; import com.dji.sample.manage.service.IDeviceRedisService; import com.dji.sample.patches.dao.GetPatchesMapper; import com.dji.sample.patches.dao.TaskInfoMapper; import com.dji.sample.patches.model.entity.LotInfo; import com.dji.sample.patches.model.entity.TaskInfo; import com.dji.sample.patches.utils.TimerUtil; import com.dji.sample.wayline.dao.IWaylineFileMapper; import com.dji.sample.wayline.dao.IWaylineJobMapper; import com.dji.sample.wayline.model.entity.WaylineFileEntity; import com.dji.sample.wayline.model.entity.WaylineJobEntity; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import org.bouncycastle.crypto.InvalidCipherTextException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.*; import org.springframework.stereotype.Service; import org.springframework.web.client.RestTemplate; import org.springframework.web.multipart.MultipartFile; import java.io.File; import java.io.IOException; import java.security.NoSuchAlgorithmException; import java.util.*; import java.util.stream.Collectors; import static com.dji.sample.patches.utils.TimerUtil.getCurrentTimestampPlus8Hours; @Service public class RegistServiceImpl implements RegistService { private final RestTemplate restTemplate = new RestTemplate(); private final ObjectMapper objectMapper = new ObjectMapper(); @Autowired private IDeviceRedisService redisService; @Autowired private DeviceExpanSionDao expanSionDao; @Autowired private TaskInfoMapper taskInfoMapper; @Autowired private GetPatchesMapper patchesMapper; @Autowired private TimerUtil timerUtil; @Autowired private IDeviceMapper deviceMapper; @Autowired private IWaylineJobMapper waylineJobMapper; @Autowired private IWaylineFileMapper fileMapper; public String registPort(DeviceExpanSionEntity airport) { try { RegistDto registDto = airportEntityToDto(airport); // 构建请求体 String jsonBody = buildRequestBody(registDto); // 设置请求头 String base64 = SM4Util.encrypt("jsimjrby3wqb7dbq", jsonBody); // 设置请求头 HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); headers.setAccept(List.of(MediaType.APPLICATION_JSON, MediaType.TEXT_PLAIN, MediaType.ALL)); headers.set("Accept-Language", "zh-CN,zh;q=0.9"); headers.setConnection("keep-alive"); headers.set("x-lc-token", AuthUtil.getToken()); headers.set("x-lc-secret", Utils.hexToBase64(Utils.encrypt("jsimjrby3wqb7dbq", "044D6061FC08A19D3F32CEAA8CF6679B40500008FD741FC26DE7E50AEBF3A9115D47274437730EADEDAEF0CCC4853C5F0B35B30C6AEA83A5F6FBCA4ABEAC9E3B98"))); // 构建请求实体 HttpEntity requestEntity = new HttpEntity<>(base64, headers); // 发送请求 ResponseEntity response = restTemplate.exchange( "https://xcx.geoway.com.cn:8033/v1/droneAirport/RegistService", HttpMethod.POST, requestEntity, String.class); return response.getBody(); } catch (Exception e) { // 异常处理 throw new IllegalArgumentException("Request failed: " + e.getMessage(), e); } } private String buildRequestBody(RegistDto dto) { try { return objectMapper.writeValueAsString(dto); } catch (JsonProcessingException e) { throw new RuntimeException("数据有误", e); } } @Override public String addDrone(String workspaceId) { try { DeviceExpanSionEntity airport = expanSionDao.selectOne(new LambdaQueryWrapper() .eq(DeviceExpanSionEntity::getWorkspaceId, workspaceId) .eq(DeviceExpanSionEntity::getType, 0)); DeviceExpanSionEntity drone = expanSionDao.selectOne(new LambdaQueryWrapper() .eq(DeviceExpanSionEntity::getWorkspaceId, workspaceId) .eq(DeviceExpanSionEntity::getType, 1)); AddDeviceDto dto = deviceEntityToDto(drone); // 构建请求体 String jsonBody = buildRequestBody(dto); String base64 = SM4Util.encrypt("jsimjrby3wqb7dbq", jsonBody); String secret = enSM2("jsimjrby3wqb7dbq", "044D6061FC08A19D3F32CEAA8CF6679B40500008FD741FC26DE7E50AEBF3A9115D47274437730EADEDAEF0CCC4853C5F0B35B30C6AEA83A5F6FBCA4ABEAC9E3B98"); // 设置请求头 HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); headers.setAccept(List.of(MediaType.APPLICATION_JSON, MediaType.TEXT_PLAIN, MediaType.ALL)); headers.set("Accept-Language", "zh-CN,zh;q=0.9"); headers.setConnection("keep-alive"); headers.set("x-lc-token", AuthUtil.getToken()); headers.set("x-lc-secret", secret); // 构建请求实体 HttpEntity requestEntity = new HttpEntity<>(base64, headers); // 发送请求 RestTemplate restTemplate = new RestTemplate(); String response = restTemplate.postForObject("https://xcx.geoway.com.cn:8033/v1/droneAirport/addDevice", requestEntity, String.class); registPort(airport); return response; } catch (Exception e) { // 异常处理 throw new IllegalArgumentException("Request failed: " + e.getMessage(), e); } } @Override public ResponseResult getDroneState(String deviceId) throws Exception { DroneStateDto data = getAirportFromCache(deviceId); String json = JSON.toJSONString(data); String SM4Screct = SM4Util.encrypt("jsimjrby3wqb7dbq", json); String SM2Screct = enSM2(SM4Screct, "23E57DA1E4AB865CCBC325B668762207DEF74345B782237808AE0BABDF26734D"); return ResponseResult.success(SM2Screct); } @Override public ResponseResult authorization(String base64, String Secret) throws Exception { String sm4Secrect = deSM2(Secret, "23E57DA1E4AB865CCBC325B668762207DEF74345B782237808AE0BABDF26734D"); String decryptedJson = SM4Util.decrypt(sm4Secrect, base64); JSONObject jsonObject = new JSONObject(decryptedJson); String deviceId = jsonObject.getStr("deviceid"); boolean online = redisService.checkDeviceOnline(deviceId); if (online) { return ResponseResult.success(200, "无人机机场授权成功!", "", ""); } return ResponseResult.error(500, "无人机机场授权失败!"); } @Override public ReturnTaskParam AddTask(String base64, String Secret, String username) throws Exception { ReturnTaskParam param = new ReturnTaskParam(); String taskId = UUID.randomUUID().toString(); String traceid = UUID.randomUUID().toString(); String sm4Secrect = deSM2(Secret, "23E57DA1E4AB865CCBC325B668762207DEF74345B782237808AE0BABDF26734D"); String decryptedJson = SM4Util.decrypt(sm4Secrect, base64); JSONObject jsonObject = new JSONObject(decryptedJson); AddTaskDto addTaskDto = jsonToDto(jsonObject); TaskInfo taskInfo = new TaskInfo(); List listx = convertStringToList(addTaskDto.getDeviceid()); String sn = listx.get(0); String workspaceId = getWorkspaceId(sn); taskInfo.setId(traceid); taskInfo.setTaskId(taskId); taskInfo.setName(addTaskDto.getBizidname()); taskInfo.setDeviceIds(addTaskDto.getDeviceid()); taskInfo.setCreateUser(username); param.setTraceId(traceid); taskInfoMapper.insert(taskInfo); List tasklist = addTaskDto.getTasklist(); for (TaskListDto taskListDto : tasklist) { LotInfo lotInfo = new LotInfo(); lotInfo = convertToLotInfo(taskListDto); lotInfo.setTaskId(taskId); lotInfo.setType(0); lotInfo.setTaskName(addTaskDto.getBizidname()); lotInfo.setUserName(username); lotInfo.setWorkspaceId(workspaceId); patchesMapper.insert(lotInfo); } Long time = getCurrentTimestampPlus8Hours(14); // 获取未规划的图斑集合 List> lists = timerUtil.getNoPlan(workspaceId); List> convertedLists = TimerUtil.convertToLists(lists); for (List list : convertedLists) { String waylineName = TimerUtil.getTimeName(); //根据获取的图斑集合获得kmz航线文件 MultipartFile multipartFile = null; try { multipartFile = timerUtil.getFile(waylineName, list, 28.62452712442823, 115.85666327144976); } catch (IOException e) { throw new RuntimeException(e); } //上传航线文件 WaylineFileEntity waylineFile = timerUtil.backWayline(multipartFile, waylineName, workspaceId, username); //将为规划的图斑状态更新为已规划 List> listOfLists = new ArrayList<>(); List sublist = new ArrayList<>(); sublist.add(time); // 添加整数值 listOfLists.add(sublist); List lists1 = new ArrayList<>(); lists1.add(time); String times = TimerUtil.convertTimestampToFormattedString(time); param.setWaylineId(taskId); TimerUtil.sendPostWithParameters(waylineName, waylineFile.getWaylineId(), times, lists1, listOfLists, taskId); timerUtil.updatePatchesStatu(list); } return param; } @Override public ReturnTaskParam updateTask(String base64, String Secret, String username) throws Exception { ReturnTaskParam param = new ReturnTaskParam(); String traceid = UUID.randomUUID().toString(); String sm4Secrect = deSM2(Secret, "23E57DA1E4AB865CCBC325B668762207DEF74345B782237808AE0BABDF26734D"); String decryptedJson = SM4Util.decrypt(sm4Secrect, base64); JSONObject jsonObject = new JSONObject(decryptedJson); UpdataTaskDto addTaskDto = UpjsonToDto(jsonObject); String taskId = addTaskDto.getTaskid(); delPatchesByTaskId(taskId); // delWaylineJob(taskId); TaskInfo taskInfo = new TaskInfo(); List listx = convertStringToList(addTaskDto.getDeviceid()); String sn = listx.get(0); String workspaceId = getWorkspaceId(sn); taskInfo.setId(traceid); taskInfo.setTaskId(taskId); taskInfo.setDeviceIds(addTaskDto.getDeviceid()); taskInfo.setCreateUser(username); param.setTraceId(traceid); updateTaskInfo(traceid, taskId, addTaskDto.getDeviceid(), username); List tasklist = addTaskDto.getTasklist(); for (TaskListDto taskListDto : tasklist) { LotInfo lotInfo = new LotInfo(); lotInfo = convertToLotInfo(taskListDto); lotInfo.setUserName(username); lotInfo.setTaskId(taskId); lotInfo.setWorkspaceId(workspaceId); patchesMapper.insert(lotInfo); } Long time = getCurrentTimestampPlus8Hours(14); // 获取未规划的图斑集合 List> lists = timerUtil.getNoPlan(workspaceId); List> convertedLists = TimerUtil.convertToLists(lists); for (List list : convertedLists) { String waylineName = TimerUtil.getTimeName(); //根据获取的图斑集合获得kmz航线文件 MultipartFile multipartFile = null; try { multipartFile = timerUtil.getFile(waylineName, list, 28.62452712442823, 115.85666327144976); } catch (IOException e) { throw new RuntimeException(e); } //上传航线文件 WaylineFileEntity waylineFile = timerUtil.backWayline(multipartFile, waylineName, workspaceId, username); updateJob(taskId, waylineFile.getWaylineId()); param.setWaylineId(taskId); timerUtil.updatePatchesStatu(list); } return param; } @Override public ResponseResult cancelTask(String taskId) { LambdaUpdateWrapper updateWrapper = new LambdaUpdateWrapper<>(); updateWrapper.eq(WaylineJobEntity::getJobId, taskId) .set(WaylineJobEntity::getStatus, 4); waylineJobMapper.update(null, updateWrapper); return null; } @Override public ResponseResult queryTaskStatus(String taskid) { WaylineJobEntity jobEntity = waylineJobMapper.selectOne(new LambdaQueryWrapper().eq(WaylineJobEntity::getJobId, taskid)); if (jobEntity == null) { return ResponseResult.error(201, "查询无人机机场任务状态失败!"); } int code = jobEntity.getStatus(); //1: 待执行; 2: 执行中; 3: 完成; 4: 取消; 5: 失败 if (code == 1) { return ResponseResult.success(200, "查询无人机机场任务状态成功!", "", ""); } else if (code == 2) { return ResponseResult.success(202, "查询无人机机场任务状态成功!", "", ""); } else if (code == 3) { return ResponseResult.success(203, "查询无人机机场任务状态成功!", "", ""); } else if (code == 4) { return ResponseResult.success(204, "查询无人机机场任务状态成功!", "", ""); } else if (code == 5) { return ResponseResult.success(205, "查询无人机机场任务状态成功!", "", ""); } return null; } private static final String BASE_DIR = "src/main/resources/tmp"; /** * 根据任务 ID 查找对应的 DB 文件路径 * * @param taskId 任务 ID * @return 匹配的 DB 文件路径列表 */ public List findDbFilesByTaskId(String taskId) { List dbFilePaths = new ArrayList<>(); File baseDir = new File(BASE_DIR); // 检查基础目录是否存在 if (!baseDir.exists() || !baseDir.isDirectory()) { throw new IllegalStateException("Base directory does not exist or is not a directory."); } // 遍历基础目录下的所有文件夹 File[] subDirs = baseDir.listFiles(File::isDirectory); if (subDirs != null) { for (File subDir : subDirs) { // 如果文件夹名称包含任务 ID,则查找该文件夹中的 DB 文件 if (subDir.getName().contains(taskId)) { File[] files = subDir.listFiles((dir, name) -> name.endsWith(".db")); if (files != null) { for (File file : files) { dbFilePaths.add(file.getAbsolutePath()); } } } } } return dbFilePaths; } public void delPatchesByTaskId(String taskId) { patchesMapper.delete(new LambdaUpdateWrapper().eq(LotInfo::getTaskId, taskId)); } private String buildRequestBody(AddDeviceDto dto) { try { return objectMapper.writeValueAsString(dto); } catch (JsonProcessingException e) { throw new RuntimeException("数据有误", e); } } public String getWorkspaceId(String devicesn) { DeviceEntity entity = deviceMapper.selectOne(new LambdaQueryWrapper() .eq(DeviceEntity::getDeviceSn, devicesn)); return entity.getWorkspaceId(); } public static String enSM2(String data, String pubKey) throws InvalidCipherTextException, IOException { String encrypt = Utils.encrypt(data, pubKey); encrypt = Utils.hexToBase64(encrypt); return encrypt; } public static String deSM2(String Base64, String priKey) throws Exception { String hex = Utils.convertBase64ToHex(Base64); return Utils.decrypt(hex, priKey); } public static Map createKey() throws NoSuchAlgorithmException { Map keyPair = Utils.createKeyPair(); Map newKey = new HashMap<>(); newKey.put("publicKey", keyPair.get("pbcky")); newKey.put("privateKey", keyPair.get("pveky")); return newKey; } public AddDeviceDto deviceEntityToDto(DeviceExpanSionEntity entity) { AddDeviceDto.AddDeviceDtoBuilder builder = AddDeviceDto.builder(); if (entity != null) { builder.brand(entity.getBrand()) .height(entity.getHeight()) .longitude(entity.getLongitude()) .latitude(entity.getLatitude()) .radius(entity.getRadius()) .regioncode(entity.getRegioncode()) .deviceid(entity.getDeviceId()) .model(entity.getModel()) .build(); } return builder.build(); } public RegistDto airportEntityToDto(DeviceExpanSionEntity entity) { RegistDto.RegistDtoBuilder builder = RegistDto.builder(); if (entity != null) { builder.serviceUrl(entity.getServiceUrl()) .contacts(entity.getContracts()) .phone(entity.getPhone()) .liveStreamPluginUrl(entity.getLiveStreamPluginUrl()) .build(); } return builder.build(); } public OsdSubDeviceReceiver getDroneFromCache(String sn) { String key = "osd:" + sn; return (OsdSubDeviceReceiver) RedisOpsUtils.get(key); } public DroneStateDto getAirportFromCache(String deviceId) { OsdSubDeviceReceiver receiver = getDroneFromCache(deviceId); if (receiver == null) { throw new IllegalArgumentException("Receiver data not found for device ID: " + deviceId); } DroneStateDto.DroneStateDtoBuilder builder = DroneStateDto.builder(); builder.gimbalYal(receiver.getAttitudeHead() != null ? receiver.getAttitudeHead() : 0.0) .gimbalPitch(receiver.getAttitudePitch() != null ? receiver.getAttitudePitch() : 0.0) .batteryCapacityPercent(receiver.getBattery() != null ? receiver.getBattery().getCapacityPercent() : 0) .height(receiver.getHeight() != null ? receiver.getHeight() : 0.0) .latitude(receiver.getLatitude() != null ? receiver.getLatitude() : 0.0) .longitude(receiver.getLongitude() != null ? receiver.getLongitude() : 0.0) .modeCode(receiver.getModeCode() != null ? receiver.getModeCode().getVal() : 0) .elevation(receiver.getElevation() != null ? receiver.getElevation() : 0.0) .gpsState(2); return builder.build(); } public static AddTaskDto jsonToDto(JSONObject jsonObject) { AddTaskDto dto = new AddTaskDto(); String deviceid = jsonObject.getStr("deviceid"); dto.setDeviceid(deviceid); dto.setBizidname(jsonObject.getStr("bizidname")); JSONArray taskListArray = jsonObject.getJSONArray("tasklist"); if (taskListArray != null) { List taskList = new ArrayList<>(); for (int i = 0; i < taskListArray.size(); i++) { JSONObject taskObject = taskListArray.getJSONObject(i); if (taskObject != null) { TaskListDto task = new TaskListDto(); task.bsm = taskObject.getStr("bsm"); task.xzqdm = taskObject.getStr("xzqdm"); task.dkbh = taskObject.getStr("dkbh"); task.dklx = taskObject.getStr("dklx"); task.zdkbh = taskObject.getStr("zdkbh"); task.dkmc = taskObject.getStr("dkmc"); task.dkmj = taskObject.getDouble("dkmj"); task.dkfw = taskObject.getStr("dkfw"); task.bz = taskObject.getStr("bz"); taskList.add(task); } } dto.tasklist = taskList; } return dto; } public static UpdataTaskDto UpjsonToDto(JSONObject jsonObject) { UpdataTaskDto dto = new UpdataTaskDto(); String deviceid = jsonObject.getStr("deviceid"); String taskid = jsonObject.getStr("taskid"); dto.setDeviceid(deviceid); dto.setTaskid(taskid); JSONArray taskListArray = jsonObject.getJSONArray("tasklist"); if (taskListArray != null) { List taskList = new ArrayList<>(); for (int i = 0; i < taskListArray.size(); i++) { JSONObject taskObject = taskListArray.getJSONObject(i); if (taskObject != null) { TaskListDto task = new TaskListDto(); task.bsm = taskObject.getStr("bsm"); task.xzqdm = taskObject.getStr("xzqdm"); task.dkbh = taskObject.getStr("dkbh"); task.dklx = taskObject.getStr("dklx"); task.zdkbh = taskObject.getStr("zdkbh"); task.dkmc = taskObject.getStr("dkmc"); task.dkmj = taskObject.getDouble("dkmj"); task.dkfw = taskObject.getStr("dkfw"); task.bz = taskObject.getStr("bz"); taskList.add(task); } } dto.tasklist = taskList; } return dto; } public static LotInfo convertToLotInfo(TaskListDto taskListDto) { if (taskListDto == null) { return null; } return LotInfo.builder() .bsm(taskListDto.bsm) .dklx(taskListDto.dklx) .xzqdm(taskListDto.xzqdm) .dkbh(taskListDto.dkbh) .dkmc(taskListDto.dkmc) .dkmj(taskListDto.dkmj) .dkfw(taskListDto.dkfw) .bz(taskListDto.bz) .build(); } public static List convertStringToList(String input) { // 使用 Hutool 解析字符串 JSONArray jsonArray = JSONUtil.parseArray(input); // 将 JSONArray 转换为 List return jsonArray.stream() .map(Object::toString) .collect(Collectors.toList()); } public void updateTaskInfo(String traceid, String taskId, String deviceIds, String username) { TaskInfo taskInfo = new TaskInfo(); taskInfo.setId(traceid); taskInfo.setTaskId(taskId); taskInfo.setDeviceIds(deviceIds); taskInfo.setCreateUser(username); LambdaUpdateWrapper updateWrapper = new LambdaUpdateWrapper<>(); updateWrapper.eq(TaskInfo::getId, traceid); updateWrapper.eq(TaskInfo::getTaskId, taskId); // 执行更新操作 taskInfoMapper.update(taskInfo, updateWrapper); } public void delWaylineFile(String waylineId) { fileMapper.delete(new LambdaUpdateWrapper().eq(WaylineFileEntity::getWaylineId, waylineId)); } public void updateJob(String jobid, String waylineId) { LambdaUpdateWrapper updateWrapper = new LambdaUpdateWrapper<>(); updateWrapper.eq(WaylineJobEntity::getJobId, jobid) .set(WaylineJobEntity::getFileId, waylineId); // 调用 update 方法进行更新操作 waylineJobMapper.update(null, updateWrapper); } }