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.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.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.util.List; /** * 无人机控制切面 *

* 注意切面顺序:同类方法注解按字母ABCD顺序,不同类注解按order(1)顺序 越小优先级越高 */ @Aspect @Component public class UavControlAspect { @Resource private UavControlService uavControlService; @Resource private IArdNoFlyZoneService ardNoFlyZoneService; @Resource private RedisCache redisCache; /** * 控制权检查 */ @Before("@annotation(checkControlRight)") public void checkUavControl(JoinPoint joinPoint, CheckControlRight checkControlRight) { // 获取当前用户 ID Long userId = SecurityUtils.getUserId(); // 获取控制类型 UavControlType controlType = checkControlRight.value(); // 获取方法参数 Object[] args = joinPoint.getArgs(); for (Object arg : args) { 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) { // 获取最小高度 double minAltitude = checkTakeoffAltitude.minAltitude(); // 获取方法参数 Object[] args = joinPoint.getArgs(); // 遍历参数,使用反射获取每个参数中的 boxSn for (Object arg : args) { String boxSn = ReflectUtils.getFieldValue(arg, "boxSn"); // 调用之前实现的 getBoxSn 方法 if (boxSn != null) { TelemetryData uavTelemetryData = UavTelemetryDataCache.get(boxSn); if (uavTelemetryData == null) { throw new ControlException("遥测数据异常,无法执行!"); } // 检查高度 if (uavTelemetryData.getAltitude() < minAltitude) { throw new ControlException("高度太低,无法执行!最低高度: " + minAltitude); } } } } /** * 状态检查 */ @Before("@annotation(checkDroneStatus)") public void checkDroneStatus(JoinPoint joinPoint, CheckDroneStatus checkDroneStatus) { for (Object arg : joinPoint.getArgs()) { if (arg == null) { continue; } 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); } } } } /** * 禁飞区检查 */ @Before("@annotation(checkNoFlyZone)") public void checkNoFlyZone(JoinPoint joinPoint, CheckNoFlyZone checkNoFlyZone) { Object[] args = joinPoint.getArgs(); if (args == null || args.length == 0) { return; } 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 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("目标点在禁飞区内,无法执行操作!"); } } } }