| | |
| | | |
| | | import com.ard.common.exception.ControlException; |
| | | import com.ard.common.utils.SecurityUtils; |
| | | import com.ard.work.domain.message.UavControlType; |
| | | import com.ard.system.service.ISysUserService; |
| | | import com.ard.work.component.websocket.handler.UavControlManager; |
| | | import com.ard.work.domain.message.UavControlType; |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | import javax.annotation.Resource; |
| | | import java.util.HashMap; |
| | | import java.util.Map; |
| | | import java.util.Set; |
| | | import java.util.concurrent.ConcurrentHashMap; |
| | | |
| | | /** |
| | | * UAV控制服务类,负责管理对飞行和载荷的控制请求、释放和权限管理。 |
| | | * UAV控制服务类,负责管理对飞行和载荷的控制请求、释放和权限管理 |
| | | * 支持优先级抢占 |
| | | */ |
| | | @Service |
| | | public class UavControlService { |
| | |
| | | @Resource |
| | | private UavControlManager uavControlManager; |
| | | |
| | | @Resource |
| | | private ISysUserService sysUserService; |
| | | |
| | | /** |
| | | * 记录当前获得飞行控制权限的用户 |
| | | * 当前飞行控制权限用户 |
| | | */ |
| | | private final ConcurrentHashMap<String, Long> uavFlyControlMap = new ConcurrentHashMap<>(); |
| | | |
| | | /** |
| | | * 记录当前获得载荷控制权限的用户 |
| | | * 当前载荷控制权限用户 |
| | | */ |
| | | private final ConcurrentHashMap<String, Long> uavPayloadControlMap = new ConcurrentHashMap<>(); |
| | | |
| | | /** |
| | | * 记录飞行控制请求 |
| | | * 飞行控制请求:boxSn -> 多个请求者 |
| | | */ |
| | | private final ConcurrentHashMap<String, Long> flyControlRequests = new ConcurrentHashMap<>(); |
| | | private final ConcurrentHashMap<String, Set<Long>> flyControlRequests = new ConcurrentHashMap<>(); |
| | | |
| | | /** |
| | | * 记录载荷控制请求 |
| | | * 载荷控制请求 |
| | | */ |
| | | private final ConcurrentHashMap<String, Long> payloadControlRequests = new ConcurrentHashMap<>(); |
| | | private final ConcurrentHashMap<String, Set<Long>> payloadControlRequests = new ConcurrentHashMap<>(); |
| | | |
| | | |
| | | /** |
| | | * 请求获取 UAV 控制权限 |
| | | * |
| | | * @param boxSn 设备序列号 |
| | | * @param type 控制类型("fly"、"payload") |
| | | * @return 是否立即获得控制权限 |
| | | */ |
| | | public boolean requestControl(String boxSn, String type) { |
| | | UavControlType controlType = UavControlType.fromString(type); |
| | |
| | | /** |
| | | * 处理单个控制类型的请求 |
| | | */ |
| | | /** |
| | | * 处理单个控制类型的请求(支持多请求者) |
| | | */ |
| | | private boolean requestSingleControl(String boxSn, UavControlType controlType, Long requester) { |
| | | |
| | | ConcurrentHashMap<String, Long> controlMap = getControlMap(controlType); |
| | | ConcurrentHashMap<String, Long> requestMap = getRequestMap(controlType); |
| | | ConcurrentHashMap<String, Set<Long>> requestMap = getRequestMap(controlType); |
| | | |
| | | Long controller = controlMap.get(boxSn); |
| | | |
| | | // 无人控制 → 直接获取 |
| | | if (controller == null) { |
| | | controlMap.put(boxSn, requester); |
| | | uavControlManager.sendControlApproval(requester, boxSn, controlType.getType(), requester); |
| | | return true; |
| | | } |
| | | if (!controller.equals(requester)) { |
| | | requestMap.put(boxSn, requester); |
| | | uavControlManager.sendControlRequest(controller, boxSn, controlType.getType(), requester); |
| | | } else { |
| | | |
| | | // 已是控制者 |
| | | if (controller.equals(requester)) { |
| | | throw new ControlException("当前已拥有控制权"); |
| | | } |
| | | |
| | | int requesterPriority = getUserPriority(requester); |
| | | int controllerPriority = getUserPriority(controller); |
| | | |
| | | // 优先级高 → 直接接管 |
| | | if (requesterPriority > controllerPriority) { |
| | | controlMap.put(boxSn, requester); |
| | | |
| | | // 通知原控制者被抢占 |
| | | uavControlManager.sendControlTakeover(controller, requester, boxSn, controlType.getType()); |
| | | return true; |
| | | } |
| | | |
| | | // ===== 以下是关键改动点 ===== |
| | | |
| | | // 优先级相同或更低 → 加入请求集合(不覆盖) |
| | | Set<Long> requesters = requestMap.computeIfAbsent(boxSn, k -> ConcurrentHashMap.newKeySet()); |
| | | requesters.add(requester); |
| | | |
| | | // 通知当前控制者:有新的请求者 |
| | | uavControlManager.sendControlRequest(controller, boxSn, controlType.getType(), requester); |
| | | |
| | | return false; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 处理 UAV 控制请求的响应(同意或拒绝) |
| | | * |
| | | * @param boxSn 设备序列号 |
| | | * @param approve 是否同意 |
| | | * @param type 控制类型 |
| | | * @return 是否成功处理 |
| | | * 处理 UAV 控制请求的响应 |
| | | */ |
| | | public boolean handleControlResponse(String boxSn, boolean approve, String type) { |
| | | public boolean handleControlResponse(String boxSn, boolean approve, String type, Long requester) { |
| | | UavControlType controlType = UavControlType.fromString(type); |
| | | Long controller = SecurityUtils.getUserId(); |
| | | return handleSingleControlResponse(boxSn, approve, controlType, controller); |
| | | return handleSingleControlResponse(boxSn, approve, controlType, controller, requester); |
| | | } |
| | | |
| | | /** |
| | | * 处理单个控制类型的请求响应 |
| | | */ |
| | | private boolean handleSingleControlResponse(String boxSn, boolean approve, UavControlType controlType, |
| | | Long controller) { |
| | | ConcurrentHashMap<String, Long> requestMap = getRequestMap(controlType); |
| | | Long requester = requestMap.get(boxSn); |
| | | |
| | | if (requester == null || requester.equals(controller)) { |
| | | /** |
| | | * 处理单个控制类型请求响应 |
| | | */ |
| | | private boolean handleSingleControlResponse(String boxSn, |
| | | boolean approve, |
| | | UavControlType controlType, |
| | | Long controller, |
| | | Long requester) { |
| | | |
| | | ConcurrentHashMap<String, Set<Long>> requestMap = getRequestMap(controlType); |
| | | Set<Long> requesters = requestMap.get(boxSn); |
| | | |
| | | if (requesters == null || !requesters.contains(requester)) { |
| | | throw new ControlException("无控制请求"); |
| | | } |
| | | |
| | | if (approve) { |
| | | getControlMap(controlType).put(boxSn, requester); |
| | | uavControlManager.sendControlApproval(requester, boxSn, controlType.getType()); |
| | | |
| | | // 通知被批准者 |
| | | uavControlManager.sendControlApproval(requester, boxSn, controlType.getType(), controller); |
| | | |
| | | // 🚨 其他请求者自动拒绝(强烈建议) |
| | | for (Long other : requesters) { |
| | | if (!other.equals(requester)) { |
| | | requesters.remove(requester); |
| | | uavControlManager.sendControlRejection(other, boxSn, controlType.getType(), controller); |
| | | } |
| | | } |
| | | } else { |
| | | uavControlManager.sendControlRejection(requester, boxSn, controlType.getType()); |
| | | uavControlManager.sendControlRejection(requester, boxSn, controlType.getType(), controller); |
| | | } |
| | | |
| | | requestMap.remove(boxSn); |
| | | requesters.remove(requester); |
| | | if (requesters.isEmpty()) { |
| | | requestMap.remove(boxSn); |
| | | } |
| | | |
| | | return true; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 释放 UAV 控制权限 |
| | | * |
| | | * @param boxSn 设备序列号 |
| | | * @param type 控制类型 |
| | | * @return 是否成功释放控制 |
| | | */ |
| | | public boolean releaseControl(String boxSn, String type) { |
| | | UavControlType controlType = UavControlType.fromString(type); |
| | |
| | | } |
| | | |
| | | /** |
| | | * 释放单个控制类型的权限 |
| | | * 释放单个控制类型权限 |
| | | */ |
| | | private boolean releaseSingleControl(String boxSn, UavControlType controlType, Long controller) { |
| | | ConcurrentHashMap<String, Long> controlMap = getControlMap(controlType); |
| | |
| | | } |
| | | |
| | | controlMap.remove(boxSn); |
| | | uavControlManager.sendControlRelease(boxSn, controlType.getType()); |
| | | uavControlManager.sendControlRelease(boxSn, controlType.getType(), controller); |
| | | return true; |
| | | } |
| | | |
| | | /** |
| | | * 释放用户所有 UAV 控制权 |
| | | * 释放用户所有控制权限 |
| | | */ |
| | | public void releaseAllControls(Long userId) { |
| | | // 释放飞行控制 |
| | | uavFlyControlMap.entrySet().removeIf(entry -> entry.getValue().equals(userId)); |
| | | |
| | | // 释放载荷控制 |
| | | uavPayloadControlMap.entrySet().removeIf(entry -> entry.getValue().equals(userId)); |
| | | } |
| | | |
| | | /** |
| | | * 获取当前某设备的控制用户 |
| | | * |
| | | * @param boxSn 设备序列号 |
| | | * @param type 控制类型 |
| | | * @return 当前控制该设备的用户 ID |
| | | */ |
| | | public Long getCurrentController(String boxSn, String type) { |
| | | UavControlType controlType = UavControlType.fromString(type); |
| | | return getControlMap(controlType).get(boxSn); |
| | | } |
| | | public Map<String,Long> getCurrentController(String boxSn) { |
| | | Long flyController = uavFlyControlMap.get(boxSn); |
| | | Map<String,Long> map=new HashMap<>(); |
| | | map.put("flyController",flyController); |
| | | Long payloadController = uavPayloadControlMap.get(boxSn); |
| | | map.put("payloadController",payloadController); |
| | | |
| | | public Map<String, Long> getCurrentController(String boxSn) { |
| | | Map<String, Long> map = new HashMap<>(); |
| | | map.put("flyController", uavFlyControlMap.get(boxSn)); |
| | | map.put("payloadController", uavPayloadControlMap.get(boxSn)); |
| | | return map; |
| | | } |
| | | |
| | | /** |
| | | * 根据控制类型获取对应的控制 Map |
| | | * 根据控制类型获取对应控制 Map |
| | | */ |
| | | private ConcurrentHashMap<String, Long> getControlMap(UavControlType controlType) { |
| | | switch (controlType) { |
| | |
| | | } |
| | | |
| | | /** |
| | | * 根据控制类型获取对应的请求 Map |
| | | * 根据控制类型获取对应请求 Map |
| | | */ |
| | | private ConcurrentHashMap<String, Long> getRequestMap(UavControlType controlType) { |
| | | private ConcurrentHashMap<String, Set<Long>> getRequestMap(UavControlType controlType) { |
| | | switch (controlType) { |
| | | case FLY: |
| | | return flyControlRequests; |
| | |
| | | throw new IllegalArgumentException("不支持的控制类型"); |
| | | } |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 获取用户优先级 |
| | | */ |
| | | private int getUserPriority(Long userId) { |
| | | return sysUserService.selectUserById(userId).getPriority(); |
| | | } |
| | | } |