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