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