Compare commits
No commits in common. "main" and "model" have entirely different histories.
51
pom.xml
51
pom.xml
|
|
@ -17,29 +17,12 @@
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.thingsboard</groupId>
|
|
||||||
<artifactId>rest-client</artifactId>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<!-- Tuoheng Device API -->
|
<!-- Tuoheng Device API -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.ruoyi</groupId>
|
<groupId>com.ruoyi</groupId>
|
||||||
<artifactId>tuoheng-api-device</artifactId>
|
<artifactId>tuoheng-api-device</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- RuoYi System API -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.ruoyi</groupId>
|
|
||||||
<artifactId>ruoyi-api-system</artifactId>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<!-- RuoYi Common Core -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.ruoyi</groupId>
|
|
||||||
<artifactId>ruoyi-common-core</artifactId>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<!-- SpringCloud Alibaba Nacos -->
|
<!-- SpringCloud Alibaba Nacos -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.alibaba.cloud</groupId>
|
<groupId>com.alibaba.cloud</groupId>
|
||||||
|
|
@ -105,40 +88,6 @@
|
||||||
<groupId>org.flywaydb</groupId>
|
<groupId>org.flywaydb</groupId>
|
||||||
<artifactId>flyway-mysql</artifactId>
|
<artifactId>flyway-mysql</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>org.projectlombok</groupId>
|
|
||||||
<artifactId>lombok</artifactId>
|
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<!-- Caffeine Cache -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.github.ben-manes.caffeine</groupId>
|
|
||||||
<artifactId>caffeine</artifactId>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<!-- WebSocket -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-starter-websocket</artifactId>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<!-- Spring Integration MQTT -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.integration</groupId>
|
|
||||||
<artifactId>spring-integration-mqtt</artifactId>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<!-- Eclipse Paho MQTT v5 Client (支持MQTT 5.0) -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.eclipse.paho</groupId>
|
|
||||||
<artifactId>org.eclipse.paho.mqttv5.client</artifactId>
|
|
||||||
<version>1.2.5</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.ruoyi</groupId>
|
|
||||||
<artifactId>tuoheng-api-task</artifactId>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,2 +1 @@
|
||||||
|
ddddda
|
||||||
iddddddddddddddddddddddddddddddddddddddddddddddddD堆堆ddddddddddddddddddddeeedddddddd
|
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,6 @@ package com.ruoyi.device;
|
||||||
|
|
||||||
import org.springframework.boot.SpringApplication;
|
import org.springframework.boot.SpringApplication;
|
||||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
import org.springframework.context.annotation.ComponentScan;
|
|
||||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
|
||||||
import com.ruoyi.common.security.annotation.EnableCustomConfig;
|
import com.ruoyi.common.security.annotation.EnableCustomConfig;
|
||||||
import com.ruoyi.common.security.annotation.EnableRyFeignClients;
|
import com.ruoyi.common.security.annotation.EnableRyFeignClients;
|
||||||
|
|
||||||
|
|
@ -12,17 +10,13 @@ import com.ruoyi.common.security.annotation.EnableRyFeignClients;
|
||||||
*
|
*
|
||||||
* @author ruoyi
|
* @author ruoyi
|
||||||
*/
|
*/
|
||||||
@EnableScheduling
|
|
||||||
@EnableCustomConfig
|
@EnableCustomConfig
|
||||||
@EnableRyFeignClients
|
@EnableRyFeignClients
|
||||||
@SpringBootApplication
|
@SpringBootApplication
|
||||||
public class TuohengDeviceApplication
|
public class TuohengDeviceApplication
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
public static void main(String[] args)
|
public static void main(String[] args)
|
||||||
{
|
{
|
||||||
|
|
||||||
SpringApplication.run(TuohengDeviceApplication.class, args);
|
SpringApplication.run(TuohengDeviceApplication.class, args);
|
||||||
System.out.println("(♥◠‿◠)ノ゙ 设备模块启动成功 ლ(´ڡ`ლ)゙ \n" +
|
System.out.println("(♥◠‿◠)ノ゙ 设备模块启动成功 ლ(´ڡ`ლ)゙ \n" +
|
||||||
" .-------. ____ __ \n" +
|
" .-------. ____ __ \n" +
|
||||||
|
|
|
||||||
|
|
@ -1,89 +0,0 @@
|
||||||
package com.ruoyi.device.config;
|
|
||||||
|
|
||||||
import org.springframework.cache.CacheManager;
|
|
||||||
import org.springframework.cache.annotation.EnableCaching;
|
|
||||||
import org.springframework.context.annotation.Bean;
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
|
||||||
import org.springframework.data.redis.cache.RedisCacheConfiguration;
|
|
||||||
import org.springframework.data.redis.cache.RedisCacheManager;
|
|
||||||
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
|
||||||
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
|
|
||||||
import org.springframework.data.redis.serializer.RedisSerializationContext;
|
|
||||||
import org.springframework.data.redis.serializer.StringRedisSerializer;
|
|
||||||
|
|
||||||
import java.time.Duration;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Device模块缓存配置
|
|
||||||
* 为Domain层提供分布式缓存支持
|
|
||||||
*
|
|
||||||
* @author ruoyi
|
|
||||||
* @date 2026-01-30
|
|
||||||
*/
|
|
||||||
@Configuration
|
|
||||||
@EnableCaching
|
|
||||||
public class DeviceCacheConfig {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 缓存名称常量
|
|
||||||
*/
|
|
||||||
public static final String DEVICE_CACHE = "device";
|
|
||||||
public static final String DOCK_CACHE = "dock";
|
|
||||||
public static final String AIRCRAFT_CACHE = "aircraft";
|
|
||||||
public static final String PAYLOAD_CACHE = "payload";
|
|
||||||
public static final String DOCK_AIRCRAFT_CACHE = "dockAircraft";
|
|
||||||
public static final String AIRCRAFT_PAYLOAD_CACHE = "aircraftPayload";
|
|
||||||
public static final String THINGSBOARD_ATTRIBUTES_CACHE = "thingsboardAttributes";
|
|
||||||
public static final String THINGSBOARD_TELEMETRY_CACHE = "thingsboardTelemetry";
|
|
||||||
public static final String WEATHER_CACHE = "weather";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 配置缓存管理器
|
|
||||||
* 为不同的实体配置不同的过期时间
|
|
||||||
*/
|
|
||||||
@Bean
|
|
||||||
public CacheManager deviceCacheManager(RedisConnectionFactory connectionFactory) {
|
|
||||||
// 默认缓存配置:30分钟过期
|
|
||||||
RedisCacheConfiguration defaultConfig = RedisCacheConfiguration.defaultCacheConfig()
|
|
||||||
.entryTtl(Duration.ofMinutes(30))
|
|
||||||
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))
|
|
||||||
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()))
|
|
||||||
.disableCachingNullValues();
|
|
||||||
|
|
||||||
// 为不同实体配置不同的过期时间
|
|
||||||
Map<String, RedisCacheConfiguration> cacheConfigurations = new HashMap<>();
|
|
||||||
|
|
||||||
// 设备信息:30分钟(基础数据,变化较少)
|
|
||||||
cacheConfigurations.put(DEVICE_CACHE, defaultConfig.entryTtl(Duration.ofMinutes(30)));
|
|
||||||
|
|
||||||
// 机场信息:30分钟(基础数据,变化较少)
|
|
||||||
cacheConfigurations.put(DOCK_CACHE, defaultConfig.entryTtl(Duration.ofMinutes(30)));
|
|
||||||
|
|
||||||
// 无人机信息:30分钟(基础数据,变化较少)
|
|
||||||
cacheConfigurations.put(AIRCRAFT_CACHE, defaultConfig.entryTtl(Duration.ofMinutes(30)));
|
|
||||||
|
|
||||||
// 挂载信息:30分钟(基础数据,变化较少)
|
|
||||||
cacheConfigurations.put(PAYLOAD_CACHE, defaultConfig.entryTtl(Duration.ofMinutes(30)));
|
|
||||||
|
|
||||||
// 关联关系:15分钟(关联关系可能变化)
|
|
||||||
cacheConfigurations.put(DOCK_AIRCRAFT_CACHE, defaultConfig.entryTtl(Duration.ofMinutes(15)));
|
|
||||||
cacheConfigurations.put(AIRCRAFT_PAYLOAD_CACHE, defaultConfig.entryTtl(Duration.ofMinutes(15)));
|
|
||||||
|
|
||||||
// ThingsBoard 设备属性:90秒(属性数据,变化较少)
|
|
||||||
cacheConfigurations.put(THINGSBOARD_ATTRIBUTES_CACHE, defaultConfig.entryTtl(Duration.ofSeconds(90)));
|
|
||||||
|
|
||||||
// ThingsBoard 设备遥测:15秒(遥测数据,实时性要求高)
|
|
||||||
cacheConfigurations.put(THINGSBOARD_TELEMETRY_CACHE, defaultConfig.entryTtl(Duration.ofSeconds(15)));
|
|
||||||
|
|
||||||
// 天气信息:5分钟(天气数据,变化较慢)
|
|
||||||
cacheConfigurations.put(WEATHER_CACHE, defaultConfig.entryTtl(Duration.ofMinutes(5)));
|
|
||||||
|
|
||||||
return RedisCacheManager.builder(connectionFactory)
|
|
||||||
.cacheDefaults(defaultConfig)
|
|
||||||
.withInitialCacheConfigurations(cacheConfigurations)
|
|
||||||
.transactionAware()
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,14 +0,0 @@
|
||||||
package com.ruoyi.device.config;
|
|
||||||
|
|
||||||
import org.springframework.context.annotation.Bean;
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
|
||||||
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
|
|
||||||
|
|
||||||
@Configuration
|
|
||||||
public class WebSocketConfig {
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
public ServerEndpointExporter serverEndpointExporter() {
|
|
||||||
return new ServerEndpointExporter();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,82 +0,0 @@
|
||||||
package com.ruoyi.device.controller;
|
|
||||||
|
|
||||||
import com.ruoyi.common.core.domain.R;
|
|
||||||
import com.ruoyi.common.core.web.controller.BaseController;
|
|
||||||
import com.ruoyi.common.security.annotation.InnerAuth;
|
|
||||||
import com.ruoyi.device.api.domain.AircraftDetailVO;
|
|
||||||
import com.ruoyi.device.api.domain.AircraftUpdateRequest;
|
|
||||||
import com.ruoyi.device.api.domain.DockAircraftVO;
|
|
||||||
import com.ruoyi.device.controller.convert.AircraftDetailVOConvert;
|
|
||||||
import com.ruoyi.device.mapper.DockAircraftMapper;
|
|
||||||
import com.ruoyi.device.service.api.IAircraftService;
|
|
||||||
import com.ruoyi.device.service.impl.DefaultBufferDeviceImpl;
|
|
||||||
import com.ruoyi.device.service.dto.AircraftDetailDTO;
|
|
||||||
import com.ruoyi.device.service.dto.AircraftDTO;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.web.bind.annotation.*;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 无人机Controller
|
|
||||||
*
|
|
||||||
* @author ruoyi
|
|
||||||
* @date 2026-01-20
|
|
||||||
*/
|
|
||||||
@RestController
|
|
||||||
@RequestMapping("/aircraft")
|
|
||||||
public class AircraftController extends BaseController
|
|
||||||
{
|
|
||||||
@Autowired
|
|
||||||
private IAircraftService aircraftService;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private DefaultBufferDeviceImpl bufferDeviceService;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private DockAircraftMapper dockAircraftMapper;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 查看无人机详情
|
|
||||||
*
|
|
||||||
* @param aircraftId 无人机ID
|
|
||||||
* @return 无人机详情
|
|
||||||
*/
|
|
||||||
// @InnerAuth
|
|
||||||
@GetMapping("/detail/{aircraftId}")
|
|
||||||
public R<AircraftDetailVO> getAircraftDetail(@PathVariable("aircraftId") Long aircraftId)
|
|
||||||
{
|
|
||||||
AircraftDetailDTO dto = bufferDeviceService.getAircraftDetailById(aircraftId);
|
|
||||||
AircraftDetailVO vo = AircraftDetailVOConvert.from(dto);
|
|
||||||
return R.ok(vo);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 修改无人机名称
|
|
||||||
*
|
|
||||||
* @param request 无人机更新请求
|
|
||||||
* @return 结果
|
|
||||||
*/
|
|
||||||
//@InnerAuth
|
|
||||||
@PostMapping("/update")
|
|
||||||
public R<Void> updateAircraft(@RequestBody AircraftUpdateRequest request)
|
|
||||||
{
|
|
||||||
AircraftDTO dto = new AircraftDTO();
|
|
||||||
dto.setAircraftId(request.getAircraftId());
|
|
||||||
dto.setAircraftName(request.getAircraftName());
|
|
||||||
aircraftService.updateAircraft(dto);
|
|
||||||
return R.ok();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取所有机场和机场的无人机
|
|
||||||
*
|
|
||||||
* @return 机场无人机列表
|
|
||||||
*/
|
|
||||||
@GetMapping("/dock-aircraft-list")
|
|
||||||
public R<List<DockAircraftVO>> getDockAircraftList()
|
|
||||||
{
|
|
||||||
List<DockAircraftVO> list = dockAircraftMapper.selectDockAircraftWithDetails();
|
|
||||||
return R.ok(list);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,486 +0,0 @@
|
||||||
package com.ruoyi.device.controller;
|
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSON;
|
|
||||||
import com.ruoyi.common.core.domain.R;
|
|
||||||
import com.ruoyi.common.core.web.controller.BaseController;
|
|
||||||
import com.ruoyi.device.api.domain.*;
|
|
||||||
import com.ruoyi.device.api.enums.DroneCurrentStatusEnum;
|
|
||||||
import com.ruoyi.device.api.enums.DroneMissionStatusEnum;
|
|
||||||
import com.ruoyi.device.domain.impl.machine.MachineCommandManager;
|
|
||||||
import com.ruoyi.device.domain.impl.machine.command.CommandResult;
|
|
||||||
import com.ruoyi.device.domain.impl.machine.command.CommandType;
|
|
||||||
import com.ruoyi.device.domain.impl.machine.state.MachineStates;
|
|
||||||
import com.ruoyi.device.service.FlightService;
|
|
||||||
import com.ruoyi.task.api.enums.StatusEnum;
|
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
|
||||||
import io.swagger.v3.oas.annotations.Parameter;
|
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.web.bind.annotation.*;
|
|
||||||
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.UUID;
|
|
||||||
import java.util.concurrent.CompletableFuture;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 无人机飞控Controller
|
|
||||||
*
|
|
||||||
* @author ruoyi
|
|
||||||
* @date 2026-02-04
|
|
||||||
*/
|
|
||||||
@Slf4j
|
|
||||||
@Tag(name = "无人机飞控管理", description = "无人机飞控相关接口")
|
|
||||||
@RestController
|
|
||||||
@RequestMapping("/drone")
|
|
||||||
public class AircraftFlyController extends BaseController
|
|
||||||
{
|
|
||||||
@Autowired
|
|
||||||
private MachineCommandManager machineCommandManager;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private com.ruoyi.device.domain.impl.machine.statemachine.MachineStateManager machineStateManager;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private FlightService flightService;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 无人机飞控命令
|
|
||||||
*
|
|
||||||
* @param request 飞控命令请求
|
|
||||||
* @return 结果
|
|
||||||
*/
|
|
||||||
@Operation(summary = "无人机飞控命令", description = "发送飞控指令")
|
|
||||||
@PostMapping("/flight-control")
|
|
||||||
public R<Void> flightControl(@RequestBody DroneFlightControlRequest request)
|
|
||||||
{
|
|
||||||
if (request.getCommand() == null || request.getSn() == null) {
|
|
||||||
return R.fail("飞控命令和机场SN号不能为空");
|
|
||||||
}
|
|
||||||
|
|
||||||
String sn = request.getSn();
|
|
||||||
log.info("收到飞控命令: sn={}, command={}", sn, request.getCommand());
|
|
||||||
|
|
||||||
try {
|
|
||||||
CommandType commandType;
|
|
||||||
java.util.Map<String, Object> params = new java.util.HashMap<>();
|
|
||||||
|
|
||||||
// 处理消息ID
|
|
||||||
if (request.getMessageID() != null) {
|
|
||||||
params.put("messageID", request.getMessageID());
|
|
||||||
} else {
|
|
||||||
params.put("messageID", System.currentTimeMillis());
|
|
||||||
}
|
|
||||||
|
|
||||||
// 处理扩展参数
|
|
||||||
if (request.getEvalue() != null) {
|
|
||||||
params.put("evalue", request.getEvalue());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (request.getValue() != null) {
|
|
||||||
params.put("value", request.getValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (request.getLightMode() != null) {
|
|
||||||
params.put("lightMode", request.getLightMode());
|
|
||||||
}
|
|
||||||
|
|
||||||
// 处理航线飞行、悬停、继续任务所需的参数
|
|
||||||
if (request.getAirlineFileUrl() != null) {
|
|
||||||
params.put("airlineFileUrl", request.getAirlineFileUrl());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (request.getFlyBatteryMin() != null) {
|
|
||||||
params.put("flyBatteryMin", request.getFlyBatteryMin());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (request.getIsMustFly() != null) {
|
|
||||||
params.put("isMustFly", request.getIsMustFly());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (request.getTaskId() != null) {
|
|
||||||
params.put("taskId", request.getTaskId());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (request.getZhilin() != null) {
|
|
||||||
params.put("zhilin", request.getZhilin());
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (request.getCommand()) {
|
|
||||||
case FORWARD:
|
|
||||||
commandType = CommandType.FORWARD;
|
|
||||||
break;
|
|
||||||
case BACKWARD:
|
|
||||||
commandType = CommandType.BACKWARD;
|
|
||||||
break;
|
|
||||||
case LEFT:
|
|
||||||
commandType = CommandType.LEFT;
|
|
||||||
break;
|
|
||||||
case RIGHT:
|
|
||||||
commandType = CommandType.RIGHT;
|
|
||||||
break;
|
|
||||||
case ROTATE_LEFT:
|
|
||||||
commandType = CommandType.ROTATE_LEFT;
|
|
||||||
break;
|
|
||||||
case ROTATE_RIGHT:
|
|
||||||
commandType = CommandType.ROTATE_RIGHT;
|
|
||||||
break;
|
|
||||||
case UP:
|
|
||||||
commandType = CommandType.UP;
|
|
||||||
break;
|
|
||||||
case DOWN:
|
|
||||||
commandType = CommandType.DOWN;
|
|
||||||
break;
|
|
||||||
case SWITCH_VISIBLE_LIGHT:
|
|
||||||
commandType = CommandType.SWITCH_VISIBLE_LIGHT;
|
|
||||||
break;
|
|
||||||
case GIMBAL_ZOOM:
|
|
||||||
commandType = CommandType.GIMBAL_ZOOM;
|
|
||||||
break;
|
|
||||||
case SWITCH_IR:
|
|
||||||
commandType = CommandType.SWITCH_IR;
|
|
||||||
break;
|
|
||||||
case SWITCH_WIDE_ANGLE:
|
|
||||||
commandType = CommandType.SWITCH_WIDE_ANGLE;
|
|
||||||
break;
|
|
||||||
case GIMBAL_MOVE_RIGHT:
|
|
||||||
commandType = CommandType.GIMBAL_MOVE_RIGHT;
|
|
||||||
break;
|
|
||||||
case GIMBAL_MOVE_LEFT:
|
|
||||||
commandType = CommandType.GIMBAL_MOVE_LEFT;
|
|
||||||
break;
|
|
||||||
case GIMBAL_PITCH_UP:
|
|
||||||
commandType = CommandType.GIMBAL_PITCH_UP;
|
|
||||||
break;
|
|
||||||
case GIMBAL_PITCH_DOWN:
|
|
||||||
commandType = CommandType.GIMBAL_PITCH_DOWN;
|
|
||||||
break;
|
|
||||||
case GIMBAL_RESET:
|
|
||||||
commandType = CommandType.GIMBAL_RESET;
|
|
||||||
break;
|
|
||||||
case AIRLINE_FLIGHT:
|
|
||||||
commandType = CommandType.AIRLINE_FLIGHT;
|
|
||||||
break;
|
|
||||||
case HOVER:
|
|
||||||
commandType = CommandType.HOVER;
|
|
||||||
break;
|
|
||||||
case CONTINUE_TASK:
|
|
||||||
commandType = CommandType.CONTINUE_TASK;
|
|
||||||
break;
|
|
||||||
case EMERGENCY_STOP:
|
|
||||||
return R.fail("急停命令暂不支持");
|
|
||||||
default:
|
|
||||||
return R.fail("不支持的飞控命令");
|
|
||||||
}
|
|
||||||
|
|
||||||
CompletableFuture<CommandResult> future = machineCommandManager.executeCommand(sn, commandType, params);
|
|
||||||
CommandResult result = future.get();
|
|
||||||
|
|
||||||
if (result.isSuccess()) {
|
|
||||||
log.info("飞控命令执行成功: sn={}, command={}", sn, request.getCommand());
|
|
||||||
return R.ok();
|
|
||||||
} else {
|
|
||||||
log.error("飞控命令执行失败: sn={}, command={}, reason={}", sn, request.getCommand(), result.getErrorMessage());
|
|
||||||
return R.fail("飞控命令执行失败: " + result.getErrorMessage());
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("飞控命令执行异常: sn={}, command={}", sn, request.getCommand(), e);
|
|
||||||
return R.fail("飞控命令执行异常: " + e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 无人机实时信息展示
|
|
||||||
*
|
|
||||||
* @param taskId 任务ID
|
|
||||||
* @return 实时信息
|
|
||||||
*/
|
|
||||||
@Operation(summary = "无人机实时信息展示", description = "根据任务ID获取无人机的实时飞行信息,包括速度、高度、姿态角等")
|
|
||||||
@GetMapping("/realtime-info/{taskId}")
|
|
||||||
public R<DroneRealtimeInfoVO> getRealtimeInfo(
|
|
||||||
@Parameter(description = "任务ID", required = true, example = "1")
|
|
||||||
@PathVariable("taskId") Long taskId)
|
|
||||||
{
|
|
||||||
// TODO: 实现获取实时信息逻辑
|
|
||||||
DroneRealtimeInfoVO vo = new DroneRealtimeInfoVO();
|
|
||||||
vo.setClimbSpeed(0);
|
|
||||||
vo.setCruiseSpeed(0);
|
|
||||||
vo.setDistanceToAirport(0);
|
|
||||||
vo.setAltitude(0);
|
|
||||||
vo.setPitch(0);
|
|
||||||
vo.setYaw(0);
|
|
||||||
vo.setGimbalPitch(0);
|
|
||||||
vo.setGimbalYaw(0);
|
|
||||||
vo.setMissionStatus(DroneMissionStatusEnum.IDLE);
|
|
||||||
return R.ok(vo);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 无人机当前状态查询
|
|
||||||
*
|
|
||||||
* @param dockId 机场ID
|
|
||||||
* @return 当前状态
|
|
||||||
*/
|
|
||||||
@Operation(summary = "无人机当前状态查询", description = "根据机场ID查询无人机的当前飞行状态")
|
|
||||||
@GetMapping("/current-status/{dockId}")
|
|
||||||
public R<DroneCurrentStatusVO> getCurrentStatus(
|
|
||||||
@Parameter(description = "机场ID", required = true, example = "1")
|
|
||||||
@PathVariable("dockId") Long dockId)
|
|
||||||
{
|
|
||||||
// TODO: 实现查询当前状态逻辑
|
|
||||||
DroneCurrentStatusVO vo = new DroneCurrentStatusVO();
|
|
||||||
vo.setDockId(dockId);
|
|
||||||
vo.setCurrentStatus(DroneCurrentStatusEnum.HOVERING);
|
|
||||||
return R.ok(vo);
|
|
||||||
}
|
|
||||||
|
|
||||||
//从配置文件获取
|
|
||||||
private final static String airlineFileUrl = "https://minio-dx.t-aaron.com:2443/th-airport/testFile/191ec54c-062c-4828-aab6-cefc901add78.waypoints";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 无人机一键起飞
|
|
||||||
*
|
|
||||||
* @param request 起飞请求对象
|
|
||||||
* @return 起飞响应
|
|
||||||
*/
|
|
||||||
@Operation(summary = "无人机一键起飞", description = "控制指定机场的无人机执行起飞操作")
|
|
||||||
@PostMapping("/takeoff")
|
|
||||||
public R<String> takeoff(@RequestBody DroneTakeoffRequest request)
|
|
||||||
{
|
|
||||||
|
|
||||||
// Long taskId = flightService.createClickTakeOffTask(request.getSn(),airlineFileUrl);
|
|
||||||
log.info("一键起飞,生成一键起飞任务 {} ", JSON.toJSONString(request));
|
|
||||||
try {
|
|
||||||
java.util.Map<String, Object> params = new java.util.HashMap<>();
|
|
||||||
params.put("airlineFileUrl", airlineFileUrl);
|
|
||||||
params.put("flyBatteryMin", request.getFlyBatteryMin());
|
|
||||||
params.put("messageID", request.getTaskId());
|
|
||||||
CompletableFuture<CommandResult> future = machineCommandManager.executeCommand(request.getSn(), CommandType.TAKE_OFF, params);
|
|
||||||
CommandResult result = future.get();
|
|
||||||
|
|
||||||
if (result.isSuccess()) {
|
|
||||||
log.info("无人机起飞命令发送成功: sn={}", request.getSn());
|
|
||||||
flightService.updateFlightStatus(request.getTaskId(), StatusEnum.CHECKING);
|
|
||||||
return R.ok("无人机起飞命令发送成功");
|
|
||||||
} else {
|
|
||||||
log.error("无人机起飞命令发送失败: sn={}, reason={}", request.getSn(), result.getErrorMessage());
|
|
||||||
flightService.updateFlightStatus(request.getTaskId(), StatusEnum.FAILED);
|
|
||||||
return R.fail("无人机起飞命令发送失败: " + result.getErrorMessage());
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("无人机起飞命令发送失败: sn={}", request.getSn(), e);
|
|
||||||
flightService.updateFlightStatus(request.getTaskId(), StatusEnum.FAILED);
|
|
||||||
return R.fail("无人机起飞命令发送失败: " + e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 无人机开机接口
|
|
||||||
*
|
|
||||||
* @param sn 机场SN号
|
|
||||||
* @return 开机响应
|
|
||||||
*/
|
|
||||||
@Operation(summary = "无人机开机", description = "控制指定机场的无人机执行开机操作")
|
|
||||||
@PostMapping("/power-on/{sn}")
|
|
||||||
public R<String> powerOn(
|
|
||||||
@Parameter(description = "机场SN号", required = true, example = "THJSQ03B2309DN7VQN43")
|
|
||||||
@PathVariable("sn") String sn)
|
|
||||||
{
|
|
||||||
log.info("收到无人机开机请求: sn={}", sn);
|
|
||||||
|
|
||||||
try {
|
|
||||||
// 调用机器命令管理器执行开机命令
|
|
||||||
CompletableFuture<CommandResult> future = machineCommandManager.executeCommand(sn, CommandType.POWER_ON);
|
|
||||||
|
|
||||||
// 等待命令执行完成
|
|
||||||
CommandResult result = future.get();
|
|
||||||
|
|
||||||
if (result.isSuccess()) {
|
|
||||||
log.info("无人机开机成功: sn={}", sn);
|
|
||||||
return R.ok("开机命令执行成功");
|
|
||||||
} else {
|
|
||||||
log.error("无人机开机失败: sn={}, reason={}", sn, result.getErrorMessage());
|
|
||||||
return R.fail("开机命令执行失败: " + result.getErrorMessage());
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("无人机开机异常: sn={}", sn, e);
|
|
||||||
return R.fail("开机命令执行异常: " + e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 无人机关机接口
|
|
||||||
*
|
|
||||||
* @param sn 机场SN号
|
|
||||||
* @return 关机响应
|
|
||||||
*/
|
|
||||||
@Operation(summary = "无人机关机", description = "控制指定机场的无人机执行关机操作")
|
|
||||||
@PostMapping("/power-off/{sn}")
|
|
||||||
public R<String> powerOff(
|
|
||||||
@Parameter(description = "机场SN号", required = true, example = "THJSQ03B2309DN7VQN43")
|
|
||||||
@PathVariable("sn") String sn)
|
|
||||||
{
|
|
||||||
log.info("收到无人机关机请求: sn={}", sn);
|
|
||||||
|
|
||||||
try {
|
|
||||||
// 调用机器命令管理器执行关机命令
|
|
||||||
CompletableFuture<CommandResult> future = machineCommandManager.executeCommand(sn, CommandType.POWER_OFF);
|
|
||||||
|
|
||||||
// 等待命令执行完成
|
|
||||||
CommandResult result = future.get();
|
|
||||||
|
|
||||||
if (result.isSuccess()) {
|
|
||||||
log.info("无人机关机成功: sn={}", sn);
|
|
||||||
return R.ok("关机命令执行成功");
|
|
||||||
} else {
|
|
||||||
log.error("无人机关机失败: sn={}, reason={}", sn, result.getErrorMessage());
|
|
||||||
return R.fail("关机命令执行失败: " + result.getErrorMessage());
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("无人机关机异常: sn={}", sn, e);
|
|
||||||
return R.fail("关机命令执行异常: " + e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 查询无人机状态
|
|
||||||
*
|
|
||||||
* @param sn 设备SN号
|
|
||||||
* @return 状态信息
|
|
||||||
*/
|
|
||||||
@Operation(summary = "查询无人机状态", description = "根据设备SN号查询无人机的实时状态信息")
|
|
||||||
@GetMapping("/machine-state/{sn}")
|
|
||||||
public R<MachineStateVO> getMachineState(
|
|
||||||
@Parameter(description = "设备SN号", required = true, example = "TH001")
|
|
||||||
@PathVariable("sn") String sn)
|
|
||||||
{
|
|
||||||
log.info("查询无人机状态: sn={}", sn);
|
|
||||||
|
|
||||||
try {
|
|
||||||
// 从 MachineStateManager 获取状态
|
|
||||||
MachineStates states = machineStateManager.getStates(sn);
|
|
||||||
|
|
||||||
// 转换为 VO 对象
|
|
||||||
MachineStateVO vo = new MachineStateVO();
|
|
||||||
vo.setSn(sn);
|
|
||||||
vo.setDroneState(states.getDroneState().name());
|
|
||||||
vo.setAirportState(states.getAirportState().name());
|
|
||||||
vo.setCoverState(states.getCoverState().name());
|
|
||||||
vo.setDrcState(states.getDrcState().name());
|
|
||||||
vo.setDebugModeState(states.getDebugModeState().name());
|
|
||||||
|
|
||||||
log.info("查询到状态: sn={}, vo={}", sn, vo);
|
|
||||||
return R.ok(vo);
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("查询无人机状态异常: sn={}", sn, e);
|
|
||||||
return R.fail("查询状态失败: " + e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 出舱接口
|
|
||||||
*
|
|
||||||
* @param sn 机场SN号
|
|
||||||
* @return 出舱响应
|
|
||||||
*/
|
|
||||||
@Operation(summary = "出舱", description = "控制指定机场执行出舱操作")
|
|
||||||
@PostMapping("/cover-open/{sn}")
|
|
||||||
public R<String> coverOpen(
|
|
||||||
@Parameter(description = "机场SN号", required = true, example = "THJSQ03B2309DN7VQN43")
|
|
||||||
@PathVariable("sn") String sn)
|
|
||||||
{
|
|
||||||
log.info("收到出舱请求: sn={}", sn);
|
|
||||||
|
|
||||||
try {
|
|
||||||
// 调用机器命令管理器执行出舱命令
|
|
||||||
CompletableFuture<CommandResult> future = machineCommandManager.executeCommand(sn, CommandType.OPEN_COVER);
|
|
||||||
|
|
||||||
// 等待命令执行完成
|
|
||||||
CommandResult result = future.get();
|
|
||||||
|
|
||||||
if (result.isSuccess()) {
|
|
||||||
log.info("出舱成功: sn={}", sn);
|
|
||||||
return R.ok("出舱命令执行成功");
|
|
||||||
} else {
|
|
||||||
log.error("出舱失败: sn={}, reason={}", sn, result.getErrorMessage());
|
|
||||||
return R.fail("出舱命令执行失败: " + result.getErrorMessage());
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("出舱异常: sn={}", sn, e);
|
|
||||||
return R.fail("出舱命令执行异常: " + e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 回舱接口
|
|
||||||
*
|
|
||||||
* @param sn 机场SN号
|
|
||||||
* @return 回舱响应
|
|
||||||
*/
|
|
||||||
@Operation(summary = "回舱", description = "控制指定机场执行回舱操作")
|
|
||||||
@PostMapping("/cover-close/{sn}")
|
|
||||||
public R<String> coverClose(
|
|
||||||
@Parameter(description = "机场SN号", required = true, example = "THJSQ03B2309DN7VQN43")
|
|
||||||
@PathVariable("sn") String sn)
|
|
||||||
{
|
|
||||||
log.info("收到回舱请求: sn={}", sn);
|
|
||||||
|
|
||||||
try {
|
|
||||||
// 调用机器命令管理器执行回舱命令
|
|
||||||
CompletableFuture<CommandResult> future = machineCommandManager.executeCommand(sn, CommandType.CLOSE_COVER);
|
|
||||||
|
|
||||||
// 等待命令执行完成
|
|
||||||
CommandResult result = future.get();
|
|
||||||
|
|
||||||
if (result.isSuccess()) {
|
|
||||||
log.info("回舱成功: sn={}", sn);
|
|
||||||
return R.ok("回舱命令执行成功");
|
|
||||||
} else {
|
|
||||||
log.error("回舱失败: sn={}, reason={}", sn, result.getErrorMessage());
|
|
||||||
return R.fail("回舱命令执行失败: " + result.getErrorMessage());
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("回舱异常: sn={}", sn, e);
|
|
||||||
return R.fail("回舱命令执行异常: " + e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 无人机返航接口
|
|
||||||
*
|
|
||||||
* @param request 返航请求对象
|
|
||||||
* @return 返航响应
|
|
||||||
*/
|
|
||||||
@Operation(summary = "无人机返航", description = "控制指定机场的无人机执行返航操作")
|
|
||||||
@PostMapping("/return-home")
|
|
||||||
public R<String> returnHome(@RequestBody DroneReturnHomeRequest request)
|
|
||||||
{
|
|
||||||
log.info("收到无人机返航请求: sn={} ", request.getSn());
|
|
||||||
|
|
||||||
try {
|
|
||||||
|
|
||||||
Long currentTaskId = flightService.currentRunningTask(request.getSn());
|
|
||||||
java.util.Map<String, Object> params = new java.util.HashMap<>();
|
|
||||||
if(Objects.isNull(currentTaskId)){
|
|
||||||
params.put("messageID", UUID.randomUUID().toString());
|
|
||||||
}else {
|
|
||||||
params.put("messageID",currentTaskId);
|
|
||||||
}
|
|
||||||
params.put("taskId", 9074);
|
|
||||||
params.put("zhilin", "03");
|
|
||||||
CompletableFuture<CommandResult> future = machineCommandManager.executeCommand(request.getSn(), CommandType.RETURN_HOME, params);
|
|
||||||
CommandResult result = future.get();
|
|
||||||
|
|
||||||
if (result.isSuccess()) {
|
|
||||||
log.info("无人机返航成功: sn={}", request.getSn());
|
|
||||||
return R.ok("返航命令执行成功");
|
|
||||||
} else {
|
|
||||||
log.error("无人机返航失败: sn={}, reason={}", request.getSn(), result.getErrorMessage());
|
|
||||||
return R.fail("返航命令执行失败: " + result.getErrorMessage());
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("无人机返航异常: sn={}", request.getSn(), e);
|
|
||||||
return R.fail("返航命令执行异常: " + e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,169 +0,0 @@
|
||||||
package com.ruoyi.device.controller;
|
|
||||||
|
|
||||||
import com.ruoyi.common.core.constant.SecurityConstants;
|
|
||||||
import com.ruoyi.common.core.domain.R;
|
|
||||||
import com.ruoyi.common.core.web.controller.BaseController;
|
|
||||||
import com.ruoyi.device.api.domain.AirTypeCategoryGroupVO;
|
|
||||||
import com.ruoyi.device.api.domain.AirTypeGeneralEnumVO;
|
|
||||||
import com.ruoyi.device.api.domain.AirTypeVendorGroupVO;
|
|
||||||
import com.ruoyi.device.controller.convert.DeviceAirTypeGeneralEnumVOConvert;
|
|
||||||
import com.ruoyi.device.service.api.IDeviceAirTypeGeneralEnumService;
|
|
||||||
import com.ruoyi.device.service.dto.DeviceAirTypeGeneralEnumDTO;
|
|
||||||
import com.ruoyi.system.api.RemoteDictService;
|
|
||||||
import com.ruoyi.system.api.domain.SysDictData;
|
|
||||||
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.ArrayList;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 无人机类型通用枚举Controller
|
|
||||||
*
|
|
||||||
* @author 拓恒
|
|
||||||
* @date 2026-01-28
|
|
||||||
*/
|
|
||||||
@RestController
|
|
||||||
@RequestMapping("/airType/generalEnum")
|
|
||||||
public class DeviceAirTypeGeneralEnumController extends BaseController
|
|
||||||
{
|
|
||||||
@Autowired
|
|
||||||
private IDeviceAirTypeGeneralEnumService airTypeGeneralEnumService;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private RemoteDictService remoteDictService;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 查询无人机类型通用枚举列表
|
|
||||||
*
|
|
||||||
* @param vo 无人机类型通用枚举VO
|
|
||||||
* @return 无人机类型通用枚举列表
|
|
||||||
*/
|
|
||||||
@GetMapping("/list")
|
|
||||||
public R<List<AirTypeGeneralEnumVO>> selectAirTypeGeneralEnumList(AirTypeGeneralEnumVO vo)
|
|
||||||
{
|
|
||||||
DeviceAirTypeGeneralEnumDTO dto = DeviceAirTypeGeneralEnumVOConvert.to(vo);
|
|
||||||
List<DeviceAirTypeGeneralEnumDTO> list = airTypeGeneralEnumService.selectAirTypeGeneralEnumList(dto);
|
|
||||||
List<AirTypeGeneralEnumVO> voList = DeviceAirTypeGeneralEnumVOConvert.fromList(list);
|
|
||||||
return R.ok(voList);
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* 按厂商分组查询无人机类型
|
|
||||||
*
|
|
||||||
* @param vo 无人机类型通用枚举VO
|
|
||||||
* @return 按厂商分组的无人机类型列表
|
|
||||||
*/
|
|
||||||
@GetMapping("/vendorGroup")
|
|
||||||
public R<List<AirTypeVendorGroupVO>> selectAirTypeGeneralEnumGroupByVendor(AirTypeGeneralEnumVO vo)
|
|
||||||
{
|
|
||||||
// 从数据字典获取无人机厂商类型
|
|
||||||
R<List<SysDictData>> dictResult = remoteDictService.getDictDataByType("air_vendor_type", SecurityConstants.INNER);
|
|
||||||
List<AirTypeVendorGroupVO> vendorGroupList = new ArrayList<>();
|
|
||||||
|
|
||||||
if (dictResult.getData() != null)
|
|
||||||
{
|
|
||||||
// 获取所有无人机类型数据
|
|
||||||
DeviceAirTypeGeneralEnumDTO dto = DeviceAirTypeGeneralEnumVOConvert.to(vo);
|
|
||||||
List<DeviceAirTypeGeneralEnumDTO> allList = airTypeGeneralEnumService.selectAirTypeGeneralEnumList(dto);
|
|
||||||
List<AirTypeGeneralEnumVO> allVoList = DeviceAirTypeGeneralEnumVOConvert.fromList(allList);
|
|
||||||
|
|
||||||
// 为每个字典项创建分组
|
|
||||||
for (SysDictData dictData : dictResult.getData())
|
|
||||||
{
|
|
||||||
AirTypeVendorGroupVO groupVO = new AirTypeVendorGroupVO();
|
|
||||||
groupVO.setLabel(dictData.getDictLabel());
|
|
||||||
groupVO.setValue(dictData.getDictValue());
|
|
||||||
|
|
||||||
// 筛选属于当前厂商的无人机类型
|
|
||||||
List<AirTypeGeneralEnumVO> vendorAirTypes = new ArrayList<>();
|
|
||||||
for (AirTypeGeneralEnumVO airTypeGeneralEnumVO : allVoList)
|
|
||||||
{
|
|
||||||
if (dictData.getDictValue().equals(airTypeGeneralEnumVO.getVendorId().toString()))
|
|
||||||
{
|
|
||||||
airTypeGeneralEnumVO.generateTypeCode();
|
|
||||||
vendorAirTypes.add(airTypeGeneralEnumVO);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
groupVO.setAirTypeList(vendorAirTypes);
|
|
||||||
vendorGroupList.add(groupVO);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return R.ok(vendorGroupList);
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* 按厂商分组查询无人机类型(厂商 -> 分类 -> 设备类型)
|
|
||||||
*
|
|
||||||
* @param vo 无人机类型通用枚举VO
|
|
||||||
* @return 按厂商分组的无人机类型列表
|
|
||||||
*/
|
|
||||||
@GetMapping("/vendorGroupNew")
|
|
||||||
public R<List<AirTypeVendorGroupVO>> selectAirTypeGeneralEnumGroupByVendorNew(AirTypeGeneralEnumVO vo)
|
|
||||||
{
|
|
||||||
// 从数据字典获取无人机厂商类型
|
|
||||||
R<List<SysDictData>> dictResult = remoteDictService.getDictDataByType("air_vendor_type", SecurityConstants.INNER);
|
|
||||||
List<AirTypeVendorGroupVO> vendorGroupList = new ArrayList<>();
|
|
||||||
|
|
||||||
if (dictResult.getData() != null)
|
|
||||||
{
|
|
||||||
// 获取所有无人机类型数据(包括生效和失效的)
|
|
||||||
DeviceAirTypeGeneralEnumDTO dto = DeviceAirTypeGeneralEnumVOConvert.to(vo);
|
|
||||||
List<DeviceAirTypeGeneralEnumDTO> allList = airTypeGeneralEnumService.selectAirTypeGeneralEnumList(dto);
|
|
||||||
List<AirTypeGeneralEnumVO> allVoList = DeviceAirTypeGeneralEnumVOConvert.fromList(allList);
|
|
||||||
|
|
||||||
// 为每个字典项创建分组
|
|
||||||
for (SysDictData dictData : dictResult.getData())
|
|
||||||
{
|
|
||||||
AirTypeVendorGroupVO groupVO = new AirTypeVendorGroupVO();
|
|
||||||
groupVO.setLabel(dictData.getDictLabel());
|
|
||||||
groupVO.setValue(dictData.getDictValue());
|
|
||||||
|
|
||||||
// 筛选属于当前厂商的无人机类型
|
|
||||||
List<AirTypeGeneralEnumVO> vendorAirTypes = new ArrayList<>();
|
|
||||||
for (AirTypeGeneralEnumVO airTypeGeneralEnumVO : allVoList)
|
|
||||||
{
|
|
||||||
if (dictData.getDictValue().equals(airTypeGeneralEnumVO.getVendorId().toString()))
|
|
||||||
{
|
|
||||||
airTypeGeneralEnumVO.generateTypeCode();
|
|
||||||
vendorAirTypes.add(airTypeGeneralEnumVO);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 按分类分组
|
|
||||||
Map<String, List<AirTypeGeneralEnumVO>> categoryMap = new HashMap<>();
|
|
||||||
for (AirTypeGeneralEnumVO airTypeGeneralEnumVO : vendorAirTypes)
|
|
||||||
{
|
|
||||||
String category = airTypeGeneralEnumVO.getCategory();
|
|
||||||
if (category == null || category.isEmpty()) {
|
|
||||||
category = "其他";
|
|
||||||
}
|
|
||||||
if (!categoryMap.containsKey(category)) {
|
|
||||||
categoryMap.put(category, new ArrayList<>());
|
|
||||||
}
|
|
||||||
categoryMap.get(category).add(airTypeGeneralEnumVO);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 构建分类分组列表
|
|
||||||
List<AirTypeCategoryGroupVO> categoryGroups = new ArrayList<>();
|
|
||||||
for (Map.Entry<String, List<AirTypeGeneralEnumVO>> entry : categoryMap.entrySet()) {
|
|
||||||
AirTypeCategoryGroupVO categoryGroup = new AirTypeCategoryGroupVO();
|
|
||||||
categoryGroup.setCategory(entry.getKey());
|
|
||||||
categoryGroup.setAirTypeList(entry.getValue());
|
|
||||||
categoryGroups.add(categoryGroup);
|
|
||||||
}
|
|
||||||
|
|
||||||
groupVO.setCategoryGroups(categoryGroups);
|
|
||||||
vendorGroupList.add(groupVO);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return R.ok(vendorGroupList);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -6,7 +6,7 @@ import com.ruoyi.common.core.web.domain.AjaxResult;
|
||||||
import com.ruoyi.common.core.web.page.TableDataInfo;
|
import com.ruoyi.common.core.web.page.TableDataInfo;
|
||||||
import com.ruoyi.common.security.annotation.InnerAuth;
|
import com.ruoyi.common.security.annotation.InnerAuth;
|
||||||
import com.ruoyi.device.api.domain.DeviceTempVO;
|
import com.ruoyi.device.api.domain.DeviceTempVO;
|
||||||
import com.ruoyi.device.controller.convert.DeviceTempVOConvert;
|
import com.ruoyi.device.controller.convert.DeviceTempControllerConvert;
|
||||||
import com.ruoyi.device.service.api.IDeviceTempService;
|
import com.ruoyi.device.service.api.IDeviceTempService;
|
||||||
import com.ruoyi.device.service.dto.DeviceTempDTO;
|
import com.ruoyi.device.service.dto.DeviceTempDTO;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
@ -38,10 +38,10 @@ public class DeviceTempController extends BaseController
|
||||||
{
|
{
|
||||||
startPage();
|
startPage();
|
||||||
// API Domain → Service DTO
|
// API Domain → Service DTO
|
||||||
DeviceTempDTO dto = DeviceTempVOConvert.to(deviceTemp);
|
DeviceTempDTO dto = DeviceTempControllerConvert.toDTO(deviceTemp);
|
||||||
List<DeviceTempDTO> dtoList = deviceTempService.selectDeviceTempList(dto);
|
List<DeviceTempDTO> dtoList = deviceTempService.selectDeviceTempList(dto);
|
||||||
// Service DTO → API Domain
|
// Service DTO → API Domain
|
||||||
List<DeviceTempVO> list = DeviceTempVOConvert.fromList(dtoList);
|
List<DeviceTempVO> list = DeviceTempControllerConvert.toApiDomainList(dtoList);
|
||||||
return getDataTable(list);
|
return getDataTable(list);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -53,7 +53,7 @@ public class DeviceTempController extends BaseController
|
||||||
public R<DeviceTempVO> getDeviceById(@PathVariable("id") String id)
|
public R<DeviceTempVO> getDeviceById(@PathVariable("id") String id)
|
||||||
{
|
{
|
||||||
DeviceTempDTO dto = deviceTempService.selectDeviceTempById(id);
|
DeviceTempDTO dto = deviceTempService.selectDeviceTempById(id);
|
||||||
DeviceTempVO deviceTemp = DeviceTempVOConvert.from(dto);
|
DeviceTempVO deviceTemp = DeviceTempControllerConvert.toVO(dto);
|
||||||
return R.ok(deviceTemp);
|
return R.ok(deviceTemp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -64,7 +64,7 @@ public class DeviceTempController extends BaseController
|
||||||
public AjaxResult getInfo(@PathVariable("id") String id)
|
public AjaxResult getInfo(@PathVariable("id") String id)
|
||||||
{
|
{
|
||||||
DeviceTempDTO dto = deviceTempService.selectDeviceTempById(id);
|
DeviceTempDTO dto = deviceTempService.selectDeviceTempById(id);
|
||||||
DeviceTempVO deviceTemp = DeviceTempVOConvert.from(dto);
|
DeviceTempVO deviceTemp = DeviceTempControllerConvert.toVO(dto);
|
||||||
return success(deviceTemp);
|
return success(deviceTemp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,112 +0,0 @@
|
||||||
package com.ruoyi.device.controller;
|
|
||||||
|
|
||||||
import com.ruoyi.common.core.domain.R;
|
|
||||||
import com.ruoyi.common.core.web.controller.BaseController;
|
|
||||||
import com.ruoyi.common.security.annotation.InnerAuth;
|
|
||||||
import com.ruoyi.device.api.domain.DockDetailVO;
|
|
||||||
import com.ruoyi.device.api.domain.DockUpdateRequest;
|
|
||||||
import com.ruoyi.device.api.domain.DockVO;
|
|
||||||
import com.ruoyi.device.api.domain.DockWithGPSVO;
|
|
||||||
import com.ruoyi.device.controller.convert.DockWithGPSVOConvert;
|
|
||||||
import com.ruoyi.device.service.api.IDockService;
|
|
||||||
import com.ruoyi.device.service.impl.DefaultBufferDeviceImpl;
|
|
||||||
import com.ruoyi.device.service.dto.DockDetailDTO;
|
|
||||||
import com.ruoyi.device.service.dto.DockDTO;
|
|
||||||
import com.ruoyi.device.controller.convert.DockVOConvert;
|
|
||||||
import org.springframework.beans.BeanUtils;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.web.bind.annotation.*;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 机场Controller
|
|
||||||
*
|
|
||||||
* @author ruoyi
|
|
||||||
* @date 2026-01-20
|
|
||||||
*/
|
|
||||||
@RestController
|
|
||||||
@RequestMapping("/dock")
|
|
||||||
public class DockController extends BaseController
|
|
||||||
{
|
|
||||||
@Autowired
|
|
||||||
private IDockService dockService;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private DefaultBufferDeviceImpl bufferDeviceService;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 搜索机场
|
|
||||||
*
|
|
||||||
* @param dockStatus 机场状态
|
|
||||||
* @param dockId 机场ID
|
|
||||||
* @return 机场列表
|
|
||||||
*/
|
|
||||||
//@InnerAuth
|
|
||||||
@GetMapping("/search")
|
|
||||||
public R<List<DockVO>> searchDocks(@RequestParam(required = false) String dockStatus, @RequestParam(required = false) Long dockId)
|
|
||||||
{
|
|
||||||
List<DockDTO> dtoList = dockService.searchDocks(dockStatus, dockId);
|
|
||||||
List<DockVO> voList = DockVOConvert.fromList(dtoList);
|
|
||||||
return R.ok(voList);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 查看机场详情
|
|
||||||
*
|
|
||||||
* @param dockId 机场ID
|
|
||||||
* @return 机场详情
|
|
||||||
*/
|
|
||||||
//@InnerAuth
|
|
||||||
@GetMapping("/detail/{dockId}")
|
|
||||||
public R<DockDetailVO> getDockDetail(@PathVariable("dockId") Long dockId)
|
|
||||||
{
|
|
||||||
DockDetailDTO dockDetailDTO = bufferDeviceService.getDockDetailById(dockId);
|
|
||||||
if (dockDetailDTO == null) {
|
|
||||||
return R.fail("机场不存在: dockId=" + dockId);
|
|
||||||
}
|
|
||||||
|
|
||||||
DockDetailVO result = new DockDetailVO();
|
|
||||||
BeanUtils.copyProperties(dockDetailDTO, result);
|
|
||||||
return R.ok(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 修改机场名称和地址
|
|
||||||
*
|
|
||||||
* @param request 机场更新请求
|
|
||||||
* @return 结果
|
|
||||||
*/
|
|
||||||
//@InnerAuth
|
|
||||||
@PostMapping("/update")
|
|
||||||
public R<Void> updateDock(@RequestBody DockUpdateRequest request)
|
|
||||||
{
|
|
||||||
DockDTO dto = new DockDTO();
|
|
||||||
dto.setDockId(request.getDockId());
|
|
||||||
dto.setDockName(request.getDockName());
|
|
||||||
dto.setDockLocation(request.getDockLocation());
|
|
||||||
dockService.updateDock(dto);
|
|
||||||
return R.ok();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 查看所有机场
|
|
||||||
*
|
|
||||||
* @return 机场列表
|
|
||||||
*/
|
|
||||||
//@InnerAuth
|
|
||||||
@GetMapping("/list")
|
|
||||||
public R<List<DockWithGPSVO>> getAllDocks()
|
|
||||||
{
|
|
||||||
List<DockDTO> dockDTOs = dockService.selectDockList(new DockDTO());
|
|
||||||
List<DockDetailDTO> dtoList = new ArrayList<>();
|
|
||||||
for (DockDTO dockDTO : dockDTOs) {
|
|
||||||
DockDetailDTO dockDetailDTO = bufferDeviceService.getDockDetailById(dockDTO.getDockId());
|
|
||||||
if (dockDetailDTO != null) {
|
|
||||||
dtoList.add(dockDetailDTO);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return R.ok(DockWithGPSVOConvert.fromList(dtoList));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,210 +0,0 @@
|
||||||
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.*;
|
|
||||||
import com.ruoyi.device.controller.convert.DockVOConvert;
|
|
||||||
import com.ruoyi.device.controller.convert.DockWithGPSVOConvert;
|
|
||||||
import com.ruoyi.device.controller.convert.GroupVOConvert;
|
|
||||||
import com.ruoyi.device.domain.api.IDockDomain;
|
|
||||||
import com.ruoyi.device.domain.model.Dock;
|
|
||||||
import com.ruoyi.device.service.impl.DefaultBufferDeviceImpl;
|
|
||||||
import com.ruoyi.device.service.api.IGroupService;
|
|
||||||
import com.ruoyi.device.service.dto.DockDetailDTO;
|
|
||||||
import com.ruoyi.device.service.dto.DockGroupDTO;
|
|
||||||
import com.ruoyi.device.service.dto.GroupDTO;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.util.CollectionUtils;
|
|
||||||
import org.springframework.web.bind.annotation.*;
|
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 分组Controller
|
|
||||||
*
|
|
||||||
* @author ruoyi
|
|
||||||
* @date 2026-01-20
|
|
||||||
*/
|
|
||||||
@RestController
|
|
||||||
@RequestMapping("/group")
|
|
||||||
public class GroupController extends BaseController
|
|
||||||
{
|
|
||||||
@Autowired
|
|
||||||
private IGroupService groupService;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private DefaultBufferDeviceImpl bufferDeviceService;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private IDockDomain dockDomain;
|
|
||||||
/**
|
|
||||||
* 创建分组
|
|
||||||
*
|
|
||||||
* @param request 分组创建请求
|
|
||||||
* @return 分组ID
|
|
||||||
*/
|
|
||||||
//@InnerAuth
|
|
||||||
@PostMapping("/create")
|
|
||||||
public R<Long> createGroup(@RequestBody GroupCreateRequest request)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
GroupDTO dto = new GroupDTO();
|
|
||||||
dto.setGroupName(request.getGroupName());
|
|
||||||
Long groupId = groupService.createGroup(dto);
|
|
||||||
return R.ok(groupId);
|
|
||||||
}
|
|
||||||
catch (RuntimeException e)
|
|
||||||
{
|
|
||||||
return R.fail("新增分组'" + request.getGroupName() + "'失败,分组名称已存在");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* 删除分组
|
|
||||||
*
|
|
||||||
* @param groupId 分组ID
|
|
||||||
* @return 结果
|
|
||||||
*/
|
|
||||||
//@InnerAuth
|
|
||||||
@DeleteMapping("/delete/{groupId}")
|
|
||||||
public R<Void> deleteGroup(@PathVariable("groupId") Long groupId)
|
|
||||||
{
|
|
||||||
groupService.deleteGroup(groupId);
|
|
||||||
return R.ok();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 修改分组名称
|
|
||||||
*
|
|
||||||
* @param request 分组更新请求
|
|
||||||
* @return 结果
|
|
||||||
*/
|
|
||||||
//@InnerAuth
|
|
||||||
@PostMapping("/update")
|
|
||||||
public R<Void> updateGroup(@RequestBody GroupUpdateRequest request)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
GroupDTO dto = new GroupDTO();
|
|
||||||
dto.setGroupId(request.getGroupId());
|
|
||||||
dto.setGroupName(request.getGroupName());
|
|
||||||
groupService.updateGroup(dto);
|
|
||||||
return R.ok();
|
|
||||||
}
|
|
||||||
catch (RuntimeException e)
|
|
||||||
{
|
|
||||||
return R.fail("修改分组'" + request.getGroupName() + "'失败,分组名称已存在");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 切换机场所在的分组
|
|
||||||
*
|
|
||||||
* @param request 切换分组请求
|
|
||||||
* @return 结果
|
|
||||||
*/
|
|
||||||
@PostMapping("/switch")
|
|
||||||
public R<Void> switchDockGroup(@RequestBody SwitchDockGroupRequest request)
|
|
||||||
{
|
|
||||||
|
|
||||||
if(!CollectionUtils.isEmpty(request.getDockIds())){
|
|
||||||
for (Long dockId : request.getDockIds()) {
|
|
||||||
groupService.switchDockGroup(dockId, request.getGroupId());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return R.ok();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 查看分组下的机场
|
|
||||||
*
|
|
||||||
* @param groupId 分组ID
|
|
||||||
* @return 机场列表
|
|
||||||
*/
|
|
||||||
//@InnerAuth
|
|
||||||
@GetMapping("/docks/{groupId}")
|
|
||||||
public R<List<DockWithGPSVO>> getDocksByGroupId(@PathVariable("groupId") Long groupId)
|
|
||||||
{
|
|
||||||
logger.info("getDocksByGroupId {}", groupId);
|
|
||||||
|
|
||||||
if(Objects.equals(groupId, -1L)){
|
|
||||||
// List<DockGroupDTO> groupDTOS = groupService.getDocksByGroupId(groupId);
|
|
||||||
List<DockDetailDTO> dtoList = new ArrayList<>();
|
|
||||||
Dock queryDock = new Dock();
|
|
||||||
List<Dock> allDocks = dockDomain.selectDockList(queryDock);
|
|
||||||
|
|
||||||
if (allDocks != null) {
|
|
||||||
for (Dock dock : allDocks) {
|
|
||||||
if (dock.getLastActiveTime() != null) {
|
|
||||||
DockDetailDTO dockDetailDTO = bufferDeviceService.getDockDetailById(dock.getDockId());
|
|
||||||
if (dockDetailDTO != null) {
|
|
||||||
dockDetailDTO.setLastActiveTime(dock.getLastActiveTime());
|
|
||||||
dockDetailDTO.setCabinVideoUrl(dock.getCabinVideoUrl());
|
|
||||||
dockDetailDTO.setOutsideVideoUrl(dock.getOutsideVideoUrl());
|
|
||||||
dockDetailDTO.setLiveVideoUrl(dock.getLiveVideoUrl());
|
|
||||||
dtoList.add(dockDetailDTO);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
dtoList.sort(Comparator.comparing(DockDetailDTO::getLastActiveTime).reversed());
|
|
||||||
|
|
||||||
return R.ok(DockWithGPSVOConvert.fromList(dtoList));
|
|
||||||
}else {
|
|
||||||
List<DockGroupDTO> groupDTOS = groupService.getDocksByGroupId(groupId);
|
|
||||||
List<DockDetailDTO> dtoList = new ArrayList<>();
|
|
||||||
for (DockGroupDTO dockGroupDTO : groupDTOS) {
|
|
||||||
DockDetailDTO dockDetailDTO = bufferDeviceService.getDockDetailById(dockGroupDTO.getDockId());
|
|
||||||
if (dockDetailDTO != null) {
|
|
||||||
dtoList.add(dockDetailDTO);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return R.ok(DockWithGPSVOConvert.fromList(dtoList));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 查看所有分组
|
|
||||||
*
|
|
||||||
* @return 分组ID列表
|
|
||||||
*/
|
|
||||||
//@InnerAuth
|
|
||||||
@GetMapping("/list")
|
|
||||||
public R<List<GroupVO>> getAllGroupIds()
|
|
||||||
{
|
|
||||||
List<GroupDTO> groupDTOs = groupService.getAllGroupIds();
|
|
||||||
List<GroupVO> groupVOS = new ArrayList<>();
|
|
||||||
|
|
||||||
// 添加虚拟的"最近使用"分组(groupId = -1)
|
|
||||||
// 统计 last_active_time 不为空的机场数量
|
|
||||||
Dock queryDock = new Dock();
|
|
||||||
List<Dock> allDocks = dockDomain.selectDockList(queryDock);
|
|
||||||
int recentlyUsedCount = 0;
|
|
||||||
if (allDocks != null) {
|
|
||||||
for (Dock dock : allDocks) {
|
|
||||||
if (dock.getLastActiveTime() != null) {
|
|
||||||
recentlyUsedCount++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 创建"最近使用"虚拟分组
|
|
||||||
GroupVO recentlyUsedGroup = new GroupVO();
|
|
||||||
recentlyUsedGroup.setGroupId(-1L);
|
|
||||||
recentlyUsedGroup.setGroupName("最近使用");
|
|
||||||
recentlyUsedGroup.setDockCount(recentlyUsedCount);
|
|
||||||
groupVOS.add(recentlyUsedGroup);
|
|
||||||
|
|
||||||
// 添加其他真实分组
|
|
||||||
for(GroupDTO groupDTO : groupDTOs){
|
|
||||||
GroupVO groupVO = GroupVOConvert.from(groupDTO);
|
|
||||||
List<DockGroupDTO> dockGroupDTOs = groupService.getDocksByGroupId(groupDTO.getGroupId());
|
|
||||||
groupVO.setDockCount(dockGroupDTOs.size());
|
|
||||||
groupVOS.add(groupVO);
|
|
||||||
}
|
|
||||||
|
|
||||||
return R.ok(groupVOS);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,442 +0,0 @@
|
||||||
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<StatisticsVO> 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<StatisticsVO> getDjiStatistics()
|
|
||||||
{
|
|
||||||
return R.ok(buildDjiStatisticsVO());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@GetMapping("/th")
|
|
||||||
public R<StatisticsVO> getThStatistics()
|
|
||||||
{
|
|
||||||
return R.ok(buildThStatisticsVO());
|
|
||||||
}
|
|
||||||
|
|
||||||
private StatisticsVO buildDjiStatisticsVO (){
|
|
||||||
log.info("========== 开始统计DJI设备信息 ==========");
|
|
||||||
StatisticsVO vo = new StatisticsVO();
|
|
||||||
|
|
||||||
// 获取所有机场
|
|
||||||
List<DockDTO> allDocks = dockService.selectDockList(new DockDTO());
|
|
||||||
|
|
||||||
// 过滤出大疆机场
|
|
||||||
List<DockDTO> docks = filterDocksByManufacturer(allDocks, "dajiang");
|
|
||||||
vo.setDockCount(docks.size());
|
|
||||||
log.info("大疆机场总数: {}", vo.getDockCount());
|
|
||||||
|
|
||||||
// 批量获取机场详情 - 优化:从N次查询减少到1次批量查询
|
|
||||||
Map<Long, DockDetailDTO> dockDetailsMap = null;
|
|
||||||
if (!docks.isEmpty()) {
|
|
||||||
List<Long> 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<AircraftDTO> allAircrafts = aircraftService.selectAircraftList(new AircraftDTO());
|
|
||||||
|
|
||||||
// 过滤出大疆无人机
|
|
||||||
List<AircraftDTO> aircrafts = filterAircraftsByManufacturer(allAircrafts, "dajiang");
|
|
||||||
vo.setAircraftCount(aircrafts.size());
|
|
||||||
log.info("大疆无人机总数: {}", vo.getAircraftCount());
|
|
||||||
|
|
||||||
// 批量获取无人机详情 - 优化:从N次查询减少到1次批量查询
|
|
||||||
Map<Long, AircraftDetailDTO> aircraftDetailsMap = null;
|
|
||||||
if (!aircrafts.isEmpty()) {
|
|
||||||
List<Long> 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.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);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
log.warn("大疆无人机[ID:{}, Name:{}] 无法获取详情或状态为空",
|
|
||||||
aircraft.getAircraftId(), aircraft.getAircraftName());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
vo.setPowerOnInCabinCount(powerOnInCabinCount);
|
|
||||||
vo.setPowerOffInCabinCount(powerOffInCabinCount);
|
|
||||||
vo.setInMissionCount(inMissionCount);
|
|
||||||
vo.setDebuggingAircraftCount(debuggingAircraftCount);
|
|
||||||
vo.setOfflineAircraftCount(offlineAircraftCount);
|
|
||||||
|
|
||||||
log.info("无人机状态统计结果 -> 舱内开机:{}, 舱内关机:{}, 任务中:{}, 调试:{}, 离线:{}",
|
|
||||||
powerOnInCabinCount, powerOffInCabinCount, inMissionCount, debuggingAircraftCount, offlineAircraftCount);
|
|
||||||
|
|
||||||
// 获取所有挂载
|
|
||||||
List<PayloadDTO> 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<DockDTO> allDocks = dockService.selectDockList(new DockDTO());
|
|
||||||
|
|
||||||
// 过滤出拓恒机场
|
|
||||||
List<DockDTO> thDocks = filterDocksByManufacturer(allDocks, "tuoheng");
|
|
||||||
vo.setDockCount(thDocks.size());
|
|
||||||
log.info("拓恒机场总数: {}", vo.getDockCount());
|
|
||||||
|
|
||||||
// 批量获取拓恒机场详情
|
|
||||||
Map<Long, DockDetailDTO> dockDetailsMap = null;
|
|
||||||
if (!thDocks.isEmpty()) {
|
|
||||||
List<Long> 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<AircraftDTO> allAircrafts = aircraftService.selectAircraftList(new AircraftDTO());
|
|
||||||
|
|
||||||
// 过滤出拓恒无人机
|
|
||||||
List<AircraftDTO> thAircrafts = filterAircraftsByManufacturer(allAircrafts, "tuoheng");
|
|
||||||
vo.setAircraftCount(thAircrafts.size());
|
|
||||||
log.info("拓恒无人机总数: {}", vo.getAircraftCount());
|
|
||||||
|
|
||||||
// 批量获取拓恒无人机详情
|
|
||||||
Map<Long, AircraftDetailDTO> aircraftDetailsMap = null;
|
|
||||||
if (!thAircrafts.isEmpty()) {
|
|
||||||
List<Long> 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);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
log.warn("拓恒无人机[ID:{}, Name:{}] 无法获取详情或状态为空",
|
|
||||||
aircraft.getAircraftId(), aircraft.getAircraftName());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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<DockDTO> filterDocksByManufacturer(List<DockDTO> 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<AircraftDTO> filterAircraftsByManufacturer(List<AircraftDTO> 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());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,86 +0,0 @@
|
||||||
package com.ruoyi.device.controller;
|
|
||||||
|
|
||||||
import com.ruoyi.common.core.domain.R;
|
|
||||||
import com.ruoyi.common.core.web.controller.BaseController;
|
|
||||||
import com.ruoyi.device.domain.api.IThingsBoardDomain;
|
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
|
||||||
import io.swagger.v3.oas.annotations.Parameter;
|
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
|
||||||
import lombok.Data;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.web.bind.annotation.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ThingsBoard设备属性管理Controller
|
|
||||||
*
|
|
||||||
* @author ruoyi
|
|
||||||
* @date 2026-02-06
|
|
||||||
*/
|
|
||||||
@RestController
|
|
||||||
@RequestMapping("/thingsboard")
|
|
||||||
@Tag(name = "ThingsBoard设备属性管理", description = "提供设备属性的读写操作")
|
|
||||||
public class ThingsBoardController extends BaseController {
|
|
||||||
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(ThingsBoardController.class);
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private IThingsBoardDomain thingsBoardDomain;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设置设备属性
|
|
||||||
*
|
|
||||||
* @param request 设置属性请求
|
|
||||||
* @return 操作结果
|
|
||||||
*/
|
|
||||||
@PostMapping("/attribute")
|
|
||||||
@Operation(summary = "设置设备属性", description = "设置ThingsBoard设备的属性值")
|
|
||||||
public R<Void> setDeviceAttribute(@RequestBody SetAttributeRequest request) {
|
|
||||||
log.info("收到设置设备属性请求: deviceIotId={}, key={}, value={}",
|
|
||||||
request.getDeviceIotId(), request.getKey(), request.getValue());
|
|
||||||
|
|
||||||
// 参数校验
|
|
||||||
if (request.getDeviceIotId() == null || request.getDeviceIotId().trim().isEmpty()) {
|
|
||||||
return R.fail("设备IOT ID不能为空");
|
|
||||||
}
|
|
||||||
if (request.getKey() == null || request.getKey().trim().isEmpty()) {
|
|
||||||
return R.fail("属性键不能为空");
|
|
||||||
}
|
|
||||||
if (request.getValue() == null) {
|
|
||||||
return R.fail("属性值不能为空");
|
|
||||||
}
|
|
||||||
|
|
||||||
// 调用Domain层设置属性
|
|
||||||
boolean success = thingsBoardDomain.setDeviceAttribute(
|
|
||||||
request.getDeviceIotId(),
|
|
||||||
request.getKey(),
|
|
||||||
request.getValue()
|
|
||||||
);
|
|
||||||
|
|
||||||
if (success) {
|
|
||||||
log.info("设备属性设置成功: deviceIotId={}, key={}",
|
|
||||||
request.getDeviceIotId(), request.getKey());
|
|
||||||
return R.ok();
|
|
||||||
} else {
|
|
||||||
log.error("设备属性设置失败: deviceIotId={}, key={}",
|
|
||||||
request.getDeviceIotId(), request.getKey());
|
|
||||||
return R.fail("设备属性设置失败");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设置属性请求对象
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
public static class SetAttributeRequest {
|
|
||||||
@Parameter(description = "设备IOT ID(ThingsBoard设备ID)", required = true)
|
|
||||||
private String deviceIotId;
|
|
||||||
|
|
||||||
@Parameter(description = "属性键", required = true)
|
|
||||||
private String key;
|
|
||||||
|
|
||||||
@Parameter(description = "属性值", required = true)
|
|
||||||
private Object value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,39 +0,0 @@
|
||||||
package com.ruoyi.device.controller.convert;
|
|
||||||
|
|
||||||
import com.ruoyi.common.core.utils.BaseConvert;
|
|
||||||
import com.ruoyi.device.api.domain.AircraftDetailVO;
|
|
||||||
import com.ruoyi.device.service.dto.AircraftDetailDTO;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
public class AircraftDetailVOConvert extends BaseConvert<AircraftDetailDTO, AircraftDetailVO>
|
|
||||||
{
|
|
||||||
|
|
||||||
private static final AircraftDetailVOConvert INSTANCE = new AircraftDetailVOConvert();
|
|
||||||
|
|
||||||
private AircraftDetailVOConvert() {
|
|
||||||
super(AircraftDetailDTO.class, AircraftDetailVO.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static AircraftDetailVO from(AircraftDetailDTO dto)
|
|
||||||
{
|
|
||||||
return INSTANCE.innerFrom(dto);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static AircraftDetailDTO to(AircraftDetailVO vo)
|
|
||||||
{
|
|
||||||
return INSTANCE.innerTo(vo);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<AircraftDetailVO> fromList(List<AircraftDetailDTO> dtoList)
|
|
||||||
{
|
|
||||||
return INSTANCE.innerFromList(dtoList);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<AircraftDetailDTO> toList(List<AircraftDetailVO> voList)
|
|
||||||
{
|
|
||||||
return INSTANCE.innerToList(voList);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,73 +0,0 @@
|
||||||
package com.ruoyi.device.controller.convert;
|
|
||||||
|
|
||||||
import com.ruoyi.common.core.utils.BaseConvert;
|
|
||||||
import com.ruoyi.device.api.domain.AirLoadTypeVO;
|
|
||||||
import com.ruoyi.device.api.domain.AirTypeGeneralEnumVO;
|
|
||||||
import com.ruoyi.device.service.dto.DeviceAirLoadTypeDTO;
|
|
||||||
import com.ruoyi.device.service.dto.DeviceAirTypeGeneralEnumDTO;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 无人机类型通用枚举Controller转换器
|
|
||||||
*
|
|
||||||
* @author 拓恒
|
|
||||||
* @date 2026-01-20
|
|
||||||
*/
|
|
||||||
public class DeviceAirTypeGeneralEnumVOConvert extends BaseConvert<DeviceAirTypeGeneralEnumDTO, AirTypeGeneralEnumVO>
|
|
||||||
{
|
|
||||||
|
|
||||||
private static final DeviceAirTypeGeneralEnumVOConvert INSTANCE = new DeviceAirTypeGeneralEnumVOConvert();
|
|
||||||
|
|
||||||
private DeviceAirTypeGeneralEnumVOConvert() {
|
|
||||||
super(DeviceAirTypeGeneralEnumDTO.class, AirTypeGeneralEnumVO.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static AirTypeGeneralEnumVO from(DeviceAirTypeGeneralEnumDTO dto)
|
|
||||||
{
|
|
||||||
AirTypeGeneralEnumVO vo = INSTANCE.innerFrom(dto);
|
|
||||||
// 手动转换负载列表(按系列分组)
|
|
||||||
if (dto.getLoadList() != null) {
|
|
||||||
Map<String, List<AirLoadTypeVO>> loadVOMap = new HashMap<>();
|
|
||||||
for (Map.Entry<String, List<DeviceAirLoadTypeDTO>> entry : dto.getLoadList().entrySet()) {
|
|
||||||
String series = entry.getKey();
|
|
||||||
List<DeviceAirLoadTypeDTO> loadDTOList = entry.getValue();
|
|
||||||
List<AirLoadTypeVO> loadVOList = new ArrayList<>();
|
|
||||||
for (DeviceAirLoadTypeDTO loadDTO : loadDTOList) {
|
|
||||||
AirLoadTypeVO loadVO = new AirLoadTypeVO();
|
|
||||||
loadVO.setLoadName(loadDTO.getLoadName());
|
|
||||||
loadVO.setLoadSeries(loadDTO.getLoadSeries());
|
|
||||||
loadVO.setLoadCategory(loadDTO.getLoadCategory());
|
|
||||||
loadVO.setSlot(loadDTO.getSlot());
|
|
||||||
loadVOList.add(loadVO);
|
|
||||||
}
|
|
||||||
loadVOMap.put(series, loadVOList);
|
|
||||||
}
|
|
||||||
vo.setLoadList(loadVOMap);
|
|
||||||
}
|
|
||||||
return vo;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static DeviceAirTypeGeneralEnumDTO to(AirTypeGeneralEnumVO vo)
|
|
||||||
{
|
|
||||||
return INSTANCE.innerTo(vo);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<AirTypeGeneralEnumVO> fromList(List<DeviceAirTypeGeneralEnumDTO> dtoList)
|
|
||||||
{
|
|
||||||
List<AirTypeGeneralEnumVO> voList = new ArrayList<>();
|
|
||||||
for (DeviceAirTypeGeneralEnumDTO dto : dtoList) {
|
|
||||||
voList.add(from(dto));
|
|
||||||
}
|
|
||||||
return voList;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<DeviceAirTypeGeneralEnumDTO> toList(List<AirTypeGeneralEnumVO> voList)
|
|
||||||
{
|
|
||||||
return INSTANCE.innerToList(voList);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,58 @@
|
||||||
|
package com.ruoyi.device.controller.convert;
|
||||||
|
|
||||||
|
import com.ruoyi.device.api.domain.DeviceTempVO;
|
||||||
|
import com.ruoyi.device.service.dto.DeviceTempDTO;
|
||||||
|
import org.springframework.beans.BeanUtils;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设备临时表Controller层转换器
|
||||||
|
* API Domain ↔ Service DTO
|
||||||
|
*
|
||||||
|
* @author ruoyi
|
||||||
|
* @date 2026-01-15
|
||||||
|
*/
|
||||||
|
public class DeviceTempControllerConvert
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* DTO 转 API Domain
|
||||||
|
*/
|
||||||
|
public static DeviceTempVO toVO(DeviceTempDTO dto)
|
||||||
|
{
|
||||||
|
if (dto == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
DeviceTempVO apiDomain = new DeviceTempVO();
|
||||||
|
BeanUtils.copyProperties(dto, apiDomain);
|
||||||
|
return apiDomain;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* API Domain 转 DTO
|
||||||
|
*/
|
||||||
|
public static DeviceTempDTO toDTO(DeviceTempVO apiDomain)
|
||||||
|
{
|
||||||
|
if (apiDomain == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
DeviceTempDTO dto = new DeviceTempDTO();
|
||||||
|
BeanUtils.copyProperties(apiDomain, dto);
|
||||||
|
return dto;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DTO List 转 API Domain List
|
||||||
|
*/
|
||||||
|
public static List<DeviceTempVO> toApiDomainList(List<DeviceTempDTO> dtoList)
|
||||||
|
{
|
||||||
|
if (dtoList == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return dtoList.stream().map(DeviceTempControllerConvert::toVO).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,56 +0,0 @@
|
||||||
package com.ruoyi.device.controller.convert;
|
|
||||||
|
|
||||||
import com.ruoyi.common.core.utils.BaseConvert;
|
|
||||||
import com.ruoyi.device.api.domain.DeviceTempVO;
|
|
||||||
import com.ruoyi.device.service.dto.DeviceTempDTO;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设备临时表Controller层转换器
|
|
||||||
* API Domain ↔ Service DTO
|
|
||||||
*
|
|
||||||
* @author ruoyi
|
|
||||||
* @date 2026-01-15
|
|
||||||
*/
|
|
||||||
public class DeviceTempVOConvert extends BaseConvert<DeviceTempDTO, DeviceTempVO>
|
|
||||||
{
|
|
||||||
|
|
||||||
private static final DeviceTempVOConvert INSTANCE = new DeviceTempVOConvert();
|
|
||||||
|
|
||||||
private DeviceTempVOConvert() {
|
|
||||||
super(DeviceTempDTO.class, DeviceTempVO.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* DTO 转 API Domain
|
|
||||||
*/
|
|
||||||
public static DeviceTempVO from(DeviceTempDTO dto)
|
|
||||||
{
|
|
||||||
return INSTANCE.innerFrom(dto);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* API Domain 转 DTO
|
|
||||||
*/
|
|
||||||
public static DeviceTempDTO to(DeviceTempVO apiDomain)
|
|
||||||
{
|
|
||||||
return INSTANCE.innerTo(apiDomain);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* DTO List 转 API Domain List
|
|
||||||
*/
|
|
||||||
public static List<DeviceTempVO> fromList(List<DeviceTempDTO> dtoList)
|
|
||||||
{
|
|
||||||
return INSTANCE.innerFromList(dtoList);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* API Domain List 转 DTO List
|
|
||||||
*/
|
|
||||||
public static List<DeviceTempDTO> toList(List<DeviceTempVO> apiDomainList)
|
|
||||||
{
|
|
||||||
return INSTANCE.innerToList(apiDomainList);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,80 +0,0 @@
|
||||||
package com.ruoyi.device.controller.convert;
|
|
||||||
|
|
||||||
import com.ruoyi.common.core.utils.BaseConvert;
|
|
||||||
import com.ruoyi.device.api.domain.DockVO;
|
|
||||||
import com.ruoyi.device.service.dto.DockDTO;
|
|
||||||
import com.ruoyi.device.service.dto.DockDetailDTO;
|
|
||||||
import org.springframework.beans.BeanUtils;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 机场Controller转换器
|
|
||||||
*
|
|
||||||
* @author ruoyi
|
|
||||||
* @date 2026-01-20
|
|
||||||
*/
|
|
||||||
public class DockVOConvert extends BaseConvert<DockDTO, DockVO>
|
|
||||||
{
|
|
||||||
|
|
||||||
private static final DockVOConvert INSTANCE = new DockVOConvert();
|
|
||||||
|
|
||||||
private DockVOConvert() {
|
|
||||||
super(DockDTO.class, DockVO.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* DTO 转 VO
|
|
||||||
*/
|
|
||||||
public static DockVO from(DockDTO dto)
|
|
||||||
{
|
|
||||||
return INSTANCE.innerFrom(dto);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* VO 转 DTO
|
|
||||||
*/
|
|
||||||
public static DockDTO to(DockVO vo)
|
|
||||||
{
|
|
||||||
return INSTANCE.innerTo(vo);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* DTO List 转 VO List
|
|
||||||
*/
|
|
||||||
public static List<DockVO> fromList(List<DockDTO> dtoList)
|
|
||||||
{
|
|
||||||
return INSTANCE.innerFromList(dtoList);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* DTO List 转 VO List
|
|
||||||
*/
|
|
||||||
public static List<DockVO> fromDockDetailDTOList(List<DockDetailDTO> sourceList)
|
|
||||||
{
|
|
||||||
if (sourceList == null) return null;
|
|
||||||
return sourceList.stream().map(DockVOConvert::fromDockDetailDTO).collect(Collectors.toList());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static DockVO fromDockDetailDTO(DockDetailDTO source){
|
|
||||||
if (source == null) return null;
|
|
||||||
try {
|
|
||||||
DockVO target = new DockVO();
|
|
||||||
BeanUtils.copyProperties(source, target);
|
|
||||||
return target;
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* VO List 转 DTO List
|
|
||||||
*/
|
|
||||||
public static List<DockDTO> toList(List<DockVO> voList)
|
|
||||||
{
|
|
||||||
return INSTANCE.innerToList(voList);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,52 +0,0 @@
|
||||||
package com.ruoyi.device.controller.convert;
|
|
||||||
|
|
||||||
import com.ruoyi.common.core.utils.BaseConvert;
|
|
||||||
import com.ruoyi.device.api.domain.DockVO;
|
|
||||||
import com.ruoyi.device.api.domain.DockWithGPSVO;
|
|
||||||
import com.ruoyi.device.service.dto.DockDTO;
|
|
||||||
import com.ruoyi.device.service.dto.DockDetailDTO;
|
|
||||||
import org.springframework.beans.BeanUtils;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
public class DockWithGPSVOConvert extends BaseConvert<DockDetailDTO, DockWithGPSVO>
|
|
||||||
{
|
|
||||||
|
|
||||||
private static final DockWithGPSVOConvert INSTANCE = new DockWithGPSVOConvert();
|
|
||||||
|
|
||||||
private DockWithGPSVOConvert() {
|
|
||||||
super(DockDetailDTO.class, DockWithGPSVO.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* DTO 转 VO
|
|
||||||
*/
|
|
||||||
public static DockWithGPSVO from(DockDetailDTO dto)
|
|
||||||
{
|
|
||||||
return INSTANCE.innerFrom(dto);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* VO 转 DTO
|
|
||||||
*/
|
|
||||||
public static DockDetailDTO to(DockWithGPSVO vo)
|
|
||||||
{
|
|
||||||
return INSTANCE.innerTo(vo);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static List<DockWithGPSVO> fromList(List<DockDetailDTO> dtoList)
|
|
||||||
{
|
|
||||||
return INSTANCE.innerFromList(dtoList);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* VO List 转 DTO List
|
|
||||||
*/
|
|
||||||
public static List<DockDetailDTO> toList(List<DockWithGPSVO> voList)
|
|
||||||
{
|
|
||||||
return INSTANCE.innerToList(voList);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,55 +0,0 @@
|
||||||
package com.ruoyi.device.controller.convert;
|
|
||||||
|
|
||||||
import com.ruoyi.common.core.utils.BaseConvert;
|
|
||||||
import com.ruoyi.device.api.domain.GroupVO;
|
|
||||||
import com.ruoyi.device.service.dto.GroupDTO;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 分组Controller转换器
|
|
||||||
*
|
|
||||||
* @author ruoyi
|
|
||||||
* @date 2026-01-20
|
|
||||||
*/
|
|
||||||
public class GroupVOConvert extends BaseConvert<GroupDTO, GroupVO>
|
|
||||||
{
|
|
||||||
|
|
||||||
private static final GroupVOConvert INSTANCE = new GroupVOConvert();
|
|
||||||
|
|
||||||
private GroupVOConvert() {
|
|
||||||
super(GroupDTO.class, GroupVO.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* DTO 转 VO
|
|
||||||
*/
|
|
||||||
public static GroupVO from(GroupDTO dto)
|
|
||||||
{
|
|
||||||
return INSTANCE.innerFrom(dto);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* VO 转 DTO
|
|
||||||
*/
|
|
||||||
public static GroupDTO to(GroupVO vo)
|
|
||||||
{
|
|
||||||
return INSTANCE.innerTo(vo);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* DTO List 转 VO List
|
|
||||||
*/
|
|
||||||
public static List<GroupVO> fromList(List<GroupDTO> dtoList)
|
|
||||||
{
|
|
||||||
return INSTANCE.innerFromList(dtoList);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* VO List 转 DTO List
|
|
||||||
*/
|
|
||||||
public static List<GroupDTO> toList(List<GroupVO> voList)
|
|
||||||
{
|
|
||||||
return INSTANCE.innerToList(voList);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,39 +0,0 @@
|
||||||
package com.ruoyi.device.controller.convert;
|
|
||||||
|
|
||||||
import com.ruoyi.common.core.utils.BaseConvert;
|
|
||||||
import com.ruoyi.device.api.domain.NetworkVO;
|
|
||||||
import com.ruoyi.device.service.dto.NetworkDTO;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
public class NetworkVOConvert extends BaseConvert<NetworkDTO, NetworkVO>
|
|
||||||
{
|
|
||||||
|
|
||||||
private static final NetworkVOConvert INSTANCE = new NetworkVOConvert();
|
|
||||||
|
|
||||||
private NetworkVOConvert() {
|
|
||||||
super(NetworkDTO.class, NetworkVO.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static NetworkVO from(NetworkDTO dto)
|
|
||||||
{
|
|
||||||
return INSTANCE.innerFrom(dto);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static NetworkDTO to(NetworkVO vo)
|
|
||||||
{
|
|
||||||
return INSTANCE.innerTo(vo);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<NetworkVO> fromList(List<NetworkDTO> dtoList)
|
|
||||||
{
|
|
||||||
return INSTANCE.innerFromList(dtoList);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<NetworkDTO> toList(List<NetworkVO> voList)
|
|
||||||
{
|
|
||||||
return INSTANCE.innerToList(voList);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,37 +0,0 @@
|
||||||
package com.ruoyi.device.controller.convert;
|
|
||||||
|
|
||||||
import com.ruoyi.common.core.utils.BaseConvert;
|
|
||||||
import com.ruoyi.device.api.domain.PayloadDetailVO;
|
|
||||||
import com.ruoyi.device.service.dto.PayloadDTO;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class PayloadDetailVOConvert extends BaseConvert<PayloadDTO, PayloadDetailVO>
|
|
||||||
{
|
|
||||||
|
|
||||||
private static final PayloadDetailVOConvert INSTANCE = new PayloadDetailVOConvert();
|
|
||||||
|
|
||||||
private PayloadDetailVOConvert() {
|
|
||||||
super(PayloadDTO.class, PayloadDetailVO.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static PayloadDetailVO from(PayloadDTO dto)
|
|
||||||
{
|
|
||||||
return INSTANCE.innerFrom(dto);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static PayloadDTO to(PayloadDetailVO vo)
|
|
||||||
{
|
|
||||||
return INSTANCE.innerTo(vo);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<PayloadDetailVO> fromList(List<PayloadDTO> dtoList)
|
|
||||||
{
|
|
||||||
return INSTANCE.innerFromList(dtoList);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<PayloadDTO> toList(List<PayloadDetailVO> voList)
|
|
||||||
{
|
|
||||||
return INSTANCE.innerToList(voList);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,38 +0,0 @@
|
||||||
package com.ruoyi.device.domain;
|
|
||||||
|
|
||||||
import com.ruoyi.common.core.web.domain.BaseEntity;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.EqualsAndHashCode;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 无人机负载槽位实体
|
|
||||||
*
|
|
||||||
* @author 拓恒
|
|
||||||
* @date 2026-03-04
|
|
||||||
*/
|
|
||||||
@EqualsAndHashCode(callSuper = true)
|
|
||||||
@Data
|
|
||||||
public class DeviceAirLoadSlot extends BaseEntity {
|
|
||||||
private static final long serialVersionUID = 1L;
|
|
||||||
|
|
||||||
/** 主键 */
|
|
||||||
private Long id;
|
|
||||||
|
|
||||||
/** 无人机厂商ID */
|
|
||||||
private Long vendorId;
|
|
||||||
|
|
||||||
/** 无人机主类型 */
|
|
||||||
private Long type;
|
|
||||||
|
|
||||||
/** 无人机子类型 */
|
|
||||||
private Long subType;
|
|
||||||
|
|
||||||
/** 槽位数 */
|
|
||||||
private Integer slotCount;
|
|
||||||
|
|
||||||
/** 负载数量限制 */
|
|
||||||
private Integer loadLimit;
|
|
||||||
|
|
||||||
/** 配件限制数量 */
|
|
||||||
private Integer accessoryLimit;
|
|
||||||
}
|
|
||||||
|
|
@ -1,41 +0,0 @@
|
||||||
package com.ruoyi.device.domain;
|
|
||||||
|
|
||||||
import com.ruoyi.common.core.web.domain.BaseEntity;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.EqualsAndHashCode;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 无人机负载类型实体
|
|
||||||
*
|
|
||||||
* @author 拓恒
|
|
||||||
* @date 2026-03-04
|
|
||||||
*/
|
|
||||||
@EqualsAndHashCode(callSuper = true)
|
|
||||||
@Data
|
|
||||||
public class DeviceAirLoadType extends BaseEntity {
|
|
||||||
private static final long serialVersionUID = 1L;
|
|
||||||
|
|
||||||
/** 主键 */
|
|
||||||
private Long id;
|
|
||||||
|
|
||||||
/** 无人机厂商ID */
|
|
||||||
private Long vendorId;
|
|
||||||
|
|
||||||
/** 无人机主类型 */
|
|
||||||
private Long type;
|
|
||||||
|
|
||||||
/** 无人机子类型 */
|
|
||||||
private Long subType;
|
|
||||||
|
|
||||||
/** 负载名称 */
|
|
||||||
private String loadName;
|
|
||||||
|
|
||||||
/** 负载系列 */
|
|
||||||
private String loadSeries;
|
|
||||||
|
|
||||||
/** 负载分类:0-负载,1-配件 */
|
|
||||||
private Integer loadCategory;
|
|
||||||
|
|
||||||
/** 槽:1、2 或者-1(-1代表全部槽位可用) */
|
|
||||||
private Integer slot;
|
|
||||||
}
|
|
||||||
|
|
@ -1,69 +0,0 @@
|
||||||
package com.ruoyi.device.domain.api;
|
|
||||||
|
|
||||||
import com.ruoyi.device.domain.model.Aircraft;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 无人机Domain接口
|
|
||||||
*
|
|
||||||
* @author ruoyi
|
|
||||||
* @date 2026-01-16
|
|
||||||
*/
|
|
||||||
public interface IAircraftDomain
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* 查询无人机列表
|
|
||||||
*
|
|
||||||
* @param aircraft 无人机
|
|
||||||
* @return 无人机集合
|
|
||||||
*/
|
|
||||||
List<Aircraft> selectAircraftList(Aircraft aircraft);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 根据无人机主键查询无人机
|
|
||||||
*
|
|
||||||
* @param aircraftId 无人机主键
|
|
||||||
* @return 无人机
|
|
||||||
*/
|
|
||||||
Aircraft selectAircraftByAircraftId(Long aircraftId);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 根据设备主键查询无人机
|
|
||||||
*
|
|
||||||
* @param deviceId 设备主键
|
|
||||||
* @return 无人机
|
|
||||||
*/
|
|
||||||
Aircraft selectAircraftByDeviceId(Long deviceId);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 新增无人机
|
|
||||||
*
|
|
||||||
* @param aircraft 无人机
|
|
||||||
* @return 结果
|
|
||||||
*/
|
|
||||||
int insertAircraft(Aircraft aircraft);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 修改无人机
|
|
||||||
*
|
|
||||||
* @param aircraft 无人机
|
|
||||||
* @return 结果
|
|
||||||
*/
|
|
||||||
int updateAircraft(Aircraft aircraft);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 删除无人机
|
|
||||||
*
|
|
||||||
* @param aircraftId 无人机主键
|
|
||||||
* @return 结果
|
|
||||||
*/
|
|
||||||
int deleteAircraftByAircraftId(Long aircraftId);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 批量删除无人机
|
|
||||||
*
|
|
||||||
* @param aircraftIds 无人机主键数组
|
|
||||||
* @return 结果
|
|
||||||
*/
|
|
||||||
int deleteAircraftByAircraftIds(Long[] aircraftIds);
|
|
||||||
}
|
|
||||||
|
|
@ -1,85 +0,0 @@
|
||||||
package com.ruoyi.device.domain.api;
|
|
||||||
|
|
||||||
import com.ruoyi.device.domain.model.AircraftPayload;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 无人机挂载关联Domain接口
|
|
||||||
*
|
|
||||||
* @author ruoyi
|
|
||||||
* @date 2026-01-16
|
|
||||||
*/
|
|
||||||
public interface IAircraftPayloadDomain
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* 查询无人机挂载关联列表
|
|
||||||
*
|
|
||||||
* @param aircraftPayload 无人机挂载关联
|
|
||||||
* @return 无人机挂载关联集合
|
|
||||||
*/
|
|
||||||
List<AircraftPayload> selectAircraftPayloadList(AircraftPayload aircraftPayload);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 根据关联主键查询无人机挂载关联
|
|
||||||
*
|
|
||||||
* @param id 关联主键
|
|
||||||
* @return 无人机挂载关联
|
|
||||||
*/
|
|
||||||
AircraftPayload selectAircraftPayloadById(Long id);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 根据无人机主键查询关联列表
|
|
||||||
*
|
|
||||||
* @param aircraftId 无人机主键
|
|
||||||
* @return 无人机挂载关联集合
|
|
||||||
*/
|
|
||||||
List<AircraftPayload> selectAircraftPayloadByAircraftId(Long aircraftId);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 根据挂载主键查询关联列表
|
|
||||||
*
|
|
||||||
* @param payloadId 挂载主键
|
|
||||||
* @return 无人机挂载关联集合
|
|
||||||
*/
|
|
||||||
List<AircraftPayload> selectAircraftPayloadByPayloadId(Long payloadId);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 根据机场主键查询关联列表
|
|
||||||
*
|
|
||||||
* @param dockId 机场主键
|
|
||||||
* @return 无人机挂载关联集合
|
|
||||||
*/
|
|
||||||
List<AircraftPayload> selectAircraftPayloadByDockId(Long dockId);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 新增无人机挂载关联
|
|
||||||
*
|
|
||||||
* @param aircraftPayload 无人机挂载关联
|
|
||||||
* @return 结果
|
|
||||||
*/
|
|
||||||
int insertAircraftPayload(AircraftPayload aircraftPayload);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 修改无人机挂载关联
|
|
||||||
*
|
|
||||||
* @param aircraftPayload 无人机挂载关联
|
|
||||||
* @return 结果
|
|
||||||
*/
|
|
||||||
int updateAircraftPayload(AircraftPayload aircraftPayload);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 删除无人机挂载关联
|
|
||||||
*
|
|
||||||
* @param id 关联主键
|
|
||||||
* @return 结果
|
|
||||||
*/
|
|
||||||
int deleteAircraftPayloadById(Long id);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 批量删除无人机挂载关联
|
|
||||||
*
|
|
||||||
* @param ids 关联主键数组
|
|
||||||
* @return 结果
|
|
||||||
*/
|
|
||||||
int deleteAircraftPayloadByIds(Long[] ids);
|
|
||||||
}
|
|
||||||
|
|
@ -1,21 +0,0 @@
|
||||||
package com.ruoyi.device.domain.api;
|
|
||||||
|
|
||||||
import com.ruoyi.device.domain.DeviceAirLoadSlot;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 无人机负载槽位领域接口
|
|
||||||
*
|
|
||||||
* @author 拓恒
|
|
||||||
* @date 2026-03-04
|
|
||||||
*/
|
|
||||||
public interface IDeviceAirLoadSlotDomain {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 根据厂商ID、主类型、子类型查询负载槽位
|
|
||||||
*
|
|
||||||
* @return 负载槽位信息
|
|
||||||
*/
|
|
||||||
DeviceAirLoadSlot selectDeviceAirLoadSlotByVendorAndType(DeviceAirLoadSlot deviceAirLoadSlot);
|
|
||||||
}
|
|
||||||
|
|
@ -1,23 +0,0 @@
|
||||||
package com.ruoyi.device.domain.api;
|
|
||||||
|
|
||||||
import com.ruoyi.device.domain.DeviceAirLoadType;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 无人机负载类型领域接口
|
|
||||||
*
|
|
||||||
* @author 拓恒
|
|
||||||
* @date 2026-03-04
|
|
||||||
*/
|
|
||||||
public interface IDeviceAirLoadTypeDomain {
|
|
||||||
/**
|
|
||||||
* 查询无人机负载类型列表
|
|
||||||
*
|
|
||||||
* @param deviceAirLoadType 无人机负载类型
|
|
||||||
* @return 无人机负载类型集合
|
|
||||||
*/
|
|
||||||
List<DeviceAirLoadType> selectDeviceAirLoadTypeList(DeviceAirLoadType deviceAirLoadType);
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,61 +0,0 @@
|
||||||
package com.ruoyi.device.domain.api;
|
|
||||||
|
|
||||||
import com.ruoyi.device.domain.model.DeviceAirTypeGeneralEnum;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 无人机类型通用枚举Domain接口
|
|
||||||
*
|
|
||||||
* @author ruoyi
|
|
||||||
* @date 2026-01-28
|
|
||||||
*/
|
|
||||||
public interface IDeviceAirTypeGeneralEnumDomain
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* 查询无人机类型通用枚举列表
|
|
||||||
*
|
|
||||||
* @param airTypeGeneralEnum 无人机类型通用枚举
|
|
||||||
* @return 无人机类型通用枚举集合
|
|
||||||
*/
|
|
||||||
List<DeviceAirTypeGeneralEnum> selectAirTypeGeneralEnumList(DeviceAirTypeGeneralEnum airTypeGeneralEnum);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 根据主键查询无人机类型通用枚举
|
|
||||||
*
|
|
||||||
* @param id 主键
|
|
||||||
* @return 无人机类型通用枚举
|
|
||||||
*/
|
|
||||||
DeviceAirTypeGeneralEnum selectAirTypeGeneralEnumById(Long id);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 新增无人机类型通用枚举
|
|
||||||
*
|
|
||||||
* @param airTypeGeneralEnum 无人机类型通用枚举
|
|
||||||
* @return 结果
|
|
||||||
*/
|
|
||||||
int insertAirTypeGeneralEnum(DeviceAirTypeGeneralEnum airTypeGeneralEnum);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 修改无人机类型通用枚举
|
|
||||||
*
|
|
||||||
* @param airTypeGeneralEnum 无人机类型通用枚举
|
|
||||||
* @return 结果
|
|
||||||
*/
|
|
||||||
int updateAirTypeGeneralEnum(DeviceAirTypeGeneralEnum airTypeGeneralEnum);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 删除无人机类型通用枚举
|
|
||||||
*
|
|
||||||
* @param id 主键
|
|
||||||
* @return 结果
|
|
||||||
*/
|
|
||||||
int deleteAirTypeGeneralEnumById(Long id);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 批量删除无人机类型通用枚举
|
|
||||||
*
|
|
||||||
* @param ids 需要删除的主键集合
|
|
||||||
* @return 影响行数
|
|
||||||
*/
|
|
||||||
int deleteAirTypeGeneralEnumByIds(Long[] ids);
|
|
||||||
}
|
|
||||||
|
|
@ -1,77 +0,0 @@
|
||||||
package com.ruoyi.device.domain.api;
|
|
||||||
|
|
||||||
import com.ruoyi.device.domain.model.Device;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设备Domain接口
|
|
||||||
*
|
|
||||||
* @author ruoyi
|
|
||||||
* @date 2026-01-16
|
|
||||||
*/
|
|
||||||
public interface IDeviceDomain
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* 查询设备列表
|
|
||||||
*
|
|
||||||
* @param device 设备
|
|
||||||
* @return 设备集合
|
|
||||||
*/
|
|
||||||
List<Device> selectDeviceList(Device device);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 根据设备主键查询设备
|
|
||||||
*
|
|
||||||
* @param deviceId 设备主键
|
|
||||||
* @return 设备
|
|
||||||
*/
|
|
||||||
Device selectDeviceByDeviceId(Long deviceId);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 根据IOT设备ID查询设备
|
|
||||||
*
|
|
||||||
* @param iotDeviceId IOT设备ID
|
|
||||||
* @return 设备
|
|
||||||
*/
|
|
||||||
Device selectDeviceByIotDeviceId(String iotDeviceId);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 根据设备SN号查询设备
|
|
||||||
*
|
|
||||||
* @param deviceSn 设备SN号
|
|
||||||
* @return 设备
|
|
||||||
*/
|
|
||||||
Device selectDeviceByDeviceSn(String deviceSn);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 新增设备
|
|
||||||
*
|
|
||||||
* @param device 设备
|
|
||||||
* @return 结果
|
|
||||||
*/
|
|
||||||
int insertDevice(Device device);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 修改设备
|
|
||||||
*
|
|
||||||
* @param device 设备
|
|
||||||
* @return 结果
|
|
||||||
*/
|
|
||||||
int updateDevice(Device device);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 删除设备
|
|
||||||
*
|
|
||||||
* @param deviceId 设备主键
|
|
||||||
* @return 结果
|
|
||||||
*/
|
|
||||||
int deleteDeviceByDeviceId(Long deviceId);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 批量删除设备
|
|
||||||
*
|
|
||||||
* @param deviceIds 设备主键数组
|
|
||||||
* @return 结果
|
|
||||||
*/
|
|
||||||
int deleteDeviceByDeviceIds(Long[] deviceIds);
|
|
||||||
}
|
|
||||||
|
|
@ -1,77 +0,0 @@
|
||||||
package com.ruoyi.device.domain.api;
|
|
||||||
|
|
||||||
import com.ruoyi.device.domain.model.DockAircraft;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 机场无人机关联Domain接口
|
|
||||||
*
|
|
||||||
* @author ruoyi
|
|
||||||
* @date 2026-01-16
|
|
||||||
*/
|
|
||||||
public interface IDockAircraftDomain
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* 查询机场无人机关联列表
|
|
||||||
*
|
|
||||||
* @param dockAircraft 机场无人机关联
|
|
||||||
* @return 机场无人机关联集合
|
|
||||||
*/
|
|
||||||
List<DockAircraft> selectDockAircraftList(DockAircraft dockAircraft);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 根据关联主键查询机场无人机关联
|
|
||||||
*
|
|
||||||
* @param id 关联主键
|
|
||||||
* @return 机场无人机关联
|
|
||||||
*/
|
|
||||||
DockAircraft selectDockAircraftById(Long id);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 根据机场主键查询关联列表
|
|
||||||
*
|
|
||||||
* @param dockId 机场主键
|
|
||||||
* @return 机场无人机关联集合
|
|
||||||
*/
|
|
||||||
List<DockAircraft> selectDockAircraftByDockId(Long dockId);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 根据无人机主键查询关联列表
|
|
||||||
*
|
|
||||||
* @param aircraftId 无人机主键
|
|
||||||
* @return 机场无人机关联集合
|
|
||||||
*/
|
|
||||||
List<DockAircraft> selectDockAircraftByAircraftId(Long aircraftId);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 新增机场无人机关联
|
|
||||||
*
|
|
||||||
* @param dockAircraft 机场无人机关联
|
|
||||||
* @return 结果
|
|
||||||
*/
|
|
||||||
int insertDockAircraft(DockAircraft dockAircraft);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 修改机场无人机关联
|
|
||||||
*
|
|
||||||
* @param dockAircraft 机场无人机关联
|
|
||||||
* @return 结果
|
|
||||||
*/
|
|
||||||
int updateDockAircraft(DockAircraft dockAircraft);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 删除机场无人机关联
|
|
||||||
*
|
|
||||||
* @param id 关联主键
|
|
||||||
* @return 结果
|
|
||||||
*/
|
|
||||||
int deleteDockAircraftById(Long id);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 批量删除机场无人机关联
|
|
||||||
*
|
|
||||||
* @param ids 关联主键数组
|
|
||||||
* @return 结果
|
|
||||||
*/
|
|
||||||
int deleteDockAircraftByIds(Long[] ids);
|
|
||||||
}
|
|
||||||
|
|
@ -1,69 +0,0 @@
|
||||||
package com.ruoyi.device.domain.api;
|
|
||||||
|
|
||||||
import com.ruoyi.device.domain.model.Dock;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 机场Domain接口
|
|
||||||
*
|
|
||||||
* @author ruoyi
|
|
||||||
* @date 2026-01-16
|
|
||||||
*/
|
|
||||||
public interface IDockDomain
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* 查询机场列表
|
|
||||||
*
|
|
||||||
* @param dock 机场
|
|
||||||
* @return 机场集合
|
|
||||||
*/
|
|
||||||
List<Dock> selectDockList(Dock dock);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 根据机场主键查询机场
|
|
||||||
*
|
|
||||||
* @param dockId 机场主键
|
|
||||||
* @return 机场
|
|
||||||
*/
|
|
||||||
Dock selectDockByDockId(Long dockId);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 根据设备主键查询机场
|
|
||||||
*
|
|
||||||
* @param deviceId 设备主键
|
|
||||||
* @return 机场
|
|
||||||
*/
|
|
||||||
Dock selectDockByDeviceId(Long deviceId);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 新增机场
|
|
||||||
*
|
|
||||||
* @param dock 机场
|
|
||||||
* @return 结果
|
|
||||||
*/
|
|
||||||
int insertDock(Dock dock);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 修改机场
|
|
||||||
*
|
|
||||||
* @param dock 机场
|
|
||||||
* @return 结果
|
|
||||||
*/
|
|
||||||
int updateDock(Dock dock);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 删除机场
|
|
||||||
*
|
|
||||||
* @param dockId 机场主键
|
|
||||||
* @return 结果
|
|
||||||
*/
|
|
||||||
int deleteDockByDockId(Long dockId);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 批量删除机场
|
|
||||||
*
|
|
||||||
* @param dockIds 机场主键数组
|
|
||||||
* @return 结果
|
|
||||||
*/
|
|
||||||
int deleteDockByDockIds(Long[] dockIds);
|
|
||||||
}
|
|
||||||
|
|
@ -1,77 +0,0 @@
|
||||||
package com.ruoyi.device.domain.api;
|
|
||||||
|
|
||||||
import com.ruoyi.device.domain.model.DockGroup;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 机场分组关联Domain接口
|
|
||||||
*
|
|
||||||
* @author ruoyi
|
|
||||||
* @date 2026-01-16
|
|
||||||
*/
|
|
||||||
public interface IDockGroupDomain
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* 查询机场分组关联列表
|
|
||||||
*
|
|
||||||
* @param dockGroup 机场分组关联
|
|
||||||
* @return 机场分组关联集合
|
|
||||||
*/
|
|
||||||
List<DockGroup> selectDockGroupList(DockGroup dockGroup);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 根据关联主键查询机场分组关联
|
|
||||||
*
|
|
||||||
* @param id 关联主键
|
|
||||||
* @return 机场分组关联
|
|
||||||
*/
|
|
||||||
DockGroup selectDockGroupById(Long id);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 根据机场主键查询关联列表
|
|
||||||
*
|
|
||||||
* @param dockId 机场主键
|
|
||||||
* @return 机场分组关联集合
|
|
||||||
*/
|
|
||||||
List<DockGroup> selectDockGroupByDockId(Long dockId);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 根据分组主键查询关联列表
|
|
||||||
*
|
|
||||||
* @param groupId 分组主键
|
|
||||||
* @return 机场分组关联集合
|
|
||||||
*/
|
|
||||||
List<DockGroup> selectDockGroupByGroupId(Long groupId);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 新增机场分组关联
|
|
||||||
*
|
|
||||||
* @param dockGroup 机场分组关联
|
|
||||||
* @return 结果
|
|
||||||
*/
|
|
||||||
int insertDockGroup(DockGroup dockGroup);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 修改机场分组关联
|
|
||||||
*
|
|
||||||
* @param dockGroup 机场分组关联
|
|
||||||
* @return 结果
|
|
||||||
*/
|
|
||||||
int updateDockGroup(DockGroup dockGroup);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 删除机场分组关联
|
|
||||||
*
|
|
||||||
* @param id 关联主键
|
|
||||||
* @return 结果
|
|
||||||
*/
|
|
||||||
int deleteDockGroupById(Long id);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 批量删除机场分组关联
|
|
||||||
*
|
|
||||||
* @param ids 关联主键数组
|
|
||||||
* @return 结果
|
|
||||||
*/
|
|
||||||
int deleteDockGroupByIds(Long[] ids);
|
|
||||||
}
|
|
||||||
|
|
@ -1,69 +0,0 @@
|
||||||
package com.ruoyi.device.domain.api;
|
|
||||||
|
|
||||||
import com.ruoyi.device.domain.model.Group;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 分组Domain接口
|
|
||||||
*
|
|
||||||
* @author ruoyi
|
|
||||||
* @date 2026-01-16
|
|
||||||
*/
|
|
||||||
public interface IGroupDomain
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* 查询分组列表
|
|
||||||
*
|
|
||||||
* @param group 分组
|
|
||||||
* @return 分组集合
|
|
||||||
*/
|
|
||||||
List<Group> selectGroupList(Group group);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 根据分组主键查询分组
|
|
||||||
*
|
|
||||||
* @param groupId 分组主键
|
|
||||||
* @return 分组
|
|
||||||
*/
|
|
||||||
Group selectGroupByGroupId(Long groupId);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 新增分组
|
|
||||||
*
|
|
||||||
* @param group 分组
|
|
||||||
* @return 结果
|
|
||||||
*/
|
|
||||||
int insertGroup(Group group);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 修改分组
|
|
||||||
*
|
|
||||||
* @param group 分组
|
|
||||||
* @return 结果
|
|
||||||
*/
|
|
||||||
int updateGroup(Group group);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 删除分组
|
|
||||||
*
|
|
||||||
* @param groupId 分组主键
|
|
||||||
* @return 结果
|
|
||||||
*/
|
|
||||||
int deleteGroupByGroupId(Long groupId);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 批量删除分组
|
|
||||||
*
|
|
||||||
* @param groupIds 分组主键数组
|
|
||||||
* @return 结果
|
|
||||||
*/
|
|
||||||
int deleteGroupByGroupIds(Long[] groupIds);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 根据分组名称查询分组
|
|
||||||
*
|
|
||||||
* @param groupName 分组名称
|
|
||||||
* @return 分组
|
|
||||||
*/
|
|
||||||
Group selectGroupByGroupName(String groupName);
|
|
||||||
}
|
|
||||||
|
|
@ -1,61 +0,0 @@
|
||||||
package com.ruoyi.device.domain.api;
|
|
||||||
|
|
||||||
import com.ruoyi.device.domain.model.Payload;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 挂载Domain接口
|
|
||||||
*
|
|
||||||
* @author ruoyi
|
|
||||||
* @date 2026-01-16
|
|
||||||
*/
|
|
||||||
public interface IPayloadDomain
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* 查询挂载列表
|
|
||||||
*
|
|
||||||
* @param payload 挂载
|
|
||||||
* @return 挂载集合
|
|
||||||
*/
|
|
||||||
List<Payload> selectPayloadList(Payload payload);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 根据挂载主键查询挂载
|
|
||||||
*
|
|
||||||
* @param payloadId 挂载主键
|
|
||||||
* @return 挂载
|
|
||||||
*/
|
|
||||||
Payload selectPayloadByPayloadId(Long payloadId);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 新增挂载
|
|
||||||
*
|
|
||||||
* @param payload 挂载
|
|
||||||
* @return 结果
|
|
||||||
*/
|
|
||||||
int insertPayload(Payload payload);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 修改挂载
|
|
||||||
*
|
|
||||||
* @param payload 挂载
|
|
||||||
* @return 结果
|
|
||||||
*/
|
|
||||||
int updatePayload(Payload payload);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 删除挂载
|
|
||||||
*
|
|
||||||
* @param payloadId 挂载主键
|
|
||||||
* @return 结果
|
|
||||||
*/
|
|
||||||
int deletePayloadByPayloadId(Long payloadId);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 批量删除挂载
|
|
||||||
*
|
|
||||||
* @param payloadIds 挂载主键数组
|
|
||||||
* @return 结果
|
|
||||||
*/
|
|
||||||
int deletePayloadByPayloadIds(Long[] payloadIds);
|
|
||||||
}
|
|
||||||
|
|
@ -1,157 +0,0 @@
|
||||||
package com.ruoyi.device.domain.api;
|
|
||||||
|
|
||||||
import com.ruoyi.device.domain.model.thingsboard.AttributeMap;
|
|
||||||
import com.ruoyi.device.domain.model.thingsboard.DeviceInfo;
|
|
||||||
import com.ruoyi.device.domain.model.thingsboard.TelemetryMap;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ThingsBoard设备服务接口
|
|
||||||
* 提供类型安全的设备查询功能
|
|
||||||
*/
|
|
||||||
public interface IThingsBoardDomain {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取所有设备的迭代器
|
|
||||||
* 每次迭代返回一页设备列表
|
|
||||||
*
|
|
||||||
* @return 设备迭代器
|
|
||||||
*/
|
|
||||||
Iterable<List<DeviceInfo>> getAllDevices();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取所有网关设备的迭代器
|
|
||||||
* 每次迭代返回一页网关设备列表
|
|
||||||
* 只返回 additionalInfo.gateway = true 的设备
|
|
||||||
*
|
|
||||||
* @return 网关设备迭代器
|
|
||||||
*/
|
|
||||||
Iterable<List<DeviceInfo>> getAllGatewayDevices();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 根据设备ID获取设备信息
|
|
||||||
*
|
|
||||||
* @param deviceId 设备ID
|
|
||||||
* @return 设备信息,如果设备不存在则返回 null
|
|
||||||
*/
|
|
||||||
DeviceInfo getDeviceInfo(String deviceId);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 根据设备ID获取设备的所有属性
|
|
||||||
* 只返回已注册的属性键对应的数据,未注册的键会被忽略
|
|
||||||
*
|
|
||||||
* @param deviceId 设备ID
|
|
||||||
* @return 类型安全的属性映射
|
|
||||||
*/
|
|
||||||
AttributeMap getDeviceAttributes(String deviceId);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 根据设备ID获取设备的所有遥测数据
|
|
||||||
* 只返回已注册的遥测键对应的数据,未注册的键会被忽略
|
|
||||||
*
|
|
||||||
* @param deviceId 设备ID
|
|
||||||
* @return 类型安全的遥测数据映射
|
|
||||||
*/
|
|
||||||
TelemetryMap getDeviceTelemetry(String deviceId);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 根据设备ID获取设备的预定义属性
|
|
||||||
* 只返回在 DeviceAttributes 中预定义的属性
|
|
||||||
*
|
|
||||||
* @param deviceId 设备ID
|
|
||||||
* @return 类型安全的属性映射,只包含预定义的属性
|
|
||||||
*/
|
|
||||||
AttributeMap getPredefinedDeviceAttributes(String deviceId);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 根据设备ID获取设备的预定义遥测数据
|
|
||||||
* 只返回在 DeviceTelemetry 中预定义的遥测数据
|
|
||||||
*
|
|
||||||
* @param deviceId 设备ID
|
|
||||||
* @return 类型安全的遥测数据映射,只包含预定义的遥测数据
|
|
||||||
*/
|
|
||||||
TelemetryMap getPredefinedDeviceTelemetry(String deviceId);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取设备所属的网关设备ID
|
|
||||||
* 通过 ThingsBoard 的 EntityRelation 查询设备与网关的 "Contains" 关系
|
|
||||||
*
|
|
||||||
* @param deviceId 设备ID
|
|
||||||
* @return 网关设备ID,如果设备不属于任何网关则返回 null
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
String getDeviceGatewayId(String deviceId);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取网关设备的所有子设备ID列表
|
|
||||||
* 通过 ThingsBoard 的 EntityRelation 查询网关的 "Contains" 关系
|
|
||||||
*
|
|
||||||
* @param gatewayDeviceId 网关设备ID
|
|
||||||
* @return 子设备ID列表,如果网关没有子设备则返回空列表
|
|
||||||
*/
|
|
||||||
List<String> getGatewayChildDevices(String gatewayDeviceId);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 清除设备属性缓存
|
|
||||||
* 使 getDeviceAttributes 方法的缓存失效
|
|
||||||
*
|
|
||||||
* @param deviceId 设备ID
|
|
||||||
*/
|
|
||||||
void evictDeviceAttributesCache(String deviceId);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 清除设备遥测数据缓存
|
|
||||||
* 使 getDeviceTelemetry 方法的缓存失效
|
|
||||||
*
|
|
||||||
* @param deviceId 设备ID
|
|
||||||
*/
|
|
||||||
void evictDeviceTelemetryCache(String deviceId);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 根据设备ID获取拓恒设备的所有属性
|
|
||||||
* 只返回已注册的属性键对应的数据,未注册的键会被忽略
|
|
||||||
*
|
|
||||||
* @param deviceId 设备ID
|
|
||||||
* @return 类型安全的属性映射
|
|
||||||
*/
|
|
||||||
AttributeMap getTuohengDeviceAttributes(String deviceId);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 根据设备ID获取拓恒设备的所有遥测数据
|
|
||||||
* 只返回已注册的遥测键对应的数据,未注册的键会被忽略
|
|
||||||
*
|
|
||||||
* @param deviceId 设备ID
|
|
||||||
* @return 类型安全的遥测数据映射
|
|
||||||
*/
|
|
||||||
TelemetryMap getTuohengDeviceTelemetry(String deviceId);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 根据设备ID获取拓恒设备的预定义属性
|
|
||||||
* 只返回在 TuohengDeviceAttributes 中预定义的属性
|
|
||||||
*
|
|
||||||
* @param deviceId 设备ID
|
|
||||||
* @return 类型安全的属性映射,只包含预定义的属性
|
|
||||||
*/
|
|
||||||
AttributeMap getPredefinedTuohengDeviceAttributes(String deviceId);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 根据设备ID获取拓恒设备的预定义遥测数据
|
|
||||||
* 只返回在 TuohengDeviceTelemetry 中预定义的遥测数据
|
|
||||||
*
|
|
||||||
* @param deviceId 设备ID
|
|
||||||
* @return 类型安全的遥测数据映射,只包含预定义的遥测数据
|
|
||||||
*/
|
|
||||||
TelemetryMap getPredefinedTuohengDeviceTelemetry(String deviceId);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设置设备属性
|
|
||||||
* 将指定的属性键值对保存到 ThingsBoard 设备的 SERVER_SCOPE 属性中
|
|
||||||
*
|
|
||||||
* @param deviceId 设备ID(ThingsBoard 的 iotDeviceId)
|
|
||||||
* @param key 属性键
|
|
||||||
* @param value 属性值
|
|
||||||
* @return 是否设置成功
|
|
||||||
*/
|
|
||||||
boolean setDeviceAttribute(String deviceId, String key, Object value);
|
|
||||||
}
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
package com.ruoyi.device.domain.api;
|
|
||||||
|
|
||||||
import com.ruoyi.device.domain.model.weather.Weather;
|
|
||||||
|
|
||||||
public interface IWeatherDomain {
|
|
||||||
Weather weatherInfo(String lat, String lon,String dockerDeviceIotId);
|
|
||||||
}
|
|
||||||
|
|
@ -1,36 +0,0 @@
|
||||||
package com.ruoyi.device.domain.config;
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 天气API配置属性
|
|
||||||
*
|
|
||||||
* @author ruoyi
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
@Component
|
|
||||||
@ConfigurationProperties(prefix = "weather.api")
|
|
||||||
public class WeatherProperties {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 天气API AppCode
|
|
||||||
*/
|
|
||||||
private String appcode = "6a152d74a3c249bfa6db6e664f2541f0";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 天气API Host
|
|
||||||
*/
|
|
||||||
private String host = "https://aliv8.data.moji.com";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 天气API Path
|
|
||||||
*/
|
|
||||||
private String path = "/whapi/json/aliweather/condition";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 天气API Token
|
|
||||||
*/
|
|
||||||
private String token = "ff826c205f8f4a59701e64e9e64e01c4";
|
|
||||||
}
|
|
||||||
|
|
@ -1,39 +0,0 @@
|
||||||
package com.ruoyi.device.domain.convert;
|
|
||||||
|
|
||||||
import com.ruoyi.common.core.utils.BaseConvert;
|
|
||||||
import com.ruoyi.device.domain.model.Aircraft;
|
|
||||||
import com.ruoyi.device.mapper.entity.AircraftEntity;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 无人机Domain层转换器
|
|
||||||
* Domain Model ↔ Mapper Entity
|
|
||||||
*
|
|
||||||
* @author ruoyi
|
|
||||||
* @date 2026-01-16
|
|
||||||
*/
|
|
||||||
public class AircraftConvert extends BaseConvert<AircraftEntity, Aircraft> {
|
|
||||||
|
|
||||||
private static final AircraftConvert INSTANCE = new AircraftConvert();
|
|
||||||
|
|
||||||
private AircraftConvert() {
|
|
||||||
super(AircraftEntity.class, Aircraft.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Aircraft from(AircraftEntity entity) {
|
|
||||||
return INSTANCE.innerFrom(entity);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static AircraftEntity to(Aircraft model) {
|
|
||||||
return INSTANCE.innerTo(model);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<Aircraft> fromList(List<AircraftEntity> entityList) {
|
|
||||||
return INSTANCE.innerFromList(entityList);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<AircraftEntity> toList(List<Aircraft> modelList) {
|
|
||||||
return INSTANCE.innerToList(modelList);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,40 +0,0 @@
|
||||||
package com.ruoyi.device.domain.convert;
|
|
||||||
|
|
||||||
import com.ruoyi.common.core.utils.BaseConvert;
|
|
||||||
import com.ruoyi.device.domain.model.AircraftPayload;
|
|
||||||
import com.ruoyi.device.mapper.entity.AircraftPayloadEntity;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 无人机挂载关联Domain层转换器
|
|
||||||
* Domain Model ↔ Mapper Entity
|
|
||||||
*
|
|
||||||
* @author ruoyi
|
|
||||||
* @date 2026-01-16
|
|
||||||
*/
|
|
||||||
public class AircraftPayloadConvert extends BaseConvert<AircraftPayloadEntity, AircraftPayload> {
|
|
||||||
|
|
||||||
private static final AircraftPayloadConvert INSTANCE = new AircraftPayloadConvert();
|
|
||||||
|
|
||||||
private AircraftPayloadConvert() {
|
|
||||||
super(AircraftPayloadEntity.class, AircraftPayload.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static AircraftPayload from(AircraftPayloadEntity entity) {
|
|
||||||
return INSTANCE.innerFrom(entity);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static AircraftPayloadEntity to(AircraftPayload model) {
|
|
||||||
return INSTANCE.innerTo(model);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<AircraftPayload> fromList(List<AircraftPayloadEntity> entityList) {
|
|
||||||
return INSTANCE.innerFromList(entityList);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<AircraftPayloadEntity> toList(List<AircraftPayload> modelList) {
|
|
||||||
return INSTANCE.innerToList(modelList);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,57 +0,0 @@
|
||||||
package com.ruoyi.device.domain.convert;
|
|
||||||
|
|
||||||
import com.ruoyi.common.core.utils.BaseConvert;
|
|
||||||
import com.ruoyi.device.domain.DeviceAirLoadSlot;
|
|
||||||
import com.ruoyi.device.mapper.entity.DeviceAirLoadSlotEntity;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 无人机负载槽位领域层转换器
|
|
||||||
* Domain Entity ↔ Mapper Entity
|
|
||||||
*
|
|
||||||
* @author 拓恒
|
|
||||||
* @date 2026-03-04
|
|
||||||
*/
|
|
||||||
public class DeviceAirLoadSlotConvert extends BaseConvert<DeviceAirLoadSlotEntity, DeviceAirLoadSlot>
|
|
||||||
{
|
|
||||||
|
|
||||||
private static final DeviceAirLoadSlotConvert INSTANCE = new DeviceAirLoadSlotConvert();
|
|
||||||
|
|
||||||
private DeviceAirLoadSlotConvert() {
|
|
||||||
super(DeviceAirLoadSlotEntity.class, DeviceAirLoadSlot.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Entity 转 Domain
|
|
||||||
*/
|
|
||||||
public static DeviceAirLoadSlot from(DeviceAirLoadSlotEntity entity)
|
|
||||||
{
|
|
||||||
return INSTANCE.innerFrom(entity);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Domain 转 Entity
|
|
||||||
*/
|
|
||||||
public static DeviceAirLoadSlotEntity to(DeviceAirLoadSlot domain)
|
|
||||||
{
|
|
||||||
return INSTANCE.innerTo(domain);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Entity List 转 Domain List
|
|
||||||
*/
|
|
||||||
public static List<DeviceAirLoadSlot> fromList(List<DeviceAirLoadSlotEntity> entityList)
|
|
||||||
{
|
|
||||||
return INSTANCE.innerFromList(entityList);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Domain List 转 Entity List
|
|
||||||
*/
|
|
||||||
public static List<DeviceAirLoadSlotEntity> toList(List<DeviceAirLoadSlot> domainList)
|
|
||||||
{
|
|
||||||
return INSTANCE.innerToList(domainList);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,57 +0,0 @@
|
||||||
package com.ruoyi.device.domain.convert;
|
|
||||||
|
|
||||||
import com.ruoyi.common.core.utils.BaseConvert;
|
|
||||||
import com.ruoyi.device.domain.DeviceAirLoadType;
|
|
||||||
import com.ruoyi.device.mapper.entity.DeviceAirLoadTypeEntity;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 无人机负载类型领域层转换器
|
|
||||||
* Domain Entity ↔ Mapper Entity
|
|
||||||
*
|
|
||||||
* @author 拓恒
|
|
||||||
* @date 2026-03-04
|
|
||||||
*/
|
|
||||||
public class DeviceAirLoadTypeConvert extends BaseConvert<DeviceAirLoadTypeEntity, DeviceAirLoadType>
|
|
||||||
{
|
|
||||||
|
|
||||||
private static final DeviceAirLoadTypeConvert INSTANCE = new DeviceAirLoadTypeConvert();
|
|
||||||
|
|
||||||
private DeviceAirLoadTypeConvert() {
|
|
||||||
super(DeviceAirLoadTypeEntity.class, DeviceAirLoadType.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Entity 转 Domain
|
|
||||||
*/
|
|
||||||
public static DeviceAirLoadType from(DeviceAirLoadTypeEntity entity)
|
|
||||||
{
|
|
||||||
return INSTANCE.innerFrom(entity);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Domain 转 Entity
|
|
||||||
*/
|
|
||||||
public static DeviceAirLoadTypeEntity to(DeviceAirLoadType domain)
|
|
||||||
{
|
|
||||||
return INSTANCE.innerTo(domain);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Entity List 转 Domain List
|
|
||||||
*/
|
|
||||||
public static List<DeviceAirLoadType> fromList(List<DeviceAirLoadTypeEntity> entityList)
|
|
||||||
{
|
|
||||||
return INSTANCE.innerFromList(entityList);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Domain List 转 Entity List
|
|
||||||
*/
|
|
||||||
public static List<DeviceAirLoadTypeEntity> toList(List<DeviceAirLoadType> domainList)
|
|
||||||
{
|
|
||||||
return INSTANCE.innerToList(domainList);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,57 +0,0 @@
|
||||||
package com.ruoyi.device.domain.convert;
|
|
||||||
|
|
||||||
import com.ruoyi.common.core.utils.BaseConvert;
|
|
||||||
import com.ruoyi.device.domain.model.DeviceAirTypeGeneralEnum;
|
|
||||||
import com.ruoyi.device.mapper.entity.DeviceAirTypeGeneralEnumEntity;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 无人机类型通用枚举领域层转换器
|
|
||||||
* Domain Model ↔ Mapper Entity
|
|
||||||
*
|
|
||||||
* @author ruoyi
|
|
||||||
* @date 2026-01-28
|
|
||||||
*/
|
|
||||||
public class DeviceAirTypeGeneralEnumConvert extends BaseConvert<DeviceAirTypeGeneralEnum, DeviceAirTypeGeneralEnumEntity>
|
|
||||||
{
|
|
||||||
|
|
||||||
private static final DeviceAirTypeGeneralEnumConvert INSTANCE = new DeviceAirTypeGeneralEnumConvert();
|
|
||||||
|
|
||||||
private DeviceAirTypeGeneralEnumConvert() {
|
|
||||||
super(DeviceAirTypeGeneralEnum.class, DeviceAirTypeGeneralEnumEntity.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Model 转 Entity
|
|
||||||
*/
|
|
||||||
public static DeviceAirTypeGeneralEnumEntity from(DeviceAirTypeGeneralEnum model)
|
|
||||||
{
|
|
||||||
return INSTANCE.innerFrom(model);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Entity 转 Model
|
|
||||||
*/
|
|
||||||
public static DeviceAirTypeGeneralEnum to(DeviceAirTypeGeneralEnumEntity entity)
|
|
||||||
{
|
|
||||||
return INSTANCE.innerTo(entity);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Model List 转 Entity List
|
|
||||||
*/
|
|
||||||
public static List<DeviceAirTypeGeneralEnumEntity> fromList(List<DeviceAirTypeGeneralEnum> modelList)
|
|
||||||
{
|
|
||||||
return INSTANCE.innerFromList(modelList);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Entity List 转 Model List
|
|
||||||
*/
|
|
||||||
public static List<DeviceAirTypeGeneralEnum> toList(List<DeviceAirTypeGeneralEnumEntity> entityList)
|
|
||||||
{
|
|
||||||
return INSTANCE.innerToList(entityList);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,39 +0,0 @@
|
||||||
package com.ruoyi.device.domain.convert;
|
|
||||||
|
|
||||||
import com.ruoyi.common.core.utils.BaseConvert;
|
|
||||||
import com.ruoyi.device.domain.model.Device;
|
|
||||||
import com.ruoyi.device.mapper.entity.DeviceEntity;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设备Domain层转换器
|
|
||||||
* Domain Model ↔ Mapper Entity
|
|
||||||
*
|
|
||||||
* @author ruoyi
|
|
||||||
* @date 2026-01-16
|
|
||||||
*/
|
|
||||||
public class DeviceConvert extends BaseConvert<DeviceEntity, Device> {
|
|
||||||
|
|
||||||
private static final DeviceConvert INSTANCE = new DeviceConvert();
|
|
||||||
|
|
||||||
private DeviceConvert() {
|
|
||||||
super(DeviceEntity.class, Device.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Device from(DeviceEntity entity) {
|
|
||||||
return INSTANCE.innerFrom(entity);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static DeviceEntity to(Device model) {
|
|
||||||
return INSTANCE.innerTo(model);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<Device> fromList(List<DeviceEntity> entityList) {
|
|
||||||
return INSTANCE.innerFromList(entityList);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<DeviceEntity> toList(List<Device> modelList) {
|
|
||||||
return INSTANCE.innerToList(modelList);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -14,7 +14,7 @@ import java.util.stream.Collectors;
|
||||||
* @author ruoyi
|
* @author ruoyi
|
||||||
* @date 2026-01-15
|
* @date 2026-01-15
|
||||||
*/
|
*/
|
||||||
public class DeviceTempDomainEntityConvert
|
public class DeviceTempDomainConvert
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Entity 转 Model
|
* Entity 转 Model
|
||||||
|
|
@ -53,6 +53,6 @@ public class DeviceTempDomainEntityConvert
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return entityList.stream().map(DeviceTempDomainEntityConvert::toModel).collect(Collectors.toList());
|
return entityList.stream().map(DeviceTempDomainConvert::toModel).collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,41 +0,0 @@
|
||||||
package com.ruoyi.device.domain.convert;
|
|
||||||
|
|
||||||
import com.ruoyi.common.core.utils.BaseConvert;
|
|
||||||
import com.ruoyi.device.domain.model.DockAircraft;
|
|
||||||
import com.ruoyi.device.mapper.entity.DockAircraftEntity;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 机场无人机关联Domain层转换器
|
|
||||||
* Domain Model ↔ Mapper Entity
|
|
||||||
*
|
|
||||||
* @author ruoyi
|
|
||||||
* @date 2026-01-16
|
|
||||||
*/
|
|
||||||
public class DockAircraftConvert extends BaseConvert<DockAircraftEntity, DockAircraft>
|
|
||||||
{
|
|
||||||
|
|
||||||
private static final DockAircraftConvert INSTANCE = new DockAircraftConvert();
|
|
||||||
|
|
||||||
private DockAircraftConvert() {
|
|
||||||
super(DockAircraftEntity.class, DockAircraft.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static DockAircraft from(DockAircraftEntity entity) {
|
|
||||||
return INSTANCE.innerFrom(entity);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static DockAircraftEntity to(DockAircraft model) {
|
|
||||||
return INSTANCE.innerTo(model);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<DockAircraft> fromList(List<DockAircraftEntity> entityList) {
|
|
||||||
return INSTANCE.innerFromList(entityList);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<DockAircraftEntity> toList(List<DockAircraft> modelList) {
|
|
||||||
return INSTANCE.innerToList(modelList);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,42 +0,0 @@
|
||||||
package com.ruoyi.device.domain.convert;
|
|
||||||
|
|
||||||
import com.ruoyi.common.core.utils.BaseConvert;
|
|
||||||
import com.ruoyi.device.domain.model.Dock;
|
|
||||||
import com.ruoyi.device.mapper.entity.DockEntity;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 机场Domain层转换器
|
|
||||||
* Domain Model ↔ Mapper Entity
|
|
||||||
*
|
|
||||||
* @author ruoyi
|
|
||||||
* @date 2026-01-16
|
|
||||||
*/
|
|
||||||
public class DockConvert extends BaseConvert<DockEntity, Dock>
|
|
||||||
{
|
|
||||||
|
|
||||||
private static final DockConvert INSTANCE = new DockConvert();
|
|
||||||
|
|
||||||
private DockConvert() {
|
|
||||||
super(DockEntity.class, Dock.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Dock from(DockEntity entity) {
|
|
||||||
return INSTANCE.innerFrom(entity);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static DockEntity to(Dock model) {
|
|
||||||
return INSTANCE.innerTo(model);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<Dock> fromList(List<DockEntity> entityList) {
|
|
||||||
return INSTANCE.innerFromList(entityList);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<DockEntity> toList(List<Dock> modelList) {
|
|
||||||
return INSTANCE.innerToList(modelList);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,39 +0,0 @@
|
||||||
package com.ruoyi.device.domain.convert;
|
|
||||||
|
|
||||||
import com.ruoyi.common.core.utils.BaseConvert;
|
|
||||||
import com.ruoyi.device.domain.model.DockGroup;
|
|
||||||
import com.ruoyi.device.mapper.entity.DockGroupEntity;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 机场分组关联Domain层转换器
|
|
||||||
* Domain Model ↔ Mapper Entity
|
|
||||||
*
|
|
||||||
* @author ruoyi
|
|
||||||
* @date 2026-01-16
|
|
||||||
*/
|
|
||||||
public class DockGroupConvert extends BaseConvert<DockGroupEntity, DockGroup> {
|
|
||||||
|
|
||||||
private static final DockGroupConvert INSTANCE = new DockGroupConvert();
|
|
||||||
|
|
||||||
private DockGroupConvert() {
|
|
||||||
super(DockGroupEntity.class, DockGroup.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static DockGroup from(DockGroupEntity entity) {
|
|
||||||
return INSTANCE.innerFrom(entity);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static DockGroupEntity to(DockGroup model) {
|
|
||||||
return INSTANCE.innerTo(model);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<DockGroup> fromList(List<DockGroupEntity> entityList) {
|
|
||||||
return INSTANCE.innerFromList(entityList);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<DockGroupEntity> toList(List<DockGroup> modelList) {
|
|
||||||
return INSTANCE.innerToList(modelList);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,39 +0,0 @@
|
||||||
package com.ruoyi.device.domain.convert;
|
|
||||||
|
|
||||||
import com.ruoyi.common.core.utils.BaseConvert;
|
|
||||||
import com.ruoyi.device.domain.model.Group;
|
|
||||||
import com.ruoyi.device.mapper.entity.GroupEntity;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 分组Domain层转换器
|
|
||||||
* Domain Model ↔ Mapper Entity
|
|
||||||
*
|
|
||||||
* @author ruoyi
|
|
||||||
* @date 2026-01-16
|
|
||||||
*/
|
|
||||||
public class GroupConvert extends BaseConvert<GroupEntity, Group> {
|
|
||||||
|
|
||||||
private static final GroupConvert INSTANCE = new GroupConvert();
|
|
||||||
|
|
||||||
private GroupConvert() {
|
|
||||||
super(GroupEntity.class, Group.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Group from(GroupEntity entity) {
|
|
||||||
return INSTANCE.innerFrom(entity);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static GroupEntity to(Group model) {
|
|
||||||
return INSTANCE.innerTo(model);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<Group> fromList(List<GroupEntity> entityList) {
|
|
||||||
return INSTANCE.innerFromList(entityList);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<GroupEntity> toList(List<Group> modelList) {
|
|
||||||
return INSTANCE.innerToList(modelList);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,40 +0,0 @@
|
||||||
package com.ruoyi.device.domain.convert;
|
|
||||||
|
|
||||||
import com.ruoyi.common.core.utils.BaseConvert;
|
|
||||||
import com.ruoyi.device.domain.model.Payload;
|
|
||||||
import com.ruoyi.device.mapper.entity.PayloadEntity;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 挂载Domain层转换器
|
|
||||||
* Domain Model ↔ Mapper Entity
|
|
||||||
*
|
|
||||||
* @author ruoyi
|
|
||||||
* @date 2026-01-16
|
|
||||||
*/
|
|
||||||
public class PayloadConvert extends BaseConvert<PayloadEntity, Payload>
|
|
||||||
{
|
|
||||||
|
|
||||||
private static final PayloadConvert INSTANCE = new PayloadConvert();
|
|
||||||
|
|
||||||
private PayloadConvert() {
|
|
||||||
super(PayloadEntity.class, Payload.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Payload from(PayloadEntity entity) {
|
|
||||||
return INSTANCE.innerFrom(entity);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static PayloadEntity to(Payload model) {
|
|
||||||
return INSTANCE.innerTo(model);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<Payload> fromList(List<PayloadEntity> entityList) {
|
|
||||||
return INSTANCE.innerFromList(entityList);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<PayloadEntity> toList(List<Payload> modelList) {
|
|
||||||
return INSTANCE.innerToList(modelList);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,91 +0,0 @@
|
||||||
package com.ruoyi.device.domain.impl;
|
|
||||||
|
|
||||||
import com.ruoyi.device.config.DeviceCacheConfig;
|
|
||||||
import com.ruoyi.device.domain.api.IAircraftDomain;
|
|
||||||
import com.ruoyi.device.domain.convert.AircraftConvert;
|
|
||||||
import com.ruoyi.device.domain.model.Aircraft;
|
|
||||||
import com.ruoyi.device.mapper.AircraftMapper;
|
|
||||||
import com.ruoyi.device.mapper.entity.AircraftEntity;
|
|
||||||
import org.springframework.cache.annotation.CacheEvict;
|
|
||||||
import org.springframework.cache.annotation.Cacheable;
|
|
||||||
import org.springframework.cache.annotation.Caching;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 无人机Domain实现
|
|
||||||
*
|
|
||||||
* @author ruoyi
|
|
||||||
* @date 2026-01-16
|
|
||||||
*/
|
|
||||||
@Component
|
|
||||||
public class AircraftDomainImpl implements IAircraftDomain
|
|
||||||
{
|
|
||||||
private final AircraftMapper aircraftMapper;
|
|
||||||
|
|
||||||
public AircraftDomainImpl(AircraftMapper aircraftMapper)
|
|
||||||
{
|
|
||||||
this.aircraftMapper = aircraftMapper;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<Aircraft> selectAircraftList(Aircraft aircraft)
|
|
||||||
{
|
|
||||||
AircraftEntity entity = AircraftConvert.to(aircraft);
|
|
||||||
List<AircraftEntity> entityList = aircraftMapper.selectAircraftList(entity);
|
|
||||||
return AircraftConvert.fromList(entityList);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Cacheable(value = DeviceCacheConfig.AIRCRAFT_CACHE, key = "'id:' + #aircraftId", unless = "#result == null")
|
|
||||||
public Aircraft selectAircraftByAircraftId(Long aircraftId)
|
|
||||||
{
|
|
||||||
AircraftEntity entity = aircraftMapper.selectAircraftByAircraftId(aircraftId);
|
|
||||||
return AircraftConvert.from(entity);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Cacheable(value = DeviceCacheConfig.AIRCRAFT_CACHE, key = "'deviceId:' + #deviceId", unless = "#result == null")
|
|
||||||
public Aircraft selectAircraftByDeviceId(Long deviceId)
|
|
||||||
{
|
|
||||||
AircraftEntity entity = aircraftMapper.selectAircraftByDeviceId(deviceId);
|
|
||||||
return AircraftConvert.from(entity);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@CacheEvict(value = DeviceCacheConfig.AIRCRAFT_CACHE, allEntries = true)
|
|
||||||
public int insertAircraft(Aircraft aircraft)
|
|
||||||
{
|
|
||||||
AircraftEntity entity = AircraftConvert.to(aircraft);
|
|
||||||
int result = aircraftMapper.insertAircraft(entity);
|
|
||||||
// MyBatis 会将自增主键回填到 entity 对象,需要同步回 aircraft 对象
|
|
||||||
aircraft.setAircraftId(entity.getAircraftId());
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Caching(evict = {
|
|
||||||
@CacheEvict(value = DeviceCacheConfig.AIRCRAFT_CACHE, key = "'id:' + #aircraft.aircraftId"),
|
|
||||||
@CacheEvict(value = DeviceCacheConfig.AIRCRAFT_CACHE, key = "'deviceId:' + #aircraft.deviceId")
|
|
||||||
})
|
|
||||||
public int updateAircraft(Aircraft aircraft)
|
|
||||||
{
|
|
||||||
AircraftEntity entity = AircraftConvert.to(aircraft);
|
|
||||||
return aircraftMapper.updateAircraft(entity);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@CacheEvict(value = DeviceCacheConfig.AIRCRAFT_CACHE, allEntries = true)
|
|
||||||
public int deleteAircraftByAircraftId(Long aircraftId)
|
|
||||||
{
|
|
||||||
return aircraftMapper.deleteAircraftByAircraftId(aircraftId);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@CacheEvict(value = DeviceCacheConfig.AIRCRAFT_CACHE, allEntries = true)
|
|
||||||
public int deleteAircraftByAircraftIds(Long[] aircraftIds)
|
|
||||||
{
|
|
||||||
return aircraftMapper.deleteAircraftByAircraftIds(aircraftIds);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,104 +0,0 @@
|
||||||
package com.ruoyi.device.domain.impl;
|
|
||||||
|
|
||||||
import com.ruoyi.device.config.DeviceCacheConfig;
|
|
||||||
import com.ruoyi.device.domain.api.IAircraftPayloadDomain;
|
|
||||||
import com.ruoyi.device.domain.convert.AircraftPayloadConvert;
|
|
||||||
import com.ruoyi.device.domain.model.AircraftPayload;
|
|
||||||
import com.ruoyi.device.mapper.AircraftPayloadMapper;
|
|
||||||
import com.ruoyi.device.mapper.entity.AircraftPayloadEntity;
|
|
||||||
import org.springframework.cache.annotation.CacheEvict;
|
|
||||||
import org.springframework.cache.annotation.Cacheable;
|
|
||||||
import org.springframework.cache.annotation.Caching;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 无人机挂载关联Domain实现
|
|
||||||
*
|
|
||||||
* @author ruoyi
|
|
||||||
* @date 2026-01-16
|
|
||||||
*/
|
|
||||||
@Component
|
|
||||||
public class AircraftPayloadDomainImpl implements IAircraftPayloadDomain
|
|
||||||
{
|
|
||||||
private final AircraftPayloadMapper aircraftPayloadMapper;
|
|
||||||
|
|
||||||
public AircraftPayloadDomainImpl(AircraftPayloadMapper aircraftPayloadMapper)
|
|
||||||
{
|
|
||||||
this.aircraftPayloadMapper = aircraftPayloadMapper;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<AircraftPayload> selectAircraftPayloadList(AircraftPayload aircraftPayload)
|
|
||||||
{
|
|
||||||
AircraftPayloadEntity entity = AircraftPayloadConvert.to(aircraftPayload);
|
|
||||||
List<AircraftPayloadEntity> entityList = aircraftPayloadMapper.selectAircraftPayloadList(entity);
|
|
||||||
return AircraftPayloadConvert.fromList(entityList);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Cacheable(value = DeviceCacheConfig.AIRCRAFT_PAYLOAD_CACHE, key = "'id:' + #id", unless = "#result == null")
|
|
||||||
public AircraftPayload selectAircraftPayloadById(Long id)
|
|
||||||
{
|
|
||||||
AircraftPayloadEntity entity = aircraftPayloadMapper.selectAircraftPayloadById(id);
|
|
||||||
return AircraftPayloadConvert.from(entity);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Cacheable(value = DeviceCacheConfig.AIRCRAFT_PAYLOAD_CACHE, key = "'aircraftId:' + #aircraftId", unless = "#result == null")
|
|
||||||
public List<AircraftPayload> selectAircraftPayloadByAircraftId(Long aircraftId)
|
|
||||||
{
|
|
||||||
List<AircraftPayloadEntity> entityList = aircraftPayloadMapper.selectAircraftPayloadListByAircraftId(aircraftId);
|
|
||||||
return AircraftPayloadConvert.fromList(entityList);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Cacheable(value = DeviceCacheConfig.AIRCRAFT_PAYLOAD_CACHE, key = "'payloadId:' + #payloadId", unless = "#result == null")
|
|
||||||
public List<AircraftPayload> selectAircraftPayloadByPayloadId(Long payloadId)
|
|
||||||
{
|
|
||||||
List<AircraftPayloadEntity> entityList = aircraftPayloadMapper.selectAircraftPayloadListByPayloadId(payloadId);
|
|
||||||
return AircraftPayloadConvert.fromList(entityList);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Cacheable(value = DeviceCacheConfig.AIRCRAFT_PAYLOAD_CACHE, key = "'dockId:' + #dockId", unless = "#result == null")
|
|
||||||
public List<AircraftPayload> selectAircraftPayloadByDockId(Long dockId)
|
|
||||||
{
|
|
||||||
List<AircraftPayloadEntity> entityList = aircraftPayloadMapper.selectAircraftPayloadListByDockId(dockId);
|
|
||||||
return AircraftPayloadConvert.fromList(entityList);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@CacheEvict(value = DeviceCacheConfig.AIRCRAFT_PAYLOAD_CACHE, allEntries = true)
|
|
||||||
public int insertAircraftPayload(AircraftPayload aircraftPayload)
|
|
||||||
{
|
|
||||||
AircraftPayloadEntity entity = AircraftPayloadConvert.to(aircraftPayload);
|
|
||||||
int result = aircraftPayloadMapper.insertAircraftPayload(entity);
|
|
||||||
// MyBatis 会将自增主键回填到 entity 对象,需要同步回 aircraftPayload 对象
|
|
||||||
aircraftPayload.setId(entity.getId());
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@CacheEvict(value = DeviceCacheConfig.AIRCRAFT_PAYLOAD_CACHE, allEntries = true)
|
|
||||||
public int updateAircraftPayload(AircraftPayload aircraftPayload)
|
|
||||||
{
|
|
||||||
AircraftPayloadEntity entity = AircraftPayloadConvert.to(aircraftPayload);
|
|
||||||
return aircraftPayloadMapper.updateAircraftPayload(entity);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@CacheEvict(value = DeviceCacheConfig.AIRCRAFT_PAYLOAD_CACHE, allEntries = true)
|
|
||||||
public int deleteAircraftPayloadById(Long id)
|
|
||||||
{
|
|
||||||
return aircraftPayloadMapper.deleteAircraftPayloadById(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@CacheEvict(value = DeviceCacheConfig.AIRCRAFT_PAYLOAD_CACHE, allEntries = true)
|
|
||||||
public int deleteAircraftPayloadByIds(Long[] ids)
|
|
||||||
{
|
|
||||||
return aircraftPayloadMapper.deleteAircraftPayloadByIds(ids);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,41 +0,0 @@
|
||||||
package com.ruoyi.device.domain.impl;
|
|
||||||
|
|
||||||
import com.ruoyi.device.domain.DeviceAirLoadSlot;
|
|
||||||
import com.ruoyi.device.domain.api.IDeviceAirLoadSlotDomain;
|
|
||||||
import com.ruoyi.device.domain.convert.DeviceAirLoadSlotConvert;
|
|
||||||
import com.ruoyi.device.domain.convert.DeviceAirLoadTypeConvert;
|
|
||||||
import com.ruoyi.device.mapper.DeviceAirLoadSlotMapper;
|
|
||||||
import com.ruoyi.device.mapper.entity.DeviceAirLoadSlotEntity;
|
|
||||||
import com.ruoyi.device.mapper.entity.DeviceAirLoadTypeEntity;
|
|
||||||
import com.ruoyi.device.service.dto.DeviceAirLoadSlotDTO;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.stereotype.Repository;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 无人机负载槽位Domain实现类
|
|
||||||
*
|
|
||||||
* @author 拓恒
|
|
||||||
* @date 2026-03-04
|
|
||||||
*/
|
|
||||||
@Repository
|
|
||||||
public class DeviceAirLoadSlotDomainImpl implements IDeviceAirLoadSlotDomain {
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private DeviceAirLoadSlotMapper deviceAirLoadSlotMapper;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public DeviceAirLoadSlot selectDeviceAirLoadSlotByVendorAndType(DeviceAirLoadSlot deviceAirLoadSlot) {
|
|
||||||
DeviceAirLoadSlotEntity entity = DeviceAirLoadSlotConvert.to(deviceAirLoadSlot);
|
|
||||||
DeviceAirLoadSlotEntity result = deviceAirLoadSlotMapper.selectDeviceAirLoadSlotByVendorAndType(entity);
|
|
||||||
if (result == null) {
|
|
||||||
// 设置默认值
|
|
||||||
result = new DeviceAirLoadSlotEntity();
|
|
||||||
result.setSlotCount(0);
|
|
||||||
result.setLoadLimit(0);
|
|
||||||
result.setAccessoryLimit(0);
|
|
||||||
}
|
|
||||||
return DeviceAirLoadSlotConvert.from(result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,35 +0,0 @@
|
||||||
package com.ruoyi.device.domain.impl;
|
|
||||||
|
|
||||||
import com.ruoyi.device.domain.DeviceAirLoadType;
|
|
||||||
import com.ruoyi.device.domain.api.IDeviceAirLoadTypeDomain;
|
|
||||||
import com.ruoyi.device.domain.convert.DeviceAirLoadTypeConvert;
|
|
||||||
import com.ruoyi.device.mapper.DeviceAirLoadTypeMapper;
|
|
||||||
import com.ruoyi.device.mapper.entity.DeviceAirLoadTypeEntity;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.stereotype.Repository;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 无人机负载类型Domain实现类
|
|
||||||
*
|
|
||||||
* @author 拓恒
|
|
||||||
* @date 2026-03-04
|
|
||||||
*/
|
|
||||||
@Repository
|
|
||||||
public class DeviceAirLoadTypeDomainImpl implements IDeviceAirLoadTypeDomain {
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private DeviceAirLoadTypeMapper deviceAirLoadTypeMapper;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<DeviceAirLoadType> selectDeviceAirLoadTypeList(DeviceAirLoadType deviceAirLoadType) {
|
|
||||||
DeviceAirLoadTypeEntity entity = DeviceAirLoadTypeConvert.to(deviceAirLoadType);
|
|
||||||
List<DeviceAirLoadTypeEntity> entityList = deviceAirLoadTypeMapper.selectDeviceAirLoadTypeList(entity);
|
|
||||||
return DeviceAirLoadTypeConvert.fromList(entityList);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,65 +0,0 @@
|
||||||
package com.ruoyi.device.domain.impl;
|
|
||||||
|
|
||||||
import com.ruoyi.device.domain.api.IDeviceAirTypeGeneralEnumDomain;
|
|
||||||
import com.ruoyi.device.domain.convert.DeviceAirTypeGeneralEnumConvert;
|
|
||||||
import com.ruoyi.device.domain.model.DeviceAirTypeGeneralEnum;
|
|
||||||
import com.ruoyi.device.mapper.DeviceAirTypeGeneralEnumMapper;
|
|
||||||
import com.ruoyi.device.mapper.entity.DeviceAirTypeGeneralEnumEntity;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.stereotype.Repository;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 无人机类型通用枚举Domain实现类
|
|
||||||
*
|
|
||||||
* @author ruoyi
|
|
||||||
* @date 2026-01-28
|
|
||||||
*/
|
|
||||||
@Repository
|
|
||||||
public class DeviceAirTypeGeneralEnumDomainImpl implements IDeviceAirTypeGeneralEnumDomain
|
|
||||||
{
|
|
||||||
@Autowired
|
|
||||||
private DeviceAirTypeGeneralEnumMapper airTypeGeneralEnumMapper;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<DeviceAirTypeGeneralEnum> selectAirTypeGeneralEnumList(DeviceAirTypeGeneralEnum airTypeGeneralEnum)
|
|
||||||
{
|
|
||||||
DeviceAirTypeGeneralEnumEntity entity = DeviceAirTypeGeneralEnumConvert.from(airTypeGeneralEnum);
|
|
||||||
List<DeviceAirTypeGeneralEnumEntity> entityList = airTypeGeneralEnumMapper.selectAirTypeGeneralEnumList(entity);
|
|
||||||
return DeviceAirTypeGeneralEnumConvert.toList(entityList);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public DeviceAirTypeGeneralEnum selectAirTypeGeneralEnumById(Long id)
|
|
||||||
{
|
|
||||||
DeviceAirTypeGeneralEnumEntity entity = airTypeGeneralEnumMapper.selectAirTypeGeneralEnumById(id);
|
|
||||||
return DeviceAirTypeGeneralEnumConvert.to(entity);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int insertAirTypeGeneralEnum(DeviceAirTypeGeneralEnum airTypeGeneralEnum)
|
|
||||||
{
|
|
||||||
DeviceAirTypeGeneralEnumEntity entity = DeviceAirTypeGeneralEnumConvert.from(airTypeGeneralEnum);
|
|
||||||
return airTypeGeneralEnumMapper.insertAirTypeGeneralEnum(entity);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int updateAirTypeGeneralEnum(DeviceAirTypeGeneralEnum airTypeGeneralEnum)
|
|
||||||
{
|
|
||||||
DeviceAirTypeGeneralEnumEntity entity = DeviceAirTypeGeneralEnumConvert.from(airTypeGeneralEnum);
|
|
||||||
return airTypeGeneralEnumMapper.updateAirTypeGeneralEnum(entity);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int deleteAirTypeGeneralEnumById(Long id)
|
|
||||||
{
|
|
||||||
return airTypeGeneralEnumMapper.deleteAirTypeGeneralEnumById(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int deleteAirTypeGeneralEnumByIds(Long[] ids)
|
|
||||||
{
|
|
||||||
return airTypeGeneralEnumMapper.deleteAirTypeGeneralEnumByIds(ids);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,105 +0,0 @@
|
||||||
package com.ruoyi.device.domain.impl;
|
|
||||||
|
|
||||||
import com.ruoyi.device.config.DeviceCacheConfig;
|
|
||||||
import com.ruoyi.device.domain.api.IDeviceDomain;
|
|
||||||
import com.ruoyi.device.domain.convert.DeviceConvert;
|
|
||||||
import com.ruoyi.device.domain.model.Device;
|
|
||||||
import com.ruoyi.device.mapper.DeviceMapper;
|
|
||||||
import com.ruoyi.device.mapper.entity.DeviceEntity;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.springframework.cache.annotation.CacheEvict;
|
|
||||||
import org.springframework.cache.annotation.Cacheable;
|
|
||||||
import org.springframework.cache.annotation.Caching;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设备Domain实现
|
|
||||||
*
|
|
||||||
* @author ruoyi
|
|
||||||
* @date 2026-01-16
|
|
||||||
*/
|
|
||||||
@Slf4j
|
|
||||||
@Component
|
|
||||||
public class DeviceDomainImpl implements IDeviceDomain
|
|
||||||
{
|
|
||||||
private final DeviceMapper deviceMapper;
|
|
||||||
|
|
||||||
public DeviceDomainImpl(DeviceMapper deviceMapper)
|
|
||||||
{
|
|
||||||
this.deviceMapper = deviceMapper;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<Device> selectDeviceList(Device device)
|
|
||||||
{
|
|
||||||
DeviceEntity entity = DeviceConvert.to(device);
|
|
||||||
List<DeviceEntity> entityList = deviceMapper.selectDeviceList(entity);
|
|
||||||
return DeviceConvert.fromList(entityList);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Cacheable(value = DeviceCacheConfig.DEVICE_CACHE, key = "'id:' + #deviceId", unless = "#result == null")
|
|
||||||
public Device selectDeviceByDeviceId(Long deviceId)
|
|
||||||
{
|
|
||||||
DeviceEntity entity = deviceMapper.selectDeviceByDeviceId(deviceId);
|
|
||||||
return DeviceConvert.from(entity);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Cacheable(value = DeviceCacheConfig.DEVICE_CACHE, key = "'iotId:' + #iotDeviceId", unless = "#result == null")
|
|
||||||
public Device selectDeviceByIotDeviceId(String iotDeviceId)
|
|
||||||
{
|
|
||||||
DeviceEntity entity = deviceMapper.selectDeviceByIotDeviceId(iotDeviceId);
|
|
||||||
return DeviceConvert.from(entity);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Cacheable(value = DeviceCacheConfig.DEVICE_CACHE, key = "'sn:' + #deviceSn", unless = "#result == null")
|
|
||||||
public Device selectDeviceByDeviceSn(String deviceSn)
|
|
||||||
{
|
|
||||||
log.info("查询设备 by device_sn: {}", deviceSn);
|
|
||||||
DeviceEntity entity = deviceMapper.selectDeviceByDeviceSn(deviceSn);
|
|
||||||
Device result = DeviceConvert.from(entity);
|
|
||||||
log.info("查询设备结果: device_sn={}, result={}", deviceSn, result != null ? result.getDeviceId() : "null");
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@CacheEvict(value = DeviceCacheConfig.DEVICE_CACHE, allEntries = true)
|
|
||||||
public int insertDevice(Device device)
|
|
||||||
{
|
|
||||||
DeviceEntity entity = DeviceConvert.to(device);
|
|
||||||
int result = deviceMapper.insertDevice(entity);
|
|
||||||
// MyBatis 会将自增主键回填到 entity 对象,需要同步回 device 对象
|
|
||||||
device.setDeviceId(entity.getDeviceId());
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Caching(evict = {
|
|
||||||
@CacheEvict(value = DeviceCacheConfig.DEVICE_CACHE, key = "'id:' + #device.deviceId"),
|
|
||||||
@CacheEvict(value = DeviceCacheConfig.DEVICE_CACHE, key = "'iotId:' + #device.iotDeviceId"),
|
|
||||||
@CacheEvict(value = DeviceCacheConfig.DEVICE_CACHE, key = "'sn:' + #device.deviceSn")
|
|
||||||
})
|
|
||||||
public int updateDevice(Device device)
|
|
||||||
{
|
|
||||||
DeviceEntity entity = DeviceConvert.to(device);
|
|
||||||
return deviceMapper.updateDevice(entity);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@CacheEvict(value = DeviceCacheConfig.DEVICE_CACHE, allEntries = true)
|
|
||||||
public int deleteDeviceByDeviceId(Long deviceId)
|
|
||||||
{
|
|
||||||
return deviceMapper.deleteDeviceByDeviceId(deviceId);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@CacheEvict(value = DeviceCacheConfig.DEVICE_CACHE, allEntries = true)
|
|
||||||
public int deleteDeviceByDeviceIds(Long[] deviceIds)
|
|
||||||
{
|
|
||||||
return deviceMapper.deleteDeviceByDeviceIds(deviceIds);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
package com.ruoyi.device.domain.impl;
|
package com.ruoyi.device.domain.impl;
|
||||||
|
|
||||||
import com.ruoyi.device.domain.api.IDeviceTempDomain;
|
import com.ruoyi.device.domain.api.IDeviceTempDomain;
|
||||||
import com.ruoyi.device.domain.convert.DeviceTempDomainEntityConvert;
|
import com.ruoyi.device.domain.convert.DeviceTempDomainConvert;
|
||||||
import com.ruoyi.device.domain.model.DeviceTemp;
|
import com.ruoyi.device.domain.model.DeviceTemp;
|
||||||
import com.ruoyi.device.mapper.DeviceTempMapper;
|
import com.ruoyi.device.mapper.DeviceTempMapper;
|
||||||
import com.ruoyi.device.mapper.entity.DeviceTempEntity;
|
import com.ruoyi.device.mapper.entity.DeviceTempEntity;
|
||||||
|
|
@ -25,15 +25,15 @@ public class DeviceTempDomainImpl implements IDeviceTempDomain
|
||||||
@Override
|
@Override
|
||||||
public List<DeviceTemp> selectDeviceTempList(DeviceTemp deviceTempModel)
|
public List<DeviceTemp> selectDeviceTempList(DeviceTemp deviceTempModel)
|
||||||
{
|
{
|
||||||
DeviceTempEntity entity = DeviceTempDomainEntityConvert.toEntity(deviceTempModel);
|
DeviceTempEntity entity = DeviceTempDomainConvert.toEntity(deviceTempModel);
|
||||||
List<DeviceTempEntity> entityList = deviceTempMapper.selectDeviceTempList(entity);
|
List<DeviceTempEntity> entityList = deviceTempMapper.selectDeviceTempList(entity);
|
||||||
return DeviceTempDomainEntityConvert.toModelList(entityList);
|
return DeviceTempDomainConvert.toModelList(entityList);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DeviceTemp selectDeviceTempById(String id)
|
public DeviceTemp selectDeviceTempById(String id)
|
||||||
{
|
{
|
||||||
DeviceTempEntity entity = deviceTempMapper.selectDeviceTempById(id);
|
DeviceTempEntity entity = deviceTempMapper.selectDeviceTempById(id);
|
||||||
return DeviceTempDomainEntityConvert.toModel(entity);
|
return DeviceTempDomainConvert.toModel(entity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,100 +0,0 @@
|
||||||
package com.ruoyi.device.domain.impl;
|
|
||||||
|
|
||||||
import com.ruoyi.device.config.DeviceCacheConfig;
|
|
||||||
import com.ruoyi.device.domain.api.IDockAircraftDomain;
|
|
||||||
import com.ruoyi.device.domain.convert.DockAircraftConvert;
|
|
||||||
import com.ruoyi.device.domain.model.DockAircraft;
|
|
||||||
import com.ruoyi.device.mapper.DockAircraftMapper;
|
|
||||||
import com.ruoyi.device.mapper.entity.DockAircraftEntity;
|
|
||||||
import org.springframework.cache.annotation.CacheEvict;
|
|
||||||
import org.springframework.cache.annotation.Cacheable;
|
|
||||||
import org.springframework.cache.annotation.Caching;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 机场无人机关联Domain实现
|
|
||||||
*
|
|
||||||
* @author ruoyi
|
|
||||||
* @date 2026-01-16
|
|
||||||
*/
|
|
||||||
@Component
|
|
||||||
public class DockAircraftDomainImpl implements IDockAircraftDomain
|
|
||||||
{
|
|
||||||
private final DockAircraftMapper dockAircraftMapper;
|
|
||||||
|
|
||||||
public DockAircraftDomainImpl(DockAircraftMapper dockAircraftMapper)
|
|
||||||
{
|
|
||||||
this.dockAircraftMapper = dockAircraftMapper;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<DockAircraft> selectDockAircraftList(DockAircraft dockAircraft)
|
|
||||||
{
|
|
||||||
DockAircraftEntity entity = DockAircraftConvert.to(dockAircraft);
|
|
||||||
List<DockAircraftEntity> entityList = dockAircraftMapper.selectDockAircraftList(entity);
|
|
||||||
return DockAircraftConvert.fromList(entityList);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Cacheable(value = DeviceCacheConfig.DOCK_AIRCRAFT_CACHE, key = "'id:' + #id", unless = "#result == null")
|
|
||||||
public DockAircraft selectDockAircraftById(Long id)
|
|
||||||
{
|
|
||||||
DockAircraftEntity entity = dockAircraftMapper.selectDockAircraftById(id);
|
|
||||||
return DockAircraftConvert.from(entity);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Cacheable(value = DeviceCacheConfig.DOCK_AIRCRAFT_CACHE, key = "'dockId:' + #dockId", unless = "#result == null")
|
|
||||||
public List<DockAircraft> selectDockAircraftByDockId(Long dockId)
|
|
||||||
{
|
|
||||||
List<DockAircraftEntity> entityList = dockAircraftMapper.selectDockAircraftListByDockId(dockId);
|
|
||||||
return DockAircraftConvert.fromList(entityList);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Cacheable(value = DeviceCacheConfig.DOCK_AIRCRAFT_CACHE, key = "'aircraftId:' + #aircraftId", unless = "#result == null")
|
|
||||||
public List<DockAircraft> selectDockAircraftByAircraftId(Long aircraftId)
|
|
||||||
{
|
|
||||||
List<DockAircraftEntity> entityList = dockAircraftMapper.selectDockAircraftListByAircraftId(aircraftId);
|
|
||||||
return DockAircraftConvert.fromList(entityList);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@CacheEvict(value = DeviceCacheConfig.DOCK_AIRCRAFT_CACHE, allEntries = true)
|
|
||||||
public int insertDockAircraft(DockAircraft dockAircraft)
|
|
||||||
{
|
|
||||||
DockAircraftEntity entity = DockAircraftConvert.to(dockAircraft);
|
|
||||||
int result = dockAircraftMapper.insertDockAircraft(entity);
|
|
||||||
// MyBatis 会将自增主键回填到 entity 对象,需要同步回 dockAircraft 对象
|
|
||||||
dockAircraft.setId(entity.getId());
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Caching(evict = {
|
|
||||||
@CacheEvict(value = DeviceCacheConfig.DOCK_AIRCRAFT_CACHE, key = "'id:' + #dockAircraft.id"),
|
|
||||||
@CacheEvict(value = DeviceCacheConfig.DOCK_AIRCRAFT_CACHE, key = "'dockId:' + #dockAircraft.dockId"),
|
|
||||||
@CacheEvict(value = DeviceCacheConfig.DOCK_AIRCRAFT_CACHE, key = "'aircraftId:' + #dockAircraft.aircraftId")
|
|
||||||
})
|
|
||||||
public int updateDockAircraft(DockAircraft dockAircraft)
|
|
||||||
{
|
|
||||||
DockAircraftEntity entity = DockAircraftConvert.to(dockAircraft);
|
|
||||||
return dockAircraftMapper.updateDockAircraft(entity);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@CacheEvict(value = DeviceCacheConfig.DOCK_AIRCRAFT_CACHE, allEntries = true)
|
|
||||||
public int deleteDockAircraftById(Long id)
|
|
||||||
{
|
|
||||||
return dockAircraftMapper.deleteDockAircraftById(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@CacheEvict(value = DeviceCacheConfig.DOCK_AIRCRAFT_CACHE, allEntries = true)
|
|
||||||
public int deleteDockAircraftByIds(Long[] ids)
|
|
||||||
{
|
|
||||||
return dockAircraftMapper.deleteDockAircraftByIds(ids);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,91 +0,0 @@
|
||||||
package com.ruoyi.device.domain.impl;
|
|
||||||
|
|
||||||
import com.ruoyi.device.config.DeviceCacheConfig;
|
|
||||||
import com.ruoyi.device.domain.api.IDockDomain;
|
|
||||||
import com.ruoyi.device.domain.convert.DockConvert;
|
|
||||||
import com.ruoyi.device.domain.model.Dock;
|
|
||||||
import com.ruoyi.device.mapper.DockMapper;
|
|
||||||
import com.ruoyi.device.mapper.entity.DockEntity;
|
|
||||||
import org.springframework.cache.annotation.CacheEvict;
|
|
||||||
import org.springframework.cache.annotation.Cacheable;
|
|
||||||
import org.springframework.cache.annotation.Caching;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 机场Domain实现
|
|
||||||
*
|
|
||||||
* @author ruoyi
|
|
||||||
* @date 2026-01-16
|
|
||||||
*/
|
|
||||||
@Component
|
|
||||||
public class DockDomainImpl implements IDockDomain
|
|
||||||
{
|
|
||||||
private final DockMapper dockMapper;
|
|
||||||
|
|
||||||
public DockDomainImpl(DockMapper dockMapper)
|
|
||||||
{
|
|
||||||
this.dockMapper = dockMapper;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<Dock> selectDockList(Dock dock)
|
|
||||||
{
|
|
||||||
DockEntity entity = DockConvert.to(dock);
|
|
||||||
List<DockEntity> entityList = dockMapper.selectDockList(entity);
|
|
||||||
return DockConvert.fromList(entityList);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Cacheable(value = DeviceCacheConfig.DOCK_CACHE, key = "'id:' + #dockId", unless = "#result == null")
|
|
||||||
public Dock selectDockByDockId(Long dockId)
|
|
||||||
{
|
|
||||||
DockEntity entity = dockMapper.selectDockByDockId(dockId);
|
|
||||||
return DockConvert.from(entity);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Cacheable(value = DeviceCacheConfig.DOCK_CACHE, key = "'deviceId:' + #deviceId", unless = "#result == null")
|
|
||||||
public Dock selectDockByDeviceId(Long deviceId)
|
|
||||||
{
|
|
||||||
DockEntity entity = dockMapper.selectDockByDeviceId(deviceId);
|
|
||||||
return DockConvert.from(entity);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@CacheEvict(value = DeviceCacheConfig.DOCK_CACHE, allEntries = true)
|
|
||||||
public int insertDock(Dock dock)
|
|
||||||
{
|
|
||||||
DockEntity entity = DockConvert.to(dock);
|
|
||||||
int result = dockMapper.insertDock(entity);
|
|
||||||
// MyBatis 会将自增主键回填到 entity 对象,需要同步回 dock 对象
|
|
||||||
dock.setDockId(entity.getDockId());
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Caching(evict = {
|
|
||||||
@CacheEvict(value = DeviceCacheConfig.DOCK_CACHE, key = "'id:' + #dock.dockId"),
|
|
||||||
@CacheEvict(value = DeviceCacheConfig.DOCK_CACHE, key = "'deviceId:' + #dock.deviceId")
|
|
||||||
})
|
|
||||||
public int updateDock(Dock dock)
|
|
||||||
{
|
|
||||||
DockEntity entity = DockConvert.to(dock);
|
|
||||||
return dockMapper.updateDock(entity);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@CacheEvict(value = DeviceCacheConfig.DOCK_CACHE, allEntries = true)
|
|
||||||
public int deleteDockByDockId(Long dockId)
|
|
||||||
{
|
|
||||||
return dockMapper.deleteDockByDockId(dockId);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@CacheEvict(value = DeviceCacheConfig.DOCK_CACHE, allEntries = true)
|
|
||||||
public int deleteDockByDockIds(Long[] dockIds)
|
|
||||||
{
|
|
||||||
return dockMapper.deleteDockByDockIds(dockIds);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,85 +0,0 @@
|
||||||
package com.ruoyi.device.domain.impl;
|
|
||||||
|
|
||||||
import com.ruoyi.device.domain.api.IDockGroupDomain;
|
|
||||||
import com.ruoyi.device.domain.convert.DockGroupConvert;
|
|
||||||
import com.ruoyi.device.domain.model.DockGroup;
|
|
||||||
import com.ruoyi.device.mapper.DockGroupMapper;
|
|
||||||
import com.ruoyi.device.mapper.entity.DockGroupEntity;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 机场分组关联Domain实现
|
|
||||||
*
|
|
||||||
* @author ruoyi
|
|
||||||
* @date 2026-01-16
|
|
||||||
*/
|
|
||||||
@Component
|
|
||||||
public class DockGroupDomainImpl implements IDockGroupDomain
|
|
||||||
{
|
|
||||||
private final DockGroupMapper dockGroupMapper;
|
|
||||||
|
|
||||||
public DockGroupDomainImpl(DockGroupMapper dockGroupMapper)
|
|
||||||
{
|
|
||||||
this.dockGroupMapper = dockGroupMapper;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<DockGroup> selectDockGroupList(DockGroup dockGroup)
|
|
||||||
{
|
|
||||||
DockGroupEntity entity = DockGroupConvert.to(dockGroup);
|
|
||||||
List<DockGroupEntity> entityList = dockGroupMapper.selectDockGroupList(entity);
|
|
||||||
return DockGroupConvert.fromList(entityList);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public DockGroup selectDockGroupById(Long id)
|
|
||||||
{
|
|
||||||
DockGroupEntity entity = dockGroupMapper.selectDockGroupById(id);
|
|
||||||
return DockGroupConvert.from(entity);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<DockGroup> selectDockGroupByDockId(Long dockId)
|
|
||||||
{
|
|
||||||
List<DockGroupEntity> entityList = dockGroupMapper.selectDockGroupListByDockId(dockId);
|
|
||||||
return DockGroupConvert.fromList(entityList);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<DockGroup> selectDockGroupByGroupId(Long groupId)
|
|
||||||
{
|
|
||||||
List<DockGroupEntity> entityList = dockGroupMapper.selectDockGroupListByGroupId(groupId);
|
|
||||||
return DockGroupConvert.fromList(entityList);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int insertDockGroup(DockGroup dockGroup)
|
|
||||||
{
|
|
||||||
DockGroupEntity entity = DockGroupConvert.to(dockGroup);
|
|
||||||
int result = dockGroupMapper.insertDockGroup(entity);
|
|
||||||
// MyBatis 会将自增主键回填到 entity 对象,需要同步回 dockGroup 对象
|
|
||||||
dockGroup.setId(entity.getId());
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int updateDockGroup(DockGroup dockGroup)
|
|
||||||
{
|
|
||||||
DockGroupEntity entity = DockGroupConvert.to(dockGroup);
|
|
||||||
return dockGroupMapper.updateDockGroup(entity);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int deleteDockGroupById(Long id)
|
|
||||||
{
|
|
||||||
return dockGroupMapper.deleteDockGroupById(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int deleteDockGroupByIds(Long[] ids)
|
|
||||||
{
|
|
||||||
return dockGroupMapper.deleteDockGroupByIds(ids);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,78 +0,0 @@
|
||||||
package com.ruoyi.device.domain.impl;
|
|
||||||
|
|
||||||
import com.ruoyi.device.domain.api.IGroupDomain;
|
|
||||||
import com.ruoyi.device.domain.convert.GroupConvert;
|
|
||||||
import com.ruoyi.device.domain.model.Group;
|
|
||||||
import com.ruoyi.device.mapper.GroupMapper;
|
|
||||||
import com.ruoyi.device.mapper.entity.GroupEntity;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 分组Domain实现
|
|
||||||
*
|
|
||||||
* @author ruoyi
|
|
||||||
* @date 2026-01-16
|
|
||||||
*/
|
|
||||||
@Component
|
|
||||||
public class GroupDomainImpl implements IGroupDomain
|
|
||||||
{
|
|
||||||
private final GroupMapper groupMapper;
|
|
||||||
|
|
||||||
public GroupDomainImpl(GroupMapper groupMapper)
|
|
||||||
{
|
|
||||||
this.groupMapper = groupMapper;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<Group> selectGroupList(Group group)
|
|
||||||
{
|
|
||||||
GroupEntity entity = GroupConvert.to(group);
|
|
||||||
List<GroupEntity> entityList = groupMapper.selectGroupList(entity);
|
|
||||||
return GroupConvert.fromList(entityList);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Group selectGroupByGroupId(Long groupId)
|
|
||||||
{
|
|
||||||
GroupEntity entity = groupMapper.selectGroupByGroupId(groupId);
|
|
||||||
return GroupConvert.from(entity);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int insertGroup(Group group)
|
|
||||||
{
|
|
||||||
GroupEntity entity = GroupConvert.to(group);
|
|
||||||
int result = groupMapper.insertGroup(entity);
|
|
||||||
// MyBatis 会将自增主键回填到 entity 对象,需要同步回 group 对象
|
|
||||||
group.setGroupId(entity.getGroupId());
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int updateGroup(Group group)
|
|
||||||
{
|
|
||||||
GroupEntity entity = GroupConvert.to(group);
|
|
||||||
return groupMapper.updateGroup(entity);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int deleteGroupByGroupId(Long groupId)
|
|
||||||
{
|
|
||||||
return groupMapper.deleteGroupByGroupId(groupId);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int deleteGroupByGroupIds(Long[] groupIds)
|
|
||||||
{
|
|
||||||
return groupMapper.deleteGroupByGroupIds(groupIds);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Group selectGroupByGroupName(String groupName)
|
|
||||||
{
|
|
||||||
GroupEntity entity = groupMapper.selectGroupByGroupName(groupName);
|
|
||||||
return GroupConvert.from(entity);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,79 +0,0 @@
|
||||||
package com.ruoyi.device.domain.impl;
|
|
||||||
|
|
||||||
import com.ruoyi.device.config.DeviceCacheConfig;
|
|
||||||
import com.ruoyi.device.domain.api.IPayloadDomain;
|
|
||||||
import com.ruoyi.device.domain.convert.PayloadConvert;
|
|
||||||
import com.ruoyi.device.domain.model.Payload;
|
|
||||||
import com.ruoyi.device.mapper.PayloadMapper;
|
|
||||||
import com.ruoyi.device.mapper.entity.PayloadEntity;
|
|
||||||
import org.springframework.cache.annotation.CacheEvict;
|
|
||||||
import org.springframework.cache.annotation.Cacheable;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 挂载Domain实现
|
|
||||||
*
|
|
||||||
* @author ruoyi
|
|
||||||
* @date 2026-01-16
|
|
||||||
*/
|
|
||||||
@Component
|
|
||||||
public class PayloadDomainImpl implements IPayloadDomain
|
|
||||||
{
|
|
||||||
private final PayloadMapper payloadMapper;
|
|
||||||
|
|
||||||
public PayloadDomainImpl(PayloadMapper payloadMapper)
|
|
||||||
{
|
|
||||||
this.payloadMapper = payloadMapper;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<Payload> selectPayloadList(Payload payload)
|
|
||||||
{
|
|
||||||
PayloadEntity entity = PayloadConvert.to(payload);
|
|
||||||
List<PayloadEntity> entityList = payloadMapper.selectPayloadList(entity);
|
|
||||||
return PayloadConvert.fromList(entityList);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Cacheable(value = DeviceCacheConfig.PAYLOAD_CACHE, key = "'id:' + #payloadId", unless = "#result == null")
|
|
||||||
public Payload selectPayloadByPayloadId(Long payloadId)
|
|
||||||
{
|
|
||||||
PayloadEntity entity = payloadMapper.selectPayloadByPayloadId(payloadId);
|
|
||||||
return PayloadConvert.from(entity);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@CacheEvict(value = DeviceCacheConfig.PAYLOAD_CACHE, allEntries = true)
|
|
||||||
public int insertPayload(Payload payload)
|
|
||||||
{
|
|
||||||
PayloadEntity entity = PayloadConvert.to(payload);
|
|
||||||
int result = payloadMapper.insertPayload(entity);
|
|
||||||
// MyBatis 会将自增主键回填到 entity 对象,需要同步回 payload 对象
|
|
||||||
payload.setPayloadId(entity.getPayloadId());
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@CacheEvict(value = DeviceCacheConfig.PAYLOAD_CACHE, key = "'id:' + #payload.payloadId")
|
|
||||||
public int updatePayload(Payload payload)
|
|
||||||
{
|
|
||||||
PayloadEntity entity = PayloadConvert.to(payload);
|
|
||||||
return payloadMapper.updatePayload(entity);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@CacheEvict(value = DeviceCacheConfig.PAYLOAD_CACHE, allEntries = true)
|
|
||||||
public int deletePayloadByPayloadId(Long payloadId)
|
|
||||||
{
|
|
||||||
return payloadMapper.deletePayloadByPayloadId(payloadId);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@CacheEvict(value = DeviceCacheConfig.PAYLOAD_CACHE, allEntries = true)
|
|
||||||
public int deletePayloadByPayloadIds(Long[] payloadIds)
|
|
||||||
{
|
|
||||||
return payloadMapper.deletePayloadByPayloadIds(payloadIds);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,509 +0,0 @@
|
||||||
package com.ruoyi.device.domain.impl;
|
|
||||||
|
|
||||||
|
|
||||||
import com.ruoyi.device.config.DeviceCacheConfig;
|
|
||||||
import com.ruoyi.device.domain.api.IThingsBoardDomain;
|
|
||||||
import com.ruoyi.device.domain.model.thingsboard.*;
|
|
||||||
import com.ruoyi.device.domain.model.thingsboard.constants.DeviceAttributes;
|
|
||||||
import com.ruoyi.device.domain.model.thingsboard.constants.DeviceTelemetry;
|
|
||||||
import com.ruoyi.device.domain.model.thingsboard.tuoheng.constants.TuohengDeviceAttributes;
|
|
||||||
import com.ruoyi.device.domain.model.thingsboard.tuoheng.constants.TuohengDeviceTelemetry;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
|
||||||
import org.springframework.cache.annotation.CacheEvict;
|
|
||||||
import org.springframework.cache.annotation.Cacheable;
|
|
||||||
import org.springframework.scheduling.annotation.Scheduled;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
import org.thingsboard.rest.client.RestClient;
|
|
||||||
import org.thingsboard.server.common.data.Device;
|
|
||||||
import org.thingsboard.server.common.data.EntityType;
|
|
||||||
import org.thingsboard.server.common.data.id.DeviceId;
|
|
||||||
import org.thingsboard.server.common.data.id.EntityId;
|
|
||||||
import org.thingsboard.server.common.data.kv.AttributeKvEntry;
|
|
||||||
import org.thingsboard.server.common.data.kv.TsKvEntry;
|
|
||||||
import org.thingsboard.server.common.data.relation.EntityRelation;
|
|
||||||
import org.thingsboard.server.common.data.relation.EntityRelationInfo;
|
|
||||||
import org.thingsboard.server.common.data.relation.EntityRelationsQuery;
|
|
||||||
import org.thingsboard.server.common.data.relation.EntitySearchDirection;
|
|
||||||
import org.thingsboard.server.common.data.relation.RelationsSearchParameters;
|
|
||||||
import org.thingsboard.server.common.data.relation.RelationTypeGroup;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ThingsBoard设备服务实现类
|
|
||||||
*/
|
|
||||||
@Component
|
|
||||||
public class ThingsBoardDomainImpl implements IThingsBoardDomain {
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(ThingsBoardDomainImpl.class);
|
|
||||||
|
|
||||||
private final RestClient client;
|
|
||||||
private final int pageSize;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 构造函数 - Spring 会自动装配
|
|
||||||
* @param clientManager RestClient 管理器
|
|
||||||
* @param pageSize 分页大小,从配置文件读取,默认值为 10
|
|
||||||
*/
|
|
||||||
public ThingsBoardDomainImpl(RestClientManager clientManager,
|
|
||||||
@Value("${thingsboard.page-size:10}") int pageSize) {
|
|
||||||
this.client = clientManager.getClient();
|
|
||||||
this.pageSize = pageSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Iterable<List<DeviceInfo>> getAllDevices() {
|
|
||||||
return new DeviceIterator(client, pageSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Iterable<List<DeviceInfo>> getAllGatewayDevices() {
|
|
||||||
return new GatewayDeviceIterator(client, pageSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public DeviceInfo getDeviceInfo(String deviceId) {
|
|
||||||
try {
|
|
||||||
DeviceId id = new DeviceId(UUID.fromString(deviceId));
|
|
||||||
Optional<Device> deviceOptional = client.getDeviceById(id);
|
|
||||||
if (deviceOptional.isEmpty()) {
|
|
||||||
log.warn("设备不存在: deviceId={}", deviceId);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return new DeviceInfo(
|
|
||||||
deviceOptional.get().getName(),
|
|
||||||
deviceOptional.get().getId().getId().toString(),
|
|
||||||
deviceOptional.get().getType(),
|
|
||||||
deviceOptional.get().getId(),
|
|
||||||
deviceOptional.get().getAdditionalInfo()
|
|
||||||
);
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("获取设备信息失败: deviceId={}, error={}", deviceId, e.getMessage(), e);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Cacheable(value = DeviceCacheConfig.THINGSBOARD_ATTRIBUTES_CACHE, key = "#deviceId", unless = "#result == null || #result.isEmpty()")
|
|
||||||
public AttributeMap getDeviceAttributes(String deviceId) {
|
|
||||||
AttributeMap attributeMap = new AttributeMap();
|
|
||||||
|
|
||||||
try {
|
|
||||||
DeviceId deviceIdObj = new DeviceId(UUID.fromString(deviceId));
|
|
||||||
|
|
||||||
List<String> attributeKeys = client.getAttributeKeys(deviceIdObj);
|
|
||||||
if (attributeKeys == null || attributeKeys.isEmpty()) {
|
|
||||||
log.debug("设备 {} 没有属性", deviceId);
|
|
||||||
return attributeMap;
|
|
||||||
}
|
|
||||||
|
|
||||||
List<AttributeKvEntry> attributeKvEntries = client.getAttributeKvEntries(deviceIdObj, attributeKeys);
|
|
||||||
if (attributeKvEntries == null || attributeKvEntries.isEmpty()) {
|
|
||||||
log.debug("设备 {} 的属性值为空", deviceId);
|
|
||||||
return attributeMap;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (AttributeKvEntry entry : attributeKvEntries) {
|
|
||||||
parseAndPutAttribute(attributeMap, entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("获取设备属性失败: deviceId={}, error={}", deviceId, e.getMessage(), e);
|
|
||||||
}
|
|
||||||
|
|
||||||
return attributeMap;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Cacheable(value = DeviceCacheConfig.THINGSBOARD_TELEMETRY_CACHE, key = "#deviceId", unless = "#result == null || #result.isEmpty()")
|
|
||||||
public TelemetryMap getDeviceTelemetry(String deviceId) {
|
|
||||||
TelemetryMap telemetryMap = new TelemetryMap();
|
|
||||||
|
|
||||||
try {
|
|
||||||
DeviceId deviceIdObj = new DeviceId(UUID.fromString(deviceId));
|
|
||||||
|
|
||||||
List<String> timeseriesKeys = client.getTimeseriesKeys(deviceIdObj);
|
|
||||||
if (timeseriesKeys == null || timeseriesKeys.isEmpty()) {
|
|
||||||
log.debug("设备 {} 没有遥测数据", deviceId);
|
|
||||||
return telemetryMap;
|
|
||||||
}
|
|
||||||
|
|
||||||
List<TsKvEntry> latestTimeseries = client.getLatestTimeseries(deviceIdObj, timeseriesKeys);
|
|
||||||
if (latestTimeseries == null || latestTimeseries.isEmpty()) {
|
|
||||||
log.debug("设备 {} 的遥测数据为空", deviceId);
|
|
||||||
return telemetryMap;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (TsKvEntry entry : latestTimeseries) {
|
|
||||||
parseAndPutTelemetry(telemetryMap, entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("获取设备遥测数据失败: deviceId={}, error={}", deviceId, e.getMessage(), e);
|
|
||||||
}
|
|
||||||
|
|
||||||
return telemetryMap;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public AttributeMap getPredefinedDeviceAttributes(String deviceId) {
|
|
||||||
// 先获取所有属性(已经处理了异常情况)
|
|
||||||
AttributeMap allAttributes = getDeviceAttributes(deviceId);
|
|
||||||
|
|
||||||
// 创建新的 AttributeMap 只包含预定义的键
|
|
||||||
AttributeMap predefinedAttributes = new AttributeMap();
|
|
||||||
|
|
||||||
// 获取预定义的键名称集合
|
|
||||||
List<String> predefinedKeyNames = DeviceAttributes.getPredefinedKeys()
|
|
||||||
.stream()
|
|
||||||
.map(AttributeKey::getName)
|
|
||||||
.toList();
|
|
||||||
|
|
||||||
// 过滤:只保留预定义的键
|
|
||||||
for (AttributeKey<?> key : allAttributes.keySet()) {
|
|
||||||
if (predefinedKeyNames.contains(key.getName())) {
|
|
||||||
// 复制到新的 map
|
|
||||||
allAttributes.get(key).ifPresent(value -> {
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
AttributeKey<Object> objKey = (AttributeKey<Object>) key;
|
|
||||||
predefinedAttributes.put(objKey, value);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return predefinedAttributes;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public TelemetryMap getPredefinedDeviceTelemetry(String deviceId) {
|
|
||||||
// 先获取所有遥测数据(已经处理了 null 值问题)
|
|
||||||
TelemetryMap allTelemetry = getDeviceTelemetry(deviceId);
|
|
||||||
|
|
||||||
// 创建新的 TelemetryMap 只包含预定义的键
|
|
||||||
TelemetryMap predefinedTelemetry = new TelemetryMap();
|
|
||||||
|
|
||||||
// 获取预定义的键名称集合
|
|
||||||
List<String> predefinedKeyNames = DeviceTelemetry.getPredefinedKeys()
|
|
||||||
.stream()
|
|
||||||
.map(TelemetryKey::getName)
|
|
||||||
.toList();
|
|
||||||
|
|
||||||
// 过滤:只保留预定义的键
|
|
||||||
for (TelemetryKey<?> key : allTelemetry.keySet()) {
|
|
||||||
if (predefinedKeyNames.contains(key.getName())) {
|
|
||||||
// 复制到新的 map
|
|
||||||
allTelemetry.get(key).ifPresent(telemetryValue -> {
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
TelemetryKey<Object> objKey = (TelemetryKey<Object>) key;
|
|
||||||
predefinedTelemetry.put(objKey, telemetryValue.getValue(), telemetryValue.getTimestamp());
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return predefinedTelemetry;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Deprecated
|
|
||||||
public String getDeviceGatewayId(String deviceId) {
|
|
||||||
try {
|
|
||||||
DeviceId id = new DeviceId(UUID.fromString(deviceId));
|
|
||||||
|
|
||||||
// 查询指向该设备的 "Contains" 关系(网关 -> 设备)
|
|
||||||
List<EntityRelation> relations = client.findByTo(
|
|
||||||
id,
|
|
||||||
EntityRelation.CONTAINS_TYPE,
|
|
||||||
RelationTypeGroup.COMMON
|
|
||||||
);
|
|
||||||
|
|
||||||
if (relations == null || relations.isEmpty()) {
|
|
||||||
log.debug("设备 {} 不属于任何网关", deviceId);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取第一个关系的 from 实体(网关设备)
|
|
||||||
EntityId gatewayEntityId = relations.get(0).getFrom();
|
|
||||||
String gatewayId = gatewayEntityId.getId().toString();
|
|
||||||
|
|
||||||
log.debug("设备 {} 属于网关 {}", deviceId, gatewayId);
|
|
||||||
return gatewayId;
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("获取设备网关关系失败: deviceId={}, error={}", deviceId, e.getMessage(), e);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<String> getGatewayChildDevices(String gatewayDeviceId) {
|
|
||||||
List<String> childDeviceIds = new ArrayList<>();
|
|
||||||
|
|
||||||
try {
|
|
||||||
|
|
||||||
EntityId gatewayId = new EntityId() {
|
|
||||||
@Override
|
|
||||||
public UUID getId() {
|
|
||||||
return UUID.fromString(gatewayDeviceId);
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public EntityType getEntityType() {
|
|
||||||
return EntityType.DEVICE;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
List<EntityRelationInfo> relationInfos = client.findInfoByFrom(
|
|
||||||
gatewayId,
|
|
||||||
RelationTypeGroup.COMMON
|
|
||||||
);
|
|
||||||
|
|
||||||
if (relationInfos == null || relationInfos.isEmpty()) {
|
|
||||||
log.debug("网关 {} 没有子设备", gatewayDeviceId);
|
|
||||||
return childDeviceIds;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 提取所有子设备的ID
|
|
||||||
for (EntityRelationInfo relationInfo : relationInfos) {
|
|
||||||
EntityId childEntityId = relationInfo.getTo();
|
|
||||||
String childDeviceId = childEntityId.getId().toString();
|
|
||||||
childDeviceIds.add(childDeviceId);
|
|
||||||
}
|
|
||||||
|
|
||||||
log.debug("网关 {} 有 {} 个子设备", gatewayDeviceId, childDeviceIds.size());
|
|
||||||
return childDeviceIds;
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("获取网关子设备失败: gatewayDeviceId={}, error={}", gatewayDeviceId, e.getMessage(), e);
|
|
||||||
return childDeviceIds;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 解析属性并添加到AttributeMap
|
|
||||||
* 使用延迟注册机制,自动处理所有属性
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
private void parseAndPutAttribute(AttributeMap attributeMap, AttributeKvEntry entry) {
|
|
||||||
String keyName = entry.getKey();
|
|
||||||
Object value = entry.getValue();
|
|
||||||
|
|
||||||
try {
|
|
||||||
// 使用延迟注册机制:如果键不存在则自动创建
|
|
||||||
AttributeKey<?> key = AttributeKey.getOrCreate(keyName, value);
|
|
||||||
|
|
||||||
// 使用键的解析器解析值
|
|
||||||
Object parsedValue = ((AttributeKey<Object>) key).parse(value);
|
|
||||||
attributeMap.put((AttributeKey<Object>) key, parsedValue);
|
|
||||||
log.debug("成功解析属性: {} = {} (type: {})", keyName, parsedValue, key.getType().getSimpleName());
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.warn("解析属性失败: key={}, value={}, error={}", keyName, value, e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 解析遥测数据并添加到TelemetryMap
|
|
||||||
* 使用延迟注册机制,自动处理所有遥测数据
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
private void parseAndPutTelemetry(TelemetryMap telemetryMap, TsKvEntry entry) {
|
|
||||||
String keyName = entry.getKey();
|
|
||||||
Object value = entry.getValue();
|
|
||||||
|
|
||||||
try {
|
|
||||||
// 使用延迟注册机制:如果键不存在则自动创建
|
|
||||||
TelemetryKey<?> key = TelemetryKey.getOrCreate(keyName, value);
|
|
||||||
|
|
||||||
// 使用键的解析器解析值
|
|
||||||
Object parsedValue = ((TelemetryKey<Object>) key).parse(value);
|
|
||||||
telemetryMap.put((TelemetryKey<Object>) key, parsedValue, entry.getTs());
|
|
||||||
log.debug("成功解析遥测数据: {} = {} (timestamp: {}, type: {})",
|
|
||||||
keyName, parsedValue, entry.getTs(), key.getType().getSimpleName());
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.warn("解析遥测数据失败: key={}, value={}, error={}", keyName, value, e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@CacheEvict(value = DeviceCacheConfig.THINGSBOARD_ATTRIBUTES_CACHE, key = "#deviceId")
|
|
||||||
public void evictDeviceAttributesCache(String deviceId) {
|
|
||||||
// 空实现,仅用于清除缓存
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@CacheEvict(value = DeviceCacheConfig.THINGSBOARD_TELEMETRY_CACHE, key = "#deviceId")
|
|
||||||
public void evictDeviceTelemetryCache(String deviceId) {
|
|
||||||
// 空实现,仅用于清除缓存
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Cacheable(value = DeviceCacheConfig.THINGSBOARD_ATTRIBUTES_CACHE, key = "#deviceId", unless = "#result == null || #result.isEmpty()")
|
|
||||||
public AttributeMap getTuohengDeviceAttributes(String deviceId) {
|
|
||||||
AttributeMap attributeMap = new AttributeMap();
|
|
||||||
|
|
||||||
try {
|
|
||||||
DeviceId deviceIdObj = new DeviceId(UUID.fromString(deviceId));
|
|
||||||
|
|
||||||
List<String> attributeKeys = client.getAttributeKeys(deviceIdObj);
|
|
||||||
if (attributeKeys == null || attributeKeys.isEmpty()) {
|
|
||||||
log.debug("拓恒设备 {} 没有属性", deviceId);
|
|
||||||
return attributeMap;
|
|
||||||
}
|
|
||||||
|
|
||||||
List<AttributeKvEntry> attributeKvEntries = client.getAttributeKvEntries(deviceIdObj, attributeKeys);
|
|
||||||
if (attributeKvEntries == null || attributeKvEntries.isEmpty()) {
|
|
||||||
log.debug("拓恒设备 {} 的属性值为空", deviceId);
|
|
||||||
return attributeMap;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (AttributeKvEntry entry : attributeKvEntries) {
|
|
||||||
parseAndPutAttribute(attributeMap, entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("获取拓恒设备属性失败: deviceId={}, error={}", deviceId, e.getMessage(), e);
|
|
||||||
}
|
|
||||||
|
|
||||||
return attributeMap;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Cacheable(value = DeviceCacheConfig.THINGSBOARD_TELEMETRY_CACHE, key = "#deviceId", unless = "#result == null || #result.isEmpty()")
|
|
||||||
public TelemetryMap getTuohengDeviceTelemetry(String deviceId) {
|
|
||||||
TelemetryMap telemetryMap = new TelemetryMap();
|
|
||||||
|
|
||||||
try {
|
|
||||||
DeviceId deviceIdObj = new DeviceId(UUID.fromString(deviceId));
|
|
||||||
|
|
||||||
List<String> timeseriesKeys = client.getTimeseriesKeys(deviceIdObj);
|
|
||||||
if (timeseriesKeys == null || timeseriesKeys.isEmpty()) {
|
|
||||||
log.debug("拓恒设备 {} 没有遥测数据", deviceId);
|
|
||||||
return telemetryMap;
|
|
||||||
}
|
|
||||||
|
|
||||||
List<TsKvEntry> latestTimeseries = client.getLatestTimeseries(deviceIdObj, timeseriesKeys);
|
|
||||||
if (latestTimeseries == null || latestTimeseries.isEmpty()) {
|
|
||||||
log.debug("拓恒设备 {} 的遥测数据为空", deviceId);
|
|
||||||
return telemetryMap;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (TsKvEntry entry : latestTimeseries) {
|
|
||||||
parseAndPutTelemetry(telemetryMap, entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("获取拓恒设备遥测数据失败: deviceId={}, error={}", deviceId, e.getMessage(), e);
|
|
||||||
}
|
|
||||||
|
|
||||||
return telemetryMap;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public AttributeMap getPredefinedTuohengDeviceAttributes(String deviceId) {
|
|
||||||
// 先获取所有属性(已经处理了异常情况)
|
|
||||||
AttributeMap allAttributes = getTuohengDeviceAttributes(deviceId);
|
|
||||||
|
|
||||||
// 创建新的 AttributeMap 只包含预定义的键
|
|
||||||
AttributeMap predefinedAttributes = new AttributeMap();
|
|
||||||
|
|
||||||
// 获取预定义的键名称集合
|
|
||||||
List<String> predefinedKeyNames = TuohengDeviceAttributes.getPredefinedKeys()
|
|
||||||
.stream()
|
|
||||||
.map(AttributeKey::getName)
|
|
||||||
.toList();
|
|
||||||
|
|
||||||
// 过滤:只保留预定义的键
|
|
||||||
for (AttributeKey<?> key : allAttributes.keySet()) {
|
|
||||||
if (predefinedKeyNames.contains(key.getName())) {
|
|
||||||
// 复制到新的 map
|
|
||||||
allAttributes.get(key).ifPresent(value -> {
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
AttributeKey<Object> objKey = (AttributeKey<Object>) key;
|
|
||||||
predefinedAttributes.put(objKey, value);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return predefinedAttributes;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public TelemetryMap getPredefinedTuohengDeviceTelemetry(String deviceId) {
|
|
||||||
// 先获取所有遥测数据(已经处理了 null 值问题)
|
|
||||||
TelemetryMap allTelemetry = getTuohengDeviceTelemetry(deviceId);
|
|
||||||
|
|
||||||
// 创建新的 TelemetryMap 只包含预定义的键
|
|
||||||
TelemetryMap predefinedTelemetry = new TelemetryMap();
|
|
||||||
|
|
||||||
// 获取预定义的键名称集合
|
|
||||||
List<String> predefinedKeyNames = TuohengDeviceTelemetry.getPredefinedKeys()
|
|
||||||
.stream()
|
|
||||||
.map(TelemetryKey::getName)
|
|
||||||
.toList();
|
|
||||||
|
|
||||||
// 过滤:只保留预定义的键
|
|
||||||
for (TelemetryKey<?> key : allTelemetry.keySet()) {
|
|
||||||
if (predefinedKeyNames.contains(key.getName())) {
|
|
||||||
// 复制到新的 map
|
|
||||||
allTelemetry.get(key).ifPresent(telemetryValue -> {
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
TelemetryKey<Object> objKey = (TelemetryKey<Object>) key;
|
|
||||||
predefinedTelemetry.put(objKey, telemetryValue.getValue(), telemetryValue.getTimestamp());
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return predefinedTelemetry;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@CacheEvict(value = DeviceCacheConfig.THINGSBOARD_ATTRIBUTES_CACHE,
|
|
||||||
allEntries = false,
|
|
||||||
key = "#deviceId")
|
|
||||||
public boolean setDeviceAttribute(String deviceId, String key, Object value) {
|
|
||||||
try {
|
|
||||||
log.info("设置设备属性: deviceId={}, key={}, value={}", deviceId, key, value);
|
|
||||||
|
|
||||||
// 将 deviceId 字符串转换为 DeviceId 对象
|
|
||||||
DeviceId deviceIdObj = new DeviceId(UUID.fromString(deviceId));
|
|
||||||
|
|
||||||
// 构建 JsonNode 对象
|
|
||||||
com.fasterxml.jackson.databind.ObjectMapper mapper = new com.fasterxml.jackson.databind.ObjectMapper();
|
|
||||||
com.fasterxml.jackson.databind.node.ObjectNode jsonNode = mapper.createObjectNode();
|
|
||||||
|
|
||||||
// 根据值的类型设置到 JsonNode
|
|
||||||
if (value instanceof String) {
|
|
||||||
jsonNode.put(key, (String) value);
|
|
||||||
} else if (value instanceof Integer) {
|
|
||||||
jsonNode.put(key, (Integer) value);
|
|
||||||
} else if (value instanceof Long) {
|
|
||||||
jsonNode.put(key, (Long) value);
|
|
||||||
} else if (value instanceof Double) {
|
|
||||||
jsonNode.put(key, (Double) value);
|
|
||||||
} else if (value instanceof Boolean) {
|
|
||||||
jsonNode.put(key, (Boolean) value);
|
|
||||||
} else {
|
|
||||||
jsonNode.put(key, value.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
// 调用 ThingsBoard REST API 保存属性
|
|
||||||
// saveDeviceAttributes 方法会将属性保存到 SERVER_SCOPE
|
|
||||||
client.saveDeviceAttributes(deviceIdObj, "SERVER_SCOPE", jsonNode);
|
|
||||||
|
|
||||||
log.info("设备属性设置成功: deviceId={}, key={}", deviceId, key);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("设置设备属性失败: deviceId=, key={}, error={}",
|
|
||||||
deviceId, key, e.getMessage(), e);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,209 +0,0 @@
|
||||||
package com.ruoyi.device.domain.impl;
|
|
||||||
|
|
||||||
import com.alibaba.fastjson2.JSON;
|
|
||||||
import com.ruoyi.device.config.DeviceCacheConfig;
|
|
||||||
import com.ruoyi.device.domain.api.IWeatherDomain;
|
|
||||||
import com.ruoyi.device.domain.impl.weather.HttpUtils;
|
|
||||||
import com.ruoyi.device.domain.model.weather.Weather;
|
|
||||||
import com.ruoyi.device.domain.model.weather.WeatherResponse;
|
|
||||||
import com.ruoyi.device.domain.config.WeatherProperties;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.apache.http.HttpResponse;
|
|
||||||
import org.apache.http.util.EntityUtils;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.cache.annotation.Cacheable;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
@Component
|
|
||||||
@Slf4j
|
|
||||||
public class WeatherDomainImpl implements IWeatherDomain {
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private WeatherProperties weatherProperties;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Cacheable(value = DeviceCacheConfig.WEATHER_CACHE, key = "#dockerDeviceIotId", unless = "#result == null")
|
|
||||||
public Weather weatherInfo(String lat, String lon, String dockerDeviceIotId) {
|
|
||||||
log.info("开始获取天气信息 - lat: {}, lon: {}", lat, lon);
|
|
||||||
|
|
||||||
String host = weatherProperties.getHost();
|
|
||||||
String path = weatherProperties.getPath();
|
|
||||||
String method = "POST";
|
|
||||||
Map<String, String> headers = new HashMap<>();
|
|
||||||
headers.put("Authorization", "APPCODE " + weatherProperties.getAppcode());
|
|
||||||
headers.put("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
|
|
||||||
Map<String, String> querys = new HashMap<>();
|
|
||||||
Map<String, String> bodys = new HashMap<>();
|
|
||||||
bodys.put("lat", lat);
|
|
||||||
bodys.put("lon", lon);
|
|
||||||
bodys.put("token", weatherProperties.getToken());
|
|
||||||
|
|
||||||
log.info("天气API配置 - host: {}, path: {}, token: {}", host, path, weatherProperties.getToken());
|
|
||||||
|
|
||||||
Weather weather = new Weather();
|
|
||||||
try {
|
|
||||||
HttpResponse response = HttpUtils.doPost(host, path, method, headers, querys, bodys);
|
|
||||||
String json = EntityUtils.toString(response.getEntity());
|
|
||||||
log.info("天气API原始响应 - json: {}", json);
|
|
||||||
|
|
||||||
WeatherResponse weatherResponse = JSON.parseObject(json, WeatherResponse.class);
|
|
||||||
log.info("天气API解析结果 - weatherResponse: {}, code: {}",
|
|
||||||
weatherResponse != null ? "not null" : "null",
|
|
||||||
weatherResponse != null ? weatherResponse.getCode() : "N/A");
|
|
||||||
|
|
||||||
if (weatherResponse != null && weatherResponse.getCode() == 0) {
|
|
||||||
String windLevel = weatherResponse.getData().getCondition().getWindLevel();
|
|
||||||
weather.setWindSpeed(convertWindLevelToSpeed(windLevel));
|
|
||||||
weather.setEnvironmentTemperature(Double.valueOf(weatherResponse.getData().getCondition().getTemp()));
|
|
||||||
weather.setEnvironmentHumidity(Double.valueOf(weatherResponse.getData().getCondition().getHumidity()));
|
|
||||||
String conditionId = weatherResponse.getData().getCondition().getConditionId();
|
|
||||||
weather.setRainfall(convertConditionIdToRainfall(conditionId));
|
|
||||||
log.info("天气数据解析成功 - windSpeed: {}, temp: {}, humidity: {}, rainfall: {}",
|
|
||||||
weather.getWindSpeed(), weather.getEnvironmentTemperature(),
|
|
||||||
weather.getEnvironmentHumidity(), weather.getRainfall());
|
|
||||||
} else {
|
|
||||||
log.warn("天气API返回异常 - weatherResponse: {}, code: {}",
|
|
||||||
JSON.toJSONString(weatherResponse),
|
|
||||||
weatherResponse != null ? weatherResponse.getCode() : "null");
|
|
||||||
}
|
|
||||||
log.info("lat {} log {} weather {}", lat, lon, JSON.toJSONString(weather));
|
|
||||||
return weather;
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("获取天气信息异常 - lat: {}, lon: {}", lat, lon, e);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 根据天气状况ID转换为降雨量等级
|
|
||||||
* @param conditionId 天气状况ID
|
|
||||||
* @return 降雨量等级:0-无雨,1-小雨/小雪,2-中雨/中雪,3-大雨/大雪
|
|
||||||
*/
|
|
||||||
private static Double convertConditionIdToRainfall(String conditionId) {
|
|
||||||
if (conditionId == null || conditionId.isEmpty()) {
|
|
||||||
return 0.0; // 默认无雨
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
int id = Integer.parseInt(conditionId);
|
|
||||||
|
|
||||||
// 小雨相关:阵雨、小阵雨、局部阵雨、小雨、小雨夹雪、小到中雨
|
|
||||||
if (id == 15 || id == 16 || id == 17 || id == 18 || id == 19 ||
|
|
||||||
id == 20 || id == 21 || id == 22 ||
|
|
||||||
id == 51 || id == 52 || id == 66 ||
|
|
||||||
id == 86 || id == 91) {
|
|
||||||
return 1.0; // 小雨
|
|
||||||
}
|
|
||||||
|
|
||||||
// 小雪相关:阵雪、小阵雪、小雪、小到中雪
|
|
||||||
if (id == 24 || id == 25 ||
|
|
||||||
id == 58 || id == 59 || id == 71 || id == 72 || id == 73 ||
|
|
||||||
id == 94) {
|
|
||||||
return 1.0; // 小雪
|
|
||||||
}
|
|
||||||
|
|
||||||
// 中雨相关:中雨、中到大雨
|
|
||||||
if (id == 53 || id == 67 || id == 92) {
|
|
||||||
return 2.0; // 中雨
|
|
||||||
}
|
|
||||||
|
|
||||||
// 中雪相关:中雪
|
|
||||||
if (id == 60 || id == 61) {
|
|
||||||
return 2.0; // 中雪
|
|
||||||
}
|
|
||||||
|
|
||||||
// 大雨相关:强阵雨、大雨、暴雨、大暴雨、特大暴雨、大到暴雨
|
|
||||||
if (id == 23 || id == 54 || id == 55 || id == 56 || id == 57 ||
|
|
||||||
id == 68 || id == 69 || id == 70 || id == 93) {
|
|
||||||
return 3.0; // 大雨
|
|
||||||
}
|
|
||||||
|
|
||||||
// 大雪相关:大雪、暴雪
|
|
||||||
if (id == 62 || id == 63 || id == 74 || id == 75 || id == 76) {
|
|
||||||
return 3.0; // 大雪
|
|
||||||
}
|
|
||||||
|
|
||||||
// 雷雨相关:雷阵雨、雷电、雷暴、雷阵雨伴有冰雹
|
|
||||||
if (id == 37 || id == 38 || id == 39 || id == 40 || id == 41 ||
|
|
||||||
id == 42 || id == 43 || id == 44 || id == 45 ||
|
|
||||||
id == 87 || id == 88 || id == 89 || id == 90 || id == 599) {
|
|
||||||
return 1.0; // 雷阵雨按小雨处理
|
|
||||||
}
|
|
||||||
|
|
||||||
// 雨夹雪、冻雨
|
|
||||||
if (id == 49 || id == 50 || id == 64 || id == 65) {
|
|
||||||
return 1.0; // 雨夹雪按小雨处理
|
|
||||||
}
|
|
||||||
|
|
||||||
// 冰雹、冰针、冰粒
|
|
||||||
if (id == 46 || id == 47 || id == 48) {
|
|
||||||
return 1.0; // 冰雹按小雨处理
|
|
||||||
}
|
|
||||||
|
|
||||||
// 雨(通用)、雪(通用)
|
|
||||||
if (id == 78 || id == 77) {
|
|
||||||
return 1.0; // 通用雨/雪按小雨处理
|
|
||||||
}
|
|
||||||
|
|
||||||
// 其他情况(晴天、多云、阴天、雾、霾、沙尘等)
|
|
||||||
return 0.0; // 无雨
|
|
||||||
|
|
||||||
} catch (NumberFormatException e) {
|
|
||||||
return 0.0; // 解析失败,默认无雨
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 根据风力等级转换为风速中间值(单位:m/s)
|
|
||||||
* @param windLevel 风力等级
|
|
||||||
* @return 风速中间值
|
|
||||||
*/
|
|
||||||
private static Double convertWindLevelToSpeed(String windLevel) {
|
|
||||||
if (windLevel == null || windLevel.isEmpty()) {
|
|
||||||
return 0.1; // 默认无风的中间值
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
int level = Integer.parseInt(windLevel);
|
|
||||||
|
|
||||||
switch (level) {
|
|
||||||
case 0: // 0-0.2 m/s
|
|
||||||
return 0.1;
|
|
||||||
case 1: // 0.3-1.5 m/s
|
|
||||||
return 0.9;
|
|
||||||
case 2: // 1.6-3.3 m/s
|
|
||||||
return 2.45;
|
|
||||||
case 3: // 3.4-5.4 m/s
|
|
||||||
return 4.4;
|
|
||||||
case 4: // 5.5-7.9 m/s
|
|
||||||
return 6.7;
|
|
||||||
case 5: // 8-10.7 m/s
|
|
||||||
return 9.35;
|
|
||||||
case 6: // 10.8-13.8 m/s
|
|
||||||
return 12.3;
|
|
||||||
case 7: // 13.9-17.1 m/s
|
|
||||||
return 15.5;
|
|
||||||
case 8: // 17.2-20.7 m/s
|
|
||||||
return 18.95;
|
|
||||||
case 9: // 20.8-24.4 m/s
|
|
||||||
return 22.6;
|
|
||||||
case 10: // 24.5-28.4 m/s
|
|
||||||
return 26.45;
|
|
||||||
case 11: // 28.5-32.6 m/s
|
|
||||||
return 30.55;
|
|
||||||
case 12: // 32.6-999.9 m/s (飓风)
|
|
||||||
return 516.25; // (32.6 + 999.9) / 2
|
|
||||||
default:
|
|
||||||
return 0.1; // 未知等级,默认无风
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (NumberFormatException e) {
|
|
||||||
return 0.1; // 解析失败,默认无风
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,211 +0,0 @@
|
||||||
# DJI MQTT 模块使用说明(支持多客户端)
|
|
||||||
|
|
||||||
## 概述
|
|
||||||
|
|
||||||
本模块实现了大疆MQTT消息的接收和处理功能,支持动态创建多个MQTT客户端,每个客户端可以连接到不同的服务器。
|
|
||||||
|
|
||||||
## 设备分类
|
|
||||||
|
|
||||||
| SN 前缀 | 设备类型 |
|
|
||||||
|---------|---------|
|
|
||||||
| `7C` 开头 | 大疆设备 |
|
|
||||||
| `158` 开头 | 大疆设备 |
|
|
||||||
|
|
||||||
**注意:本模块只处理大疆设备(7C、158开头),会自动过滤拓恒设备(TH开头,包括THJS)。**
|
|
||||||
|
|
||||||
## 核心特性
|
|
||||||
|
|
||||||
✅ **多客户端支持** - 可以同时创建多个MQTT客户端
|
|
||||||
✅ **动态配置** - 每个客户端可以独立配置IP、端口、用户名等
|
|
||||||
✅ **独立消息处理** - 每个客户端有独立的消息处理器
|
|
||||||
✅ **共享订阅可选** - 支持开启/关闭共享订阅
|
|
||||||
✅ **完整数据模型** - 包含所有无人机和机场字段
|
|
||||||
✅ **自动区分设备** - 自动识别无人机和机场数据
|
|
||||||
|
|
||||||
## 架构设计
|
|
||||||
|
|
||||||
```
|
|
||||||
DjiMqttClientManager (管理器)
|
|
||||||
↓
|
|
||||||
DjiMqttClientService (客户端实例)
|
|
||||||
↓
|
|
||||||
DjiMqttMessageHandler (消息处理器)
|
|
||||||
↓
|
|
||||||
IDroneDataCallback / IDockDataCallback (回调接口)
|
|
||||||
```
|
|
||||||
|
|
||||||
## 快速开始
|
|
||||||
|
|
||||||
### 1. 注入管理器
|
|
||||||
|
|
||||||
```java
|
|
||||||
@Autowired
|
|
||||||
private DjiMqttClientManager clientManager;
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. 创建客户端
|
|
||||||
|
|
||||||
```java
|
|
||||||
// 构建配置
|
|
||||||
DjiMqttClientConfig config = DjiMqttClientConfig.builder()
|
|
||||||
.host("mqtt.t-aaron.com") // MQTT服务器地址
|
|
||||||
.port(10883) // 端口
|
|
||||||
.clientId("my_client_1") // 客户端ID(必须唯一)
|
|
||||||
.username("admin") // 用户名
|
|
||||||
.password("admin") // 密码
|
|
||||||
.useSharedSubscription(true) // 是否使用共享订阅
|
|
||||||
.sharedGroupName("dji-group") // 共享订阅组名
|
|
||||||
.build();
|
|
||||||
|
|
||||||
// 创建并连接客户端
|
|
||||||
String clientId = clientManager.createClient(config);
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. 注册回调
|
|
||||||
|
|
||||||
```java
|
|
||||||
// 获取消息处理器
|
|
||||||
DjiMqttMessageHandler handler = clientManager.getHandler(clientId);
|
|
||||||
|
|
||||||
// 注册无人机数据回调
|
|
||||||
handler.registerDroneDataCallback(droneData -> {
|
|
||||||
System.out.println("无人机SN: " + droneData.getDeviceSn());
|
|
||||||
System.out.println("位置: " + droneData.getLatitude() + ", " + droneData.getLongitude());
|
|
||||||
});
|
|
||||||
|
|
||||||
// 注册机场数据回调
|
|
||||||
handler.registerDockDataCallback(dockData -> {
|
|
||||||
System.out.println("机场SN: " + dockData.getDeviceSn());
|
|
||||||
System.out.println("温度: " + dockData.getTemperature());
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
## 多客户端示例
|
|
||||||
|
|
||||||
### 场景:同时连接多个MQTT服务器
|
|
||||||
|
|
||||||
```java
|
|
||||||
@Component
|
|
||||||
public class MyMqttService {
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private DjiMqttClientManager clientManager;
|
|
||||||
|
|
||||||
public void init() {
|
|
||||||
// 客户端1:连接到服务器A
|
|
||||||
DjiMqttClientConfig config1 = DjiMqttClientConfig.builder()
|
|
||||||
.host("mqtt.server-a.com")
|
|
||||||
.port(10883)
|
|
||||||
.clientId("client_a")
|
|
||||||
.username("admin")
|
|
||||||
.password("admin")
|
|
||||||
.useSharedSubscription(true)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
String clientId1 = clientManager.createClient(config1);
|
|
||||||
DjiMqttMessageHandler handler1 = clientManager.getHandler(clientId1);
|
|
||||||
handler1.registerDroneDataCallback(data -> processServerA(data));
|
|
||||||
|
|
||||||
// 客户端2:连接到服务器B
|
|
||||||
DjiMqttClientConfig config2 = DjiMqttClientConfig.builder()
|
|
||||||
.host("mqtt.server-b.com")
|
|
||||||
.port(1883)
|
|
||||||
.clientId("client_b")
|
|
||||||
.username("user2")
|
|
||||||
.password("pass2")
|
|
||||||
.useSharedSubscription(false)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
String clientId2 = clientManager.createClient(config2);
|
|
||||||
DjiMqttMessageHandler handler2 = clientManager.getHandler(clientId2);
|
|
||||||
handler2.registerDroneDataCallback(data -> processServerB(data));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## 管理器API
|
|
||||||
|
|
||||||
### 创建客户端
|
|
||||||
```java
|
|
||||||
String clientId = clientManager.createClient(config);
|
|
||||||
```
|
|
||||||
|
|
||||||
### 获取消息处理器
|
|
||||||
```java
|
|
||||||
DjiMqttMessageHandler handler = clientManager.getHandler(clientId);
|
|
||||||
```
|
|
||||||
|
|
||||||
### 获取客户端
|
|
||||||
```java
|
|
||||||
DjiMqttClientService client = clientManager.getClient(clientId);
|
|
||||||
boolean isConnected = client.isConnected();
|
|
||||||
```
|
|
||||||
|
|
||||||
### 移除客户端
|
|
||||||
```java
|
|
||||||
clientManager.removeClient(clientId);
|
|
||||||
```
|
|
||||||
|
|
||||||
### 断开所有客户端
|
|
||||||
```java
|
|
||||||
clientManager.disconnectAll();
|
|
||||||
```
|
|
||||||
|
|
||||||
### 获取所有客户端ID
|
|
||||||
```java
|
|
||||||
Set<String> clientIds = clientManager.getAllClientIds();
|
|
||||||
```
|
|
||||||
|
|
||||||
## 配置参数说明
|
|
||||||
|
|
||||||
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|
|
||||||
|------|------|------|--------|------|
|
|
||||||
| host | String | 是 | - | MQTT服务器地址 |
|
|
||||||
| port | Integer | 是 | - | MQTT服务器端口 |
|
|
||||||
| clientId | String | 是 | - | 客户端ID(必须唯一) |
|
|
||||||
| username | String | 是 | - | 用户名 |
|
|
||||||
| password | String | 是 | - | 密码 |
|
|
||||||
| connectionTimeout | Integer | 否 | 30 | 连接超时时间(秒) |
|
|
||||||
| keepAliveInterval | Integer | 否 | 60 | 保持连接时间(秒) |
|
|
||||||
| autoReconnect | Boolean | 否 | true | 自动重连 |
|
|
||||||
| cleanSession | Boolean | 否 | false | 清除会话 |
|
|
||||||
| useSharedSubscription | Boolean | 否 | true | 是否使用共享订阅 |
|
|
||||||
| sharedGroupName | String | 否 | dji-group | 共享订阅组名 |
|
|
||||||
|
|
||||||
## 数据模型
|
|
||||||
|
|
||||||
### DroneData(无人机数据)
|
|
||||||
|
|
||||||
包含100+字段,主要分类:
|
|
||||||
- **基础信息**:固件版本、飞行器状态、档位等
|
|
||||||
- **位置信息**:经纬度、高度、Home点等
|
|
||||||
- **姿态信息**:偏航角、横滚角、俯仰角
|
|
||||||
- **速度信息**:水平速度、垂直速度、风速
|
|
||||||
- **电池信息**:电量、剩余飞行时间、电池详情
|
|
||||||
- **相机信息**:拍照录像状态、变焦、红外测温等
|
|
||||||
- **避障信息**:水平/上视/下视避障状态
|
|
||||||
- **保养信息**:保养状态、累计飞行时间/架次
|
|
||||||
|
|
||||||
### DockData(机场数据)
|
|
||||||
|
|
||||||
包含60+字段,主要分类:
|
|
||||||
- **基础信息**:固件版本、机场状态、任务状态
|
|
||||||
- **位置信息**:经纬度、高度、朝向角
|
|
||||||
- **环境信息**:温度、湿度、风速、降雨量
|
|
||||||
- **设备状态**:舱盖状态、飞行器在舱状态、补光灯等
|
|
||||||
- **电池信息**:充电状态、备用电池、电池保养
|
|
||||||
- **网络信息**:网络类型、质量、速率
|
|
||||||
- **图传信息**:4G/SDR链路状态、信号质量
|
|
||||||
|
|
||||||
## 注意事项
|
|
||||||
|
|
||||||
1. **clientId必须唯一**:每个MQTT客户端的clientId必须全局唯一
|
|
||||||
2. **部分字段推送**:每次MQTT消息可能只包含部分字段,使用时需要判空
|
|
||||||
3. **原始数据访问**:所有字段都保存在`rawData`中,可以通过Map访问
|
|
||||||
4. **共享订阅**:多实例部署时建议开启共享订阅,避免重复消费
|
|
||||||
5. **独立处理器**:每个客户端有独立的消息处理器,互不影响
|
|
||||||
6. **自动重连**:连接断开后会自动重连(可配置)
|
|
||||||
|
|
||||||
## 完整示例
|
|
||||||
|
|
||||||
参考 `DjiMqttUsageExample.java` 获取完整示例代码。
|
|
||||||
|
|
@ -1,18 +0,0 @@
|
||||||
package com.ruoyi.device.domain.impl.djimqtt.callback;
|
|
||||||
|
|
||||||
import com.ruoyi.device.domain.impl.djimqtt.model.DockData;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 机场数据回调接口
|
|
||||||
*
|
|
||||||
* @author ruoyi
|
|
||||||
*/
|
|
||||||
public interface IDockDataCallback {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 处理机场数据
|
|
||||||
*
|
|
||||||
* @param dockData 机场数据
|
|
||||||
*/
|
|
||||||
void onDockData(DockData dockData);
|
|
||||||
}
|
|
||||||
|
|
@ -1,18 +0,0 @@
|
||||||
package com.ruoyi.device.domain.impl.djimqtt.callback;
|
|
||||||
|
|
||||||
import com.ruoyi.device.domain.impl.djimqtt.model.DroneData;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 无人机数据回调接口
|
|
||||||
*
|
|
||||||
* @author ruoyi
|
|
||||||
*/
|
|
||||||
public interface IDroneDataCallback {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 处理无人机数据
|
|
||||||
*
|
|
||||||
* @param droneData 无人机数据
|
|
||||||
*/
|
|
||||||
void onDroneData(DroneData droneData);
|
|
||||||
}
|
|
||||||
|
|
@ -1,76 +0,0 @@
|
||||||
package com.ruoyi.device.domain.impl.djimqtt.config;
|
|
||||||
|
|
||||||
import lombok.Builder;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* DJI MQTT客户端配置
|
|
||||||
* 用于动态创建MQTT客户端
|
|
||||||
*
|
|
||||||
* @author ruoyi
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
@Builder
|
|
||||||
public class DjiMqttClientConfig {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* MQTT服务器地址
|
|
||||||
*/
|
|
||||||
private String host;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* MQTT服务器端口
|
|
||||||
*/
|
|
||||||
private Integer port;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 客户端ID(必须唯一)
|
|
||||||
*/
|
|
||||||
private String clientId;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 用户名
|
|
||||||
*/
|
|
||||||
private String username;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 密码
|
|
||||||
*/
|
|
||||||
private String password;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 连接超时时间(秒)
|
|
||||||
*/
|
|
||||||
@Builder.Default
|
|
||||||
private Integer connectionTimeout = 30;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 保持连接时间(秒)
|
|
||||||
*/
|
|
||||||
@Builder.Default
|
|
||||||
private Integer keepAliveInterval = 60;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 自动重连
|
|
||||||
*/
|
|
||||||
@Builder.Default
|
|
||||||
private Boolean autoReconnect = true;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 清除会话
|
|
||||||
*/
|
|
||||||
@Builder.Default
|
|
||||||
private Boolean cleanSession = false;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 是否使用共享订阅
|
|
||||||
*/
|
|
||||||
@Builder.Default
|
|
||||||
private Boolean useSharedSubscription = true;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 共享订阅组名
|
|
||||||
*/
|
|
||||||
@Builder.Default
|
|
||||||
private String sharedGroupName = "dji-group";
|
|
||||||
}
|
|
||||||
|
|
@ -1,153 +0,0 @@
|
||||||
package com.ruoyi.device.domain.impl.djimqtt.example;
|
|
||||||
|
|
||||||
import com.ruoyi.device.domain.impl.djimqtt.callback.IDockDataCallback;
|
|
||||||
import com.ruoyi.device.domain.impl.djimqtt.callback.IDroneDataCallback;
|
|
||||||
import com.ruoyi.device.domain.impl.djimqtt.config.DjiMqttClientConfig;
|
|
||||||
import com.ruoyi.device.domain.impl.djimqtt.handler.DjiMqttMessageHandler;
|
|
||||||
import com.ruoyi.device.domain.impl.djimqtt.manager.DjiMqttClientManager;
|
|
||||||
import com.ruoyi.device.domain.impl.djimqtt.model.DockData;
|
|
||||||
import com.ruoyi.device.domain.impl.djimqtt.model.DroneData;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.boot.context.event.ApplicationReadyEvent;
|
|
||||||
import org.springframework.context.event.EventListener;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* DJI MQTT使用示例(支持多客户端)
|
|
||||||
*
|
|
||||||
* 使用说明:
|
|
||||||
* 1. 注入 DjiMqttClientManager
|
|
||||||
* 2. 使用 DjiMqttClientConfig.builder() 创建配置
|
|
||||||
* 3. 调用 manager.createClient(config) 创建客户端
|
|
||||||
* 4. 通过 manager.getHandler(clientId) 获取消息处理器
|
|
||||||
* 5. 注册回调处理数据
|
|
||||||
*
|
|
||||||
* @author ruoyi
|
|
||||||
*/
|
|
||||||
@Slf4j
|
|
||||||
@Component
|
|
||||||
public class DjiMqttUsageExample {
|
|
||||||
|
|
||||||
// @Autowired
|
|
||||||
// private DjiMqttClientManager clientManager;
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * 应用启动后创建MQTT客户端
|
|
||||||
// */
|
|
||||||
// @EventListener(ApplicationReadyEvent.class)
|
|
||||||
// public void onApplicationReady() {
|
|
||||||
// // 示例1:创建第一个MQTT客户端
|
|
||||||
// createClient1();
|
|
||||||
//
|
|
||||||
// // 示例2:创建第二个MQTT客户端(不同的服务器)
|
|
||||||
// createClient2();
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * 创建第一个MQTT客户端
|
|
||||||
// */
|
|
||||||
// private void createClient1() {
|
|
||||||
// // 构建配置
|
|
||||||
// DjiMqttClientConfig config = DjiMqttClientConfig.builder()
|
|
||||||
// .host("mqtt.t-aaron.com")
|
|
||||||
// .port(10883)
|
|
||||||
// .clientId("client_1")
|
|
||||||
// .username("admin")
|
|
||||||
// .password("admin")
|
|
||||||
// .useSharedSubscription(true)
|
|
||||||
// .sharedGroupName("dji-group-1")
|
|
||||||
// .build();
|
|
||||||
//
|
|
||||||
// // 创建客户端
|
|
||||||
// String clientId = clientManager.createClient(config);
|
|
||||||
//
|
|
||||||
// // 获取消息处理器
|
|
||||||
// DjiMqttMessageHandler handler = clientManager.getHandler(clientId);
|
|
||||||
//
|
|
||||||
// // 注册无人机数据回调
|
|
||||||
// handler.registerDroneDataCallback(new IDroneDataCallback() {
|
|
||||||
// @Override
|
|
||||||
// public void onDroneData(DroneData droneData) {
|
|
||||||
// handleDroneDataForClient1(droneData);
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
//
|
|
||||||
// // 注册机场数据回调
|
|
||||||
// handler.registerDockDataCallback(new IDockDataCallback() {
|
|
||||||
// @Override
|
|
||||||
// public void onDockData(DockData dockData) {
|
|
||||||
// handleDockDataForClient1(dockData);
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
//
|
|
||||||
// log.info("客户端1已创建并注册回调");
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * 创建第二个MQTT客户端(连接到不同的服务器)
|
|
||||||
// */
|
|
||||||
// private void createClient2() {
|
|
||||||
// // 构建配置
|
|
||||||
// DjiMqttClientConfig config = DjiMqttClientConfig.builder()
|
|
||||||
// .host("mqtt.another-server.com")
|
|
||||||
// .port(1883)
|
|
||||||
// .clientId("client_2")
|
|
||||||
// .username("user2")
|
|
||||||
// .password("pass2")
|
|
||||||
// .useSharedSubscription(false) // 不使用共享订阅
|
|
||||||
// .build();
|
|
||||||
//
|
|
||||||
// // 创建客户端
|
|
||||||
// String clientId = clientManager.createClient(config);
|
|
||||||
//
|
|
||||||
// // 获取消息处理器
|
|
||||||
// DjiMqttMessageHandler handler = clientManager.getHandler(clientId);
|
|
||||||
//
|
|
||||||
// // 注册回调
|
|
||||||
// handler.registerDroneDataCallback(droneData -> handleDroneDataForClient2(droneData));
|
|
||||||
// handler.registerDockDataCallback(dockData -> handleDockDataForClient2(dockData));
|
|
||||||
//
|
|
||||||
// log.info("客户端2已创建并注册回调");
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * 处理客户端1的无人机数据
|
|
||||||
// */
|
|
||||||
// private void handleDroneDataForClient1(DroneData droneData) {
|
|
||||||
// log.info("[客户端1] 收到无人机数据 - SN: {}, Type: {}",
|
|
||||||
// droneData.getDeviceSn(),
|
|
||||||
// droneData.getMessageType());
|
|
||||||
//
|
|
||||||
// // 处理位置信息
|
|
||||||
// if (droneData.getLatitude() != null && droneData.getLongitude() != null) {
|
|
||||||
// log.info("[客户端1] 无人机位置 - 纬度: {}, 经度: {}, 高度: {}",
|
|
||||||
// droneData.getLatitude(),
|
|
||||||
// droneData.getLongitude(),
|
|
||||||
// droneData.getElevation());
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * 处理客户端1的机场数据
|
|
||||||
// */
|
|
||||||
// private void handleDockDataForClient1(DockData dockData) {
|
|
||||||
// log.info("[客户端1] 收到机场数据 - SN: {}, Type: {}",
|
|
||||||
// dockData.getDeviceSn(),
|
|
||||||
// dockData.getMessageType());
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * 处理客户端2的无人机数据
|
|
||||||
// */
|
|
||||||
// private void handleDroneDataForClient2(DroneData droneData) {
|
|
||||||
// log.info("[客户端2] 收到无人机数据 - SN: {}", droneData.getDeviceSn());
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * 处理客户端2的机场数据
|
|
||||||
// */
|
|
||||||
// private void handleDockDataForClient2(DockData dockData) {
|
|
||||||
// log.info("[客户端2] 收到机场数据 - SN: {}", dockData.getDeviceSn());
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
@ -1,243 +0,0 @@
|
||||||
package com.ruoyi.device.domain.impl.djimqtt.handler;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
||||||
import com.ruoyi.device.domain.impl.djimqtt.callback.IDockDataCallback;
|
|
||||||
import com.ruoyi.device.domain.impl.djimqtt.callback.IDroneDataCallback;
|
|
||||||
import com.ruoyi.device.domain.impl.djimqtt.model.DjiMqttMessage;
|
|
||||||
import com.ruoyi.device.domain.impl.djimqtt.model.DockData;
|
|
||||||
import com.ruoyi.device.domain.impl.djimqtt.model.DroneData;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.regex.Matcher;
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* DJI MQTT消息处理器
|
|
||||||
* 订阅 thing/product/+ 格式的topic
|
|
||||||
* 只处理大疆设备:7C、158 开头的SN
|
|
||||||
* 过滤拓恒设备:TH 开头的SN(包括THJS)
|
|
||||||
*
|
|
||||||
* @author ruoyi
|
|
||||||
*/
|
|
||||||
@Slf4j
|
|
||||||
@Component
|
|
||||||
public class DjiMqttMessageHandler {
|
|
||||||
|
|
||||||
private final ObjectMapper objectMapper = new ObjectMapper();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 无人机数据回调列表
|
|
||||||
*/
|
|
||||||
private final List<IDroneDataCallback> droneDataCallbacks = new ArrayList<>();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 机场数据回调列表
|
|
||||||
*/
|
|
||||||
private final List<IDockDataCallback> dockDataCallbacks = new ArrayList<>();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 无人机SN正则表达式(只匹配大疆7C、158开头的SN)
|
|
||||||
* 示例:7CXXXXXXXXXX, 158XXXXXXXXXX
|
|
||||||
*/
|
|
||||||
private static final Pattern DRONE_SN_PATTERN = Pattern.compile("^(7C|158)[0-9A-Z]+");
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 机场SN正则表达式(只匹配大疆7C、158开头的SN)
|
|
||||||
* 示例:7CXXXXXXXXXX, 158XXXXXXXXXX
|
|
||||||
*/
|
|
||||||
private static final Pattern DOCK_SN_PATTERN = Pattern.compile("^(7C|158)[0-9A-Z]+");
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 拓恒设备SN前缀(需要过滤)
|
|
||||||
* TH开头的设备是拓恒设备,需要跳过
|
|
||||||
*/
|
|
||||||
private static final Pattern TUOHENG_SN_PATTERN = Pattern.compile("^TH[0-9A-Z]+");
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 注册无人机数据回调
|
|
||||||
*
|
|
||||||
* @param callback 回调接口
|
|
||||||
*/
|
|
||||||
public void registerDroneDataCallback(IDroneDataCallback callback) {
|
|
||||||
if (callback != null && !droneDataCallbacks.contains(callback)) {
|
|
||||||
droneDataCallbacks.add(callback);
|
|
||||||
log.info("注册无人机数据回调: {}", callback.getClass().getSimpleName());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 注册机场数据回调
|
|
||||||
*
|
|
||||||
* @param callback 回调接口
|
|
||||||
*/
|
|
||||||
public void registerDockDataCallback(IDockDataCallback callback) {
|
|
||||||
if (callback != null && !dockDataCallbacks.contains(callback)) {
|
|
||||||
dockDataCallbacks.add(callback);
|
|
||||||
log.info("注册机场数据回调: {}", callback.getClass().getSimpleName());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 处理MQTT消息
|
|
||||||
*
|
|
||||||
* @param topic 主题
|
|
||||||
* @param payload 消息内容
|
|
||||||
*/
|
|
||||||
public void handleMessage(String topic, String payload) {
|
|
||||||
try {
|
|
||||||
log.debug("收到MQTT消息 - Topic: {}, Payload: {}", topic, payload);
|
|
||||||
|
|
||||||
// 解析设备SN和消息类型
|
|
||||||
String deviceSn = extractDeviceSnFromTopic(topic);
|
|
||||||
String messageType = extractMessageTypeFromTopic(topic);
|
|
||||||
|
|
||||||
if (deviceSn == null || messageType == null) {
|
|
||||||
log.warn("无法从Topic解析设备SN或消息类型: {}", topic);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isTuohengSn(deviceSn)) {
|
|
||||||
log.debug("跳过拓恒设备消息 - SN: {}", deviceSn);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 解析JSON消息
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
DjiMqttMessage<Map<String, Object>> message = objectMapper.readValue(
|
|
||||||
payload,
|
|
||||||
objectMapper.getTypeFactory().constructParametricType(
|
|
||||||
DjiMqttMessage.class,
|
|
||||||
Map.class
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
// 判断是无人机还是机场
|
|
||||||
if (isDroneSn(deviceSn)) {
|
|
||||||
handleDroneMessage(deviceSn, messageType, message);
|
|
||||||
} else if (isDockSn(deviceSn)) {
|
|
||||||
handleDockMessage(deviceSn, messageType, message);
|
|
||||||
} else {
|
|
||||||
// log.warn("未知的设备SN格式: {}", deviceSn);
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("处理MQTT消息失败 - Topic: {}, Error: {}", topic, e.getMessage(), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 处理无人机消息
|
|
||||||
*/
|
|
||||||
private void handleDroneMessage(String deviceSn, String messageType, DjiMqttMessage<Map<String, Object>> message) {
|
|
||||||
try {
|
|
||||||
DroneData droneData = objectMapper.convertValue(message.getData(), DroneData.class);
|
|
||||||
droneData.setDeviceSn(deviceSn);
|
|
||||||
droneData.setMessageType(messageType);
|
|
||||||
droneData.setRawData(message.getData());
|
|
||||||
|
|
||||||
log.debug("处理无人机数据 - SN: {}, Type: {}", deviceSn, messageType);
|
|
||||||
|
|
||||||
// 通知所有回调
|
|
||||||
for (IDroneDataCallback callback : droneDataCallbacks) {
|
|
||||||
try {
|
|
||||||
callback.onDroneData(droneData);
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("无人机数据回调执行失败: {}", e.getMessage(), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("处理无人机消息失败 - SN: {}, Error: {}", deviceSn, e.getMessage(), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 处理机场消息
|
|
||||||
*/
|
|
||||||
private void handleDockMessage(String deviceSn, String messageType, DjiMqttMessage<Map<String, Object>> message) {
|
|
||||||
try {
|
|
||||||
DockData dockData = objectMapper.convertValue(message.getData(), DockData.class);
|
|
||||||
dockData.setDeviceSn(deviceSn);
|
|
||||||
dockData.setMessageType(messageType);
|
|
||||||
dockData.setRawData(message.getData());
|
|
||||||
|
|
||||||
log.debug("处理机场数据 - SN: {}, Type: {}", deviceSn, messageType);
|
|
||||||
|
|
||||||
// 通知所有回调
|
|
||||||
for (IDockDataCallback callback : dockDataCallbacks) {
|
|
||||||
try {
|
|
||||||
callback.onDockData(dockData);
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("机场数据回调执行失败: {}", e.getMessage(), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("处理机场消息失败 - SN: {}, Error: {}", deviceSn, e.getMessage(), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 从Topic中提取设备SN
|
|
||||||
* Topic格式: thing/product/{deviceSn}/osd 或 thing/product/{deviceSn}/state
|
|
||||||
*/
|
|
||||||
private String extractDeviceSnFromTopic(String topic) {
|
|
||||||
if (topic == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
String[] parts = topic.split("/");
|
|
||||||
if (parts.length >= 3) {
|
|
||||||
return parts[2];
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 从Topic中提取消息类型
|
|
||||||
*/
|
|
||||||
private String extractMessageTypeFromTopic(String topic) {
|
|
||||||
if (topic == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
String[] parts = topic.split("/");
|
|
||||||
if (parts.length >= 4) {
|
|
||||||
return parts[3]; // osd 或 state
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 判断是否为无人机SN
|
|
||||||
*/
|
|
||||||
private boolean isDroneSn(String sn) {
|
|
||||||
if (sn == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
Matcher matcher = DRONE_SN_PATTERN.matcher(sn);
|
|
||||||
return matcher.matches();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 判断是否为机场SN
|
|
||||||
*/
|
|
||||||
private boolean isDockSn(String sn) {
|
|
||||||
if (sn == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
Matcher matcher = DOCK_SN_PATTERN.matcher(sn);
|
|
||||||
return matcher.matches();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 判断是否为拓恒设备SN
|
|
||||||
*/
|
|
||||||
private boolean isTuohengSn(String sn) {
|
|
||||||
if (sn == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
Matcher matcher = TUOHENG_SN_PATTERN.matcher(sn);
|
|
||||||
return matcher.matches();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,125 +0,0 @@
|
||||||
package com.ruoyi.device.domain.impl.djimqtt.manager;
|
|
||||||
|
|
||||||
import com.ruoyi.device.domain.impl.djimqtt.config.DjiMqttClientConfig;
|
|
||||||
import com.ruoyi.device.domain.impl.djimqtt.handler.DjiMqttMessageHandler;
|
|
||||||
import com.ruoyi.device.domain.impl.djimqtt.service.DjiMqttClientService;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* DJI MQTT客户端管理器
|
|
||||||
* 管理多个MQTT客户端实例
|
|
||||||
*
|
|
||||||
* @author ruoyi
|
|
||||||
*/
|
|
||||||
@Slf4j
|
|
||||||
@Component
|
|
||||||
public class DjiMqttClientManager {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 客户端映射表 clientId -> DjiMqttClientService
|
|
||||||
*/
|
|
||||||
private final Map<String, DjiMqttClientService> clients = new ConcurrentHashMap<>();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 消息处理器映射表 clientId -> DjiMqttMessageHandler
|
|
||||||
*/
|
|
||||||
private final Map<String, DjiMqttMessageHandler> handlers = new ConcurrentHashMap<>();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 创建并连接MQTT客户端
|
|
||||||
*
|
|
||||||
* @param config 客户端配置
|
|
||||||
* @return 客户端ID
|
|
||||||
*/
|
|
||||||
public String createClient(DjiMqttClientConfig config) {
|
|
||||||
String clientId = config.getClientId();
|
|
||||||
|
|
||||||
if (clients.containsKey(clientId)) {
|
|
||||||
log.warn("MQTT客户端[{}]已存在", clientId);
|
|
||||||
return clientId;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 为每个客户端创建独立的消息处理器
|
|
||||||
DjiMqttMessageHandler handler = new DjiMqttMessageHandler();
|
|
||||||
handlers.put(clientId, handler);
|
|
||||||
|
|
||||||
// 创建客户端
|
|
||||||
DjiMqttClientService client = new DjiMqttClientService(config, handler);
|
|
||||||
clients.put(clientId, client);
|
|
||||||
|
|
||||||
// 连接
|
|
||||||
client.connect();
|
|
||||||
|
|
||||||
log.info("成功创建MQTT客户端[{}]", clientId);
|
|
||||||
return clientId;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取消息处理器
|
|
||||||
*
|
|
||||||
* @param clientId 客户端ID
|
|
||||||
* @return 消息处理器
|
|
||||||
*/
|
|
||||||
public DjiMqttMessageHandler getHandler(String clientId) {
|
|
||||||
return handlers.get(clientId);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取客户端
|
|
||||||
*
|
|
||||||
* @param clientId 客户端ID
|
|
||||||
* @return 客户端服务
|
|
||||||
*/
|
|
||||||
public DjiMqttClientService getClient(String clientId) {
|
|
||||||
return clients.get(clientId);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 断开并移除客户端
|
|
||||||
*
|
|
||||||
* @param clientId 客户端ID
|
|
||||||
*/
|
|
||||||
public void removeClient(String clientId) {
|
|
||||||
DjiMqttClientService client = clients.remove(clientId);
|
|
||||||
if (client != null) {
|
|
||||||
client.disconnect();
|
|
||||||
log.info("已移除MQTT客户端[{}]", clientId);
|
|
||||||
}
|
|
||||||
|
|
||||||
handlers.remove(clientId);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 断开所有客户端
|
|
||||||
*/
|
|
||||||
public void disconnectAll() {
|
|
||||||
clients.forEach((clientId, client) -> {
|
|
||||||
try {
|
|
||||||
client.disconnect();
|
|
||||||
log.info("已断开MQTT客户端[{}]", clientId);
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("断开MQTT客户端[{}]失败: {}", clientId, e.getMessage(), e);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
clients.clear();
|
|
||||||
handlers.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取所有客户端ID
|
|
||||||
*/
|
|
||||||
public java.util.Set<String> getAllClientIds() {
|
|
||||||
return clients.keySet();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 检查客户端是否存在
|
|
||||||
*/
|
|
||||||
public boolean hasClient(String clientId) {
|
|
||||||
return clients.containsKey(clientId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,57 +0,0 @@
|
||||||
package com.ruoyi.device.domain.impl.djimqtt.model;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* DJI MQTT消息基础结构
|
|
||||||
*
|
|
||||||
* @author ruoyi
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
|
||||||
public class DjiMqttMessage<T> {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 事务ID
|
|
||||||
*/
|
|
||||||
@JsonProperty("tid")
|
|
||||||
private String tid;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 业务ID
|
|
||||||
*/
|
|
||||||
@JsonProperty("bid")
|
|
||||||
private String bid;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 时间戳
|
|
||||||
*/
|
|
||||||
@JsonProperty("timestamp")
|
|
||||||
private Long timestamp;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 数据内容
|
|
||||||
*/
|
|
||||||
@JsonProperty("data")
|
|
||||||
private T data;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 网关设备SN
|
|
||||||
*/
|
|
||||||
@JsonProperty("gateway")
|
|
||||||
private String gateway;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 消息来源
|
|
||||||
*/
|
|
||||||
@JsonProperty("source")
|
|
||||||
private String source;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 是否需要回复
|
|
||||||
*/
|
|
||||||
@JsonProperty("need_reply")
|
|
||||||
private Integer needReply;
|
|
||||||
}
|
|
||||||
|
|
@ -1,291 +0,0 @@
|
||||||
package com.ruoyi.device.domain.impl.djimqtt.model;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
|
||||||
import com.ruoyi.device.domain.impl.djimqtt.model.dock.*;
|
|
||||||
import com.ruoyi.device.domain.impl.djimqtt.model.drone.MaintainStatus;
|
|
||||||
import com.ruoyi.device.domain.impl.djimqtt.model.drone.PositionState;
|
|
||||||
import com.ruoyi.device.domain.impl.djimqtt.model.drone.StorageInfo;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 机场完整数据(从osd和state主题接收)
|
|
||||||
* 注意:每次推送可能只包含部分字段
|
|
||||||
*
|
|
||||||
* @author ruoyi
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
|
||||||
public class DockData {
|
|
||||||
|
|
||||||
// ========== 元数据 ==========
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设备SN(从topic中解析)
|
|
||||||
*/
|
|
||||||
private String deviceSn;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 消息类型(osd或state)
|
|
||||||
*/
|
|
||||||
private String messageType;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 原始数据(用于存储所有字段)
|
|
||||||
*/
|
|
||||||
private Map<String, Object> rawData;
|
|
||||||
|
|
||||||
// ========== 基础信息 ==========
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Home 点有效性:0-无效,1-有效
|
|
||||||
*/
|
|
||||||
@JsonProperty("home_position_is_valid")
|
|
||||||
private Integer homePositionIsValid;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 机场朝向角
|
|
||||||
*/
|
|
||||||
@JsonProperty("heading")
|
|
||||||
private Double heading;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 固件版本
|
|
||||||
*/
|
|
||||||
@JsonProperty("firmware_version")
|
|
||||||
private String firmwareVersion;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 机场状态
|
|
||||||
*/
|
|
||||||
@JsonProperty("mode_code")
|
|
||||||
private Integer modeCode;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 机场任务状态
|
|
||||||
*/
|
|
||||||
@JsonProperty("flighttask_step_code")
|
|
||||||
private Integer flighttaskStepCode;
|
|
||||||
|
|
||||||
// ========== 位置信息 ==========
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 纬度
|
|
||||||
*/
|
|
||||||
@JsonProperty("latitude")
|
|
||||||
private Double latitude;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 经度
|
|
||||||
*/
|
|
||||||
@JsonProperty("longitude")
|
|
||||||
private Double longitude;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 椭球高度(米)
|
|
||||||
*/
|
|
||||||
@JsonProperty("height")
|
|
||||||
private Double height;
|
|
||||||
|
|
||||||
// ========== 环境信息 ==========
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 舱内温度(摄氏度)
|
|
||||||
*/
|
|
||||||
@JsonProperty("temperature")
|
|
||||||
private Float temperature;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 舱内湿度(%RH)
|
|
||||||
*/
|
|
||||||
@JsonProperty("humidity")
|
|
||||||
private Float humidity;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 环境温度(摄氏度)
|
|
||||||
*/
|
|
||||||
@JsonProperty("environment_temperature")
|
|
||||||
private Float environmentTemperature;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 风速(米/秒)
|
|
||||||
*/
|
|
||||||
@JsonProperty("wind_speed")
|
|
||||||
private Float windSpeed;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 降雨量:0-无雨,1-小雨,2-中雨,3-大雨
|
|
||||||
*/
|
|
||||||
@JsonProperty("rainfall")
|
|
||||||
private Integer rainfall;
|
|
||||||
|
|
||||||
// ========== 设备状态 ==========
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 舱盖状态:0-关闭,1-打开,2-半开,3-舱盖状态异常
|
|
||||||
*/
|
|
||||||
@JsonProperty("cover_state")
|
|
||||||
private Integer coverState;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 飞行器是否在舱:0-舱外,1-舱内
|
|
||||||
*/
|
|
||||||
@JsonProperty("drone_in_dock")
|
|
||||||
private Integer droneInDock;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* DRC链路状态:0-未连接,1-连接中,2-已连接
|
|
||||||
*/
|
|
||||||
@JsonProperty("drc_state")
|
|
||||||
private Integer drcState;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 紧急停止按钮状态:0-关闭,1-开启
|
|
||||||
*/
|
|
||||||
@JsonProperty("emergency_stop_state")
|
|
||||||
private Integer emergencyStopState;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 补光灯状态:0-关闭,1-打开
|
|
||||||
*/
|
|
||||||
@JsonProperty("supplement_light_state")
|
|
||||||
private Integer supplementLightState;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 机场声光报警状态:0-关闭,1-开启
|
|
||||||
*/
|
|
||||||
@JsonProperty("alarm_state")
|
|
||||||
private Integer alarmState;
|
|
||||||
|
|
||||||
// ========== 电池和电源 ==========
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 飞行器电池保养信息
|
|
||||||
*/
|
|
||||||
@JsonProperty("drone_battery_maintenance_info")
|
|
||||||
private DroneBatteryMaintenanceInfo droneBatteryMaintenanceInfo;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 飞行器充电状态
|
|
||||||
*/
|
|
||||||
@JsonProperty("drone_charge_state")
|
|
||||||
private DroneChargeState droneChargeState;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 机场备用电池信息
|
|
||||||
*/
|
|
||||||
@JsonProperty("backup_battery")
|
|
||||||
private BackupBattery backupBattery;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 电池运行模式:1-计划模式,2-待命模式
|
|
||||||
*/
|
|
||||||
@JsonProperty("battery_store_mode")
|
|
||||||
private Integer batteryStoreMode;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 工作电流(毫安)
|
|
||||||
*/
|
|
||||||
@JsonProperty("working_current")
|
|
||||||
private Float workingCurrent;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 工作电压(毫伏)
|
|
||||||
*/
|
|
||||||
@JsonProperty("working_voltage")
|
|
||||||
private Integer workingVoltage;
|
|
||||||
|
|
||||||
// ========== 网络和存储 ==========
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 网络状态
|
|
||||||
*/
|
|
||||||
@JsonProperty("network_state")
|
|
||||||
private NetworkState networkState;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 图传链路
|
|
||||||
*/
|
|
||||||
@JsonProperty("wireless_link")
|
|
||||||
private WirelessLink wirelessLink;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 存储容量
|
|
||||||
*/
|
|
||||||
@JsonProperty("storage")
|
|
||||||
private StorageInfo storage;
|
|
||||||
|
|
||||||
// ========== 空调和配置 ==========
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 机场空调工作状态信息
|
|
||||||
*/
|
|
||||||
@JsonProperty("air_conditioner")
|
|
||||||
private AirConditioner airConditioner;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 空中回传:false-关闭,true-开启
|
|
||||||
*/
|
|
||||||
@JsonProperty("air_transfer_enable")
|
|
||||||
private Boolean airTransferEnable;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 机场静音模式:0-非静音模式,1-静音模式
|
|
||||||
*/
|
|
||||||
@JsonProperty("silent_mode")
|
|
||||||
private Integer silentMode;
|
|
||||||
|
|
||||||
// ========== 保养和固件 ==========
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 保养信息
|
|
||||||
*/
|
|
||||||
@JsonProperty("maintain_status")
|
|
||||||
private MaintainStatus maintainStatus;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 搜星状态
|
|
||||||
*/
|
|
||||||
@JsonProperty("position_state")
|
|
||||||
private PositionState positionState;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 机场激活时间(unix 时间戳)
|
|
||||||
*/
|
|
||||||
@JsonProperty("activation_time")
|
|
||||||
private Long activationTime;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 固件升级状态:0-未升级,1-升级中
|
|
||||||
*/
|
|
||||||
@JsonProperty("firmware_upgrade_status")
|
|
||||||
private Integer firmwareUpgradeStatus;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 固件一致性:0-不需要一致性升级,1-需要一致性升级
|
|
||||||
*/
|
|
||||||
@JsonProperty("compatible_status")
|
|
||||||
private Integer compatibleStatus;
|
|
||||||
|
|
||||||
// ========== 统计信息 ==========
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 机场累计运行时长(秒)
|
|
||||||
*/
|
|
||||||
@JsonProperty("acc_time")
|
|
||||||
private Integer accTime;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 机场累计作业次数
|
|
||||||
*/
|
|
||||||
@JsonProperty("job_number")
|
|
||||||
private Integer jobNumber;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 首次上电时间(毫秒)
|
|
||||||
*/
|
|
||||||
@JsonProperty("first_power_on")
|
|
||||||
private Long firstPowerOn;
|
|
||||||
}
|
|
||||||
|
|
@ -1,329 +0,0 @@
|
||||||
package com.ruoyi.device.domain.impl.djimqtt.model;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
|
||||||
import com.ruoyi.device.domain.impl.djimqtt.model.drone.*;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 无人机完整数据(从osd和state主题接收)
|
|
||||||
* 注意:每次推送可能只包含部分字段
|
|
||||||
*
|
|
||||||
* @author ruoyi
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
|
||||||
public class DroneData {
|
|
||||||
|
|
||||||
// ========== 元数据 ==========
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设备SN(从topic中解析)
|
|
||||||
*/
|
|
||||||
private String deviceSn;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 消息类型(osd或state)
|
|
||||||
*/
|
|
||||||
private String messageType;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 原始数据(用于存储所有字段)
|
|
||||||
*/
|
|
||||||
private Map<String, Object> rawData;
|
|
||||||
|
|
||||||
// ========== 基础信息 ==========
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 飞行器图传连接质量最好的网关SN
|
|
||||||
*/
|
|
||||||
@JsonProperty("best_link_gateway")
|
|
||||||
private String bestLinkGateway;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 图传连接拓扑
|
|
||||||
*/
|
|
||||||
@JsonProperty("wireless_link_topo")
|
|
||||||
private WirelessLinkTopo wirelessLinkTopo;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 飞行器相机信息
|
|
||||||
*/
|
|
||||||
@JsonProperty("cameras")
|
|
||||||
private List<CameraInfo> cameras;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 飞行安全数据库版本
|
|
||||||
*/
|
|
||||||
@JsonProperty("flysafe_database_version")
|
|
||||||
private String flysafeDatabaseVersion;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 离线地图开关:false-关闭,true-开启
|
|
||||||
*/
|
|
||||||
@JsonProperty("offline_map_enable")
|
|
||||||
private Boolean offlineMapEnable;
|
|
||||||
|
|
||||||
// ========== 返航和限制 ==========
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 返航高度模式当前值:0-智能高度,1-设定高度
|
|
||||||
*/
|
|
||||||
@JsonProperty("current_rth_mode")
|
|
||||||
private Integer currentRthMode;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 返航高度模式设置值:0-智能高度,1-设定高度
|
|
||||||
*/
|
|
||||||
@JsonProperty("rth_mode")
|
|
||||||
private Integer rthMode;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 飞行器避障状态
|
|
||||||
*/
|
|
||||||
@JsonProperty("obstacle_avoidance")
|
|
||||||
private ObstacleAvoidance obstacleAvoidance;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 是否接近限飞区:0-未达到,1-接近
|
|
||||||
*/
|
|
||||||
@JsonProperty("is_near_area_limit")
|
|
||||||
private Integer isNearAreaLimit;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 是否接近设定的限制高度:0-未达到,1-接近
|
|
||||||
*/
|
|
||||||
@JsonProperty("is_near_height_limit")
|
|
||||||
private Integer isNearHeightLimit;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 飞行器限高(米)
|
|
||||||
*/
|
|
||||||
@JsonProperty("height_limit")
|
|
||||||
private Integer heightLimit;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 飞行器限远状态
|
|
||||||
*/
|
|
||||||
@JsonProperty("distance_limit_status")
|
|
||||||
private DistanceLimitStatus distanceLimitStatus;
|
|
||||||
|
|
||||||
// ========== 设备状态 ==========
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 飞行器夜航灯状态:0-关闭,1-打开
|
|
||||||
*/
|
|
||||||
@JsonProperty("night_lights_state")
|
|
||||||
private Integer nightLightsState;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 飞行器激活时间(unix 时间戳)
|
|
||||||
*/
|
|
||||||
@JsonProperty("activation_time")
|
|
||||||
private Long activationTime;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 保养信息
|
|
||||||
*/
|
|
||||||
@JsonProperty("maintain_status")
|
|
||||||
private MaintainStatus maintainStatus;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 飞行器累计飞行总架次
|
|
||||||
*/
|
|
||||||
@JsonProperty("total_flight_sorties")
|
|
||||||
private Integer totalFlightSorties;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 飞行器累计飞行总里程(米)
|
|
||||||
*/
|
|
||||||
@JsonProperty("total_flight_distance")
|
|
||||||
private Float totalFlightDistance;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 飞行器累计飞行航时(秒)
|
|
||||||
*/
|
|
||||||
@JsonProperty("total_flight_time")
|
|
||||||
private Float totalFlightTime;
|
|
||||||
|
|
||||||
// ========== 位置信息 ==========
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 搜星状态
|
|
||||||
*/
|
|
||||||
@JsonProperty("position_state")
|
|
||||||
private PositionState positionState;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 存储容量
|
|
||||||
*/
|
|
||||||
@JsonProperty("storage")
|
|
||||||
private StorageInfo storage;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 当前位置纬度
|
|
||||||
*/
|
|
||||||
@JsonProperty("latitude")
|
|
||||||
private Double latitude;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 当前位置经度
|
|
||||||
*/
|
|
||||||
@JsonProperty("longitude")
|
|
||||||
private Double longitude;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 相对起飞点高度(米)
|
|
||||||
*/
|
|
||||||
@JsonProperty("elevation")
|
|
||||||
private Float elevation;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 绝对高度(米)
|
|
||||||
*/
|
|
||||||
@JsonProperty("height")
|
|
||||||
private Double height;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Home点纬度
|
|
||||||
*/
|
|
||||||
@JsonProperty("home_latitude")
|
|
||||||
private Double homeLatitude;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Home点经度
|
|
||||||
*/
|
|
||||||
@JsonProperty("home_longitude")
|
|
||||||
private Double homeLongitude;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 距离Home点的距离(米)
|
|
||||||
*/
|
|
||||||
@JsonProperty("home_distance")
|
|
||||||
private Float homeDistance;
|
|
||||||
|
|
||||||
// ========== 姿态信息 ==========
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 偏航轴角度
|
|
||||||
*/
|
|
||||||
@JsonProperty("attitude_head")
|
|
||||||
private Integer attitudeHead;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 横滚轴角度
|
|
||||||
*/
|
|
||||||
@JsonProperty("attitude_roll")
|
|
||||||
private Float attitudeRoll;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 俯仰轴角度
|
|
||||||
*/
|
|
||||||
@JsonProperty("attitude_pitch")
|
|
||||||
private Float attitudePitch;
|
|
||||||
|
|
||||||
// ========== 速度和风速 ==========
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 水平速度(米/秒)
|
|
||||||
*/
|
|
||||||
@JsonProperty("horizontal_speed")
|
|
||||||
private Float horizontalSpeed;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 垂直速度(米/秒)
|
|
||||||
*/
|
|
||||||
@JsonProperty("vertical_speed")
|
|
||||||
private Float verticalSpeed;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 当前风向
|
|
||||||
*/
|
|
||||||
@JsonProperty("wind_direction")
|
|
||||||
private Integer windDirection;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 风速(米/秒)
|
|
||||||
*/
|
|
||||||
@JsonProperty("wind_speed")
|
|
||||||
private Float windSpeed;
|
|
||||||
|
|
||||||
// ========== 电池信息 ==========
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 飞行器电池信息
|
|
||||||
*/
|
|
||||||
@JsonProperty("battery")
|
|
||||||
private DroneBatteryInfo battery;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 严重低电量告警百分比
|
|
||||||
*/
|
|
||||||
@JsonProperty("serious_low_battery_warning_threshold")
|
|
||||||
private Integer seriousLowBatteryWarningThreshold;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 低电量告警百分比
|
|
||||||
*/
|
|
||||||
@JsonProperty("low_battery_warning_threshold")
|
|
||||||
private Integer lowBatteryWarningThreshold;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 返航预留电量百分比
|
|
||||||
*/
|
|
||||||
@JsonProperty("remaining_power_for_return_home")
|
|
||||||
private Integer remainingPowerForReturnHome;
|
|
||||||
|
|
||||||
// ========== 控制和状态 ==========
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 当前控制源
|
|
||||||
*/
|
|
||||||
@JsonProperty("control_source")
|
|
||||||
private String controlSource;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 固件升级状态:0-未升级,1-升级中
|
|
||||||
*/
|
|
||||||
@JsonProperty("firmware_upgrade_status")
|
|
||||||
private Integer firmwareUpgradeStatus;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 固件一致性:0-不需要一致性升级,1-需要一致性升级
|
|
||||||
*/
|
|
||||||
@JsonProperty("compatible_status")
|
|
||||||
private Integer compatibleStatus;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 固件版本
|
|
||||||
*/
|
|
||||||
@JsonProperty("firmware_version")
|
|
||||||
private String firmwareVersion;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 档位
|
|
||||||
*/
|
|
||||||
@JsonProperty("gear")
|
|
||||||
private Integer gear;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 飞行器状态
|
|
||||||
*/
|
|
||||||
@JsonProperty("mode_code")
|
|
||||||
private Integer modeCode;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 飞行器进入当前状态的原因
|
|
||||||
*/
|
|
||||||
@JsonProperty("mode_code_reason")
|
|
||||||
private Integer modeCodeReason;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 航迹ID
|
|
||||||
*/
|
|
||||||
@JsonProperty("track_id")
|
|
||||||
private String trackId;
|
|
||||||
}
|
|
||||||
|
|
@ -1,27 +0,0 @@
|
||||||
package com.ruoyi.device.domain.impl.djimqtt.model.dock;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 机场空调工作状态信息
|
|
||||||
*
|
|
||||||
* @author ruoyi
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
|
||||||
public class AirConditioner {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 机场空调状态
|
|
||||||
*/
|
|
||||||
@JsonProperty("air_conditioner_state")
|
|
||||||
private Integer airConditionerState;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 剩余等待可切换时间(秒)
|
|
||||||
*/
|
|
||||||
@JsonProperty("switch_time")
|
|
||||||
private Integer switchTime;
|
|
||||||
}
|
|
||||||
|
|
@ -1,33 +0,0 @@
|
||||||
package com.ruoyi.device.domain.impl.djimqtt.model.dock;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 机场备用电池信息
|
|
||||||
*
|
|
||||||
* @author ruoyi
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
|
||||||
public class BackupBattery {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 备用电池开关:0-关闭,1-开启
|
|
||||||
*/
|
|
||||||
@JsonProperty("switch")
|
|
||||||
private Integer switchState;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 备用电池电压(毫伏)
|
|
||||||
*/
|
|
||||||
@JsonProperty("voltage")
|
|
||||||
private Integer voltage;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 备用电池温度(摄氏度)
|
|
||||||
*/
|
|
||||||
@JsonProperty("temperature")
|
|
||||||
private Float temperature;
|
|
||||||
}
|
|
||||||
|
|
@ -1,39 +0,0 @@
|
||||||
package com.ruoyi.device.domain.impl.djimqtt.model.dock;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 机场电池详细信息
|
|
||||||
*
|
|
||||||
* @author ruoyi
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
|
||||||
public class DockBatteryDetail {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 电池剩余电量
|
|
||||||
*/
|
|
||||||
@JsonProperty("capacity_percent")
|
|
||||||
private Integer capacityPercent;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 电池序号:0-左电池,1-右电池
|
|
||||||
*/
|
|
||||||
@JsonProperty("index")
|
|
||||||
private Integer index;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 电压(毫伏)
|
|
||||||
*/
|
|
||||||
@JsonProperty("voltage")
|
|
||||||
private Integer voltage;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 温度(摄氏度)
|
|
||||||
*/
|
|
||||||
@JsonProperty("temperature")
|
|
||||||
private Float temperature;
|
|
||||||
}
|
|
||||||
|
|
@ -1,41 +0,0 @@
|
||||||
package com.ruoyi.device.domain.impl.djimqtt.model.dock;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 飞行器电池保养信息
|
|
||||||
*
|
|
||||||
* @author ruoyi
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
|
||||||
public class DroneBatteryMaintenanceInfo {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 保养状态:0-无需保养,1-待保养,2-正在保养
|
|
||||||
*/
|
|
||||||
@JsonProperty("maintenance_state")
|
|
||||||
private Integer maintenanceState;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 电池保养剩余时间(小时)
|
|
||||||
*/
|
|
||||||
@JsonProperty("maintenance_time_left")
|
|
||||||
private Integer maintenanceTimeLeft;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 电池加热保温状态:0-未开启,1-加热中,2-保温中
|
|
||||||
*/
|
|
||||||
@JsonProperty("heat_state")
|
|
||||||
private Integer heatState;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 电池详细信息
|
|
||||||
*/
|
|
||||||
@JsonProperty("batteries")
|
|
||||||
private List<DockBatteryDetail> batteries;
|
|
||||||
}
|
|
||||||
|
|
@ -1,27 +0,0 @@
|
||||||
package com.ruoyi.device.domain.impl.djimqtt.model.dock;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 飞行器充电状态
|
|
||||||
*
|
|
||||||
* @author ruoyi
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
|
||||||
public class DroneChargeState {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 电量百分比
|
|
||||||
*/
|
|
||||||
@JsonProperty("capacity_percent")
|
|
||||||
private Integer capacityPercent;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 充电状态:0-空闲,1-充电中
|
|
||||||
*/
|
|
||||||
@JsonProperty("state")
|
|
||||||
private Integer state;
|
|
||||||
}
|
|
||||||
|
|
@ -1,33 +0,0 @@
|
||||||
package com.ruoyi.device.domain.impl.djimqtt.model.dock;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 网络状态
|
|
||||||
*
|
|
||||||
* @author ruoyi
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
|
||||||
public class NetworkState {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 网络类型:1-4G,2-以太网
|
|
||||||
*/
|
|
||||||
@JsonProperty("type")
|
|
||||||
private Integer type;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 网络质量:0-无信号,1-差,2-较差,3-一般,4-较好,5-好
|
|
||||||
*/
|
|
||||||
@JsonProperty("quality")
|
|
||||||
private Integer quality;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 网络速率(KB/s)
|
|
||||||
*/
|
|
||||||
@JsonProperty("rate")
|
|
||||||
private Float rate;
|
|
||||||
}
|
|
||||||
|
|
@ -1,75 +0,0 @@
|
||||||
package com.ruoyi.device.domain.impl.djimqtt.model.dock;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 图传链路
|
|
||||||
*
|
|
||||||
* @author ruoyi
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
|
||||||
public class WirelessLink {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 飞行器上 Dongle 数量
|
|
||||||
*/
|
|
||||||
@JsonProperty("dongle_number")
|
|
||||||
private Integer dongleNumber;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 4G 链路连接状态:0-断开,1-连接
|
|
||||||
*/
|
|
||||||
@JsonProperty("4g_link_state")
|
|
||||||
private Integer fourGLinkState;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* SDR 链路连接状态:0-断开,1-连接
|
|
||||||
*/
|
|
||||||
@JsonProperty("sdr_link_state")
|
|
||||||
private Integer sdrLinkState;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 机场的图传链路模式:0-SDR 模式,1-4G 融合模式
|
|
||||||
*/
|
|
||||||
@JsonProperty("link_workmode")
|
|
||||||
private Integer linkWorkmode;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* SDR 信号质量(0-5)
|
|
||||||
*/
|
|
||||||
@JsonProperty("sdr_quality")
|
|
||||||
private Integer sdrQuality;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 总体 4G 信号质量(0-5)
|
|
||||||
*/
|
|
||||||
@JsonProperty("4g_quality")
|
|
||||||
private Integer fourGQuality;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 天端 4G 信号质量(0-5)
|
|
||||||
*/
|
|
||||||
@JsonProperty("4g_uav_quality")
|
|
||||||
private Integer fourGUavQuality;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 地端 4G 信号质量(0-5)
|
|
||||||
*/
|
|
||||||
@JsonProperty("4g_gnd_quality")
|
|
||||||
private Integer fourGGndQuality;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* SDR 频段
|
|
||||||
*/
|
|
||||||
@JsonProperty("sdr_freq_band")
|
|
||||||
private Float sdrFreqBand;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 4G 频段
|
|
||||||
*/
|
|
||||||
@JsonProperty("4g_freq_band")
|
|
||||||
private Float fourGFreqBand;
|
|
||||||
}
|
|
||||||
|
|
@ -1,75 +0,0 @@
|
||||||
package com.ruoyi.device.domain.impl.djimqtt.model.drone;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 电池详细信息
|
|
||||||
*
|
|
||||||
* @author ruoyi
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
|
||||||
public class BatteryDetail {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 电池剩余电量
|
|
||||||
*/
|
|
||||||
@JsonProperty("capacity_percent")
|
|
||||||
private Integer capacityPercent;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 电池序号
|
|
||||||
*/
|
|
||||||
@JsonProperty("index")
|
|
||||||
private Integer index;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 电池序列号(SN)
|
|
||||||
*/
|
|
||||||
@JsonProperty("sn")
|
|
||||||
private String sn;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 电池类型
|
|
||||||
*/
|
|
||||||
@JsonProperty("type")
|
|
||||||
private Integer type;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 电池子类型
|
|
||||||
*/
|
|
||||||
@JsonProperty("sub_type")
|
|
||||||
private Integer subType;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 固件版本
|
|
||||||
*/
|
|
||||||
@JsonProperty("firmware_version")
|
|
||||||
private String firmwareVersion;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 电池循环次数
|
|
||||||
*/
|
|
||||||
@JsonProperty("loop_times")
|
|
||||||
private Integer loopTimes;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 电压(毫伏)
|
|
||||||
*/
|
|
||||||
@JsonProperty("voltage")
|
|
||||||
private Integer voltage;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 温度(摄氏度)
|
|
||||||
*/
|
|
||||||
@JsonProperty("temperature")
|
|
||||||
private Float temperature;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 高电压存储天数
|
|
||||||
*/
|
|
||||||
@JsonProperty("high_voltage_storage_days")
|
|
||||||
private Integer highVoltageStorageDays;
|
|
||||||
}
|
|
||||||
|
|
@ -1,167 +0,0 @@
|
||||||
package com.ruoyi.device.domain.impl.djimqtt.model.drone;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 飞行器相机信息
|
|
||||||
*
|
|
||||||
* @author ruoyi
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
|
||||||
public class CameraInfo {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 剩余拍照张数
|
|
||||||
*/
|
|
||||||
@JsonProperty("remain_photo_num")
|
|
||||||
private Integer remainPhotoNum;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 剩余录像时间(秒)
|
|
||||||
*/
|
|
||||||
@JsonProperty("remain_record_duration")
|
|
||||||
private Integer remainRecordDuration;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 视频录制时长(秒)
|
|
||||||
*/
|
|
||||||
@JsonProperty("record_time")
|
|
||||||
private Integer recordTime;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 负载编号
|
|
||||||
*/
|
|
||||||
@JsonProperty("payload_index")
|
|
||||||
private String payloadIndex;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 相机模式:0-拍照,1-录像,2-智能低光,3-全景拍照
|
|
||||||
*/
|
|
||||||
@JsonProperty("camera_mode")
|
|
||||||
private Integer cameraMode;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 拍照状态:0-空闲,1-拍照中
|
|
||||||
*/
|
|
||||||
@JsonProperty("photo_state")
|
|
||||||
private Integer photoState;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 录像状态:0-空闲,1-录像中
|
|
||||||
*/
|
|
||||||
@JsonProperty("recording_state")
|
|
||||||
private Integer recordingState;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 变焦倍数
|
|
||||||
*/
|
|
||||||
@JsonProperty("zoom_factor")
|
|
||||||
private Float zoomFactor;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 红外变焦倍数
|
|
||||||
*/
|
|
||||||
@JsonProperty("ir_zoom_factor")
|
|
||||||
private Float irZoomFactor;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 视场角(FOV)在 liveview 中的区域
|
|
||||||
*/
|
|
||||||
@JsonProperty("liveview_world_region")
|
|
||||||
private LiveviewWorldRegion liveviewWorldRegion;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 照片存储设置集合
|
|
||||||
*/
|
|
||||||
@JsonProperty("photo_storage_settings")
|
|
||||||
private List<String> photoStorageSettings;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 视频存储设置集合
|
|
||||||
*/
|
|
||||||
@JsonProperty("video_storage_settings")
|
|
||||||
private List<String> videoStorageSettings;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 广角镜头曝光模式
|
|
||||||
*/
|
|
||||||
@JsonProperty("wide_exposure_mode")
|
|
||||||
private Integer wideExposureMode;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 广角镜头感光度
|
|
||||||
*/
|
|
||||||
@JsonProperty("wide_iso")
|
|
||||||
private Integer wideIso;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 广角镜头快门速度
|
|
||||||
*/
|
|
||||||
@JsonProperty("wide_shutter_speed")
|
|
||||||
private Integer wideShutterSpeed;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 广角镜头曝光值
|
|
||||||
*/
|
|
||||||
@JsonProperty("wide_exposure_value")
|
|
||||||
private Integer wideExposureValue;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 变焦镜头曝光模式
|
|
||||||
*/
|
|
||||||
@JsonProperty("zoom_exposure_mode")
|
|
||||||
private Integer zoomExposureMode;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 变焦镜头感光度
|
|
||||||
*/
|
|
||||||
@JsonProperty("zoom_iso")
|
|
||||||
private Integer zoomIso;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 变焦镜头快门速度
|
|
||||||
*/
|
|
||||||
@JsonProperty("zoom_shutter_speed")
|
|
||||||
private Integer zoomShutterSpeed;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 变焦镜头曝光值
|
|
||||||
*/
|
|
||||||
@JsonProperty("zoom_exposure_value")
|
|
||||||
private Integer zoomExposureValue;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 变焦镜头对焦模式
|
|
||||||
*/
|
|
||||||
@JsonProperty("zoom_focus_mode")
|
|
||||||
private Integer zoomFocusMode;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 变焦镜头对焦值
|
|
||||||
*/
|
|
||||||
@JsonProperty("zoom_focus_value")
|
|
||||||
private Integer zoomFocusValue;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 红外测温模式
|
|
||||||
*/
|
|
||||||
@JsonProperty("ir_metering_mode")
|
|
||||||
private Integer irMeteringMode;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 红外测温点
|
|
||||||
*/
|
|
||||||
@JsonProperty("ir_metering_point")
|
|
||||||
private IrMeteringPoint irMeteringPoint;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 红外测温区域
|
|
||||||
*/
|
|
||||||
@JsonProperty("ir_metering_area")
|
|
||||||
private IrMeteringArea irMeteringArea;
|
|
||||||
}
|
|
||||||
|
|
@ -1,27 +0,0 @@
|
||||||
package com.ruoyi.device.domain.impl.djimqtt.model.drone;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 飞行器对频信息(中心节点)
|
|
||||||
*
|
|
||||||
* @author ruoyi
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
|
||||||
public class CenterNode {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 扰码信息
|
|
||||||
*/
|
|
||||||
@JsonProperty("sdr_id")
|
|
||||||
private Integer sdrId;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设备sn
|
|
||||||
*/
|
|
||||||
@JsonProperty("sn")
|
|
||||||
private String sn;
|
|
||||||
}
|
|
||||||
|
|
@ -1,33 +0,0 @@
|
||||||
package com.ruoyi.device.domain.impl.djimqtt.model.drone;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 飞行器限远状态
|
|
||||||
*
|
|
||||||
* @author ruoyi
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
|
||||||
public class DistanceLimitStatus {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 是否开启限远:0-未设置,1-已设置
|
|
||||||
*/
|
|
||||||
@JsonProperty("state")
|
|
||||||
private Integer state;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 限远距离(米)
|
|
||||||
*/
|
|
||||||
@JsonProperty("distance_limit")
|
|
||||||
private Integer distanceLimit;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 是否接近设定的限制距离:0-未达到,1-接近
|
|
||||||
*/
|
|
||||||
@JsonProperty("is_near_distance_limit")
|
|
||||||
private Integer isNearDistanceLimit;
|
|
||||||
}
|
|
||||||
|
|
@ -1,47 +0,0 @@
|
||||||
package com.ruoyi.device.domain.impl.djimqtt.model.drone;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 飞行器电池信息
|
|
||||||
*
|
|
||||||
* @author ruoyi
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
|
||||||
public class DroneBatteryInfo {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 电池的总剩余电量
|
|
||||||
*/
|
|
||||||
@JsonProperty("capacity_percent")
|
|
||||||
private Integer capacityPercent;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 剩余飞行时间(秒)
|
|
||||||
*/
|
|
||||||
@JsonProperty("remain_flight_time")
|
|
||||||
private Integer remainFlightTime;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 返航所需电量百分比
|
|
||||||
*/
|
|
||||||
@JsonProperty("return_home_power")
|
|
||||||
private Integer returnHomePower;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 强制降落电量百分比
|
|
||||||
*/
|
|
||||||
@JsonProperty("landing_power")
|
|
||||||
private Integer landingPower;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 电池详细信息
|
|
||||||
*/
|
|
||||||
@JsonProperty("batteries")
|
|
||||||
private List<BatteryDetail> batteries;
|
|
||||||
}
|
|
||||||
|
|
@ -1,57 +0,0 @@
|
||||||
package com.ruoyi.device.domain.impl.djimqtt.model.drone;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 红外测温区域
|
|
||||||
*
|
|
||||||
* @author ruoyi
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
|
||||||
public class IrMeteringArea {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 测温区域左上角点坐标 x
|
|
||||||
*/
|
|
||||||
@JsonProperty("x")
|
|
||||||
private Double x;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 测温区域左上角点坐标 y
|
|
||||||
*/
|
|
||||||
@JsonProperty("y")
|
|
||||||
private Double y;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 测温区域宽度
|
|
||||||
*/
|
|
||||||
@JsonProperty("width")
|
|
||||||
private Double width;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 测温区域高度
|
|
||||||
*/
|
|
||||||
@JsonProperty("height")
|
|
||||||
private Double height;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 测温区域平均温度
|
|
||||||
*/
|
|
||||||
@JsonProperty("aver_temperature")
|
|
||||||
private Double averTemperature;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 测温区域最低温度点
|
|
||||||
*/
|
|
||||||
@JsonProperty("min_temperature_point")
|
|
||||||
private TemperaturePoint minTemperaturePoint;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 测温区域最高温度点
|
|
||||||
*/
|
|
||||||
@JsonProperty("max_temperature_point")
|
|
||||||
private TemperaturePoint maxTemperaturePoint;
|
|
||||||
}
|
|
||||||
|
|
@ -1,33 +0,0 @@
|
||||||
package com.ruoyi.device.domain.impl.djimqtt.model.drone;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 红外测温点
|
|
||||||
*
|
|
||||||
* @author ruoyi
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
|
||||||
public class IrMeteringPoint {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 测温点坐标 x
|
|
||||||
*/
|
|
||||||
@JsonProperty("x")
|
|
||||||
private Double x;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 测温点坐标 y
|
|
||||||
*/
|
|
||||||
@JsonProperty("y")
|
|
||||||
private Double y;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 测温点的温度
|
|
||||||
*/
|
|
||||||
@JsonProperty("temperature")
|
|
||||||
private Double temperature;
|
|
||||||
}
|
|
||||||
|
|
@ -1,33 +0,0 @@
|
||||||
package com.ruoyi.device.domain.impl.djimqtt.model.drone;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 机场或遥控器对频信息(叶子节点)
|
|
||||||
*
|
|
||||||
* @author ruoyi
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
|
||||||
public class LeafNode {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 扰码信息
|
|
||||||
*/
|
|
||||||
@JsonProperty("sdr_id")
|
|
||||||
private Integer sdrId;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设备sn
|
|
||||||
*/
|
|
||||||
@JsonProperty("sn")
|
|
||||||
private String sn;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 控制源序号
|
|
||||||
*/
|
|
||||||
@JsonProperty("control_source_index")
|
|
||||||
private Integer controlSourceIndex;
|
|
||||||
}
|
|
||||||
|
|
@ -1,39 +0,0 @@
|
||||||
package com.ruoyi.device.domain.impl.djimqtt.model.drone;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 视场角(FOV)在 liveview 中的区域
|
|
||||||
*
|
|
||||||
* @author ruoyi
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
|
||||||
public class LiveviewWorldRegion {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 左上角的 x 轴起始点
|
|
||||||
*/
|
|
||||||
@JsonProperty("left")
|
|
||||||
private Float left;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 左上角的 y 轴起始点
|
|
||||||
*/
|
|
||||||
@JsonProperty("top")
|
|
||||||
private Float top;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 右下角的 x 轴起始点
|
|
||||||
*/
|
|
||||||
@JsonProperty("right")
|
|
||||||
private Float right;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 右下角的 y 轴起始点
|
|
||||||
*/
|
|
||||||
@JsonProperty("bottom")
|
|
||||||
private Float bottom;
|
|
||||||
}
|
|
||||||
|
|
@ -1,23 +0,0 @@
|
||||||
package com.ruoyi.device.domain.impl.djimqtt.model.drone;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 保养信息
|
|
||||||
*
|
|
||||||
* @author ruoyi
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
|
||||||
public class MaintainStatus {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 保养信息数组
|
|
||||||
*/
|
|
||||||
@JsonProperty("maintain_status_array")
|
|
||||||
private List<MaintainStatusItem> maintainStatusArray;
|
|
||||||
}
|
|
||||||
|
|
@ -1,45 +0,0 @@
|
||||||
package com.ruoyi.device.domain.impl.djimqtt.model.drone;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 保养信息项
|
|
||||||
*
|
|
||||||
* @author ruoyi
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
|
||||||
public class MaintainStatusItem {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 保养状态:0-无保养,1-有保养
|
|
||||||
*/
|
|
||||||
@JsonProperty("state")
|
|
||||||
private Integer state;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 上一次保养类型:1-飞行器基础保养,2-飞行器常规保养,3-飞行器深度保养
|
|
||||||
*/
|
|
||||||
@JsonProperty("last_maintain_type")
|
|
||||||
private Integer lastMaintainType;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 上一次保养时间
|
|
||||||
*/
|
|
||||||
@JsonProperty("last_maintain_time")
|
|
||||||
private Long lastMaintainTime;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 上一次保养时飞行航时(小时)
|
|
||||||
*/
|
|
||||||
@JsonProperty("last_maintain_flight_time")
|
|
||||||
private Integer lastMaintainFlightTime;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 上一次保养时飞行架次
|
|
||||||
*/
|
|
||||||
@JsonProperty("last_maintain_flight_sorties")
|
|
||||||
private Integer lastMaintainFlightSorties;
|
|
||||||
}
|
|
||||||
|
|
@ -1,33 +0,0 @@
|
||||||
package com.ruoyi.device.domain.impl.djimqtt.model.drone;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 飞行器避障状态
|
|
||||||
*
|
|
||||||
* @author ruoyi
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
|
||||||
public class ObstacleAvoidance {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 水平避障状态:0-关闭,1-开启
|
|
||||||
*/
|
|
||||||
@JsonProperty("horizon")
|
|
||||||
private Integer horizon;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 上视避障状态:0-关闭,1-开启
|
|
||||||
*/
|
|
||||||
@JsonProperty("upside")
|
|
||||||
private Integer upside;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 下视避障状态:0-关闭,1-开启
|
|
||||||
*/
|
|
||||||
@JsonProperty("downside")
|
|
||||||
private Integer downside;
|
|
||||||
}
|
|
||||||
|
|
@ -1,39 +0,0 @@
|
||||||
package com.ruoyi.device.domain.impl.djimqtt.model.drone;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 搜星状态
|
|
||||||
*
|
|
||||||
* @author ruoyi
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
|
||||||
public class PositionState {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 是否收敛:0-未开始,1-收敛中,2-收敛成功,3-收敛失败
|
|
||||||
*/
|
|
||||||
@JsonProperty("is_fixed")
|
|
||||||
private Integer isFixed;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 搜星档位:1-1档,2-2档,3-3档,4-4档,5-5档,10-RTK fixed
|
|
||||||
*/
|
|
||||||
@JsonProperty("quality")
|
|
||||||
private Integer quality;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* GPS 搜星数量
|
|
||||||
*/
|
|
||||||
@JsonProperty("gps_number")
|
|
||||||
private Integer gpsNumber;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* RTK 搜星数量
|
|
||||||
*/
|
|
||||||
@JsonProperty("rtk_number")
|
|
||||||
private Integer rtkNumber;
|
|
||||||
}
|
|
||||||
|
|
@ -1,27 +0,0 @@
|
||||||
package com.ruoyi.device.domain.impl.djimqtt.model.drone;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 存储容量
|
|
||||||
*
|
|
||||||
* @author ruoyi
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
|
||||||
public class StorageInfo {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 总容量(KB)
|
|
||||||
*/
|
|
||||||
@JsonProperty("total")
|
|
||||||
private Integer total;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 已使用容量(KB)
|
|
||||||
*/
|
|
||||||
@JsonProperty("used")
|
|
||||||
private Integer used;
|
|
||||||
}
|
|
||||||
|
|
@ -1,33 +0,0 @@
|
||||||
package com.ruoyi.device.domain.impl.djimqtt.model.drone;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 温度点
|
|
||||||
*
|
|
||||||
* @author ruoyi
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
|
||||||
public class TemperaturePoint {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 温度点坐标 x
|
|
||||||
*/
|
|
||||||
@JsonProperty("x")
|
|
||||||
private Double x;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 温度点坐标 y
|
|
||||||
*/
|
|
||||||
@JsonProperty("y")
|
|
||||||
private Double y;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 温度点的温度
|
|
||||||
*/
|
|
||||||
@JsonProperty("temperature")
|
|
||||||
private Double temperature;
|
|
||||||
}
|
|
||||||
|
|
@ -1,35 +0,0 @@
|
||||||
package com.ruoyi.device.domain.impl.djimqtt.model.drone;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 图传连接拓扑
|
|
||||||
*
|
|
||||||
* @author ruoyi
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
|
||||||
public class WirelessLinkTopo {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 加密编码
|
|
||||||
*/
|
|
||||||
@JsonProperty("secret_code")
|
|
||||||
private List<Integer> secretCode;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 飞行器对频信息
|
|
||||||
*/
|
|
||||||
@JsonProperty("center_node")
|
|
||||||
private CenterNode centerNode;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 当前连接的机场或遥控器对频信息
|
|
||||||
*/
|
|
||||||
@JsonProperty("leaf_nodes")
|
|
||||||
private List<LeafNode> leafNodes;
|
|
||||||
}
|
|
||||||
|
|
@ -1,190 +0,0 @@
|
||||||
package com.ruoyi.device.domain.impl.djimqtt.service;
|
|
||||||
|
|
||||||
import com.ruoyi.device.domain.impl.djimqtt.config.DjiMqttClientConfig;
|
|
||||||
import com.ruoyi.device.domain.impl.djimqtt.handler.DjiMqttMessageHandler;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.eclipse.paho.mqttv5.client.IMqttToken;
|
|
||||||
import org.eclipse.paho.mqttv5.client.MqttCallback;
|
|
||||||
import org.eclipse.paho.mqttv5.client.MqttClient;
|
|
||||||
import org.eclipse.paho.mqttv5.client.MqttConnectionOptions;
|
|
||||||
import org.eclipse.paho.mqttv5.client.MqttDisconnectResponse;
|
|
||||||
import org.eclipse.paho.mqttv5.client.persist.MemoryPersistence;
|
|
||||||
import org.eclipse.paho.mqttv5.common.MqttException;
|
|
||||||
import org.eclipse.paho.mqttv5.common.MqttMessage;
|
|
||||||
import org.eclipse.paho.mqttv5.common.packet.MqttProperties;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* DJI MQTT客户端服务(基于Eclipse Paho MQTT v5)
|
|
||||||
* 支持MQTT 5.0协议,动态创建多个客户端
|
|
||||||
*
|
|
||||||
* @author ruoyi
|
|
||||||
*/
|
|
||||||
@Slf4j
|
|
||||||
public class DjiMqttClientService {
|
|
||||||
|
|
||||||
private final DjiMqttClientConfig config;
|
|
||||||
private final DjiMqttMessageHandler messageHandler;
|
|
||||||
private MqttClient mqttClient;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 无人机OSD主题
|
|
||||||
*/
|
|
||||||
private static final String DRONE_OSD_TOPIC = "thing/product/+/osd";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 无人机State主题
|
|
||||||
*/
|
|
||||||
private static final String DRONE_STATE_TOPIC = "thing/product/+/state";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 构造函数
|
|
||||||
*
|
|
||||||
* @param config 客户端配置
|
|
||||||
* @param messageHandler 消息处理器
|
|
||||||
*/
|
|
||||||
public DjiMqttClientService(DjiMqttClientConfig config, DjiMqttMessageHandler messageHandler) {
|
|
||||||
this.config = config;
|
|
||||||
this.messageHandler = messageHandler;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 连接到MQTT服务器
|
|
||||||
*/
|
|
||||||
public void connect() {
|
|
||||||
try {
|
|
||||||
if (mqttClient != null && mqttClient.isConnected()) {
|
|
||||||
log.info("MQTT客户端[{}]已连接,无需重复连接", config.getClientId());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
String broker = String.format("tcp://%s:%d", config.getHost(), config.getPort());
|
|
||||||
log.info("开始连接DJI MQTT服务器[{}]: {}", config.getClientId(), broker);
|
|
||||||
|
|
||||||
mqttClient = new MqttClient(broker, config.getClientId(), new MemoryPersistence());
|
|
||||||
|
|
||||||
MqttConnectionOptions options = new MqttConnectionOptions();
|
|
||||||
options.setUserName(config.getUsername());
|
|
||||||
options.setPassword(config.getPassword().getBytes());
|
|
||||||
options.setConnectionTimeout(config.getConnectionTimeout());
|
|
||||||
options.setKeepAliveInterval(config.getKeepAliveInterval());
|
|
||||||
options.setAutomaticReconnect(config.getAutoReconnect());
|
|
||||||
options.setCleanStart(config.getCleanSession());
|
|
||||||
|
|
||||||
mqttClient.setCallback(new MqttCallback() {
|
|
||||||
@Override
|
|
||||||
public void disconnected(MqttDisconnectResponse disconnectResponse) {
|
|
||||||
log.error("MQTT客户端[{}]连接丢失: {}", config.getClientId(),
|
|
||||||
disconnectResponse.getReasonString());
|
|
||||||
|
|
||||||
if (config.getAutoReconnect()) {
|
|
||||||
log.info("MQTT客户端[{}]将自动重连...", config.getClientId());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void mqttErrorOccurred(MqttException exception) {
|
|
||||||
log.error("MQTT客户端[{}]发生错误: {}", config.getClientId(),
|
|
||||||
exception.getMessage(), exception);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void messageArrived(String topic, MqttMessage message) {
|
|
||||||
try {
|
|
||||||
String payload = new String(message.getPayload());
|
|
||||||
messageHandler.handleMessage(topic, payload);
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("MQTT客户端[{}]处理消息失败: {}", config.getClientId(),
|
|
||||||
e.getMessage(), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void deliveryComplete(IMqttToken token) {
|
|
||||||
// 不需要处理
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void connectComplete(boolean reconnect, String serverURI) {
|
|
||||||
if (reconnect) {
|
|
||||||
log.info("MQTT客户端[{}]重连成功: {}", config.getClientId(), serverURI);
|
|
||||||
// 重连后重新订阅
|
|
||||||
subscribe();
|
|
||||||
} else {
|
|
||||||
log.info("MQTT客户端[{}]首次连接成功: {}", config.getClientId(), serverURI);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void authPacketArrived(int reasonCode, MqttProperties properties) {
|
|
||||||
// 不需要处理
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
mqttClient.connect(options);
|
|
||||||
log.info("MQTT客户端[{}]成功连接到服务器", config.getClientId());
|
|
||||||
|
|
||||||
subscribe();
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("MQTT客户端[{}]连接失败: {}", config.getClientId(), e.getMessage(), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 订阅主题
|
|
||||||
*/
|
|
||||||
private void subscribe() {
|
|
||||||
try {
|
|
||||||
if (mqttClient == null || !mqttClient.isConnected()) {
|
|
||||||
log.warn("MQTT客户端[{}]未连接,无法订阅主题", config.getClientId());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
String osdTopic = config.getUseSharedSubscription()
|
|
||||||
? String.format("$share/%s/%s", config.getSharedGroupName(), DRONE_OSD_TOPIC)
|
|
||||||
: DRONE_OSD_TOPIC;
|
|
||||||
|
|
||||||
String stateTopic = config.getUseSharedSubscription()
|
|
||||||
? String.format("$share/%s/%s", config.getSharedGroupName(), DRONE_STATE_TOPIC)
|
|
||||||
: DRONE_STATE_TOPIC;
|
|
||||||
|
|
||||||
mqttClient.subscribe(osdTopic, 1);
|
|
||||||
log.info("MQTT客户端[{}]成功订阅主题: {}", config.getClientId(), osdTopic);
|
|
||||||
|
|
||||||
mqttClient.subscribe(stateTopic, 1);
|
|
||||||
log.info("MQTT客户端[{}]成功订阅主题: {}", config.getClientId(), stateTopic);
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("MQTT客户端[{}]订阅主题失败: {}", config.getClientId(), e.getMessage(), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 断开连接
|
|
||||||
*/
|
|
||||||
public void disconnect() {
|
|
||||||
try {
|
|
||||||
if (mqttClient != null && mqttClient.isConnected()) {
|
|
||||||
mqttClient.disconnect();
|
|
||||||
mqttClient.close();
|
|
||||||
log.info("MQTT客户端[{}]已断开连接", config.getClientId());
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("MQTT客户端[{}]断开连接失败: {}", config.getClientId(), e.getMessage(), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 检查连接状态
|
|
||||||
*/
|
|
||||||
public boolean isConnected() {
|
|
||||||
return mqttClient != null && mqttClient.isConnected();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取客户端ID
|
|
||||||
*/
|
|
||||||
public String getClientId() {
|
|
||||||
return config.getClientId();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,272 +0,0 @@
|
||||||
package com.ruoyi.device.domain.impl.machine;
|
|
||||||
|
|
||||||
|
|
||||||
import com.ruoyi.device.domain.impl.machine.command.*;
|
|
||||||
import com.ruoyi.device.domain.impl.machine.instruction.InstructionContext;
|
|
||||||
import com.ruoyi.device.domain.impl.machine.mqtt.MqttClient;
|
|
||||||
import com.ruoyi.device.domain.impl.machine.state.MachineStates;
|
|
||||||
import com.ruoyi.device.domain.impl.machine.statemachine.MachineStateManager;
|
|
||||||
import com.ruoyi.device.domain.impl.machine.statemachine.StateChangeListener;
|
|
||||||
import com.ruoyi.device.domain.impl.machine.vendor.VendorConfig;
|
|
||||||
import com.ruoyi.device.domain.impl.machine.vendor.VendorRegistry;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.concurrent.CompletableFuture;
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设备命令管理器(框架使用者的主要入口)
|
|
||||||
*/
|
|
||||||
@Slf4j
|
|
||||||
@Component
|
|
||||||
public class MachineCommandManager {
|
|
||||||
|
|
||||||
private final VendorRegistry vendorRegistry;
|
|
||||||
private final MachineStateManager stateManager;
|
|
||||||
private final TransactionExecutor transactionExecutor;
|
|
||||||
private final MqttClient mqttClient;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* SN -> 当前正在执行的命令
|
|
||||||
*/
|
|
||||||
private final Map<String, CommandExecution> executingCommands = new ConcurrentHashMap<>();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 命令执行监听器
|
|
||||||
*/
|
|
||||||
private final Map<String, CommandExecutionListener> commandListeners = new ConcurrentHashMap<>();
|
|
||||||
|
|
||||||
public MachineCommandManager(VendorRegistry vendorRegistry,
|
|
||||||
MachineStateManager stateManager,
|
|
||||||
TransactionExecutor transactionExecutor,
|
|
||||||
MqttClient mqttClient) {
|
|
||||||
this.vendorRegistry = vendorRegistry;
|
|
||||||
this.stateManager = stateManager;
|
|
||||||
this.transactionExecutor = transactionExecutor;
|
|
||||||
this.mqttClient = mqttClient;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取设备当前状态
|
|
||||||
*
|
|
||||||
* @param sn 设备SN号
|
|
||||||
* @return 设备状态
|
|
||||||
*/
|
|
||||||
public MachineStates getMachineStates(String sn) {
|
|
||||||
return stateManager.getStates(sn);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 更新设备状态(通常在心跳中调用)
|
|
||||||
*
|
|
||||||
* @param sn 设备SN号
|
|
||||||
* @param newStates 新状态
|
|
||||||
*/
|
|
||||||
public void updateMachineStates(String sn, MachineStates newStates,Boolean force) {
|
|
||||||
stateManager.updateStates(sn, newStates,force);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 判断设备是否正在执行命令
|
|
||||||
*
|
|
||||||
* @param sn 设备SN号
|
|
||||||
* @return 是否正在执行命令
|
|
||||||
*/
|
|
||||||
public boolean isExecutingCommand(String sn) {
|
|
||||||
CommandExecution execution = executingCommands.get(sn);
|
|
||||||
return execution != null && !execution.getFuture().isDone();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取设备当前正在执行的命令类型
|
|
||||||
*
|
|
||||||
* @param sn 设备SN号
|
|
||||||
* @return 命令类型,如果没有正在执行的命令则返回null
|
|
||||||
*/
|
|
||||||
public CommandType getExecutingCommandType(String sn) {
|
|
||||||
CommandExecution execution = executingCommands.get(sn);
|
|
||||||
if (execution != null && !execution.getFuture().isDone()) {
|
|
||||||
return execution.getCommandType();
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取设备在当前状态下可以执行的命令列表
|
|
||||||
*
|
|
||||||
* @param sn 设备SN号
|
|
||||||
* @return 可执行的命令列表
|
|
||||||
*/
|
|
||||||
public List<CommandType> getAvailableCommands(String sn) {
|
|
||||||
VendorConfig vendorConfig = vendorRegistry.getVendorConfig(sn);
|
|
||||||
if (vendorConfig == null) {
|
|
||||||
log.warn("设备未绑定厂家: sn={}", sn);
|
|
||||||
return List.of();
|
|
||||||
}
|
|
||||||
|
|
||||||
MachineStates currentStates = stateManager.getStates(sn);
|
|
||||||
return vendorConfig.getAvailableCommands(currentStates);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 执行命令
|
|
||||||
*
|
|
||||||
* @param sn 设备SN号
|
|
||||||
* @param commandType 命令类型
|
|
||||||
* @return 命令执行结果的Future
|
|
||||||
*/
|
|
||||||
public CompletableFuture<CommandResult> executeCommand(String sn, CommandType commandType) {
|
|
||||||
return executeCommand(sn, commandType, Map.of());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 执行命令(带参数)
|
|
||||||
*
|
|
||||||
* @param sn 设备SN号
|
|
||||||
* @param commandType 命令类型
|
|
||||||
* @param params 命令参数
|
|
||||||
* @return 命令执行结果的Future
|
|
||||||
*/
|
|
||||||
public CompletableFuture<CommandResult> executeCommand(String sn, CommandType commandType, Map<String, Object> params) {
|
|
||||||
log.info("收到命令执行请求: sn={}, commandType={}, params={}", sn, commandType, params);
|
|
||||||
|
|
||||||
// 1. 检查设备是否已绑定厂家
|
|
||||||
VendorConfig vendorConfig = vendorRegistry.getVendorConfig(sn);
|
|
||||||
if (vendorConfig == null) {
|
|
||||||
String error = "设备未绑定厂家";
|
|
||||||
log.error("{}: sn={}", error, sn);
|
|
||||||
return CompletableFuture.completedFuture(CommandResult.failure(commandType, error));
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2. 检查是否正在执行其他命令
|
|
||||||
if (isExecutingCommand(sn)) {
|
|
||||||
String error = "设备正在执行其他命令: " + getExecutingCommandType(sn);
|
|
||||||
log.warn("{}: sn={}", error, sn);
|
|
||||||
return CompletableFuture.completedFuture(CommandResult.failure(commandType, error));
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3. 检查当前状态是否可以执行该命令
|
|
||||||
MachineStates currentStates = stateManager.getStates(sn);
|
|
||||||
if (!vendorConfig.canExecuteCommand(currentStates, commandType)) {
|
|
||||||
String error = "当前状态不允许执行该命令";
|
|
||||||
log.warn("{}: sn={}, commandType={}, currentStates={}", error, sn, commandType, currentStates);
|
|
||||||
return CompletableFuture.completedFuture(CommandResult.failure(commandType, error));
|
|
||||||
}
|
|
||||||
|
|
||||||
// 4. 获取事务定义
|
|
||||||
Transaction transaction = vendorConfig.getTransaction(commandType);
|
|
||||||
if (transaction == null) {
|
|
||||||
String error = "厂家不支持该命令";
|
|
||||||
log.error("{}: sn={}, commandType={}, vendorType={}", error, sn, commandType, vendorConfig.getVendorType());
|
|
||||||
return CompletableFuture.completedFuture(CommandResult.failure(commandType, error));
|
|
||||||
}
|
|
||||||
|
|
||||||
// 5. 创建指令上下文
|
|
||||||
InstructionContext context = new InstructionContext(sn, vendorConfig.getVendorType(), mqttClient);
|
|
||||||
params.forEach(context::putCommandParam);
|
|
||||||
|
|
||||||
// 6. 执行事务
|
|
||||||
CompletableFuture<CommandResult> future = transactionExecutor.executeTransaction(transaction, context);
|
|
||||||
|
|
||||||
// 7. 记录正在执行的命令
|
|
||||||
executingCommands.put(sn, new CommandExecution(commandType, future, System.currentTimeMillis()));
|
|
||||||
|
|
||||||
// 8. 添加完成回调
|
|
||||||
future.whenComplete((result, throwable) -> {
|
|
||||||
executingCommands.remove(sn);
|
|
||||||
|
|
||||||
if (throwable != null) {
|
|
||||||
log.error("命令执行异常: sn={}, commandType={}", sn, commandType, throwable);
|
|
||||||
notifyCommandComplete(sn, CommandResult.failure(commandType, "命令执行异常: " + throwable.getMessage()));
|
|
||||||
} else {
|
|
||||||
log.info("命令执行完成: sn={}, commandType={}, success={}", sn, commandType, result.isSuccess());
|
|
||||||
notifyCommandComplete(sn, result);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return future;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 注册命令执行监听器
|
|
||||||
*
|
|
||||||
* @param listenerId 监听器ID
|
|
||||||
* @param listener 监听器
|
|
||||||
*/
|
|
||||||
public void registerCommandListener(String listenerId, CommandExecutionListener listener) {
|
|
||||||
commandListeners.put(listenerId, listener);
|
|
||||||
log.debug("注册命令执行监听器: listenerId={}", listenerId);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 取消注册命令执行监听器
|
|
||||||
*
|
|
||||||
* @param listenerId 监听器ID
|
|
||||||
*/
|
|
||||||
public void unregisterCommandListener(String listenerId) {
|
|
||||||
commandListeners.remove(listenerId);
|
|
||||||
log.debug("取消注册命令执行监听器: listenerId={}", listenerId);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 注册状态变化监听器
|
|
||||||
*
|
|
||||||
* @param listenerId 监听器ID
|
|
||||||
* @param listener 监听器
|
|
||||||
*/
|
|
||||||
public void registerStateChangeListener(String listenerId, StateChangeListener listener) {
|
|
||||||
stateManager.registerStateChangeListener(listenerId, listener);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 取消注册状态变化监听器
|
|
||||||
*
|
|
||||||
* @param listenerId 监听器ID
|
|
||||||
*/
|
|
||||||
public void unregisterStateChangeListener(String listenerId) {
|
|
||||||
stateManager.unregisterStateChangeListener(listenerId);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 通知命令执行完成
|
|
||||||
*/
|
|
||||||
private void notifyCommandComplete(String sn, CommandResult result) {
|
|
||||||
for (CommandExecutionListener listener : commandListeners.values()) {
|
|
||||||
try {
|
|
||||||
listener.onCommandComplete(sn, result);
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("命令执行监听器执行失败: sn={}, commandType={}", sn, result.getCommandType(), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 命令执行信息
|
|
||||||
*/
|
|
||||||
private static class CommandExecution {
|
|
||||||
private final CommandType commandType;
|
|
||||||
private final CompletableFuture<CommandResult> future;
|
|
||||||
private final long startTime;
|
|
||||||
|
|
||||||
public CommandExecution(CommandType commandType, CompletableFuture<CommandResult> future, long startTime) {
|
|
||||||
this.commandType = commandType;
|
|
||||||
this.future = future;
|
|
||||||
this.startTime = startTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
public CommandType getCommandType() {
|
|
||||||
return commandType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public CompletableFuture<CommandResult> getFuture() {
|
|
||||||
return future;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getStartTime() {
|
|
||||||
return startTime;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,15 +0,0 @@
|
||||||
package com.ruoyi.device.domain.impl.machine.command;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 命令执行监听器
|
|
||||||
*/
|
|
||||||
@FunctionalInterface
|
|
||||||
public interface CommandExecutionListener {
|
|
||||||
/**
|
|
||||||
* 命令执行完成回调
|
|
||||||
*
|
|
||||||
* @param sn 设备SN号
|
|
||||||
* @param result 命令执行结果
|
|
||||||
*/
|
|
||||||
void onCommandComplete(String sn, CommandResult result);
|
|
||||||
}
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue