From d267efe74181bbc89e7ecda1032f11965984769b Mon Sep 17 00:00:00 2001
From: liusuyi <1951119284@qq.com>
Date: Wed, 19 Mar 2025 14:08:07 +0800
Subject: [PATCH] 增加状态统一订阅 增加载荷和飞控用户同时获取

---
 ard-work/src/main/java/com/ard/tianyu/websocket/domain/UavControlMessage.java        |   15 +++
 ard-work/src/main/java/com/ard/tianyu/websocket/handler/BaseSubscriptionManager.java |    8 +-
 ard-work/src/main/java/com/ard/tianyu/domain/dto/state/UavState.java                 |   15 +++
 ard-work/src/main/java/com/ard/tianyu/websocket/handler/UavStateManager.java         |    4 
 ard-work/src/main/java/com/ard/tianyu/websocket/handler/UavControlManager.java       |   38 +++++++++
 ard-work/src/main/java/com/ard/tianyu/controller/UavControlController.java           |   15 +++
 ard-work/src/main/java/com/ard/tianyu/websocket/handler/UavAllManager.java           |   50 ++++++++++++
 ard-work/src/main/java/com/ard/tianyu/controller/UavRealDataController.java          |    1 
 ard-work/src/main/java/com/ard/tianyu/service/control/UavControlService.java         |   11 ++
 ard-work/src/main/java/com/ard/tianyu/domain/dto/state/CameraState.java              |    2 
 ard-work/src/main/java/com/ard/tianyu/websocket/handler/TyMessageHandler.java        |   72 +++++++++++++++++-
 11 files changed, 214 insertions(+), 17 deletions(-)

diff --git a/ard-work/src/main/java/com/ard/tianyu/controller/UavControlController.java b/ard-work/src/main/java/com/ard/tianyu/controller/UavControlController.java
index bb3cec6..1d7f550 100644
--- a/ard-work/src/main/java/com/ard/tianyu/controller/UavControlController.java
+++ b/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));
+    }
+
 }
diff --git a/ard-work/src/main/java/com/ard/tianyu/controller/UavRealDataController.java b/ard-work/src/main/java/com/ard/tianyu/controller/UavRealDataController.java
index 22d59b9..284348d 100644
--- a/ard-work/src/main/java/com/ard/tianyu/controller/UavRealDataController.java
+++ b/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);
     }
 
diff --git a/ard-work/src/main/java/com/ard/tianyu/domain/dto/state/CameraState.java b/ard-work/src/main/java/com/ard/tianyu/domain/dto/state/CameraState.java
index a8cbcea..a01b108 100644
--- a/ard-work/src/main/java/com/ard/tianyu/domain/dto/state/CameraState.java
+++ b/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)
diff --git a/ard-work/src/main/java/com/ard/tianyu/domain/dto/state/UavState.java b/ard-work/src/main/java/com/ard/tianyu/domain/dto/state/UavState.java
index 5271ad2..32051c4 100644
--- a/ard-work/src/main/java/com/ard/tianyu/domain/dto/state/UavState.java
+++ b/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
+        }
+    }
+}
\ No newline at end of file
diff --git a/ard-work/src/main/java/com/ard/tianyu/service/control/UavControlService.java b/ard-work/src/main/java/com/ard/tianyu/service/control/UavControlService.java
index 850fb75..c30411c 100644
--- a/ard-work/src/main/java/com/ard/tianyu/service/control/UavControlService.java
+++ b/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
      */
diff --git a/ard-work/src/main/java/com/ard/tianyu/websocket/domain/UavControlMessage.java b/ard-work/src/main/java/com/ard/tianyu/websocket/domain/UavControlMessage.java
index c862dcf..5cba1c6 100644
--- a/ard-work/src/main/java/com/ard/tianyu/websocket/domain/UavControlMessage.java
+++ b/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;
 }
diff --git a/ard-work/src/main/java/com/ard/tianyu/websocket/handler/BaseSubscriptionManager.java b/ard-work/src/main/java/com/ard/tianyu/websocket/handler/BaseSubscriptionManager.java
index b36100b..1ef237b 100644
--- a/ard-work/src/main/java/com/ard/tianyu/websocket/handler/BaseSubscriptionManager.java
+++ b/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);
     }
diff --git a/ard-work/src/main/java/com/ard/tianyu/websocket/handler/TyMessageHandler.java b/ard-work/src/main/java/com/ard/tianyu/websocket/handler/TyMessageHandler.java
index 663323b..082386f 100644
--- a/ard-work/src/main/java/com/ard/tianyu/websocket/handler/TyMessageHandler.java
+++ b/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);
     }
 }
diff --git a/ard-work/src/main/java/com/ard/tianyu/websocket/handler/UavAllManager.java b/ard-work/src/main/java/com/ard/tianyu/websocket/handler/UavAllManager.java
new file mode 100644
index 0000000..b3329f7
--- /dev/null
+++ b/ard-work/src/main/java/com/ard/tianyu/websocket/handler/UavAllManager.java
@@ -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";
+    }
+
+}
\ No newline at end of file
diff --git a/ard-work/src/main/java/com/ard/tianyu/websocket/handler/UavControlManager.java b/ard-work/src/main/java/com/ard/tianyu/websocket/handler/UavControlManager.java
index de927df..25cf4a6 100644
--- a/ard-work/src/main/java/com/ard/tianyu/websocket/handler/UavControlManager.java
+++ b/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";
+    }
 }
diff --git a/ard-work/src/main/java/com/ard/tianyu/websocket/handler/UavStateManager.java b/ard-work/src/main/java/com/ard/tianyu/websocket/handler/UavStateManager.java
index 2253628..f6944e6 100644
--- a/ard-work/src/main/java/com/ard/tianyu/websocket/handler/UavStateManager.java
+++ b/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

--
Gitblit v1.9.3