liusuyi
2025-03-19 d267efe74181bbc89e7ecda1032f11965984769b
增加状态统一订阅 增加载荷和飞控用户同时获取
1 files added
10 files modified
229 ■■■■■ changed files
ard-work/src/main/java/com/ard/tianyu/controller/UavControlController.java 15 ●●●●● patch | view | raw | blame | history
ard-work/src/main/java/com/ard/tianyu/controller/UavRealDataController.java 1 ●●●●● patch | view | raw | blame | history
ard-work/src/main/java/com/ard/tianyu/domain/dto/state/CameraState.java 2 ●●●●● patch | view | raw | blame | history
ard-work/src/main/java/com/ard/tianyu/domain/dto/state/UavState.java 13 ●●●●● patch | view | raw | blame | history
ard-work/src/main/java/com/ard/tianyu/service/control/UavControlService.java 11 ●●●●● patch | view | raw | blame | history
ard-work/src/main/java/com/ard/tianyu/websocket/domain/UavControlMessage.java 15 ●●●●● patch | view | raw | blame | history
ard-work/src/main/java/com/ard/tianyu/websocket/handler/BaseSubscriptionManager.java 8 ●●●●● patch | view | raw | blame | history
ard-work/src/main/java/com/ard/tianyu/websocket/handler/TyMessageHandler.java 72 ●●●●● patch | view | raw | blame | history
ard-work/src/main/java/com/ard/tianyu/websocket/handler/UavAllManager.java 50 ●●●●● patch | view | raw | blame | history
ard-work/src/main/java/com/ard/tianyu/websocket/handler/UavControlManager.java 38 ●●●●● patch | view | raw | blame | history
ard-work/src/main/java/com/ard/tianyu/websocket/handler/UavStateManager.java 4 ●●●●● patch | view | raw | blame | history
ard-work/src/main/java/com/ard/tianyu/controller/UavControlController.java
@@ -47,11 +47,20 @@
    }
    /**
     * 获取当前控制者
     * 按类型获取当前控制者
     */
    @ApiOperation("获取当前控制者")
    @GetMapping("/current")
    @ApiOperation("按类型获取当前控制者")
    @GetMapping("/getCurrentControllerByType")
    public AjaxResult getCurrentController(@RequestParam String boxSn, @RequestParam String type) {
        return AjaxResult.success(uavControlService.getCurrentController(boxSn, type));
    }
    /**
     * 获取全部类型当前控制者
     */
    @ApiOperation("获取全部类型当前控制者")
    @GetMapping("/getAllCurrentController")
    public AjaxResult getAllCurrentController(@RequestParam String boxSn) {
        return AjaxResult.success(uavControlService.getCurrentController(boxSn));
    }
}
ard-work/src/main/java/com/ard/tianyu/controller/UavRealDataController.java
@@ -29,6 +29,7 @@
    @GetMapping("/getUavState")
    public AjaxResult getUavState(String boxSn) {
        UavState uavState = tyService.getUavState(boxSn);
        uavState.calculateFieldAngle();// 计算当前无人机的FieldAngle
        return AjaxResult.success(uavState);
    }
ard-work/src/main/java/com/ard/tianyu/domain/dto/state/CameraState.java
@@ -10,7 +10,7 @@
    private int recordDuration;        // 录制时长(单位:秒)
    private int source;                // 相机视源:0=可见,1=变焦,2=红外
    private int camera;                // 相机:0=FPV,1=相机(1),2=相机(2)
    private float zoomFactor;          // 相机当前变焦倍数
    private float zoomfactor;          // 相机当前变焦倍数
    private int width;                 // 水平像素(例如:1920)
    private int height;                // 垂直像素(例如:1080)
    private int frameRate;             // 帧率(例如:30)
ard-work/src/main/java/com/ard/tianyu/domain/dto/state/UavState.java
@@ -1,5 +1,6 @@
package com.ard.tianyu.domain.dto.state;
import com.ard.tianyu.util.CameraUtil;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
@@ -21,4 +22,16 @@
    private String boxSn;                                 // 云盒编号
    private AvoidanceData avoidanceData;                  // 避障数据
    private List<HmsAlarmData> hmsAlarmData;              // HMS报警信息 (飞机告警信息)
    private Float FieldAngle;                             // 自动计算视场角
    /**
     * 计算并设置视场角
     */
    public void calculateFieldAngle() {
        if (cameraState != null) {
            this.FieldAngle = CameraUtil.getFieldAngleFromZoom(cameraState.getSource(), cameraState.getZoomfactor());
        } else {
            this.FieldAngle = null; // 如果 cameraState 为 null,则 FieldAngle 也为 null
        }
    }
}
ard-work/src/main/java/com/ard/tianyu/service/control/UavControlService.java
@@ -7,6 +7,8 @@
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
@@ -158,7 +160,14 @@
        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);
        return map;
    }
    /**
     * 根据控制类型获取对应的控制 Map
     */
ard-work/src/main/java/com/ard/tianyu/websocket/domain/UavControlMessage.java
@@ -4,12 +4,27 @@
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Map;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class UavControlMessage {
    private String boxSn;       // 无人机编号
    private String type;        // 控制类型(fly 或 payload)
    private Long requester;     // 申请者ID(仅在请求控制时使用)
    private Boolean approved;   // 控制是否被批准(仅在处理请求控制时使用)
    public UavControlMessage(String boxSn, String type, Long requester, Boolean approved) {
        this.boxSn = boxSn;
        this.type = type;
        this.requester = requester;
        this.approved = approved;
    }
    /**
     * 是否订阅
     */
    private Boolean subscribe;
    private Map<String, Long> controller;
}
ard-work/src/main/java/com/ard/tianyu/websocket/handler/BaseSubscriptionManager.java
@@ -23,10 +23,10 @@
    /**
     * 订阅指定设备的数据
     */
    public void subscribe(String boxSn, Long userId) {
    public void subscribe(String boxSn, Long userId,Integer period) {
        subscriptions.computeIfAbsent(boxSn, k -> new HashSet<>()).add(userId);
        if (subscriptions.get(boxSn).size() == 1) {
            startPushTask(boxSn);
            startPushTask(boxSn,period);
        }
    }
@@ -46,14 +46,14 @@
    /**
     * 启动推送任务
     */
    private void startPushTask(String boxSn) {
    private void startPushTask(String boxSn,Integer period) {
        // 如果已经存在任务,则不再创建
        if (pushTasks.containsKey(boxSn)) {
            return;
        }
        ScheduledFuture<?> future = scheduler.scheduleAtFixedRate(() -> {
            sendDataToSubscribers(boxSn);
        }, 0, 2, TimeUnit.SECONDS);
        }, 0, period, TimeUnit.SECONDS);
        pushTasks.put(boxSn, future);
    }
ard-work/src/main/java/com/ard/tianyu/websocket/handler/TyMessageHandler.java
@@ -29,7 +29,10 @@
    private UavTelemetryManager uavTelemetryManager;
    @Resource
    private UavSignalManager uavSignalManager;
    @Resource
    private UavControlManager uavControlManager;
    @Resource
    private UavAllManager uavAllManager;
    @Override
    public void handleTextMessage(WebSocketSession session, TextMessage message) {
        String userIdStr = (String) session.getAttributes().get("userId");
@@ -51,6 +54,12 @@
                break;
            case "signal":
                handleSignalMessage(payload, userId);
                break;
            case "controller":
                handleControlMessage(payload, userId);
                break;
            case "all":
                handleAllMessage(payload, userId);
                break;
        }
    }
@@ -106,7 +115,7 @@
            Boolean subscribe = uavStateMessage.getSubscribe();
            if (subscribe) {
                // 执行订阅操作
                uavStateManager.subscribe(boxSn, userId);
                uavStateManager.subscribe(boxSn, userId, 2);
            } else {
                // 执行退订操作
                uavStateManager.unsubscribe(boxSn, userId);
@@ -137,7 +146,7 @@
            Boolean subscribe = uavTelemetryMessage.getSubscribe();
            if (subscribe) {
                // 执行订阅操作
                uavTelemetryManager.subscribe(boxSn, userId);
                uavTelemetryManager.subscribe(boxSn, userId, 2);
            } else {
                // 执行退订操作
                uavTelemetryManager.unsubscribe(boxSn, userId);
@@ -168,10 +177,64 @@
            Boolean subscribe = uavSignalMessage.getSubscribe();
            if (subscribe) {
                // 执行订阅操作
                uavSignalManager.subscribe(boxSn, userId);
                uavSignalManager.subscribe(boxSn, userId, 2);
            } else {
                // 执行退订操作
                uavSignalManager.unsubscribe(boxSn, userId);
            }
        }
    }
    /**
     * 处理无人机控制
     * 根据接收到的消息内容,决定无人机控制信息的订阅或退订
     *
     * @param payload 消息负载,包含控制信息
     * @param userId  用户ID,用于标识用户
     */
    private void handleControlMessage(String payload, Long userId) {
        // 解析接收到的JSON消息,将其转换为BaseMessage对象
        BaseMessage<UavControlMessage> controlMessage = JSON.parseObject(payload,
                new TypeReference<BaseMessage<UavControlMessage>>() {
                });
        // 获取消息的有效载荷部分
        UavControlMessage uavControlMessage = controlMessage.getPayload();
        // 检查有效载荷是否存在
        if (uavControlMessage != null) {
            // 获取无人机盒子的序列号
            String boxSn = uavControlMessage.getBoxSn();
            // 根据消息中的订阅标志,决定是订阅还是退订无人机状态
            Boolean subscribe = uavControlMessage.getSubscribe();
            if (subscribe) {
                // 执行订阅操作
                uavControlManager.subscribe(boxSn, userId, 2);
            } else {
                // 执行退订操作
                uavControlManager.unsubscribe(boxSn, userId);
            }
        }
    }
    private void handleAllMessage(String payload, Long userId) {
        // 解析接收到的JSON消息,将其转换为BaseMessage对象
        BaseMessage<UavControlMessage> controlMessage = JSON.parseObject(payload,
                new TypeReference<BaseMessage<UavControlMessage>>() {
                });
        // 获取消息的有效载荷部分
        UavControlMessage uavControlMessage = controlMessage.getPayload();
        // 检查有效载荷是否存在
        if (uavControlMessage != null) {
            // 获取无人机盒子的序列号
            String boxSn = uavControlMessage.getBoxSn();
            // 根据消息中的订阅标志,决定是订阅还是退订无人机状态
            Boolean subscribe = uavControlMessage.getSubscribe();
            if (subscribe) {
                // 执行订阅操作
                uavAllManager.subscribe(boxSn, userId, 2);
            } else {
                // 执行退订操作
                uavAllManager.unsubscribe(boxSn, userId);
            }
        }
    }
@@ -201,5 +264,6 @@
        uavStateManager.removeSubscribe(userId);
        uavTelemetryManager.removeSubscribe(userId);
        uavSignalManager.removeSubscribe(userId);
        uavControlManager.removeSubscribe(userId);
    }
}
ard-work/src/main/java/com/ard/tianyu/websocket/handler/UavAllManager.java
New file
@@ -0,0 +1,50 @@
package com.ard.tianyu.websocket.handler;
import com.ard.tianyu.domain.cache.UavSignalInfoCache;
import com.ard.tianyu.domain.cache.UavStateCache;
import com.ard.tianyu.domain.cache.UavTelemetryDataCache;
import com.ard.tianyu.domain.dto.signal.SignalInfo;
import com.ard.tianyu.domain.dto.state.CameraState;
import com.ard.tianyu.domain.dto.state.UavState;
import com.ard.tianyu.domain.dto.telemetry.TelemetryData;
import com.ard.tianyu.service.control.UavControlService;
import com.ard.tianyu.util.CameraUtil;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;
@Component
public class UavAllManager extends BaseSubscriptionManager<Map<String,Object>> {
    @Resource
    private UavControlService uavControlService;
    @Override
    protected Map<String,Object> getData(String boxSn) {
        Map<String,Object> map=new HashMap<>();
        UavState uavState = UavStateCache.getUavState(boxSn);
        uavState.calculateFieldAngle();// 计算当前无人机的FieldAngle
        map.put("state", uavState);
        TelemetryData uavTelemetryData = UavTelemetryDataCache.getUavTelemetryData(boxSn);
        map.put("telemetry", uavTelemetryData);
        SignalInfo uavSignalInfo = UavSignalInfoCache.getUavSignalInfo(boxSn);
        map.put("signal", uavSignalInfo);
        // 获取当前控制飞行的用户ID
        Long flyUserId = uavControlService.getCurrentController(boxSn, "fly");
        // 将飞行当前控制者用户ID添加到映射中
        map.put("flyController", flyUserId);
        // 获取当前控制载荷的用户ID
        Long payloadUserId = uavControlService.getCurrentController(boxSn, "payload");
        // 将载荷当前控制者用户ID添加到映射中
        map.put("payloadController", payloadUserId);
        return map;
    }
    @Override
    protected String getMessageType() {
        return "all";
    }
}
ard-work/src/main/java/com/ard/tianyu/websocket/handler/UavControlManager.java
@@ -1,15 +1,21 @@
package com.ard.tianyu.websocket.handler;
import com.alibaba.fastjson2.JSON;
import com.ard.tianyu.service.control.UavControlService;
import com.ard.tianyu.websocket.domain.BaseMessage;
import com.ard.tianyu.websocket.domain.UavControlMessage;
import com.ard.tianyu.websocket.utils.WebSocketUtil;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;
@Service
public class UavControlManager {
public class UavControlManager  extends BaseSubscriptionManager<Map<String, Long>> {
    @Resource
    private UavControlService uavControlService;
    /**
     * 发送控制请求
     */
@@ -45,4 +51,32 @@
        BaseMessage<UavControlMessage> baseMessage = new BaseMessage<>("control", message);
        WebSocketUtil.sendMessageAll(JSON.toJSONString(baseMessage));
    }
    /**
     * 获取指定设备的当前操作者信息
     * 该方法重写自父类,用于获取无人机和载荷的当前控制者用户ID
     *
     * @param boxSn 设备序列号,用于标识特定的设备
     * @return 返回一个映射,包含无人机(fly)和载荷(payload)的当前控制者用户ID
     */
    @Override
    protected Map<String, Long> getData(String boxSn) {
        // 获取当前控制飞行的用户ID
        Long flyUserId = uavControlService.getCurrentController(boxSn, "fly");
        // 获取当前控制载荷的用户ID
        Long payloadUserId = uavControlService.getCurrentController(boxSn, "payload");
        // 创建一个映射,用于存储飞行和载荷的当前控制者用户ID
        Map<String, Long> map=new HashMap<>();
        // 将飞行当前控制者用户ID添加到映射中
        map.put("flyController", flyUserId);
        // 将载荷当前控制者用户ID添加到映射中
        map.put("payloadController", payloadUserId);
        // 返回包含当前控制者信息的映射
        return map;
    }
    @Override
    protected String getMessageType() {
        return "controller";
    }
}
ard-work/src/main/java/com/ard/tianyu/websocket/handler/UavStateManager.java
@@ -10,7 +10,9 @@
    @Override
    protected UavState getData(String boxSn) {
        return UavStateCache.getUavState(boxSn);
        UavState uavState = UavStateCache.getUavState(boxSn);
        uavState.calculateFieldAngle();// 计算当前无人机的FieldAngle
        return uavState;
    }
    @Override