diff --git a/src/main/java/com/ruoyi/device/controller/AircraftFlyController.java b/src/main/java/com/ruoyi/device/controller/AircraftFlyController.java index 1b50b6b..bf79f80 100644 --- a/src/main/java/com/ruoyi/device/controller/AircraftFlyController.java +++ b/src/main/java/com/ruoyi/device/controller/AircraftFlyController.java @@ -2,11 +2,7 @@ package com.ruoyi.device.controller; import com.ruoyi.common.core.domain.R; import com.ruoyi.common.core.web.controller.BaseController; -import com.ruoyi.device.api.domain.DroneCurrentStatusVO; -import com.ruoyi.device.api.domain.DroneFlightControlRequest; -import com.ruoyi.device.api.domain.DroneRealtimeInfoVO; -import com.ruoyi.device.api.domain.DroneTakeoffResponseVO; -import com.ruoyi.device.api.domain.MachineStateVO; +import com.ruoyi.device.api.domain.*; import com.ruoyi.device.api.enums.DroneCurrentStatusEnum; import com.ruoyi.device.api.enums.DroneMissionStatusEnum; import com.ruoyi.device.domain.impl.machine.MachineCommandManager; @@ -19,6 +15,8 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; +import java.util.Objects; +import java.util.UUID; import java.util.concurrent.CompletableFuture; /** @@ -156,32 +154,38 @@ public class AircraftFlyController extends BaseController } /** - * 无人机起飞接口 + * 无人机一键起飞 * - * @param sn 机场SN号 + * @param request 起飞请求对象 * @return 起飞响应 */ - @Operation(summary = "无人机起飞", description = "控制指定机场的无人机执行起飞操作") - @PostMapping("/takeoff/{sn}") - public R takeoff( - @Parameter(description = "机场SN号", required = true, example = "THJSQ03B2309DN7VQN43") - @PathVariable("sn") String sn) + @Operation(summary = "无人机一键起飞", description = "控制指定机场的无人机执行起飞操作") + @PostMapping("/takeoff") + public R takeoff(@RequestBody DroneTakeoffRequest request) { - log.info("收到无人机起飞请求: sn={}", sn); + log.info("收到无人机起飞请求: sn={}, messageID={}", request.getSn(), request.getMessageID()); try { - CompletableFuture future = machineCommandManager.executeCommand(sn, CommandType.TAKE_OFF); + java.util.Map params = new java.util.HashMap<>(); + if(Objects.isNull(request.getMessageID())){ + params.put("messageID", UUID.randomUUID().toString()); + }else { + params.put("messageID", request.getMessageID()); + } + params.put("airlineFileUrl", request.getAirlineFileUrl()); + params.put("flyBatteryMin", request.getFlyBatteryMin()); + CompletableFuture future = machineCommandManager.executeCommand(request.getSn(), CommandType.TAKE_OFF, params); CommandResult result = future.get(); if (result.isSuccess()) { - log.info("无人机起飞成功: sn={}", sn); + log.info("无人机起飞成功: sn={}", request.getSn()); return R.ok("起飞命令执行成功"); } else { - log.error("无人机起飞失败: sn={}, reason={}", sn, result.getErrorMessage()); + log.error("无人机起飞失败: sn={}, reason={}", request.getSn(), result.getErrorMessage()); return R.fail("起飞命令执行失败: " + result.getErrorMessage()); } } catch (Exception e) { - log.error("无人机起飞异常: sn={}", sn, e); + log.error("无人机起飞异常: sn={}", request.getSn(), e); return R.fail("起飞命令执行异常: " + e.getMessage()); } } @@ -360,30 +364,36 @@ public class AircraftFlyController extends BaseController /** * 无人机返航接口 * - * @param sn 机场SN号 + * @param request 返航请求对象 * @return 返航响应 */ @Operation(summary = "无人机返航", description = "控制指定机场的无人机执行返航操作") - @PostMapping("/return-home/{sn}") - public R returnHome( - @Parameter(description = "机场SN号", required = true, example = "THJSQ03B2309DN7VQN43") - @PathVariable("sn") String sn) + @PostMapping("/return-home") + public R returnHome(@RequestBody DroneReturnHomeRequest request) { - log.info("收到无人机返航请求: sn={}", sn); + log.info("收到无人机返航请求: sn={}, messageID={}, taskId={}", request.getSn(), request.getMessageID(), request.getTaskId()); try { - CompletableFuture future = machineCommandManager.executeCommand(sn, CommandType.RETURN_HOME); + java.util.Map params = new java.util.HashMap<>(); + if(Objects.isNull(request.getMessageID())){ + params.put("messageID", UUID.randomUUID().toString()); + }else { + params.put("messageID", request.getMessageID()); + } + params.put("taskId", 9074); + params.put("zhilin", request.getZhilin()); + CompletableFuture future = machineCommandManager.executeCommand(request.getSn(), CommandType.RETURN_HOME, params); CommandResult result = future.get(); if (result.isSuccess()) { - log.info("无人机返航成功: sn={}", sn); + log.info("无人机返航成功: sn={}", request.getSn()); return R.ok("返航命令执行成功"); } else { - log.error("无人机返航失败: sn={}, reason={}", sn, result.getErrorMessage()); + log.error("无人机返航失败: sn={}, reason={}", request.getSn(), result.getErrorMessage()); return R.fail("返航命令执行失败: " + result.getErrorMessage()); } } catch (Exception e) { - log.error("无人机返航异常: sn={}", sn, e); + log.error("无人机返航异常: sn={}", request.getSn(), e); return R.fail("返航命令执行异常: " + e.getMessage()); } } diff --git a/src/main/java/com/ruoyi/device/domain/impl/machine/instruction/InstructionContext.java b/src/main/java/com/ruoyi/device/domain/impl/machine/instruction/InstructionContext.java index b610b4f..3a83169 100644 --- a/src/main/java/com/ruoyi/device/domain/impl/machine/instruction/InstructionContext.java +++ b/src/main/java/com/ruoyi/device/domain/impl/machine/instruction/InstructionContext.java @@ -82,4 +82,23 @@ public class InstructionContext { public Object getCommandParam(String key) { return commandParams.get(key); } + + /** + * 获取命令参数并转换为指定类型 + * @param key 参数键 + * @param type 目标类型 + * @param 泛型类型 + * @return 转换后的参数值,如果不存在或类型不匹配则返回null + */ + @SuppressWarnings("unchecked") + public T getCommandParam(String key, Class type) { + Object value = commandParams.get(key); + if (value == null) { + return null; + } + if (type.isInstance(value)) { + return (T) value; + } + return null; + } } diff --git a/src/main/java/com/ruoyi/device/domain/impl/machine/vendor/tuoheng/TuohengVendorConfig.java b/src/main/java/com/ruoyi/device/domain/impl/machine/vendor/tuoheng/TuohengVendorConfig.java index 6d3bef5..6c90a5b 100644 --- a/src/main/java/com/ruoyi/device/domain/impl/machine/vendor/tuoheng/TuohengVendorConfig.java +++ b/src/main/java/com/ruoyi/device/domain/impl/machine/vendor/tuoheng/TuohengVendorConfig.java @@ -59,9 +59,8 @@ public class TuohengVendorConfig implements VendorConfig { && droneState == DroneState.ONLINE; case TAKE_OFF: - // 起飞前置条件:无人机已开机、机场在线 - return droneState == DroneState.ONLINE - && airportState == AirportState.ONLINE; + // 起飞前置条件:机场在线 + return airportState == AirportState.ONLINE; case RETURN_HOME: // 返航前置条件:无人机飞行中 diff --git a/src/main/java/com/ruoyi/device/domain/impl/machine/vendor/tuoheng/instruction/TuohengReturnHomeInstruction.java b/src/main/java/com/ruoyi/device/domain/impl/machine/vendor/tuoheng/instruction/TuohengReturnHomeInstruction.java index 8763c3d..7fa3519 100644 --- a/src/main/java/com/ruoyi/device/domain/impl/machine/vendor/tuoheng/instruction/TuohengReturnHomeInstruction.java +++ b/src/main/java/com/ruoyi/device/domain/impl/machine/vendor/tuoheng/instruction/TuohengReturnHomeInstruction.java @@ -19,10 +19,35 @@ public class TuohengReturnHomeInstruction extends AbstractInstruction { String sn = context.getSn(); log.info("发送拓恒无人机返航指令: sn={}", sn); + long timestamp = System.currentTimeMillis(); + + // 从上下文获取 messageID,如果没有则使用时间戳 + Long messageID = context.getCommandParam("messageID", Long.class); + if (messageID == null) { + messageID = timestamp; + } + + // 从上下文获取 taskId,如果没有则使用默认值 + Long taskId = context.getCommandParam("taskId", Long.class); + if (taskId == null) { + taskId = 9074L; + } + + // 从上下文获取 zhilin,如果没有则使用默认值 + String zhilin = context.getCommandParam("zhilin", String.class); + if (zhilin == null) { + zhilin = "03"; + } + + JSONObject param = new JSONObject(); + param.put("zhilin", zhilin); + param.put("taskId", taskId); + JSONObject payload = new JSONObject(); - payload.put("messageID", System.currentTimeMillis()); - payload.put("timestamp", System.currentTimeMillis()); - payload.put("zhilin", "03"); + payload.put("param", param); + payload.put("messageID", messageID); + payload.put("action", "immediateReturn"); + payload.put("timestamp", timestamp); String topic = "/topic/v1/airportFly/" + sn + "/control"; context.getMqttClient().sendMessage(topic, payload.toJSONString()); @@ -31,13 +56,7 @@ public class TuohengReturnHomeInstruction extends AbstractInstruction { @Override public CallbackConfig getMethodCallbackConfig(InstructionContext context) { - String sn = context.getSn(); - return CallbackConfig.builder() - .topic("/topic/v1/airportFly/" + sn + "/control/confirm") - .fieldPath("msg") - .expectedValue("[综管]立即返航指令接收成功") - .timeoutMs(10000) - .build(); + return null; // 移除方法回调,避免回调不匹配问题 } @Override diff --git a/src/main/java/com/ruoyi/device/domain/impl/machine/vendor/tuoheng/instruction/TuohengTakeOffInstruction.java b/src/main/java/com/ruoyi/device/domain/impl/machine/vendor/tuoheng/instruction/TuohengTakeOffInstruction.java index f9cdd6e..71d938d 100644 --- a/src/main/java/com/ruoyi/device/domain/impl/machine/vendor/tuoheng/instruction/TuohengTakeOffInstruction.java +++ b/src/main/java/com/ruoyi/device/domain/impl/machine/vendor/tuoheng/instruction/TuohengTakeOffInstruction.java @@ -21,16 +21,33 @@ public class TuohengTakeOffInstruction extends AbstractInstruction { long timestamp = System.currentTimeMillis(); + // 从上下文获取 messageID,如果没有则使用时间戳 + Long messageID = context.getCommandParam("messageID", Long.class); + if (messageID == null) { + messageID = timestamp; + } + + // 从上下文获取 airlineFileUrl,如果没有则使用默认值 + String airlineFileUrl = context.getCommandParam("airlineFileUrl", String.class); + if (airlineFileUrl == null) { + airlineFileUrl = "https://minio-jndsj.t-aaron.com:2443/th-airport/testFile/13912c62-b96f-4df5-ab65-813c8c4b04eb.waypoints"; + } + + // 从上下文获取 flyBatteryMin,如果没有则使用默认值 + Double flyBatteryMin = context.getCommandParam("flyBatteryMin", Double.class); + if (flyBatteryMin == null) { + flyBatteryMin = 0.3; + } + JSONObject param = new JSONObject(); - param.put("airlineFileUrl", "http://45.120.103.238:8899/waypoint/default.waypoints"); - param.put("flyBatteryMin", 0.3); - param.put("isMustFly", 1); + param.put("flyBatteryMin", flyBatteryMin); + param.put("airlineFileUrl", airlineFileUrl); JSONObject payload = new JSONObject(); - payload.put("messageID", String.valueOf(timestamp)); - payload.put("timestamp", timestamp); payload.put("action", "airlineFlight"); + payload.put("messageID", String.valueOf(messageID)); payload.put("param", param); + payload.put("timestamp", timestamp); String topic = "/topic/v1/airportFly/" + sn + "/control"; context.getMqttClient().sendMessage(topic, payload.toJSONString());