2026-02-25 13:06:56 +08:00
|
|
|
|
package com.ruoyi.device.service.impl;
|
|
|
|
|
|
|
|
|
|
|
|
import com.alibaba.fastjson2.JSONObject;
|
2026-02-27 15:30:09 +08:00
|
|
|
|
import com.ruoyi.device.domain.impl.tuohengmqtt.callback.IAirportFlyControlCallback;
|
2026-02-25 13:06:56 +08:00
|
|
|
|
import com.ruoyi.device.domain.impl.tuohengmqtt.callback.IAirportFlyControlDataCallback;
|
|
|
|
|
|
import com.ruoyi.device.mapper.entity.FlightEntity;
|
|
|
|
|
|
import com.ruoyi.device.mapper.entity.FlightLogEntity;
|
2026-02-25 13:17:42 +08:00
|
|
|
|
import com.ruoyi.device.mapper.entity.PreCheckLogEntity;
|
2026-02-25 13:06:56 +08:00
|
|
|
|
import com.ruoyi.device.service.FlightService;
|
2026-03-10 14:56:42 +08:00
|
|
|
|
import com.ruoyi.task.api.enums.StatusEnum;
|
2026-02-25 13:06:56 +08:00
|
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
|
|
|
import org.springframework.stereotype.Component;
|
|
|
|
|
|
|
2026-02-27 15:30:09 +08:00
|
|
|
|
import java.util.Arrays;
|
|
|
|
|
|
import java.util.List;
|
|
|
|
|
|
|
2026-02-25 13:06:56 +08:00
|
|
|
|
@Slf4j
|
|
|
|
|
|
@Component
|
2026-02-27 15:30:09 +08:00
|
|
|
|
public class FlightEventCallback implements IAirportFlyControlCallback, IAirportFlyControlDataCallback {
|
2026-02-25 13:06:56 +08:00
|
|
|
|
|
|
|
|
|
|
@Autowired
|
|
|
|
|
|
private FlightService flightService;
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
2026-02-27 15:30:09 +08:00
|
|
|
|
public void onAirportFlyControl(String deviceSn, String payload, String topic) {
|
|
|
|
|
|
log.info("【FlightEventCallback】收到飞行控制消息: deviceSn={}, topic={}, payload={}", deviceSn, topic, payload);
|
2026-02-26 08:41:14 +08:00
|
|
|
|
|
2026-02-27 08:58:36 +08:00
|
|
|
|
try {
|
2026-02-25 13:06:56 +08:00
|
|
|
|
JSONObject data = JSONObject.parseObject(payload);
|
|
|
|
|
|
if (data == null) {
|
2026-02-27 08:58:36 +08:00
|
|
|
|
log.warn("【FlightEventCallback】解析payload失败: deviceSn={}, topic={}, payload={}", deviceSn, topic, payload);
|
2026-02-25 13:06:56 +08:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-27 15:30:09 +08:00
|
|
|
|
handleControlMessage(deviceSn, data);
|
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
|
log.error("【FlightEventCallback】处理飞行控制消息失败: deviceSn={}, topic={}, error={}", deviceSn, topic, e.getMessage(), e);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-02-25 13:06:56 +08:00
|
|
|
|
|
2026-02-27 15:30:09 +08:00
|
|
|
|
@Override
|
|
|
|
|
|
public void onAirportFlyControlData(String deviceSn, String payload, String topic) {
|
|
|
|
|
|
log.info("【FlightEventCallback】收到飞行控制数据消息: deviceSn={}, topic={}, payload={}", deviceSn, topic, payload);
|
2026-02-25 13:06:56 +08:00
|
|
|
|
|
2026-02-27 15:30:09 +08:00
|
|
|
|
try {
|
|
|
|
|
|
JSONObject data = JSONObject.parseObject(payload);
|
|
|
|
|
|
if (data == null) {
|
|
|
|
|
|
log.warn("【FlightEventCallback】解析payload失败: deviceSn={}, topic={}, payload={}", deviceSn, topic, payload);
|
2026-02-27 08:58:36 +08:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-27 15:30:09 +08:00
|
|
|
|
handleControlDataMessage(deviceSn, data);
|
2026-02-25 13:06:56 +08:00
|
|
|
|
} catch (Exception e) {
|
2026-02-27 15:30:09 +08:00
|
|
|
|
log.error("【FlightEventCallback】处理飞行控制数据消息失败: deviceSn={}, topic={}, error={}", deviceSn, topic, e.getMessage(), e);
|
2026-02-25 13:06:56 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-27 15:30:09 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 处理 /control 主题消息
|
|
|
|
|
|
* 收到 airlineFlight 动作时创建飞行记录
|
|
|
|
|
|
*/
|
|
|
|
|
|
private void handleControlMessage(String deviceSn, JSONObject data) {
|
|
|
|
|
|
String action = data.getString("action");
|
|
|
|
|
|
String messageID = data.getString("messageID");
|
|
|
|
|
|
|
|
|
|
|
|
log.info("【FlightEventCallback】处理control消息: deviceSn={}, action={}, messageID={}", deviceSn, action, messageID);
|
|
|
|
|
|
|
|
|
|
|
|
if ("airlineFlight".equals(action) && messageID != null && !messageID.isEmpty()) {
|
2026-03-10 14:56:42 +08:00
|
|
|
|
// // 创建飞行记录(如果不存在)
|
|
|
|
|
|
// flightService.getOrCreateFlightByMessageId(deviceSn, messageID);
|
|
|
|
|
|
// log.info("【FlightEventCallback】创建/获取飞行记录: deviceSn={}, messageID={}", deviceSn, messageID);
|
2026-02-27 15:30:09 +08:00
|
|
|
|
} else if ("immediateReturn".equals(action) && messageID != null && !messageID.isEmpty()) {
|
2026-03-10 14:56:42 +08:00
|
|
|
|
// FlightEntity flight = flightService.getOrCreateFlightByMessageId(deviceSn, messageID);
|
|
|
|
|
|
// flightService.updateFlightStatus(flight.getFlightId(), "RETURNING");
|
|
|
|
|
|
// log.info("【FlightEventCallback】更新飞行状态为RETURNING: deviceSn={}, flightId={}", deviceSn, flight.getFlightId());
|
2026-02-25 13:06:56 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-27 15:30:09 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 处理 /control/data 主题消息
|
|
|
|
|
|
* 根据消息内容写入自检日志或飞行日志,并更新飞行状态
|
|
|
|
|
|
*/
|
|
|
|
|
|
private void handleControlDataMessage(String deviceSn, JSONObject data) {
|
|
|
|
|
|
String msg = data.getString("msg");
|
|
|
|
|
|
String messageID = data.getString("messageID");
|
|
|
|
|
|
Integer code = data.getInteger("code");
|
|
|
|
|
|
|
|
|
|
|
|
if (messageID == null || messageID.isEmpty()) {
|
|
|
|
|
|
log.warn("【FlightEventCallback】消息缺少messageID: deviceSn={}, msg={}", deviceSn, msg);
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-10 14:56:42 +08:00
|
|
|
|
Long taskId = Long.valueOf(messageID);
|
|
|
|
|
|
//
|
|
|
|
|
|
// // 通过 messageID 获取飞行记录
|
|
|
|
|
|
// FlightEntity flight = flightService.getOrCreateFlightByMessageId(deviceSn, messageID);
|
|
|
|
|
|
// if (flight == null) {
|
|
|
|
|
|
// log.error("【FlightEventCallback】获取飞行记录失败: deviceSn={}, messageID={}", deviceSn, messageID);
|
|
|
|
|
|
// return;
|
|
|
|
|
|
// }
|
|
|
|
|
|
//
|
|
|
|
|
|
// log.info("【FlightEventCallback】处理control/data消息: deviceSn={}, flightId={}, messageID={}, msg={}, code={}",
|
|
|
|
|
|
// deviceSn, flight.getFlightId(), messageID, msg, code);
|
2026-02-27 08:58:36 +08:00
|
|
|
|
|
2026-02-27 15:30:09 +08:00
|
|
|
|
// 判断是否为 [地面站]无人机起飞成功
|
|
|
|
|
|
if (msg != null && msg.contains("[地面站]无人机起飞成功")) {
|
|
|
|
|
|
// 起飞成功,存到 device_flight_log
|
2026-03-10 14:56:42 +08:00
|
|
|
|
handleFlightLog(deviceSn, msg, taskId);
|
2026-02-27 15:30:09 +08:00
|
|
|
|
// 更新状态为 FLYING
|
2026-03-10 14:56:42 +08:00
|
|
|
|
log.info("【FlightEventCallback】检测到起飞成功,更新状态为FLYING: deviceSn={}, flightId={}", deviceSn, taskId);
|
|
|
|
|
|
flightService.updateFlightStatus(taskId, StatusEnum.RUNNING);
|
2026-02-27 15:30:09 +08:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
2026-02-27 08:58:36 +08:00
|
|
|
|
|
2026-02-27 15:30:09 +08:00
|
|
|
|
// 检查 device_flight_log 是否有数据,判断是否已起飞
|
2026-03-10 14:56:42 +08:00
|
|
|
|
boolean hasTakenOff = flightService.hasFlightLog(taskId);
|
2026-02-27 08:58:36 +08:00
|
|
|
|
|
2026-02-27 15:30:09 +08:00
|
|
|
|
if (hasTakenOff) {
|
|
|
|
|
|
// 已起飞,所有消息存到 device_flight_log
|
2026-03-10 14:56:42 +08:00
|
|
|
|
log.info("【FlightEventCallback】已起飞,存入飞行日志: deviceSn={}, flightId={}, msg={}", deviceSn, taskId, msg);
|
|
|
|
|
|
handleFlightLog(deviceSn, msg, taskId);
|
2026-02-27 15:30:09 +08:00
|
|
|
|
|
|
|
|
|
|
// 检查是否任务完成
|
|
|
|
|
|
String dataContent = data.getString("data");
|
|
|
|
|
|
if ("操作成功".equals(msg) && "[地面站]任务飞行完成".equals(dataContent)) {
|
2026-03-10 14:56:42 +08:00
|
|
|
|
log.info("【FlightEventCallback】检测到任务完成,更新状态为HOME: deviceSn={}, flightId={}", deviceSn, taskId);
|
|
|
|
|
|
flightService.updateFlightStatus(taskId, StatusEnum.COMPLETED);
|
2026-02-27 15:30:09 +08:00
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
// 未起飞,所有消息存到 device_pre_check_log
|
2026-03-10 14:56:42 +08:00
|
|
|
|
log.info("【FlightEventCallback】未起飞,存入自检日志: deviceSn={}, flightId={}, msg={}, code={}", deviceSn, taskId, msg, code);
|
|
|
|
|
|
handlePreCheckLog(deviceSn, msg, code, taskId);
|
2026-02-27 15:30:09 +08:00
|
|
|
|
|
|
|
|
|
|
// 检查是否自检失败(code=1 表示失败)
|
|
|
|
|
|
if (code != null && (code == 1 || code == -1)) {
|
2026-03-10 14:56:42 +08:00
|
|
|
|
log.info("【FlightEventCallback】检测到自检失败(code=1),更新状态为ERROR: deviceSn={}, flightId={}", deviceSn, taskId);
|
|
|
|
|
|
flightService.updateFlightStatus(taskId, StatusEnum.FAILED);
|
2026-02-27 15:30:09 +08:00
|
|
|
|
}
|
2026-02-25 13:06:56 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-27 15:30:09 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 保存自检日志
|
|
|
|
|
|
* @param code 0=成功,1=失败
|
|
|
|
|
|
*/
|
2026-03-10 14:56:42 +08:00
|
|
|
|
private void handlePreCheckLog(String deviceSn, String msg, Integer code, Long taskId) {
|
|
|
|
|
|
// if (flight == null) {
|
|
|
|
|
|
// log.error("【FlightEventCallback】飞行记录为空,无法保存自检日志: deviceSn={}, msg={}", deviceSn, msg);
|
|
|
|
|
|
// return;
|
|
|
|
|
|
// }
|
|
|
|
|
|
//
|
|
|
|
|
|
// log.info("【FlightEventCallback】准备保存自检日志: deviceSn={}, flightId={}, msg={}, code={}",
|
|
|
|
|
|
// deviceSn, flight.getFlightId(), msg, code);
|
2026-02-27 08:58:36 +08:00
|
|
|
|
|
2026-02-25 13:17:42 +08:00
|
|
|
|
try {
|
2026-02-27 15:30:09 +08:00
|
|
|
|
// code=0 表示成功,code=1 表示失败
|
|
|
|
|
|
Boolean success = (code != null && code == 0);
|
2026-02-27 08:58:36 +08:00
|
|
|
|
|
2026-02-25 13:17:42 +08:00
|
|
|
|
PreCheckLogEntity logEntity = new PreCheckLogEntity();
|
2026-03-10 14:56:42 +08:00
|
|
|
|
logEntity.setFlightId(taskId);
|
2026-02-25 13:17:42 +08:00
|
|
|
|
logEntity.setLogContent(msg);
|
|
|
|
|
|
logEntity.setSuccess(success);
|
2026-02-27 08:58:36 +08:00
|
|
|
|
|
2026-02-25 13:17:42 +08:00
|
|
|
|
flightService.insertPreCheckLog(logEntity);
|
2026-02-27 08:58:36 +08:00
|
|
|
|
|
2026-02-27 15:30:09 +08:00
|
|
|
|
log.info("【FlightEventCallback】成功保存自检日志: deviceSn={}, flightId={}, logId={}, msg={}, code={}, success={}",
|
2026-03-10 14:56:42 +08:00
|
|
|
|
deviceSn, taskId, logEntity.getLogId(), msg, code, success);
|
2026-02-25 13:17:42 +08:00
|
|
|
|
} catch (Exception e) {
|
2026-02-27 08:58:36 +08:00
|
|
|
|
log.error("【FlightEventCallback】保存自检日志失败: deviceSn={}, flightId={}, msg={}, error={}",
|
2026-03-10 14:56:42 +08:00
|
|
|
|
deviceSn, taskId, msg, e.getMessage(), e);
|
2026-02-25 13:17:42 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-27 15:30:09 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 保存飞行日志
|
|
|
|
|
|
*/
|
2026-03-10 14:56:42 +08:00
|
|
|
|
private void handleFlightLog(String deviceSn, String message, Long taskId) {
|
|
|
|
|
|
// if (flight == null) {
|
|
|
|
|
|
// log.error("【FlightEventCallback】飞行记录为空,无法保存飞行日志: deviceSn={}, message={}", deviceSn, message);
|
|
|
|
|
|
// return;
|
|
|
|
|
|
// }
|
2026-02-27 08:58:36 +08:00
|
|
|
|
|
2026-03-10 14:56:42 +08:00
|
|
|
|
log.info("【FlightEventCallback】准备保存飞行日志: deviceSn={}, flightId={}, message={}", deviceSn, taskId, message);
|
2026-02-27 08:58:36 +08:00
|
|
|
|
|
2026-02-25 13:06:56 +08:00
|
|
|
|
try {
|
2026-03-10 14:56:42 +08:00
|
|
|
|
|
2026-02-27 15:30:09 +08:00
|
|
|
|
FlightLogEntity logEntity = new FlightLogEntity();
|
2026-03-10 14:56:42 +08:00
|
|
|
|
logEntity.setFlightId(taskId);
|
2026-02-27 15:30:09 +08:00
|
|
|
|
logEntity.setLogContent(message);
|
|
|
|
|
|
flightService.insertFlightLog(logEntity);
|
2026-03-10 14:56:42 +08:00
|
|
|
|
log.info("【FlightEventCallback】成功保存飞行日志: deviceSn={}, taskId={}, logId={}, message={}",
|
|
|
|
|
|
deviceSn, taskId, logEntity.getLogId(), message);
|
2026-02-27 15:30:09 +08:00
|
|
|
|
|
2026-02-25 13:06:56 +08:00
|
|
|
|
} catch (Exception e) {
|
2026-03-10 14:56:42 +08:00
|
|
|
|
log.error("【FlightEventCallback】保存飞行日志失败: deviceSn={}, taskId={}, message={}, error={}",
|
|
|
|
|
|
deviceSn, taskId, message, e.getMessage(), e);
|
2026-02-25 13:06:56 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|