From c5b490be173ae53bf6423dba76be8ab72fafd12a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AD=99=E5=B0=8F=E4=BA=91?= Date: Wed, 4 Mar 2026 15:04:21 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=20=E8=88=AA=E7=BA=BF?= =?UTF-8?q?=E8=B5=B7=E9=A3=9E=20=E6=82=AC=E5=81=9C=20=E7=BB=A7=E7=BB=AD?= =?UTF-8?q?=E4=BB=BB=E5=8A=A1=E6=8C=87=E4=BB=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/AircraftFlyController.java | 30 +++++++ .../impl/machine/command/CommandType.java | 17 +++- .../vendor/tuoheng/TuohengVendorConfig.java | 15 ++++ .../TuohengAirlineFlightInstruction.java | 78 +++++++++++++++++++ .../TuohengContinueTaskInstruction.java | 71 +++++++++++++++++ .../instruction/TuohengHoverInstruction.java | 71 +++++++++++++++++ 6 files changed, 281 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/ruoyi/device/domain/impl/machine/vendor/tuoheng/instruction/TuohengAirlineFlightInstruction.java create mode 100644 src/main/java/com/ruoyi/device/domain/impl/machine/vendor/tuoheng/instruction/TuohengContinueTaskInstruction.java create mode 100644 src/main/java/com/ruoyi/device/domain/impl/machine/vendor/tuoheng/instruction/TuohengHoverInstruction.java diff --git a/src/main/java/com/ruoyi/device/controller/AircraftFlyController.java b/src/main/java/com/ruoyi/device/controller/AircraftFlyController.java index 7f9acc3..9e2eaa4 100644 --- a/src/main/java/com/ruoyi/device/controller/AircraftFlyController.java +++ b/src/main/java/com/ruoyi/device/controller/AircraftFlyController.java @@ -80,6 +80,27 @@ public class AircraftFlyController extends BaseController params.put("lightMode", request.getLightMode()); } + // 处理航线飞行、悬停、继续任务所需的参数 + if (request.getAirlineFileUrl() != null) { + params.put("airlineFileUrl", request.getAirlineFileUrl()); + } + + if (request.getFlyBatteryMin() != null) { + params.put("flyBatteryMin", request.getFlyBatteryMin()); + } + + if (request.getIsMustFly() != null) { + params.put("isMustFly", request.getIsMustFly()); + } + + if (request.getTaskId() != null) { + params.put("taskId", request.getTaskId()); + } + + if (request.getZhilin() != null) { + params.put("zhilin", request.getZhilin()); + } + switch (request.getCommand()) { case FORWARD: commandType = CommandType.FORWARD; @@ -132,6 +153,15 @@ public class AircraftFlyController extends BaseController case GIMBAL_RESET: commandType = CommandType.GIMBAL_RESET; break; + case AIRLINE_FLIGHT: + commandType = CommandType.AIRLINE_FLIGHT; + break; + case HOVER: + commandType = CommandType.HOVER; + break; + case CONTINUE_TASK: + commandType = CommandType.CONTINUE_TASK; + break; case EMERGENCY_STOP: return R.fail("急停命令暂不支持"); default: diff --git a/src/main/java/com/ruoyi/device/domain/impl/machine/command/CommandType.java b/src/main/java/com/ruoyi/device/domain/impl/machine/command/CommandType.java index fc1cc0d..261458e 100644 --- a/src/main/java/com/ruoyi/device/domain/impl/machine/command/CommandType.java +++ b/src/main/java/com/ruoyi/device/domain/impl/machine/command/CommandType.java @@ -177,5 +177,20 @@ public enum CommandType { /** * 云台复位 */ - GIMBAL_RESET + GIMBAL_RESET, + + /** + * 航线飞行 + */ + AIRLINE_FLIGHT, + + /** + * 悬停 + */ + HOVER, + + /** + * 继续任务 + */ + CONTINUE_TASK } 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 722b4a0..246428e 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 @@ -186,6 +186,21 @@ public class TuohengVendorConfig implements VendorConfig { .root(new com.ruoyi.device.domain.impl.machine.vendor.tuoheng.instruction.TuohengGimbalResetInstruction()) .setTimeout(5000)); + // 航线飞行命令 + transactionMap.put(CommandType.AIRLINE_FLIGHT, new Transaction("航线飞行", CommandType.AIRLINE_FLIGHT) + .root(new com.ruoyi.device.domain.impl.machine.vendor.tuoheng.instruction.TuohengAirlineFlightInstruction()) + .setTimeout(300000)); + + // 悬停命令 + transactionMap.put(CommandType.HOVER, new Transaction("悬停", CommandType.HOVER) + .root(new com.ruoyi.device.domain.impl.machine.vendor.tuoheng.instruction.TuohengHoverInstruction()) + .setTimeout(15000)); + + // 继续任务命令 + transactionMap.put(CommandType.CONTINUE_TASK, new Transaction("继续任务", CommandType.CONTINUE_TASK) + .root(new com.ruoyi.device.domain.impl.machine.vendor.tuoheng.instruction.TuohengContinueTaskInstruction()) + .setTimeout(15000)); + log.info("拓恒厂家配置初始化完成,共配置{}个命令", transactionMap.size()); } } \ No newline at end of file diff --git a/src/main/java/com/ruoyi/device/domain/impl/machine/vendor/tuoheng/instruction/TuohengAirlineFlightInstruction.java b/src/main/java/com/ruoyi/device/domain/impl/machine/vendor/tuoheng/instruction/TuohengAirlineFlightInstruction.java new file mode 100644 index 0000000..19e63fc --- /dev/null +++ b/src/main/java/com/ruoyi/device/domain/impl/machine/vendor/tuoheng/instruction/TuohengAirlineFlightInstruction.java @@ -0,0 +1,78 @@ +package com.ruoyi.device.domain.impl.machine.vendor.tuoheng.instruction; + +import com.alibaba.fastjson.JSONObject; +import com.ruoyi.device.domain.impl.machine.instruction.AbstractInstruction; +import com.ruoyi.device.domain.impl.machine.instruction.CallbackConfig; +import com.ruoyi.device.domain.impl.machine.instruction.InstructionContext; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class TuohengAirlineFlightInstruction extends AbstractInstruction { + + @Override + public String getName() { + return "TUOHENG_AIRLINE_FLIGHT"; + } + + @Override + public void executeRemoteCall(InstructionContext context) throws Exception { + 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; + } + + // 从上下文获取 airlineFileUrl,如果没有则使用默认值 + String airlineFileUrl = context.getCommandParam("airlineFileUrl", String.class); + if (airlineFileUrl == null) { + throw new Exception("航线文件URL不能为空"); + } + + // 从上下文获取 flyBatteryMin,如果没有则使用默认值 + Double flyBatteryMin = context.getCommandParam("flyBatteryMin", Double.class); + if (flyBatteryMin == null) { + flyBatteryMin = 0.3; + } + + // 从上下文获取 isMustFly,如果没有则使用默认值 + Integer isMustFly = context.getCommandParam("isMustFly", Integer.class); + if (isMustFly == null) { + isMustFly = 0; + } + + JSONObject param = new JSONObject(); + param.put("flyBatteryMin", flyBatteryMin); + param.put("isMustFly", isMustFly); + param.put("airlineFileUrl", airlineFileUrl); + + JSONObject payload = new JSONObject(); + 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()); + log.info("拓恒航线飞行指令发送成功: topic={}, payload={}", topic, payload.toJSONString()); + } + + @Override + public CallbackConfig getMethodCallbackConfig(InstructionContext context) { + return null; + } + + @Override + public CallbackConfig getStateCallbackConfig(InstructionContext context) { + return null; + } + + @Override + public long getTimeoutMs() { + return 300000; + } +} \ No newline at end of file diff --git a/src/main/java/com/ruoyi/device/domain/impl/machine/vendor/tuoheng/instruction/TuohengContinueTaskInstruction.java b/src/main/java/com/ruoyi/device/domain/impl/machine/vendor/tuoheng/instruction/TuohengContinueTaskInstruction.java new file mode 100644 index 0000000..e41337e --- /dev/null +++ b/src/main/java/com/ruoyi/device/domain/impl/machine/vendor/tuoheng/instruction/TuohengContinueTaskInstruction.java @@ -0,0 +1,71 @@ +package com.ruoyi.device.domain.impl.machine.vendor.tuoheng.instruction; + +import com.alibaba.fastjson.JSONObject; +import com.ruoyi.device.domain.impl.machine.instruction.AbstractInstruction; +import com.ruoyi.device.domain.impl.machine.instruction.CallbackConfig; +import com.ruoyi.device.domain.impl.machine.instruction.InstructionContext; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class TuohengContinueTaskInstruction extends AbstractInstruction { + + @Override + public String getName() { + return "TUOHENG_CONTINUE_TASK"; + } + + @Override + public void executeRemoteCall(InstructionContext context) throws Exception { + 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) { +// throw new Exception("任务ID不能为空"); +// } + + // 从上下文获取 zhilin,如果没有则使用默认值 + String zhilin = context.getCommandParam("zhilin", String.class); + if (zhilin == null) { + zhilin = "04"; + } + + JSONObject param = new JSONObject(); + param.put("zhilin", zhilin); + param.put("taskId", 0); + + JSONObject payload = new JSONObject(); + payload.put("param", param); + payload.put("messageID", messageID); + payload.put("action", "continueTask"); + payload.put("timestamp", timestamp); + + String topic = "/topic/v1/airportFly/" + sn + "/control"; + context.getMqttClient().sendMessage(topic, payload.toJSONString()); + log.info("拓恒继续任务指令发送成功: topic={}, payload={}", topic, payload.toJSONString()); + } + + @Override + public CallbackConfig getMethodCallbackConfig(InstructionContext context) { + return null; + } + + @Override + public CallbackConfig getStateCallbackConfig(InstructionContext context) { + return null; + } + + @Override + public long getTimeoutMs() { + return 15000; + } +} \ No newline at end of file diff --git a/src/main/java/com/ruoyi/device/domain/impl/machine/vendor/tuoheng/instruction/TuohengHoverInstruction.java b/src/main/java/com/ruoyi/device/domain/impl/machine/vendor/tuoheng/instruction/TuohengHoverInstruction.java new file mode 100644 index 0000000..f05f0af --- /dev/null +++ b/src/main/java/com/ruoyi/device/domain/impl/machine/vendor/tuoheng/instruction/TuohengHoverInstruction.java @@ -0,0 +1,71 @@ +package com.ruoyi.device.domain.impl.machine.vendor.tuoheng.instruction; + +import com.alibaba.fastjson.JSONObject; +import com.ruoyi.device.domain.impl.machine.instruction.AbstractInstruction; +import com.ruoyi.device.domain.impl.machine.instruction.CallbackConfig; +import com.ruoyi.device.domain.impl.machine.instruction.InstructionContext; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class TuohengHoverInstruction extends AbstractInstruction { + + @Override + public String getName() { + return "TUOHENG_HOVER"; + } + + @Override + public void executeRemoteCall(InstructionContext context) throws Exception { + 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) { +// throw new Exception("任务ID不能为空"); +// } + + // 从上下文获取 zhilin,如果没有则使用默认值 + String zhilin = context.getCommandParam("zhilin", String.class); + if (zhilin == null) { + zhilin = "01"; + } + + JSONObject param = new JSONObject(); + param.put("zhilin", zhilin); + param.put("taskId", 0); + + JSONObject payload = new JSONObject(); + payload.put("param", param); + payload.put("messageID", messageID); + payload.put("action", "hover"); + payload.put("timestamp", timestamp); + + String topic = "/topic/v1/airportFly/" + sn + "/control"; + context.getMqttClient().sendMessage(topic, payload.toJSONString()); + log.info("拓恒悬停指令发送成功: topic={}, payload={}", topic, payload.toJSONString()); + } + + @Override + public CallbackConfig getMethodCallbackConfig(InstructionContext context) { + return null; + } + + @Override + public CallbackConfig getStateCallbackConfig(InstructionContext context) { + return null; + } + + @Override + public long getTimeoutMs() { + return 15000; + } +} \ No newline at end of file