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