From f9b841b419c0d57679e535604b87d8b263390535 Mon Sep 17 00:00:00 2001
From: liusuyi <1951119284@qq.com>
Date: Thu, 13 Nov 2025 08:08:13 +0800
Subject: [PATCH] 修复无人机在线检查

---
 ard-work/src/main/java/com/ard/work/aspect/UavControlAspect.java |  150 ++++++++++++++++++++++++++++++++++----------------
 1 files changed, 102 insertions(+), 48 deletions(-)

diff --git a/ard-work/src/main/java/com/ard/work/aspect/UavControlAspect.java b/ard-work/src/main/java/com/ard/work/aspect/UavControlAspect.java
index 5cd5cd4..0450d6a 100644
--- a/ard-work/src/main/java/com/ard/work/aspect/UavControlAspect.java
+++ b/ard-work/src/main/java/com/ard/work/aspect/UavControlAspect.java
@@ -1,24 +1,35 @@
 package com.ard.work.aspect;
 
+import com.ard.common.constant.CacheConstants;
+import com.ard.common.core.redis.RedisCache;
 import com.ard.common.exception.ControlException;
 import com.ard.common.utils.SecurityUtils;
-import com.ard.work.aspect.annotation.CheckTakeoffAltitude;
+import com.ard.common.utils.StringUtils;
+import com.ard.common.utils.reflect.ReflectUtils;
+import com.ard.data.noflyzone.domain.ArdNoFlyZone;
+import com.ard.data.noflyzone.domain.Vertex;
+import com.ard.data.noflyzone.service.IArdNoFlyZoneService;
+import com.ard.data.noflyzone.utils.NoFlyZoneUtils;
 import com.ard.work.aspect.annotation.CheckControlRight;
+import com.ard.work.aspect.annotation.CheckDroneStatus;
+import com.ard.work.aspect.annotation.CheckNoFlyZone;
+import com.ard.work.aspect.annotation.CheckTakeoffAltitude;
 import com.ard.work.domain.cache.UavTelemetryDataCache;
 import com.ard.work.domain.dto.telemetry.TelemetryData;
-import com.ard.work.service.control.UavControlService;
 import com.ard.work.domain.message.UavControlType;
+import com.ard.work.domain.receiver.BoxInfoReceiver;
+import com.ard.work.service.control.UavControlService;
 import org.aspectj.lang.JoinPoint;
 import org.aspectj.lang.annotation.Aspect;
 import org.aspectj.lang.annotation.Before;
 import org.springframework.stereotype.Component;
 
 import javax.annotation.Resource;
-import java.lang.reflect.Field;
+import java.util.List;
 
 /**
- * AOP 切面:拦截 @RequireUavControl,检查用户是否拥有 UAV 控制权限
- *
+ * 无人机控制切面
+ * <p>
  * 注意切面顺序:同类方法注解按字母ABCD顺序,不同类注解按order(1)顺序 越小优先级越高
  */
 @Aspect
@@ -27,9 +38,13 @@
 
     @Resource
     private UavControlService uavControlService;
+    @Resource
+    private IArdNoFlyZoneService ardNoFlyZoneService;
+    @Resource
+    private RedisCache redisCache;
 
     /**
-     * 前置通知:控制权检测
+     * 控制权检查
      */
     @Before("@annotation(checkControlRight)")
     public void checkUavControl(JoinPoint joinPoint, CheckControlRight checkControlRight) {
@@ -42,22 +57,35 @@
         // 获取方法参数
         Object[] args = joinPoint.getArgs();
 
-        // 遍历参数,使用反射获取每个参数中的 boxSn
         for (Object arg : args) {
-            String boxSn = getBoxSn(arg);  // 调用之前实现的 getBoxSn 方法
-            if (boxSn != null) {
-                // 检查当前用户是否拥有该设备的控制权限
-                Long currentController = uavControlService.getCurrentController(boxSn,
-                        controlType.name().toLowerCase());
-                if (currentController == null || !currentController.equals(userId)) {
-                    throw new ControlException("无权执行该操作,需要 " + controlType + " 控制权限");
-                }
+            if (arg == null) {
+                continue;
             }
+
+            // 1️⃣ 获取 boxSn
+            String boxSn = ReflectUtils.getFieldValue(arg, "boxSn");
+            if (StringUtils.isBlank(boxSn)) {
+                continue;
+            }
+
+            // 2️⃣ 检查控制权
+            Long currentController = uavControlService.getCurrentController(boxSn,
+                    controlType.name().toLowerCase());
+            if (currentController == null || !currentController.equals(userId)) {
+                throw new ControlException("无权执行该操作,需要 " + controlType + " 控制权限");
+            }
+
+            // 3️⃣ 检查在线状态
+            BoxInfoReceiver obj = redisCache.getCacheObject(CacheConstants.UAV_ONLINE_KEY + boxSn);
+            if (obj == null || !obj.getOnLine().equals(1)) {
+                throw new ControlException("无人机离线,无法执行操作!boxSn: " + boxSn);
+            }
+
         }
     }
 
     /**
-     * 前置通知:高度检查
+     * 高度检查
      */
     @Before("@annotation(checkTakeoffAltitude)")
     public void takeoffAltitudeCheck(JoinPoint joinPoint, CheckTakeoffAltitude checkTakeoffAltitude) {
@@ -68,9 +96,9 @@
 
         // 遍历参数,使用反射获取每个参数中的 boxSn
         for (Object arg : args) {
-            String boxSn = getBoxSn(arg);  // 调用之前实现的 getBoxSn 方法
+            String boxSn = ReflectUtils.getFieldValue(arg, "boxSn");  // 调用之前实现的 getBoxSn 方法
             if (boxSn != null) {
-                TelemetryData uavTelemetryData = UavTelemetryDataCache.getUavTelemetryData(boxSn);
+                TelemetryData uavTelemetryData = UavTelemetryDataCache.get(boxSn);
                 if (uavTelemetryData == null) {
                     throw new ControlException("遥测数据异常,无法执行!");
                 }
@@ -83,41 +111,67 @@
     }
 
     /**
-     * 通过反射获取对象中的 boxSn 字段
-     *
-     * @param dto 要反射的对象
-     * @return boxSn 字段的值,如果没有找到则返回 null
+     * 状态检查
      */
-    public static String getBoxSn(Object dto) {
-        if (dto == null) {
-            return null; // 如果对象为空,直接返回 null
-        }
+    @Before("@annotation(checkDroneStatus)")
+    public void checkDroneStatus(JoinPoint joinPoint, CheckDroneStatus checkDroneStatus) {
+        for (Object arg : joinPoint.getArgs()) {
+            if (arg == null) {
+                continue;
+            }
 
-        try {
-            // 获取类的所有字段
-            Field[] fields = dto.getClass().getDeclaredFields();
-            for (Field field : fields) {
-                // 设置字段可访问
-                field.setAccessible(true);
-
-                // 判断是否是 boxSn 字段
-                if ("boxSn".equals(field.getName())) {
-                    // 检查字段类型是否是 String 类型
-                    if (field.getType().equals(String.class)) {
-                        // 获取并返回 boxSn 字段的值
-                        return (String) field.get(dto);
-                    } else {
-                        // 如果字段类型不是 String,返回 null
-                        return null;
-                    }
+            String boxSn = ReflectUtils.getFieldValue(arg, "boxSn");
+            if (boxSn == null) {
+                continue;
+            }
+            // 检查在线状态
+            if (checkDroneStatus.checkOnline()) {
+                Boolean online = redisCache.getCacheObject(CacheConstants.UAV_ONLINE_KEY + boxSn);
+                if (online == null || !online) {
+                    throw new ControlException("无人机离线,无法执行操作!boxSn: " + boxSn);
                 }
             }
-        } catch (IllegalAccessException e) {
-            // 捕获异常并打印日志
-            System.err.println("反射访问失败: " + e.getMessage());
-            e.printStackTrace();
+        }
+    }
+
+    /**
+     * 禁飞区检查
+     */
+    @Before("@annotation(checkNoFlyZone)")
+    public void checkNoFlyZone(JoinPoint joinPoint, CheckNoFlyZone checkNoFlyZone) {
+        Object[] args = joinPoint.getArgs();
+        if (args == null || args.length == 0) {
+            return;
         }
 
-        return null; // 如果没有找到 boxSn 字段,返回 null
+        Double longitude = null;
+        Double latitude = null;
+
+        for (Object arg : args) {
+            if (arg == null) {
+                continue;
+            }
+            Double lon = ReflectUtils.getFieldValue(arg, "longitude");
+            Double lat = ReflectUtils.getFieldValue(arg, "latitude");
+            if (lon != null && lat != null) {
+                longitude = lon;
+                latitude = lat;
+                break;
+            }
+        }
+
+        if (longitude == null || latitude == null) {
+            throw new ControlException("方法参数中未找到有效经纬度字段,无法判断禁飞区!");
+        }
+
+        List<ArdNoFlyZone> ardNoFlyZones = ardNoFlyZoneService.selectArdNoFlyZoneList(new ArdNoFlyZone());
+        if (!ardNoFlyZones.isEmpty()) {
+            Vertex vertex = new Vertex(longitude, latitude);
+            boolean inNoFlyZones = NoFlyZoneUtils.isInNoFlyZones(vertex, ardNoFlyZones);
+            if (inNoFlyZones) {
+                throw new ControlException("目标点在禁飞区内,无法执行操作!");
+            }
+        }
     }
+
 }

--
Gitblit v1.9.3