liusuyi
2025-03-03 6531e781105e073a55a23529e2b7b31e85110951
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
package com.ard.tianyu.service.impl;
 
import com.alibaba.fastjson2.JSON;
import com.ard.common.exception.NoPermissionException;
import com.ard.common.utils.SecurityUtils;
import com.ard.tianyu.websocket.domain.ControlAuthorityDTO;
import com.ard.tianyu.websocket.domain.BaseMessage;
import com.ard.tianyu.websocket.utils.WebSocketUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
 
import java.util.concurrent.ConcurrentHashMap;
 
 
/**
 * 无人机控制管理器
 *
 * @author liusuyi
 * @date 2024年02月21日8:37
 **/
@Service
@Slf4j
public class UavControlManager {
 
    private static final String CONTROL_REQUEST_ACTION = "controlRequest";
    private static final String REQUEST_ACTION = "request";
    private static final String APPROVE_ACTION = "approve";
    private static final String REJECT_ACTION = "reject";
 
    // 存储每个无人机的当前控制者
    public static final ConcurrentHashMap<String, Long> uavControlMap = new ConcurrentHashMap<>();
    // 存储无人机的控制请求(用于判断哪个控制者正在等待)
    public static final ConcurrentHashMap<String, Long> controlRequestMap = new ConcurrentHashMap<>();
 
 
    /**
     * 申请控制
     *
     * @param boxSn 盒子编号
     */
    public boolean requestControl(String boxSn) {
        Long requester = SecurityUtils.getUserId();
        Long controller = uavControlMap.get(boxSn);
        // 如果无人机没有控制者,直接控制
        if (controller == null) {
            uavControlMap.put(boxSn, requester);
            log.info("控制权已授予给用户: {}", requester);
            return true; // 控制成功
        }
        // 如果无人机已经有控制者,则发送申请给当前控制者
        if (!controller.equals(requester)) {
            // 则将控制请求加入请求队列
            controlRequestMap.put(boxSn, requester);
            // 通知当前控制者,有新的控制请求
            notifyMessage(boxSn, REQUEST_ACTION, requester, controller);
            log.info("控制请求已发送给当前控制者: {}", controller);
        } else {
            throw new NoPermissionException("当前已经获取控制权,无需重复申请");
        }
        return false; // 等待当前控制者的同意
    }
 
    /**
     * 处理控制请求
     *
     * @param boxSn   盒子编号
     * @param approve 是否同意
     */
    public boolean handleControlResponse(String boxSn, boolean approve) {
        Long controller = SecurityUtils.getUserId();
        Long requester = controlRequestMap.get(boxSn);
 
        if (requester == null || requester.equals(controller)) {
            throw new NoPermissionException("无申请不需要处理控制权");
        }
 
        if (approve) {
            uavControlMap.put(boxSn, requester);
            notifyMessage(boxSn, APPROVE_ACTION, controller, requester);
            log.info("控制权已转移给用户: {}", requester);
        } else {
            notifyMessage(boxSn, REJECT_ACTION, controller, requester);
            log.info("控制请求被拒绝,请求者: {}", requester);
        }
 
        controlRequestMap.remove(boxSn);
        return true;
    }
 
    /**
     * 释放控制
     *
     * @param boxSn 盒子编号
     */
    public boolean releaseControl(String boxSn) {
        Long controller = uavControlMap.get(boxSn);
 
        if (controller == null) {
            log.warn("无人机当前 {} 没有控制者,无需释放", boxSn);
            throw new NoPermissionException("无人机" + boxSn + "当前没有控制者,无需释放");
        }
 
        if (!controller.equals(SecurityUtils.getUserId())) {
            log.warn("无权限释放控制, 实际控制者是 {}", controller);
            throw new NoPermissionException("无权限释放控制, 实际控制者是 " + controller);
        }
 
        uavControlMap.remove(boxSn);
        log.info("控制权已释放,无人机: {}", boxSn);
        return true;
    }
 
 
    /**
     * 释放指定用户控制的无人机
     *
     * @param userId 用户id
     */
    public void releaseAllControlByUser(String userId) {
        String boxSn = uavControlMap.entrySet().stream()
                .filter(entry -> entry.getValue().toString().equals(userId))
                .map(ConcurrentHashMap.Entry::getKey)
                .findFirst()
                .orElse(null);
        if (boxSn != null) {
            // 用户控制了某个无人机,移除缓存
            uavControlMap.remove(boxSn);
            log.info("移除{}控制的无人机: {}", userId, boxSn);
        }
    }
 
 
    /**
     * 发送消息给指定用户
     *
     * @param boxSn   盒子编号
     * @param action  指令()
     * @param source  发送方用户ID
     * @param target  接收方用户ID
     */
    private void notifyMessage(String boxSn, String action, Long source, Long target) {
        ControlAuthorityDTO controlAuthorityDTO = buildControlAuthorityDTO(boxSn, action, source);
        BaseMessage<ControlAuthorityDTO> baseMessage = buildBaseMessage(CONTROL_REQUEST_ACTION, controlAuthorityDTO);
        WebSocketUtil.sendMessage(target.toString(), JSON.toJSONString(baseMessage));
    }
 
    private ControlAuthorityDTO buildControlAuthorityDTO(String boxSn, String action, Long userId) {
        return ControlAuthorityDTO.builder()
                .boxSn(boxSn)
                .userId(userId)
                .action(action)
                .build();
    }
 
    private <T> BaseMessage<T> buildBaseMessage(String type, T data) {
        return new BaseMessage<>(type, data);
    }
}