package com.ruoyi.device.controller; import com.ruoyi.common.core.domain.R; import com.ruoyi.common.core.web.controller.BaseController; import com.ruoyi.device.api.domain.StatisticsVO; import com.ruoyi.device.api.enums.AircraftStatusEnum; import com.ruoyi.device.api.enums.DockStatusEnum; import com.ruoyi.device.api.enums.PayloadStatusEnum; import com.ruoyi.device.service.api.IAircraftService; import com.ruoyi.device.service.impl.DaJiangBufferDeviceImpl; import com.ruoyi.device.service.impl.TuohengBufferDeviceImpl; import com.ruoyi.device.service.api.IDockService; import com.ruoyi.device.domain.api.IDeviceDomain; import com.ruoyi.device.domain.model.Device; import com.ruoyi.device.service.api.IPayloadService; import com.ruoyi.device.service.dto.AircraftDTO; import com.ruoyi.device.service.dto.AircraftDetailDTO; import com.ruoyi.device.service.dto.DockDTO; import com.ruoyi.device.service.dto.DockDetailDTO; import com.ruoyi.device.service.dto.PayloadDTO; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.util.List; import java.util.Map; import java.util.stream.Collectors; /** * 统计Controller * * @author ruoyi * @date 2026-01-23 */ @RestController @RequestMapping("/statistics") public class StaticsController extends BaseController { private static final Logger log = LoggerFactory.getLogger(StaticsController.class); @Autowired private IDockService dockService; @Autowired private IAircraftService aircraftService; @Autowired private IPayloadService payloadService; @Autowired private DaJiangBufferDeviceImpl daJiangBufferDeviceService; @Autowired private TuohengBufferDeviceImpl tuohengBufferDeviceService; @Autowired private IDeviceDomain deviceDomain; /** * 获取系统统计信息(合并大疆和拓恒) * * @return 统计信息 */ @GetMapping public R getStatistics() { log.info("========== 开始统计所有设备信息(大疆+拓恒) =========="); // 获取大疆统计 StatisticsVO djiStats = buildDjiStatisticsVO(); // 获取拓恒统计 StatisticsVO thStats = buildThStatisticsVO(); // 合并统计结果 StatisticsVO totalStats = new StatisticsVO(); // 机场统计 totalStats.setDockCount(djiStats.getDockCount() + thStats.getDockCount()); totalStats.setIdleDockCount(djiStats.getIdleDockCount() + thStats.getIdleDockCount()); totalStats.setWorkingDockCount(djiStats.getWorkingDockCount() + thStats.getWorkingDockCount()); totalStats.setDebuggingDockCount(djiStats.getDebuggingDockCount() + thStats.getDebuggingDockCount()); totalStats.setOfflineDockCount(djiStats.getOfflineDockCount() + thStats.getOfflineDockCount()); // 无人机统计 totalStats.setAircraftCount(djiStats.getAircraftCount() + thStats.getAircraftCount()); totalStats.setPowerOnInCabinCount(djiStats.getPowerOnInCabinCount() + thStats.getPowerOnInCabinCount()); totalStats.setPowerOffInCabinCount(djiStats.getPowerOffInCabinCount() + thStats.getPowerOffInCabinCount()); totalStats.setInMissionCount(djiStats.getInMissionCount() + thStats.getInMissionCount()); totalStats.setDebuggingAircraftCount(djiStats.getDebuggingAircraftCount() + thStats.getDebuggingAircraftCount()); totalStats.setOfflineAircraftCount(djiStats.getOfflineAircraftCount() + thStats.getOfflineAircraftCount()); // 挂载统计 totalStats.setPayloadCount(djiStats.getPayloadCount() + thStats.getPayloadCount()); totalStats.setOfflinePayloadCount(djiStats.getOfflinePayloadCount() + thStats.getOfflinePayloadCount()); log.info("========== 所有设备统计完成 =========="); log.info("总计: 机场={}, 任务中机场={}, 无人机={}, 任务中无人机={}", totalStats.getDockCount(), totalStats.getWorkingDockCount(), totalStats.getAircraftCount(), totalStats.getInMissionCount()); return R.ok(totalStats); } @GetMapping("/dji") public R getDjiStatistics() { return R.ok(buildDjiStatisticsVO()); } @GetMapping("/th") public R getThStatistics() { return R.ok(buildThStatisticsVO()); } private StatisticsVO buildDjiStatisticsVO (){ log.info("========== 开始统计DJI设备信息 =========="); StatisticsVO vo = new StatisticsVO(); // 获取所有机场 List allDocks = dockService.selectDockList(new DockDTO()); // 过滤出大疆机场 List docks = filterDocksByManufacturer(allDocks, "dajiang"); vo.setDockCount(docks.size()); log.info("大疆机场总数: {}", vo.getDockCount()); // 批量获取机场详情 - 优化:从N次查询减少到1次批量查询 Map dockDetailsMap = null; if (!docks.isEmpty()) { List dockIds = docks.stream() .map(DockDTO::getDockId) .collect(Collectors.toList()); dockDetailsMap = daJiangBufferDeviceService.getDockDetailsByIds(dockIds); } // 统计各状态机场数量 int idleCount = 0; int workingCount = 0; int debuggingCount = 0; int offlineCount = 0; if (docks != null && dockDetailsMap != null) { log.info("---------- 开始统计机场状态 ----------"); for (DockDTO dock : docks) { DockDetailDTO dockDetail = dockDetailsMap.get(dock.getDockId()); if (dockDetail != null && dockDetail.getDockStatus() != null) { String status = dockDetail.getDockStatus(); log.info("机场[ID:{}, Name:{}] 状态: {}", dock.getDockId(), dock.getDockName(), status); if (DockStatusEnum.IDLE.getCode().equalsIgnoreCase(status)) { idleCount++; log.debug(" -> 匹配到IDLE状态"); } else if (DockStatusEnum.WORKING.getCode().equalsIgnoreCase(status)) { workingCount++; log.info(" -> 匹配到WORKING状态 (任务中)"); } else if (DockStatusEnum.Debugging.getCode().equalsIgnoreCase(status)) { debuggingCount++; log.debug(" -> 匹配到Debugging状态"); } else { offlineCount++; log.debug(" -> 其他状态,归类为离线"); } } } } vo.setIdleDockCount(idleCount); vo.setWorkingDockCount(workingCount); vo.setDebuggingDockCount(debuggingCount); vo.setOfflineDockCount(offlineCount); log.info("机场状态统计结果 -> 空闲:{}, 任务中:{}, 调试:{}, 离线:{}", idleCount, workingCount, debuggingCount, offlineCount); // 获取所有无人机 List allAircrafts = aircraftService.selectAircraftList(new AircraftDTO()); // 过滤出大疆无人机 List aircrafts = filterAircraftsByManufacturer(allAircrafts, "dajiang"); vo.setAircraftCount(aircrafts.size()); log.info("大疆无人机总数: {}", vo.getAircraftCount()); // 批量获取无人机详情 - 优化:从N次查询减少到1次批量查询 Map aircraftDetailsMap = null; if (!aircrafts.isEmpty()) { List aircraftIds = aircrafts.stream() .map(AircraftDTO::getAircraftId) .collect(Collectors.toList()); aircraftDetailsMap = daJiangBufferDeviceService.getAircraftDetailsByIds(aircraftIds); } // 统计各状态无人机数量 int powerOnInCabinCount = 0; int powerOffInCabinCount = 0; int inMissionCount = 0; int debuggingAircraftCount = 0; int offlineAircraftCount = 0; if (aircrafts != null && aircraftDetailsMap != null) { log.info("---------- 开始统计无人机状态 ----------"); for (AircraftDTO aircraft : aircrafts) { AircraftDetailDTO aircraftDetail = aircraftDetailsMap.get(aircraft.getAircraftId()); if (aircraftDetail != null && aircraftDetail.getAircraftStatus() != null) { String status = aircraftDetail.getAircraftStatus(); log.info("无人机[ID:{}, Name:{}] 状态: {}", aircraft.getAircraftId(), aircraft.getAircraftName(), status); if (AircraftStatusEnum.POWER_ON_IN_CABIN.getCode().equalsIgnoreCase(status)) { powerOnInCabinCount++; log.debug(" -> 匹配到舱内开机状态"); } else if (AircraftStatusEnum.POWER_OFF_IN_CABIN.getCode().equalsIgnoreCase(status)) { powerOffInCabinCount++; log.debug(" -> 匹配到舱内关机状态"); } else if (AircraftStatusEnum.IN_MISSION.getCode().equalsIgnoreCase(status)) { inMissionCount++; log.info(" -> 匹配到IN_MISSION状态 (任务中)"); } else if (AircraftStatusEnum.DEBUGGING.getCode().equalsIgnoreCase(status)) { debuggingAircraftCount++; log.debug(" -> 匹配到调试状态"); } else if (AircraftStatusEnum.OFFLINE.getCode().equalsIgnoreCase(status)) { offlineAircraftCount++; log.debug(" -> 匹配到离线状态"); } else { offlineAircraftCount++; log.debug(" -> 其他状态,归类为离线"); } } } } vo.setPowerOnInCabinCount(powerOnInCabinCount); vo.setPowerOffInCabinCount(powerOffInCabinCount); vo.setInMissionCount(inMissionCount); vo.setDebuggingAircraftCount(debuggingAircraftCount); vo.setOfflineAircraftCount(offlineAircraftCount); log.info("无人机状态统计结果 -> 舱内开机:{}, 舱内关机:{}, 任务中:{}, 调试:{}, 离线:{}", powerOnInCabinCount, powerOffInCabinCount, inMissionCount, debuggingAircraftCount, offlineAircraftCount); // 获取所有挂载 List payloads = payloadService.selectPayloadList(new PayloadDTO()); vo.setPayloadCount(payloads != null ? payloads.size() : 0); // 统计离线挂载数量(暂时设置为0,因为挂载状态需要从实时数据获取) vo.setOfflinePayloadCount(0); log.info("========== DJI设备统计完成 =========="); log.info("最终统计结果: 机场总数={}, 任务中机场={}, 无人机总数={}, 任务中无人机={}", vo.getDockCount(), vo.getWorkingDockCount(), vo.getAircraftCount(), vo.getInMissionCount()); return vo; } /** * 构建拓恒设备统计信息 */ private StatisticsVO buildThStatisticsVO() { log.info("========== 开始统计拓恒设备信息 =========="); StatisticsVO vo = new StatisticsVO(); // 获取所有机场 List allDocks = dockService.selectDockList(new DockDTO()); // 过滤出拓恒机场 List thDocks = filterDocksByManufacturer(allDocks, "tuoheng"); vo.setDockCount(thDocks.size()); log.info("拓恒机场总数: {}", vo.getDockCount()); // 批量获取拓恒机场详情 Map dockDetailsMap = null; if (!thDocks.isEmpty()) { List dockIds = thDocks.stream() .map(DockDTO::getDockId) .collect(Collectors.toList()); dockDetailsMap = tuohengBufferDeviceService.getDockDetailsByIds(dockIds); } // 统计各状态机场数量 int idleCount = 0; int workingCount = 0; int debuggingCount = 0; int offlineCount = 0; if (dockDetailsMap != null) { log.info("---------- 开始统计拓恒机场状态 ----------"); for (DockDTO dock : thDocks) { DockDetailDTO dockDetail = dockDetailsMap.get(dock.getDockId()); if (dockDetail != null && dockDetail.getDockStatus() != null) { String status = dockDetail.getDockStatus(); log.info("拓恒机场[ID:{}, Name:{}] 状态: {}", dock.getDockId(), dock.getDockName(), status); if (DockStatusEnum.IDLE.getCode().equalsIgnoreCase(status)) { idleCount++; } else if (DockStatusEnum.WORKING.getCode().equalsIgnoreCase(status)) { workingCount++; } else if (DockStatusEnum.Debugging.getCode().equalsIgnoreCase(status)) { debuggingCount++; } else { offlineCount++; } } } } vo.setIdleDockCount(idleCount); vo.setWorkingDockCount(workingCount); vo.setDebuggingDockCount(debuggingCount); vo.setOfflineDockCount(offlineCount); log.info("拓恒机场状态统计 -> 空闲:{}, 任务中:{}, 调试:{}, 离线:{}", idleCount, workingCount, debuggingCount, offlineCount); // 获取所有无人机 List allAircrafts = aircraftService.selectAircraftList(new AircraftDTO()); // 过滤出拓恒无人机 List thAircrafts = filterAircraftsByManufacturer(allAircrafts, "tuoheng"); vo.setAircraftCount(thAircrafts.size()); log.info("拓恒无人机总数: {}", vo.getAircraftCount()); // 批量获取拓恒无人机详情 Map aircraftDetailsMap = null; if (!thAircrafts.isEmpty()) { List aircraftIds = thAircrafts.stream() .map(AircraftDTO::getAircraftId) .collect(Collectors.toList()); aircraftDetailsMap = tuohengBufferDeviceService.getAircraftDetailsByIds(aircraftIds); } // 统计各状态无人机数量 int powerOnInCabinCount = 0; int powerOffInCabinCount = 0; int inMissionCount = 0; int debuggingAircraftCount = 0; int offlineAircraftCount = 0; if (aircraftDetailsMap != null) { log.info("---------- 开始统计拓恒无人机状态 ----------"); for (AircraftDTO aircraft : thAircrafts) { AircraftDetailDTO aircraftDetail = aircraftDetailsMap.get(aircraft.getAircraftId()); if (aircraftDetail != null && aircraftDetail.getAircraftStatus() != null) { String status = aircraftDetail.getAircraftStatus(); log.info("拓恒无人机[ID:{}, Name:{}] 状态: {}", aircraft.getAircraftId(), aircraft.getAircraftName(), status); if (AircraftStatusEnum.POWER_ON_IN_CABIN.getCode().equalsIgnoreCase(status)) { powerOnInCabinCount++; log.info(" -> 匹配到舱内开机状态"); } else if (AircraftStatusEnum.POWER_OFF_IN_CABIN.getCode().equalsIgnoreCase(status)) { powerOffInCabinCount++; log.info(" -> 匹配到舱内关机状态"); } else if (AircraftStatusEnum.POWER_ON_OUT_CABIN.getCode().equalsIgnoreCase(status)) { // 舱外开机归类到舱内开机 powerOnInCabinCount++; log.info(" -> 匹配到舱外开机状态,归类到舱内开机"); } else if (AircraftStatusEnum.POWER_OFF_OUT_CABIN.getCode().equalsIgnoreCase(status)) { // 舱外关机归类到舱内关机 powerOffInCabinCount++; log.info(" -> 匹配到舱外关机状态,归类到舱内关机"); } else if (AircraftStatusEnum.IN_MISSION.getCode().equalsIgnoreCase(status)) { inMissionCount++; log.info(" -> 匹配到IN_MISSION状态 (任务中)"); } else if (AircraftStatusEnum.DEBUGGING.getCode().equalsIgnoreCase(status)) { debuggingAircraftCount++; log.info(" -> 匹配到调试状态"); } else if (AircraftStatusEnum.OFFLINE.getCode().equalsIgnoreCase(status)) { offlineAircraftCount++; log.info(" -> 匹配到离线状态"); } else { offlineAircraftCount++; log.info(" -> 未知状态[{}],归类为离线", status); } } } } vo.setPowerOnInCabinCount(powerOnInCabinCount); vo.setPowerOffInCabinCount(powerOffInCabinCount); vo.setInMissionCount(inMissionCount); vo.setDebuggingAircraftCount(debuggingAircraftCount); vo.setOfflineAircraftCount(offlineAircraftCount); log.info("拓恒无人机状态统计 -> 舱内开机:{}, 舱内关机:{}, 任务中:{}, 调试:{}, 离线:{}", powerOnInCabinCount, powerOffInCabinCount, inMissionCount, debuggingAircraftCount, offlineAircraftCount); // 挂载统计(拓恒设备暂时设置为0) vo.setPayloadCount(0); vo.setOfflinePayloadCount(0); log.info("========== 拓恒设备统计完成 =========="); return vo; } /** * 根据厂商过滤机场列表 */ private List filterDocksByManufacturer(List docks, String manufacturer) { if (docks == null || docks.isEmpty()) { return List.of(); } return docks.stream() .filter(dock -> { Device device = deviceDomain.selectDeviceByDeviceId(dock.getDeviceId()); return device != null && manufacturer.equals(device.getDeviceManufacturer()); }) .collect(Collectors.toList()); } /** * 根据厂商过滤无人机列表 */ private List filterAircraftsByManufacturer(List aircrafts, String manufacturer) { if (aircrafts == null || aircrafts.isEmpty()) { return List.of(); } return aircrafts.stream() .filter(aircraft -> { Device device = deviceDomain.selectDeviceByDeviceId(aircraft.getDeviceId()); return device != null && manufacturer.equals(device.getDeviceManufacturer()); }) .collect(Collectors.toList()); } }