2026-01-20 14:54:53 +08:00
|
|
|
|
package com.ruoyi.device.service.impl;
|
|
|
|
|
|
|
2026-01-21 13:43:27 +08:00
|
|
|
|
import com.alibaba.fastjson2.JSON;
|
2026-01-21 16:12:50 +08:00
|
|
|
|
import com.ruoyi.device.domain.api.*;
|
|
|
|
|
|
import com.ruoyi.device.domain.model.Aircraft;
|
2026-01-20 17:05:25 +08:00
|
|
|
|
import com.ruoyi.device.domain.model.Device;
|
2026-01-20 15:37:54 +08:00
|
|
|
|
import com.ruoyi.device.domain.model.Dock;
|
2026-01-21 16:12:50 +08:00
|
|
|
|
import com.ruoyi.device.domain.model.DockAircraft;
|
2026-01-21 15:37:43 +08:00
|
|
|
|
import com.ruoyi.device.domain.model.thingsboard.AttributeMap;
|
|
|
|
|
|
import com.ruoyi.device.domain.model.thingsboard.TelemetryMap;
|
2026-01-21 15:47:50 +08:00
|
|
|
|
import com.ruoyi.device.domain.model.thingsboard.constants.DeviceAttributes;
|
2026-01-21 16:29:46 +08:00
|
|
|
|
import com.ruoyi.device.domain.model.thingsboard.constants.DeviceTelemetry;
|
2026-01-20 14:54:53 +08:00
|
|
|
|
import com.ruoyi.device.service.api.IBufferDeviceService;
|
2026-01-21 16:12:50 +08:00
|
|
|
|
import com.ruoyi.device.service.dto.AircraftDTO;
|
2026-01-20 15:37:54 +08:00
|
|
|
|
import com.ruoyi.device.service.dto.AircraftDetailDTO;
|
|
|
|
|
|
import com.ruoyi.device.service.dto.DockDetailDTO;
|
2026-01-21 16:29:46 +08:00
|
|
|
|
import com.ruoyi.device.api.enums.AircraftStatusEnum;
|
2026-01-21 15:58:12 +08:00
|
|
|
|
import com.ruoyi.device.api.enums.DockStatusEnum;
|
2026-01-21 15:19:55 +08:00
|
|
|
|
|
2026-01-21 13:43:27 +08:00
|
|
|
|
import lombok.extern.slf4j.Slf4j;
|
2026-01-20 15:37:54 +08:00
|
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
|
|
|
import org.springframework.stereotype.Service;
|
2026-01-21 16:12:50 +08:00
|
|
|
|
import org.springframework.util.CollectionUtils;
|
2026-01-20 15:37:54 +08:00
|
|
|
|
|
|
|
|
|
|
import java.util.List;
|
|
|
|
|
|
import java.util.stream.Collectors;
|
2026-01-20 14:54:53 +08:00
|
|
|
|
|
|
|
|
|
|
/**
|
2026-01-20 15:37:54 +08:00
|
|
|
|
* 设备缓冲服务实现
|
|
|
|
|
|
* 整合数据库数据和ThingsBoard数据
|
2026-01-20 14:54:53 +08:00
|
|
|
|
*
|
2026-01-20 15:37:54 +08:00
|
|
|
|
* @author ruoyi
|
|
|
|
|
|
* @date 2026-01-20
|
2026-01-20 14:54:53 +08:00
|
|
|
|
*/
|
2026-01-20 15:37:54 +08:00
|
|
|
|
@Service
|
2026-01-21 13:43:27 +08:00
|
|
|
|
@Slf4j
|
2026-01-20 15:37:54 +08:00
|
|
|
|
public class BufferDeviceImpl implements IBufferDeviceService
|
|
|
|
|
|
{
|
|
|
|
|
|
@Autowired
|
|
|
|
|
|
private IDockDomain dockDomain;
|
|
|
|
|
|
|
2026-01-20 17:05:25 +08:00
|
|
|
|
@Autowired
|
|
|
|
|
|
private IDeviceDomain deviceDomain;
|
|
|
|
|
|
|
2026-01-20 15:37:54 +08:00
|
|
|
|
@Autowired
|
|
|
|
|
|
private IAircraftDomain aircraftDomain;
|
|
|
|
|
|
|
2026-01-21 16:12:50 +08:00
|
|
|
|
@Autowired
|
|
|
|
|
|
private IDockAircraftDomain dockAircraftDomain;
|
|
|
|
|
|
|
2026-01-20 15:37:54 +08:00
|
|
|
|
@Autowired
|
|
|
|
|
|
private IThingsBoardDomain thingsBoardDomain;
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
|
public DockDetailDTO getDockDetailById(Long dockId)
|
|
|
|
|
|
{
|
2026-01-21 14:16:24 +08:00
|
|
|
|
|
2026-01-20 15:37:54 +08:00
|
|
|
|
Dock dock = dockDomain.selectDockByDockId(dockId);
|
2026-01-21 14:16:24 +08:00
|
|
|
|
log.info("selectDockByDockId {}",JSON.toJSONString(dock));
|
2026-01-20 15:37:54 +08:00
|
|
|
|
if (dock == null)
|
|
|
|
|
|
{
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
2026-01-21 14:16:24 +08:00
|
|
|
|
|
2026-01-20 17:05:25 +08:00
|
|
|
|
Device device = deviceDomain.selectDeviceByDeviceId(dock.getDeviceId());
|
2026-01-21 14:16:24 +08:00
|
|
|
|
log.info("selectDeviceByDeviceId {}",JSON.toJSONString(device));
|
|
|
|
|
|
|
2026-01-21 15:16:32 +08:00
|
|
|
|
DockDetailDTO dto = getChangeAbleDockDetailDTO(device.getIotDeviceId());
|
|
|
|
|
|
dto.setDockId(dock.getDockId());
|
|
|
|
|
|
dto.setDockName(dock.getDockName());
|
|
|
|
|
|
dto.setDockLocation(dock.getDockLocation());
|
|
|
|
|
|
dto.setDockIotId(device.getIotDeviceId());
|
2026-01-21 16:12:50 +08:00
|
|
|
|
|
2026-01-21 16:29:46 +08:00
|
|
|
|
|
2026-01-21 16:12:50 +08:00
|
|
|
|
List<DockAircraft> aircrafts = dockAircraftDomain.selectDockAircraftByDockId(dockId);
|
|
|
|
|
|
|
|
|
|
|
|
if(!CollectionUtils.isEmpty(aircrafts)){
|
|
|
|
|
|
DockAircraft dockAircraft = aircrafts.get(0);
|
|
|
|
|
|
Aircraft aircraft = aircraftDomain.selectAircraftByAircraftId(dockAircraft.getAircraftId());
|
|
|
|
|
|
dto.setAircraftId(aircraft.getAircraftId());
|
|
|
|
|
|
dto.setAircraftName(aircraft.getAircraftName());
|
|
|
|
|
|
|
|
|
|
|
|
Device airDevice = deviceDomain.selectDeviceByDeviceId(aircraft.getDeviceId());
|
|
|
|
|
|
dto.setAircraftIotId(airDevice.getIotDeviceId());
|
|
|
|
|
|
|
2026-01-21 16:29:46 +08:00
|
|
|
|
AircraftDetailDTO aircraftDetailDTO = getChangeAbleAirDetailDTO(airDevice.getIotDeviceId());
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 设置无人机状态
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
2026-01-21 16:12:50 +08:00
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2026-01-21 15:37:43 +08:00
|
|
|
|
return dto;
|
|
|
|
|
|
|
2026-01-21 14:16:24 +08:00
|
|
|
|
|
2026-01-20 15:37:54 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
2026-01-21 16:29:46 +08:00
|
|
|
|
public AircraftDetailDTO getAircraftDetailById(Long aircraftId) {
|
2026-01-21 15:16:32 +08:00
|
|
|
|
return null;
|
2026-01-20 15:37:54 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2026-01-21 16:29:46 +08:00
|
|
|
|
|
|
|
|
|
|
|
2026-01-21 15:16:32 +08:00
|
|
|
|
private DockDetailDTO getChangeAbleDockDetailDTO(String deviceIotId)
|
2026-01-20 15:37:54 +08:00
|
|
|
|
{
|
2026-01-21 15:37:43 +08:00
|
|
|
|
DockDetailDTO dto = new DockDetailDTO();
|
|
|
|
|
|
AttributeMap attributeMap = thingsBoardDomain.getPredefinedDeviceAttributes(deviceIotId);
|
|
|
|
|
|
TelemetryMap telemetryMap = thingsBoardDomain.getPredefinedDeviceTelemetry(deviceIotId);
|
2026-01-20 15:37:54 +08:00
|
|
|
|
|
2026-01-21 15:47:50 +08:00
|
|
|
|
// 根据 MODE_CODE 设置机场状态
|
|
|
|
|
|
// MODE_CODE 定义: {"0":"空闲中","1":"现场调试","2":"远程调试","3":"固件升级中","4":"作业中","5":"待标定"}
|
|
|
|
|
|
attributeMap.get(DeviceAttributes.MODE_CODE).ifPresent(modeCode -> {
|
|
|
|
|
|
String dockStatus = mapModeCodeToDockStatus(modeCode);
|
|
|
|
|
|
dto.setDockStatus(dockStatus);
|
|
|
|
|
|
});
|
2026-01-21 15:37:43 +08:00
|
|
|
|
|
|
|
|
|
|
return dto;
|
2026-01-20 15:37:54 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-01-21 15:47:50 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 将 MODE_CODE 映射到机场状态
|
|
|
|
|
|
* @param modeCode 模式代码
|
|
|
|
|
|
* @return 机场状态字符串
|
|
|
|
|
|
*/
|
|
|
|
|
|
private String mapModeCodeToDockStatus(Integer modeCode) {
|
|
|
|
|
|
switch (modeCode) {
|
|
|
|
|
|
case 0:
|
|
|
|
|
|
return DockStatusEnum.IDLE.getCode();
|
|
|
|
|
|
case 1:
|
|
|
|
|
|
case 2:
|
|
|
|
|
|
return DockStatusEnum.Debugging.getCode();
|
|
|
|
|
|
case 3:
|
|
|
|
|
|
return DockStatusEnum.FIRMWARE_UPGRADING.getCode();
|
|
|
|
|
|
case 4:
|
|
|
|
|
|
return DockStatusEnum.WORKING.getCode();
|
|
|
|
|
|
case 5:
|
|
|
|
|
|
default:
|
|
|
|
|
|
return DockStatusEnum.UNKNOWN.getCode();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-01-21 15:16:32 +08:00
|
|
|
|
private AircraftDetailDTO getChangeAbleAirDetailDTO(String deviceIotId)
|
2026-01-20 15:37:54 +08:00
|
|
|
|
{
|
|
|
|
|
|
|
2026-01-21 16:29:46 +08:00
|
|
|
|
AircraftDetailDTO dto = new AircraftDetailDTO();
|
|
|
|
|
|
AttributeMap attributeMap = thingsBoardDomain.getPredefinedDeviceAttributes(deviceIotId);
|
|
|
|
|
|
TelemetryMap telemetryMap = thingsBoardDomain.getPredefinedDeviceTelemetry(deviceIotId);
|
2026-01-20 15:37:54 +08:00
|
|
|
|
|
2026-01-21 16:29:46 +08:00
|
|
|
|
//设置aircraftStatus
|
|
|
|
|
|
// drone_in_dock 表示是否在舱外
|
|
|
|
|
|
// device_online_status 表示是否开机
|
|
|
|
|
|
// 先判断机场的状态是否是
|
|
|
|
|
|
// 任务中 和 调试, 这两个状态用机场的, 暂时不要用离线状态
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
|
|
String aircraftStatus = determineAircraftStatus(attributeMap, telemetryMap);
|
|
|
|
|
|
dto.setAircraftStatus(aircraftStatus);
|
|
|
|
|
|
|
|
|
|
|
|
return dto;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 根据设备属性和遥测数据确定无人机状态
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param attributeMap 设备属性映射
|
|
|
|
|
|
* @param telemetryMap 设备遥测数据映射
|
|
|
|
|
|
* @return 无人机状态字符串
|
|
|
|
|
|
*/
|
|
|
|
|
|
private String determineAircraftStatus(AttributeMap attributeMap, TelemetryMap telemetryMap) {
|
|
|
|
|
|
// 先检查 MODE_CODE,判断是否处于任务中或调试状态
|
|
|
|
|
|
// MODE_CODE 定义: {"0":"待机","1":"起飞准备","2":"起飞准备完毕","3":"手动飞行","4":"自动起飞",
|
|
|
|
|
|
// "5":"航线飞行","6":"全景拍照","7":"智能跟随","8":"ADS-B 躲避","9":"自动返航",
|
|
|
|
|
|
// "10":"自动降落","11":"强制降落","12":"三桨叶降落","13":"升级中","14":"未连接",
|
|
|
|
|
|
// "15":"APAS","16":"虚拟摇杆状态","17":"指令飞行","18":"空中 RTK 收敛模式",
|
|
|
|
|
|
// "19":"机场选址中","20":"POI环绕"}
|
|
|
|
|
|
Integer modeCode = attributeMap.get(DeviceAttributes.MODE_CODE).orElse(null);
|
|
|
|
|
|
|
|
|
|
|
|
if (modeCode != null) {
|
|
|
|
|
|
// 14 = 未连接,直接返回离线状态
|
|
|
|
|
|
if (modeCode == 14) {
|
|
|
|
|
|
return AircraftStatusEnum.OFFLINE.getCode();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 判断是否在任务中 (飞行相关状态: 1-12, 15-20)
|
|
|
|
|
|
if (modeCode >= 1 && modeCode <= 12 || modeCode >= 15 && modeCode <= 20) {
|
|
|
|
|
|
return AircraftStatusEnum.IN_MISSION.getCode();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 获取无人机是否在舱内: {"0":"舱外","1":"舱内"}
|
|
|
|
|
|
Integer droneInDock = telemetryMap.get(DeviceTelemetry.Drone_In_Dock)
|
|
|
|
|
|
.map(telemetryValue -> telemetryValue.getValue())
|
|
|
|
|
|
.orElse(null);
|
|
|
|
|
|
|
|
|
|
|
|
// 获取无人机是否开机: {"0":"关机","1":"开机"}
|
|
|
|
|
|
Integer deviceOnlineStatus = telemetryMap.get(DeviceTelemetry.Sub_Device_Online_Status)
|
|
|
|
|
|
.map(telemetryValue -> telemetryValue.getValue())
|
|
|
|
|
|
.orElse(null);
|
|
|
|
|
|
|
|
|
|
|
|
// 根据舱内/舱外和开机/关机状态确定无人机状态
|
|
|
|
|
|
boolean isInCabin = droneInDock != null && droneInDock == 1;
|
|
|
|
|
|
boolean isPowerOn = deviceOnlineStatus != null && deviceOnlineStatus == 1;
|
|
|
|
|
|
|
|
|
|
|
|
if (isInCabin) {
|
|
|
|
|
|
// 舱内
|
|
|
|
|
|
if (isPowerOn) {
|
|
|
|
|
|
return AircraftStatusEnum.POWER_ON_IN_CABIN.getCode();
|
|
|
|
|
|
} else {
|
|
|
|
|
|
return AircraftStatusEnum.POWER_OFF_IN_CABIN.getCode();
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
// 舱外
|
|
|
|
|
|
if (isPowerOn) {
|
|
|
|
|
|
return AircraftStatusEnum.POWER_ON_OUT_CABIN.getCode();
|
|
|
|
|
|
} else {
|
|
|
|
|
|
return AircraftStatusEnum.POWER_OFF_OUT_CABIN.getCode();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-01-20 15:37:54 +08:00
|
|
|
|
}
|
2026-01-21 15:16:32 +08:00
|
|
|
|
|
2026-01-20 14:54:53 +08:00
|
|
|
|
}
|