package com.ruoyi.device.websocket; import com.alibaba.fastjson2.JSON; import com.ruoyi.common.core.constant.SecurityConstants; import com.ruoyi.common.core.domain.R; import com.ruoyi.device.mapper.entity.FlightLogEntity; import com.ruoyi.device.mapper.entity.PreCheckLogEntity; import com.ruoyi.device.service.FlightService; import com.ruoyi.task.api.RemoteTaskService; import com.ruoyi.task.api.domain.TaskVO; import com.ruoyi.task.api.enums.StatusEnum; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; import jakarta.websocket.*; import jakarta.websocket.server.PathParam; import jakarta.websocket.server.ServerEndpoint; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CopyOnWriteArraySet; /** * 飞行日志WebSocket (包含自检日志和飞行日志) * * @author ruoyi * @date 2026-02-25 */ @Slf4j @Component @ServerEndpoint("/websocket/flightLog/{deviceSn}") public class PreCheckLogWebSocket { private Session session; private String deviceSn; private static final CopyOnWriteArraySet sessions = new CopyOnWriteArraySet<>(); private static final Map sessionMap = new ConcurrentHashMap<>(); private static FlightService flightService; @Autowired private RemoteTaskService remoteTaskService; @Autowired public void setFlightService(FlightService flightService) { PreCheckLogWebSocket.flightService = flightService; } @OnOpen public void onOpen(Session session, @PathParam("deviceSn") String deviceSn) { this.session = session; this.deviceSn = deviceSn; sessions.add(this); sessionMap.put(session.getId(), this); log.info("飞行日志WebSocket连接建立: sessionId={}, deviceSn={}", session.getId(), deviceSn); } @OnClose public void onClose() { sessions.remove(this); if (session != null) { sessionMap.remove(session.getId()); log.info("自检日志WebSocket连接关闭: sessionId={}, deviceSn={}", session.getId(), deviceSn); } else { log.info("自检日志WebSocket连接关闭: session为null"); } } @OnMessage public void onMessage(String message) { log.info("收到自检日志WebSocket消息: sessionId={}, message={}", session.getId(), message); } @OnError public void onError(Session session, Throwable error) { log.error("自检日志WebSocket错误: sessionId={}, deviceSn={}, error={}", session.getId(), deviceSn, error.getMessage(), error); } private void sendMessage(String message) { try { if (session != null && session.isOpen()) { session.getBasicRemote().sendText(message); } } catch (Exception e) { log.error("发送自检日志WebSocket消息失败: deviceSn={}, error={}", deviceSn, e.getMessage(), e); } } @Scheduled(fixedRate = 3000) public void broadcast() { for (PreCheckLogWebSocket ws : sessions) { R taskVOR = remoteTaskService.getCurrentTaskByUavId(ws.deviceSn, SecurityConstants.INNER); if(Objects.nonNull(taskVOR) && Objects.nonNull(taskVOR.getData())){ TaskVO taskVO = taskVOR.getData(); if(Objects.equals(true,taskVO.getRecovery())){ continue; } if(taskVO.getStatus() == StatusEnum.PENDING || taskVO.getStatus() == StatusEnum.CANCELED || taskVO.getStatus() == StatusEnum.COMPLETED){ continue; } } Map flightData = flightService.getLatestFlightWithLogs(ws.deviceSn); if (flightData == null) { continue; } ws.sendMessage(JSON.toJSONString(flightData)); } } }