Compare commits

...

130 Commits

Author SHA1 Message Date
孙小云 c57f66e0b7 xx 2026-01-22 20:06:14 +08:00
孙小云 31454217ea 添加group/docks/2 2026-01-22 20:05:40 +08:00
孙小云 d70132180b 添加group/docks/2 2026-01-22 20:04:09 +08:00
孙小云 9bee1836dd 添加经纬度 2026-01-22 17:44:06 +08:00
孙小云 2ea81a491c 添加无人机名称的修改 2026-01-22 10:57:50 +08:00
孙小云 595f431388 添加无人机名称的修改 2026-01-22 10:03:31 +08:00
孙小云 6f4b8863f0 添加机场名称和地址修改 2026-01-22 09:54:34 +08:00
孙小云 cb4df3bb17 添加分组名称修改 2026-01-22 09:40:03 +08:00
孙小云 3933ea2ed3 分组里面添加个数 2026-01-22 09:29:48 +08:00
孙小云 21702f04d1 添加飞行时长 2026-01-21 19:21:20 +08:00
孙小云 c09f7358f1 添加电池剩余飞行时间 2026-01-21 19:15:05 +08:00
孙小云 34cba3d6a2 添加电池信息 2026-01-21 19:10:51 +08:00
孙小云 442e8c4844 添加RTK 2026-01-21 19:05:03 +08:00
孙小云 9943cfe1f2 添加电池的信息获取 2026-01-21 19:00:43 +08:00
孙小云 b3c3515322 添加无人机信息获取的逻辑 2026-01-21 18:55:21 +08:00
孙小云 cbfd77da5c 添加无人机信息获取的逻辑 2026-01-21 18:51:20 +08:00
孙小云 acf586de85 添加舱内温度和湿度 2026-01-21 18:39:16 +08:00
孙小云 ec5dba7fc5 添加舱门状态 2026-01-21 18:33:36 +08:00
孙小云 6e538bd4cb 添加空调状态 2026-01-21 18:31:50 +08:00
孙小云 372a289cf7 添加空调状态 2026-01-21 18:28:21 +08:00
孙小云 833c8e5cec 添加网络类型 2026-01-21 18:00:32 +08:00
孙小云 68cdcd4c9a 设置环境温度 2026-01-21 17:51:26 +08:00
孙小云 04c6f23da7 设置作业架次 2026-01-21 17:43:10 +08:00
孙小云 8dabee82ac 添加运行时长的数据 2026-01-21 17:32:03 +08:00
孙小云 fcd6628923 添加备降点数据 2026-01-21 17:28:11 +08:00
孙小云 a3347f2983 添加备降点映射 2026-01-21 17:24:24 +08:00
孙小云 e097e597f5 添加机场详情查看接口 2026-01-21 17:14:29 +08:00
孙小云 123de67f76 修改无人机挂载状态 2026-01-21 17:07:21 +08:00
孙小云 48641d76eb 修改无人机挂载状态 2026-01-21 17:05:10 +08:00
孙小云 35c0cf0c63 修改无人机状态 2026-01-21 16:55:54 +08:00
孙小云 1ea9422f40 修改无人机状态 2026-01-21 16:37:06 +08:00
孙小云 680cdc2cb0 修改无人机状态 2026-01-21 16:34:15 +08:00
孙小云 7d51087047 修改无人机状态 2026-01-21 16:29:46 +08:00
孙小云 1fdf6dc22d 修改获取机场状态的代码 2026-01-21 16:12:50 +08:00
孙小云 624936dffc 修改获取机场状态的代码 2026-01-21 15:58:12 +08:00
孙小云 cb1c303a6c 修改获取机场状态的代码 2026-01-21 15:47:50 +08:00
孙小云 ac9a8944cb 修改代码结构 2026-01-21 15:37:43 +08:00
孙小云 679a3e7bf2 修改代码结构 2026-01-21 15:23:43 +08:00
孙小云 3e5a358b48 修改代码结构 2026-01-21 15:19:55 +08:00
孙小云 8efbc0de01 修改代码结构 2026-01-21 15:17:29 +08:00
孙小云 3c5ef8e508 修改代码结构 2026-01-21 15:16:32 +08:00
孙小云 eb62f34dc6 添加日志 2026-01-21 14:21:10 +08:00
孙小云 894bceaa22 添加日志 2026-01-21 14:16:24 +08:00
孙小云 f2c7d5e265 添加日志 2026-01-21 14:08:21 +08:00
孙小云 749b8e87dd 修改convert 2026-01-21 14:04:29 +08:00
孙小云 215c2f1558 xx 2026-01-21 14:00:54 +08:00
孙小云 f42a12af04 修改convert 2026-01-21 13:51:04 +08:00
孙小云 40eaed2dac 修改convert 2026-01-21 13:45:14 +08:00
孙小云 9ccd38bb50 修改convert 2026-01-21 13:43:27 +08:00
孙小云 f4f5db269a 修改convert 2026-01-21 13:18:33 +08:00
孙小云 518a2bff17 修改convert 2026-01-21 11:43:56 +08:00
孙小云 aed2112e59 修改convert 2026-01-21 11:14:31 +08:00
孙小云 97aad653f6 修改convert 2026-01-21 10:41:00 +08:00
孙小云 49fb0f2471 修改convert 2026-01-21 10:32:13 +08:00
孙小云 f3137ac76f 修改convert 2026-01-21 10:21:20 +08:00
孙小云 edc8751162 添加接口 2026-01-20 17:05:25 +08:00
孙小云 20e528b183 xx 2026-01-20 16:09:06 +08:00
孙小云 4832c03a3d x 2026-01-20 15:56:42 +08:00
孙小云 b3644698fe 添加接口 2026-01-20 15:48:23 +08:00
孙小云 4c21f59b71 完善接口内容 2026-01-20 15:37:54 +08:00
孙小云 2bc461334c 添加接口 2026-01-20 14:54:53 +08:00
孙小云 12f3e2be88 完成 getAllGroupIds 逻辑 2026-01-20 14:44:54 +08:00
孙小云 5c28ec5f27 添加删除分组的逻辑 2026-01-20 14:41:13 +08:00
孙小云 453a7eb5d6 添加修改分组的信息 2026-01-20 14:30:21 +08:00
孙小云 87d452c444 xx 2026-01-20 14:22:43 +08:00
孙小云 7bd282b9e2 xx 2026-01-20 14:21:13 +08:00
孙小云 69af79b842 xx 2026-01-20 14:20:08 +08:00
孙小云 9645f45af7 修改切换分组的逻辑 2026-01-20 14:18:50 +08:00
孙小云 8f80eb8a96 关闭校验 2026-01-20 14:13:29 +08:00
孙小云 83cf9933fb 关闭权限 2026-01-20 14:07:45 +08:00
孙小云 154d7c86f3 ss 2026-01-20 13:47:45 +08:00
孙小云 7a6ff325c4 修改/group/create 2026-01-20 13:45:42 +08:00
孙小云 a3577b01d1 测试 2026-01-20 13:39:42 +08:00
孙小云 3bf5b6ddff 创建分组接口完成 2026-01-20 13:38:15 +08:00
孙小云 a35759f5e6 测试 2026-01-20 13:29:02 +08:00
孙小云 aa328169e3 添加controller层定义 2026-01-20 13:20:39 +08:00
孙小云 4a2a6c3c0a 添加信息 2026-01-20 10:53:38 +08:00
孙小云 406a1e9e5f 添加信息 2026-01-20 09:29:24 +08:00
孙小云 b997cc4899 修改枚举 2026-01-19 17:19:59 +08:00
孙小云 9f5457a2fa 修改枚举 2026-01-19 17:14:11 +08:00
孙小云 e79d8e15fb 修改枚举 2026-01-19 17:03:57 +08:00
孙小云 b78437444b 修改枚举 2026-01-19 16:58:30 +08:00
孙小云 b134358cdc 修改枚举 2026-01-19 16:50:18 +08:00
孙小云 f8ae8f4f34 修改枚举 2026-01-19 16:48:10 +08:00
孙小云 57302a8e42 修改枚举 2026-01-19 16:47:03 +08:00
孙小云 a876c6c310 修改枚举 2026-01-19 16:41:52 +08:00
孙小云 64662f6f26 添加枚举 2026-01-19 16:39:01 +08:00
孙小云 425ba35452 添加枚举 2026-01-19 16:33:46 +08:00
孙小云 57e145b4ff 添加枚举 2026-01-19 16:07:36 +08:00
孙小云 8cc7a6d4a7 添加枚举 2026-01-19 16:06:58 +08:00
孙小云 85f39feac1 添加喊话器的同步 2026-01-19 09:46:35 +08:00
孙小云 a9623faf24 添加喊话器的同步 2026-01-19 09:30:12 +08:00
孙小云 41a86fb8b7 添加挂载 2026-01-19 09:12:27 +08:00
孙小云 4a36cdf89f 修改代码 2026-01-17 17:10:32 +08:00
孙小云 ea07df5491 修改代码 2026-01-17 17:00:30 +08:00
孙小云 b35f7438b1 修改代码 2026-01-17 16:57:03 +08:00
孙小云 a64a96ca76 修改代码 2026-01-17 16:49:58 +08:00
孙小云 37c3147835 修改代码 2026-01-17 16:49:52 +08:00
孙小云 b5281c0858 修改代码 2026-01-17 16:41:22 +08:00
孙小云 aa333a1271 修改代码 2026-01-17 16:39:18 +08:00
孙小云 040359177e 修改代码 2026-01-17 16:08:58 +08:00
孙小云 a99053e108 修改代码 2026-01-17 16:02:03 +08:00
孙小云 5fc82d4bc3 修改代码 2026-01-17 15:56:05 +08:00
孙小云 6cad98b742 修改代码 2026-01-17 15:54:52 +08:00
孙小云 054460beaf 修改代码 2026-01-17 15:52:36 +08:00
孙小云 c08855a3b5 修改代码 2026-01-17 15:49:35 +08:00
孙小云 39f423dd28 修改代码 2026-01-17 15:36:25 +08:00
孙小云 ac95f0a163 修改代码 2026-01-17 15:22:02 +08:00
孙小云 ec4985d819 添加过滤无效设备 2026-01-17 14:08:11 +08:00
孙小云 296d535b25 添加基本数据同步功能 2026-01-17 13:57:14 +08:00
孙小云 f728d1f0c1 添加规范说明 2026-01-17 13:05:43 +08:00
孙小云 a0fd20ca51 修改端口 2026-01-17 10:57:19 +08:00
孙小云 a1d7e2a730 添加service层实现 2026-01-16 19:38:06 +08:00
孙小云 3772e1d6de 添加domain层的接口和实现 2026-01-16 19:13:33 +08:00
孙小云 40e1878d76 添加外键索引 2026-01-16 18:53:34 +08:00
孙小云 aed6203e78 添加IOT的MAPPER 2026-01-16 18:47:52 +08:00
孙小云 35d61801fe 修改IOT客户端和代码结构 2026-01-16 16:05:17 +08:00
孙小云 7ce75685aa 添加PSDK的配置 2026-01-16 15:46:03 +08:00
孙小云 6292b3f9b6 添加网关名称字段,表示是从哪个网关接入的 2026-01-16 13:59:52 +08:00
孙小云 18777f9cdd 修改代码 使用 dock_sn 替代 gateway的表达 2026-01-16 13:52:00 +08:00
孙小云 f762f92846 xx 2026-01-16 10:26:09 +08:00
孙小云 e9630d60e5 修改IOT代码,添加定时器测试是否可以获取到设备信息 2026-01-16 10:23:43 +08:00
孙小云 9fd9602718 添加IOT接口 2026-01-16 09:06:30 +08:00
孙小云 34f86b6329 x 2026-01-15 19:14:11 +08:00
孙小云 1a7c7caa71 修改标准代码结构 2026-01-15 19:03:34 +08:00
孙小云 f0f8603550 修改代码模版 2026-01-15 18:25:25 +08:00
孙小云 8500a7cd0d src/main/resources/bootstrap.yml 2026-01-15 17:05:26 +08:00
孙小云 ed2782abcb xx 2026-01-15 16:20:51 +08:00
孙小云 47a9e4a984 init device 2026-01-15 16:03:11 +08:00
孙小云 72f39521a0 x 2026-01-13 14:14:28 +08:00
147 changed files with 12454 additions and 8 deletions

36
pom.xml
View File

@ -16,7 +16,24 @@
</description>
<dependencies>
<dependency>
<groupId>org.thingsboard</groupId>
<artifactId>rest-client</artifactId>
</dependency>
<!-- Tuoheng Device API -->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>tuoheng-api-device</artifactId>
</dependency>
<!-- RuoYi Common Core -->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common-core</artifactId>
</dependency>
<!-- SpringCloud Alibaba Nacos -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
@ -71,6 +88,23 @@
<artifactId>ruoyi-common-swagger</artifactId>
</dependency>
<!-- Flyway Database Migration -->
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
</dependency>
<!-- Flyway MySQL Support -->
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-mysql</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
<build>

View File

@ -1 +1 @@
a
dddddddd

View File

@ -2,23 +2,25 @@ package com.ruoyi.device;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;
import com.ruoyi.common.security.annotation.EnableCustomConfig;
import com.ruoyi.common.security.annotation.EnableRyFeignClients;
/**
* 系统模块
*
* 设备模块
*
* @author ruoyi
*/
@EnableScheduling
@EnableCustomConfig
@EnableRyFeignClients
@SpringBootApplication
public class Application
public class TuohengDeviceApplication
{
public static void main(String[] args)
{
SpringApplication.run(Application.class, args);
System.out.println("(♥◠‿◠)ノ゙ 系统模块启动成功 ლ(´ڡ`ლ)゙ \n" +
SpringApplication.run(TuohengDeviceApplication.class, args);
System.out.println("(♥◠‿◠)ノ゙ 设备模块启动成功 ლ(´ڡ`ლ)゙ \n" +
" .-------. ____ __ \n" +
" | _ _ \\ \\ \\ / / \n" +
" | ( ' ) | \\ _. / ' \n" +

View File

@ -0,0 +1,63 @@
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.controller.convert.AircraftDetailVOConvert;
import com.ruoyi.device.service.api.IAircraftService;
import com.ruoyi.device.service.api.IBufferDeviceService;
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.*;
/**
* 无人机Controller
*
* @author ruoyi
* @date 2026-01-20
*/
@RestController
@RequestMapping("/aircraft")
public class AircraftController extends BaseController
{
@Autowired
private IAircraftService aircraftService;
@Autowired
private IBufferDeviceService bufferDeviceService;
/**
* 查看无人机详情
*
* @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();
}
}

View File

@ -0,0 +1,70 @@
package com.ruoyi.device.controller;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.web.controller.BaseController;
import com.ruoyi.common.core.web.domain.AjaxResult;
import com.ruoyi.common.core.web.page.TableDataInfo;
import com.ruoyi.common.security.annotation.InnerAuth;
import com.ruoyi.device.api.domain.DeviceTempVO;
import com.ruoyi.device.controller.convert.DeviceTempVOConvert;
import com.ruoyi.device.service.api.IDeviceTempService;
import com.ruoyi.device.service.dto.DeviceTempDTO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
* 设备临时表Controller
*
* @author ruoyi
* @date 2026-01-15
*/
@RestController
@RequestMapping("/device/temp")
public class DeviceTempController extends BaseController
{
@Autowired
private IDeviceTempService deviceTempService;
/**
* 查询设备临时表列表
*/
@GetMapping("/list")
public TableDataInfo list(DeviceTempVO deviceTemp)
{
startPage();
// API Domain Service DTO
DeviceTempDTO dto = DeviceTempVOConvert.to(deviceTemp);
List<DeviceTempDTO> dtoList = deviceTempService.selectDeviceTempList(dto);
// Service DTO API Domain
List<DeviceTempVO> list = DeviceTempVOConvert.fromList(dtoList);
return getDataTable(list);
}
/**
* 获取设备临时表详细信息内部调用
*/
@InnerAuth
@GetMapping(value = "/{id}")
public R<DeviceTempVO> getDeviceById(@PathVariable("id") String id)
{
DeviceTempDTO dto = deviceTempService.selectDeviceTempById(id);
DeviceTempVO deviceTemp = DeviceTempVOConvert.from(dto);
return R.ok(deviceTemp);
}
/**
* 获取设备临时表详细信息外部调用
*/
@GetMapping(value = "/info/{id}")
public AjaxResult getInfo(@PathVariable("id") String id)
{
DeviceTempDTO dto = deviceTempService.selectDeviceTempById(id);
DeviceTempVO deviceTemp = DeviceTempVOConvert.from(dto);
return success(deviceTemp);
}
}

View File

@ -0,0 +1,107 @@
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.api.IBufferDeviceService;
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 IBufferDeviceService 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);
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());
dtoList.add(dockDetailDTO);
}
return R.ok(DockWithGPSVOConvert.fromList(dtoList));
}
}

View File

@ -0,0 +1,138 @@
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.service.api.IBufferDeviceService;
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.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.List;
/**
* 分组Controller
*
* @author ruoyi
* @date 2026-01-20
*/
@RestController
@RequestMapping("/group")
public class GroupController extends BaseController
{
@Autowired
private IGroupService groupService;
@Autowired
private IBufferDeviceService bufferDeviceService;
/**
* 创建分组
*
* @param request 分组创建请求
* @return 分组ID
*/
//@InnerAuth
@PostMapping("/create")
public R<Long> createGroup(@RequestBody GroupCreateRequest request)
{
GroupDTO dto = new GroupDTO();
dto.setGroupName(request.getGroupName());
Long groupId = groupService.createGroup(dto);
return R.ok(groupId);
}
/**
* 删除分组
*
* @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)
{
GroupDTO dto = new GroupDTO();
dto.setGroupId(request.getGroupId());
dto.setGroupName(request.getGroupName());
groupService.updateGroup(dto);
return R.ok();
}
/**
* 切换机场所在的分组
*
* @param request 切换分组请求
* @return 结果
*/
@PostMapping("/switch")
public R<Void> switchDockGroup(@RequestBody SwitchDockGroupRequest request)
{
groupService.switchDockGroup(request.getDockId(), 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);
List<DockGroupDTO> groupDTOS = groupService.getDocksByGroupId(groupId);
List<DockDetailDTO> dtoList = new ArrayList<>();
for (DockGroupDTO dockGroupDTO : groupDTOS) {
DockDetailDTO dockDetailDTO = bufferDeviceService.getDockDetailById(dockGroupDTO.getDockId());
dtoList.add(dockDetailDTO);
}
return R.ok(DockWithGPSVOConvert.fromList(dtoList));
}
/**
* 查看所有分组
*
* @return 分组ID列表
*/
//@InnerAuth
@GetMapping("/list")
public R<List<GroupVO>> getAllGroupIds()
{
List<GroupDTO> groupDTOs = groupService.getAllGroupIds();
// Calculate aircraft count for each group
List<GroupVO> groupVOS = new ArrayList<>();
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);
}
}

View File

@ -0,0 +1,39 @@
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);
}
}

View File

@ -0,0 +1,56 @@
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);
}
}

View File

@ -0,0 +1,80 @@
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);
}
}

View File

@ -0,0 +1,52 @@
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);
}
}

View File

@ -0,0 +1,55 @@
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);
}
}

View File

@ -0,0 +1,39 @@
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);
}
}

View File

@ -0,0 +1,37 @@
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);
}
}

View File

@ -0,0 +1,69 @@
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);
}

View File

@ -0,0 +1,85 @@
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);
}

View File

@ -0,0 +1,69 @@
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);
/**
* 新增设备
*
* @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);
}

View File

@ -0,0 +1,29 @@
package com.ruoyi.device.domain.api;
import com.ruoyi.device.domain.model.DeviceTemp;
import java.util.List;
/**
* 设备临时表Domain接口
*
* @author ruoyi
* @date 2026-01-15
*/
public interface IDeviceTempDomain
{
/**
* 查询设备临时表列表
*
* @param deviceTemp 设备临时表
* @return 设备临时表集合
*/
List<DeviceTemp> selectDeviceTempList(DeviceTemp deviceTemp);
/**
* 根据ID查询设备临时表
*
* @param id 主键ID
* @return 设备临时表
*/
DeviceTemp selectDeviceTempById(String id);
}

View File

@ -0,0 +1,77 @@
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);
}

View File

@ -0,0 +1,69 @@
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);
}

View File

@ -0,0 +1,77 @@
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);
}

View File

@ -0,0 +1,61 @@
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);
}

View File

@ -0,0 +1,61 @@
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);
}

View File

@ -0,0 +1,94 @@
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);
}

View File

@ -0,0 +1,39 @@
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);
}
}

View File

@ -0,0 +1,40 @@
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);
}
}

View File

@ -0,0 +1,39 @@
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);
}
}

View File

@ -0,0 +1,58 @@
package com.ruoyi.device.domain.convert;
import com.ruoyi.device.domain.model.DeviceTemp;
import com.ruoyi.device.mapper.entity.DeviceTempEntity;
import org.springframework.beans.BeanUtils;
import java.util.List;
import java.util.stream.Collectors;
/**
* 设备临时表Domain层转换器
* Domain Model Mapper Entity
*
* @author ruoyi
* @date 2026-01-15
*/
public class DeviceTempDomainEntityConvert
{
/**
* Entity Model
*/
public static DeviceTemp toModel(DeviceTempEntity entity)
{
if (entity == null)
{
return null;
}
DeviceTemp model = new DeviceTemp();
BeanUtils.copyProperties(entity, model);
return model;
}
/**
* Model Entity
*/
public static DeviceTempEntity toEntity(DeviceTemp model)
{
if (model == null)
{
return null;
}
DeviceTempEntity entity = new DeviceTempEntity();
BeanUtils.copyProperties(model, entity);
return entity;
}
/**
* Entity List Model List
*/
public static List<DeviceTemp> toModelList(List<DeviceTempEntity> entityList)
{
if (entityList == null)
{
return null;
}
return entityList.stream().map(DeviceTempDomainEntityConvert::toModel).collect(Collectors.toList());
}
}

View File

@ -0,0 +1,41 @@
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);
}
}

View File

@ -0,0 +1,42 @@
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);
}
}

View File

@ -0,0 +1,39 @@
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);
}
}

View File

@ -0,0 +1,39 @@
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);
}
}

View File

@ -0,0 +1,40 @@
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);
}
}

View File

@ -0,0 +1,78 @@
package com.ruoyi.device.domain.impl;
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.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
public Aircraft selectAircraftByAircraftId(Long aircraftId)
{
AircraftEntity entity = aircraftMapper.selectAircraftByAircraftId(aircraftId);
return AircraftConvert.from(entity);
}
@Override
public Aircraft selectAircraftByDeviceId(Long deviceId)
{
AircraftEntity entity = aircraftMapper.selectAircraftByDeviceId(deviceId);
return AircraftConvert.from(entity);
}
@Override
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
public int updateAircraft(Aircraft aircraft)
{
AircraftEntity entity = AircraftConvert.to(aircraft);
return aircraftMapper.updateAircraft(entity);
}
@Override
public int deleteAircraftByAircraftId(Long aircraftId)
{
return aircraftMapper.deleteAircraftByAircraftId(aircraftId);
}
@Override
public int deleteAircraftByAircraftIds(Long[] aircraftIds)
{
return aircraftMapper.deleteAircraftByAircraftIds(aircraftIds);
}
}

View File

@ -0,0 +1,92 @@
package com.ruoyi.device.domain.impl;
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.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
public AircraftPayload selectAircraftPayloadById(Long id)
{
AircraftPayloadEntity entity = aircraftPayloadMapper.selectAircraftPayloadById(id);
return AircraftPayloadConvert.from(entity);
}
@Override
public List<AircraftPayload> selectAircraftPayloadByAircraftId(Long aircraftId)
{
List<AircraftPayloadEntity> entityList = aircraftPayloadMapper.selectAircraftPayloadListByAircraftId(aircraftId);
return AircraftPayloadConvert.fromList(entityList);
}
@Override
public List<AircraftPayload> selectAircraftPayloadByPayloadId(Long payloadId)
{
List<AircraftPayloadEntity> entityList = aircraftPayloadMapper.selectAircraftPayloadListByPayloadId(payloadId);
return AircraftPayloadConvert.fromList(entityList);
}
@Override
public List<AircraftPayload> selectAircraftPayloadByDockId(Long dockId)
{
List<AircraftPayloadEntity> entityList = aircraftPayloadMapper.selectAircraftPayloadListByDockId(dockId);
return AircraftPayloadConvert.fromList(entityList);
}
@Override
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
public int updateAircraftPayload(AircraftPayload aircraftPayload)
{
AircraftPayloadEntity entity = AircraftPayloadConvert.to(aircraftPayload);
return aircraftPayloadMapper.updateAircraftPayload(entity);
}
@Override
public int deleteAircraftPayloadById(Long id)
{
return aircraftPayloadMapper.deleteAircraftPayloadById(id);
}
@Override
public int deleteAircraftPayloadByIds(Long[] ids)
{
return aircraftPayloadMapper.deleteAircraftPayloadByIds(ids);
}
}

View File

@ -0,0 +1,78 @@
package com.ruoyi.device.domain.impl;
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 org.springframework.stereotype.Component;
import java.util.List;
/**
* 设备Domain实现
*
* @author ruoyi
* @date 2026-01-16
*/
@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
public Device selectDeviceByDeviceId(Long deviceId)
{
DeviceEntity entity = deviceMapper.selectDeviceByDeviceId(deviceId);
return DeviceConvert.from(entity);
}
@Override
public Device selectDeviceByIotDeviceId(String iotDeviceId)
{
DeviceEntity entity = deviceMapper.selectDeviceByIotDeviceId(iotDeviceId);
return DeviceConvert.from(entity);
}
@Override
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
public int updateDevice(Device device)
{
DeviceEntity entity = DeviceConvert.to(device);
return deviceMapper.updateDevice(entity);
}
@Override
public int deleteDeviceByDeviceId(Long deviceId)
{
return deviceMapper.deleteDeviceByDeviceId(deviceId);
}
@Override
public int deleteDeviceByDeviceIds(Long[] deviceIds)
{
return deviceMapper.deleteDeviceByDeviceIds(deviceIds);
}
}

View File

@ -0,0 +1,39 @@
package com.ruoyi.device.domain.impl;
import com.ruoyi.device.domain.api.IDeviceTempDomain;
import com.ruoyi.device.domain.convert.DeviceTempDomainEntityConvert;
import com.ruoyi.device.domain.model.DeviceTemp;
import com.ruoyi.device.mapper.DeviceTempMapper;
import com.ruoyi.device.mapper.entity.DeviceTempEntity;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* 设备临时表Domain实现
*
* @author ruoyi
* @date 2026-01-15
*/
@Component
public class DeviceTempDomainImpl implements IDeviceTempDomain
{
@Autowired
private DeviceTempMapper deviceTempMapper;
@Override
public List<DeviceTemp> selectDeviceTempList(DeviceTemp deviceTempModel)
{
DeviceTempEntity entity = DeviceTempDomainEntityConvert.toEntity(deviceTempModel);
List<DeviceTempEntity> entityList = deviceTempMapper.selectDeviceTempList(entity);
return DeviceTempDomainEntityConvert.toModelList(entityList);
}
@Override
public DeviceTemp selectDeviceTempById(String id)
{
DeviceTempEntity entity = deviceTempMapper.selectDeviceTempById(id);
return DeviceTempDomainEntityConvert.toModel(entity);
}
}

View File

@ -0,0 +1,85 @@
package com.ruoyi.device.domain.impl;
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.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
public DockAircraft selectDockAircraftById(Long id)
{
DockAircraftEntity entity = dockAircraftMapper.selectDockAircraftById(id);
return DockAircraftConvert.from(entity);
}
@Override
public List<DockAircraft> selectDockAircraftByDockId(Long dockId)
{
List<DockAircraftEntity> entityList = dockAircraftMapper.selectDockAircraftListByDockId(dockId);
return DockAircraftConvert.fromList(entityList);
}
@Override
public List<DockAircraft> selectDockAircraftByAircraftId(Long aircraftId)
{
List<DockAircraftEntity> entityList = dockAircraftMapper.selectDockAircraftListByAircraftId(aircraftId);
return DockAircraftConvert.fromList(entityList);
}
@Override
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
public int updateDockAircraft(DockAircraft dockAircraft)
{
DockAircraftEntity entity = DockAircraftConvert.to(dockAircraft);
return dockAircraftMapper.updateDockAircraft(entity);
}
@Override
public int deleteDockAircraftById(Long id)
{
return dockAircraftMapper.deleteDockAircraftById(id);
}
@Override
public int deleteDockAircraftByIds(Long[] ids)
{
return dockAircraftMapper.deleteDockAircraftByIds(ids);
}
}

View File

@ -0,0 +1,78 @@
package com.ruoyi.device.domain.impl;
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.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
public Dock selectDockByDockId(Long dockId)
{
DockEntity entity = dockMapper.selectDockByDockId(dockId);
return DockConvert.from(entity);
}
@Override
public Dock selectDockByDeviceId(Long deviceId)
{
DockEntity entity = dockMapper.selectDockByDeviceId(deviceId);
return DockConvert.from(entity);
}
@Override
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
public int updateDock(Dock dock)
{
DockEntity entity = DockConvert.to(dock);
return dockMapper.updateDock(entity);
}
@Override
public int deleteDockByDockId(Long dockId)
{
return dockMapper.deleteDockByDockId(dockId);
}
@Override
public int deleteDockByDockIds(Long[] dockIds)
{
return dockMapper.deleteDockByDockIds(dockIds);
}
}

View File

@ -0,0 +1,85 @@
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);
}
}

View File

@ -0,0 +1,71 @@
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);
}
}

View File

@ -0,0 +1,71 @@
package com.ruoyi.device.domain.impl;
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.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
public Payload selectPayloadByPayloadId(Long payloadId)
{
PayloadEntity entity = payloadMapper.selectPayloadByPayloadId(payloadId);
return PayloadConvert.from(entity);
}
@Override
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
public int updatePayload(Payload payload)
{
PayloadEntity entity = PayloadConvert.to(payload);
return payloadMapper.updatePayload(entity);
}
@Override
public int deletePayloadByPayloadId(Long payloadId)
{
return payloadMapper.deletePayloadByPayloadId(payloadId);
}
@Override
public int deletePayloadByPayloadIds(Long[] payloadIds)
{
return payloadMapper.deletePayloadByPayloadIds(payloadIds);
}
}

View File

@ -0,0 +1,334 @@
package com.ruoyi.device.domain.impl;
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 org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
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
public AttributeMap getDeviceAttributes(String deviceId) {
AttributeMap attributeMap = new AttributeMap();
try {
DeviceId id = new DeviceId(UUID.fromString(deviceId));
// 获取所有属性键
List<String> attributeKeys = client.getAttributeKeys(id);
if (attributeKeys == null || attributeKeys.isEmpty()) {
log.debug("设备 {} 没有属性", deviceId);
return attributeMap;
}
// 获取属性值
List<AttributeKvEntry> attributeKvEntries = client.getAttributeKvEntries(id, attributeKeys);
if (attributeKvEntries == null || attributeKvEntries.isEmpty()) {
log.debug("设备 {} 的属性值为空", deviceId);
return attributeMap;
}
// 解析并填充到AttributeMap
for (AttributeKvEntry entry : attributeKvEntries) {
parseAndPutAttribute(attributeMap, entry);
}
} catch (Exception e) {
log.error("获取设备属性失败: deviceId={}, error={}", deviceId, e.getMessage(), e);
}
return attributeMap;
}
@Override
public TelemetryMap getDeviceTelemetry(String deviceId) {
TelemetryMap telemetryMap = new TelemetryMap();
try {
DeviceId id = new DeviceId(UUID.fromString(deviceId));
// 获取所有遥测键
List<String> timeseriesKeys = client.getTimeseriesKeys(id);
if (timeseriesKeys == null || timeseriesKeys.isEmpty()) {
log.debug("设备 {} 没有遥测数据", deviceId);
return telemetryMap;
}
// 获取最新的遥测数据
List<TsKvEntry> latestTimeseries = client.getLatestTimeseries(id, timeseriesKeys);
if (latestTimeseries == null || latestTimeseries.isEmpty()) {
log.debug("设备 {} 的遥测数据为空", deviceId);
return telemetryMap;
}
// 解析并填充到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());
}
}
}

View File

@ -0,0 +1,120 @@
package com.ruoyi.device.domain.model;
import java.io.Serializable;
import java.util.Date;
/**
* 无人机领域模型
* Domain 层对外暴露的对象
*
* @author ruoyi
* @date 2026-01-16
*/
public class Aircraft implements Serializable
{
private static final long serialVersionUID = 1L;
/** 无人机主键 */
private Long aircraftId;
/** 无人机名称 */
private String aircraftName;
/** 设备表主键 */
private Long deviceId;
/** 创建者 */
private String createBy;
/** 创建时间 */
private Date createTime;
/** 更新者 */
private String updateBy;
/** 更新时间 */
private Date updateTime;
/** 备注 */
private String remark;
public Long getAircraftId()
{
return aircraftId;
}
public void setAircraftId(Long aircraftId)
{
this.aircraftId = aircraftId;
}
public String getAircraftName()
{
return aircraftName;
}
public void setAircraftName(String aircraftName)
{
this.aircraftName = aircraftName;
}
public Long getDeviceId()
{
return deviceId;
}
public void setDeviceId(Long deviceId)
{
this.deviceId = deviceId;
}
public String getCreateBy()
{
return createBy;
}
public void setCreateBy(String createBy)
{
this.createBy = createBy;
}
public Date getCreateTime()
{
return createTime;
}
public void setCreateTime(Date createTime)
{
this.createTime = createTime;
}
public String getUpdateBy()
{
return updateBy;
}
public void setUpdateBy(String updateBy)
{
this.updateBy = updateBy;
}
public Date getUpdateTime()
{
return updateTime;
}
public void setUpdateTime(Date updateTime)
{
this.updateTime = updateTime;
}
public String getRemark()
{
return remark;
}
public void setRemark(String remark)
{
this.remark = remark;
}
}

View File

@ -0,0 +1,133 @@
package com.ruoyi.device.domain.model;
import java.io.Serializable;
import java.util.Date;
/**
* 无人机挂载关联领域模型
* Domain 层对外暴露的对象
*
* @author ruoyi
* @date 2026-01-16
*/
public class AircraftPayload implements Serializable
{
private static final long serialVersionUID = 1L;
/** 关联主键 */
private Long id;
/** 无人机主键 */
private Long aircraftId;
/** 挂载主键 */
private Long payloadId;
/** 机场主键 */
private Long dockId;
/** 创建者 */
private String createBy;
/** 创建时间 */
private Date createTime;
/** 更新者 */
private String updateBy;
/** 更新时间 */
private Date updateTime;
/** 备注 */
private String remark;
public Long getId()
{
return id;
}
public void setId(Long id)
{
this.id = id;
}
public Long getAircraftId()
{
return aircraftId;
}
public void setAircraftId(Long aircraftId)
{
this.aircraftId = aircraftId;
}
public Long getPayloadId()
{
return payloadId;
}
public void setPayloadId(Long payloadId)
{
this.payloadId = payloadId;
}
public Long getDockId()
{
return dockId;
}
public void setDockId(Long dockId)
{
this.dockId = dockId;
}
public String getCreateBy()
{
return createBy;
}
public void setCreateBy(String createBy)
{
this.createBy = createBy;
}
public Date getCreateTime()
{
return createTime;
}
public void setCreateTime(Date createTime)
{
this.createTime = createTime;
}
public String getUpdateBy()
{
return updateBy;
}
public void setUpdateBy(String updateBy)
{
this.updateBy = updateBy;
}
public Date getUpdateTime()
{
return updateTime;
}
public void setUpdateTime(Date updateTime)
{
this.updateTime = updateTime;
}
public String getRemark()
{
return remark;
}
public void setRemark(String remark)
{
this.remark = remark;
}
}

View File

@ -0,0 +1,198 @@
package com.ruoyi.device.domain.model;
import java.io.Serializable;
import java.util.Date;
/**
* 设备领域模型
* Domain 层对外暴露的对象
*
* @author ruoyi
* @date 2026-01-16
*/
public class Device implements Serializable
{
private static final long serialVersionUID = 1L;
/** 设备主键 */
private Long deviceId;
/** 设备名称 */
private String deviceName;
/** IOT中的设备ID */
private String iotDeviceId;
/** 设备类型 */
private String deviceType;
/** 设备厂商 */
private String deviceManufacturer;
/** 设备型号 */
private String deviceModel;
/** 设备SN号 */
private String deviceSn;
/** 所属部门主键 */
private Long deptId;
/** 网关 */
private String gateway;
/** 创建者 */
private String createBy;
/** 创建时间 */
private Date createTime;
/** 更新者 */
private String updateBy;
/** 更新时间 */
private Date updateTime;
/** 备注 */
private String remark;
public Long getDeviceId()
{
return deviceId;
}
public void setDeviceId(Long deviceId)
{
this.deviceId = deviceId;
}
public String getDeviceName()
{
return deviceName;
}
public void setDeviceName(String deviceName)
{
this.deviceName = deviceName;
}
public String getIotDeviceId()
{
return iotDeviceId;
}
public void setIotDeviceId(String iotDeviceId)
{
this.iotDeviceId = iotDeviceId;
}
public String getDeviceType()
{
return deviceType;
}
public void setDeviceType(String deviceType)
{
this.deviceType = deviceType;
}
public String getDeviceManufacturer()
{
return deviceManufacturer;
}
public void setDeviceManufacturer(String deviceManufacturer)
{
this.deviceManufacturer = deviceManufacturer;
}
public String getDeviceModel()
{
return deviceModel;
}
public void setDeviceModel(String deviceModel)
{
this.deviceModel = deviceModel;
}
public String getDeviceSn()
{
return deviceSn;
}
public void setDeviceSn(String deviceSn)
{
this.deviceSn = deviceSn;
}
public Long getDeptId()
{
return deptId;
}
public void setDeptId(Long deptId)
{
this.deptId = deptId;
}
public String getGateway()
{
return gateway;
}
public void setGateway(String gateway)
{
this.gateway = gateway;
}
public String getCreateBy()
{
return createBy;
}
public void setCreateBy(String createBy)
{
this.createBy = createBy;
}
public Date getCreateTime()
{
return createTime;
}
public void setCreateTime(Date createTime)
{
this.createTime = createTime;
}
public String getUpdateBy()
{
return updateBy;
}
public void setUpdateBy(String updateBy)
{
this.updateBy = updateBy;
}
public Date getUpdateTime()
{
return updateTime;
}
public void setUpdateTime(Date updateTime)
{
this.updateTime = updateTime;
}
public String getRemark()
{
return remark;
}
public void setRemark(String remark)
{
this.remark = remark;
}
}

View File

@ -0,0 +1,55 @@
package com.ruoyi.device.domain.model;
import java.io.Serializable;
import java.util.Date;
/**
* 设备临时表领域模型
* Domain 层对外暴露的对象
*
* @author ruoyi
* @date 2026-01-15
*/
public class DeviceTemp implements Serializable
{
private static final long serialVersionUID = 1L;
/** 主键ID */
private String id;
/** 创建时间 */
private Date createTime;
/** 更新时间 */
private Date updateTime;
public String getId()
{
return id;
}
public void setId(String id)
{
this.id = id;
}
public Date getCreateTime()
{
return createTime;
}
public void setCreateTime(Date createTime)
{
this.createTime = createTime;
}
public Date getUpdateTime()
{
return updateTime;
}
public void setUpdateTime(Date updateTime)
{
this.updateTime = updateTime;
}
}

View File

@ -0,0 +1,133 @@
package com.ruoyi.device.domain.model;
import java.io.Serializable;
import java.util.Date;
/**
* 机场领域模型
* Domain 层对外暴露的对象
*
* @author ruoyi
* @date 2026-01-16
*/
public class Dock implements Serializable
{
private static final long serialVersionUID = 1L;
/** 机场主键 */
private Long dockId;
/** 机场名称 */
private String dockName;
/** 机场位置 */
private String dockLocation;
/** 设备表主键 */
private Long deviceId;
/** 创建者 */
private String createBy;
/** 创建时间 */
private Date createTime;
/** 更新者 */
private String updateBy;
/** 更新时间 */
private Date updateTime;
/** 备注 */
private String remark;
public Long getDockId()
{
return dockId;
}
public void setDockId(Long dockId)
{
this.dockId = dockId;
}
public String getDockName()
{
return dockName;
}
public void setDockName(String dockName)
{
this.dockName = dockName;
}
public String getDockLocation()
{
return dockLocation;
}
public void setDockLocation(String dockLocation)
{
this.dockLocation = dockLocation;
}
public Long getDeviceId()
{
return deviceId;
}
public void setDeviceId(Long deviceId)
{
this.deviceId = deviceId;
}
public String getCreateBy()
{
return createBy;
}
public void setCreateBy(String createBy)
{
this.createBy = createBy;
}
public Date getCreateTime()
{
return createTime;
}
public void setCreateTime(Date createTime)
{
this.createTime = createTime;
}
public String getUpdateBy()
{
return updateBy;
}
public void setUpdateBy(String updateBy)
{
this.updateBy = updateBy;
}
public Date getUpdateTime()
{
return updateTime;
}
public void setUpdateTime(Date updateTime)
{
this.updateTime = updateTime;
}
public String getRemark()
{
return remark;
}
public void setRemark(String remark)
{
this.remark = remark;
}
}

View File

@ -0,0 +1,120 @@
package com.ruoyi.device.domain.model;
import java.io.Serializable;
import java.util.Date;
/**
* 机场无人机关联领域模型
* Domain 层对外暴露的对象
*
* @author ruoyi
* @date 2026-01-16
*/
public class DockAircraft implements Serializable
{
private static final long serialVersionUID = 1L;
/** 关联主键 */
private Long id;
/** 机场主键 */
private Long dockId;
/** 无人机主键 */
private Long aircraftId;
/** 创建者 */
private String createBy;
/** 创建时间 */
private Date createTime;
/** 更新者 */
private String updateBy;
/** 更新时间 */
private Date updateTime;
/** 备注 */
private String remark;
public Long getId()
{
return id;
}
public void setId(Long id)
{
this.id = id;
}
public Long getDockId()
{
return dockId;
}
public void setDockId(Long dockId)
{
this.dockId = dockId;
}
public Long getAircraftId()
{
return aircraftId;
}
public void setAircraftId(Long aircraftId)
{
this.aircraftId = aircraftId;
}
public String getCreateBy()
{
return createBy;
}
public void setCreateBy(String createBy)
{
this.createBy = createBy;
}
public Date getCreateTime()
{
return createTime;
}
public void setCreateTime(Date createTime)
{
this.createTime = createTime;
}
public String getUpdateBy()
{
return updateBy;
}
public void setUpdateBy(String updateBy)
{
this.updateBy = updateBy;
}
public Date getUpdateTime()
{
return updateTime;
}
public void setUpdateTime(Date updateTime)
{
this.updateTime = updateTime;
}
public String getRemark()
{
return remark;
}
public void setRemark(String remark)
{
this.remark = remark;
}
}

View File

@ -0,0 +1,120 @@
package com.ruoyi.device.domain.model;
import java.io.Serializable;
import java.util.Date;
/**
* 机场分组关联领域模型
* Domain 层对外暴露的对象
*
* @author ruoyi
* @date 2026-01-16
*/
public class DockGroup implements Serializable
{
private static final long serialVersionUID = 1L;
/** 关联主键 */
private Long id;
/** 机场主键 */
private Long dockId;
/** 分组主键 */
private Long groupId;
/** 创建者 */
private String createBy;
/** 创建时间 */
private Date createTime;
/** 更新者 */
private String updateBy;
/** 更新时间 */
private Date updateTime;
/** 备注 */
private String remark;
public Long getId()
{
return id;
}
public void setId(Long id)
{
this.id = id;
}
public Long getDockId()
{
return dockId;
}
public void setDockId(Long dockId)
{
this.dockId = dockId;
}
public Long getGroupId()
{
return groupId;
}
public void setGroupId(Long groupId)
{
this.groupId = groupId;
}
public String getCreateBy()
{
return createBy;
}
public void setCreateBy(String createBy)
{
this.createBy = createBy;
}
public Date getCreateTime()
{
return createTime;
}
public void setCreateTime(Date createTime)
{
this.createTime = createTime;
}
public String getUpdateBy()
{
return updateBy;
}
public void setUpdateBy(String updateBy)
{
this.updateBy = updateBy;
}
public Date getUpdateTime()
{
return updateTime;
}
public void setUpdateTime(Date updateTime)
{
this.updateTime = updateTime;
}
public String getRemark()
{
return remark;
}
public void setRemark(String remark)
{
this.remark = remark;
}
}

View File

@ -0,0 +1,107 @@
package com.ruoyi.device.domain.model;
import java.io.Serializable;
import java.util.Date;
/**
* 分组领域模型
* Domain 层对外暴露的对象
*
* @author ruoyi
* @date 2026-01-16
*/
public class Group implements Serializable
{
private static final long serialVersionUID = 1L;
/** 分组主键 */
private Long groupId;
/** 分组名称 */
private String groupName;
/** 创建者 */
private String createBy;
/** 创建时间 */
private Date createTime;
/** 更新者 */
private String updateBy;
/** 更新时间 */
private Date updateTime;
/** 备注 */
private String remark;
public Long getGroupId()
{
return groupId;
}
public void setGroupId(Long groupId)
{
this.groupId = groupId;
}
public String getGroupName()
{
return groupName;
}
public void setGroupName(String groupName)
{
this.groupName = groupName;
}
public String getCreateBy()
{
return createBy;
}
public void setCreateBy(String createBy)
{
this.createBy = createBy;
}
public Date getCreateTime()
{
return createTime;
}
public void setCreateTime(Date createTime)
{
this.createTime = createTime;
}
public String getUpdateBy()
{
return updateBy;
}
public void setUpdateBy(String updateBy)
{
this.updateBy = updateBy;
}
public Date getUpdateTime()
{
return updateTime;
}
public void setUpdateTime(Date updateTime)
{
this.updateTime = updateTime;
}
public String getRemark()
{
return remark;
}
public void setRemark(String remark)
{
this.remark = remark;
}
}

View File

@ -0,0 +1,172 @@
package com.ruoyi.device.domain.model;
import java.io.Serializable;
import java.util.Date;
/**
* 挂载领域模型
* Domain 层对外暴露的对象
*
* @author ruoyi
* @date 2026-01-16
*/
public class Payload implements Serializable
{
private static final long serialVersionUID = 1L;
/** 挂载主键 */
private Long payloadId;
/** 挂载名称 */
private String payloadName;
/** 挂载类型 */
private String payloadType;
/** 挂载显示名称 */
private String payloadDisplayName;
/** 挂载动态信息 */
private String payloadDynamicInfo;
/** 挂载SN号 */
private String payloadSn;
/** IOT中的设备ID */
private String iotDeviceId;
/** 创建者 */
private String createBy;
/** 创建时间 */
private Date createTime;
/** 更新者 */
private String updateBy;
/** 更新时间 */
private Date updateTime;
/** 备注 */
private String remark;
public Long getPayloadId()
{
return payloadId;
}
public void setPayloadId(Long payloadId)
{
this.payloadId = payloadId;
}
public String getPayloadName()
{
return payloadName;
}
public void setPayloadName(String payloadName)
{
this.payloadName = payloadName;
}
public String getPayloadType()
{
return payloadType;
}
public void setPayloadType(String payloadType)
{
this.payloadType = payloadType;
}
public String getPayloadDisplayName()
{
return payloadDisplayName;
}
public void setPayloadDisplayName(String payloadDisplayName)
{
this.payloadDisplayName = payloadDisplayName;
}
public String getPayloadDynamicInfo()
{
return payloadDynamicInfo;
}
public void setPayloadDynamicInfo(String payloadDynamicInfo)
{
this.payloadDynamicInfo = payloadDynamicInfo;
}
public String getPayloadSn()
{
return payloadSn;
}
public void setPayloadSn(String payloadSn)
{
this.payloadSn = payloadSn;
}
public String getIotDeviceId()
{
return iotDeviceId;
}
public void setIotDeviceId(String iotDeviceId)
{
this.iotDeviceId = iotDeviceId;
}
public String getCreateBy()
{
return createBy;
}
public void setCreateBy(String createBy)
{
this.createBy = createBy;
}
public Date getCreateTime()
{
return createTime;
}
public void setCreateTime(Date createTime)
{
this.createTime = createTime;
}
public String getUpdateBy()
{
return updateBy;
}
public void setUpdateBy(String updateBy)
{
this.updateBy = updateBy;
}
public Date getUpdateTime()
{
return updateTime;
}
public void setUpdateTime(Date updateTime)
{
this.updateTime = updateTime;
}
public String getRemark()
{
return remark;
}
public void setRemark(String remark)
{
this.remark = remark;
}
}

View File

@ -0,0 +1,144 @@
package com.ruoyi.device.domain.model.thingsboard;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
/**
* 类型安全的属性键
* 使用泛型确保类型安全避免使用Object作为返回值
*
* @param <T> 属性值的类型
*/
public class AttributeKey<T> {
private final String name;
private final Class<T> type;
private final ValueParser<T> parser;
private static final Map<String, AttributeKey<?>> REGISTRY = new ConcurrentHashMap<>();
private AttributeKey(String name, Class<T> type, ValueParser<T> parser) {
this.name = name;
this.type = type;
this.parser = parser;
}
/**
* 创建属性键并注册
*/
public static <T> AttributeKey<T> of(String name, Class<T> type, ValueParser<T> parser) {
AttributeKey<T> key = new AttributeKey<>(name, type, parser);
REGISTRY.put(name, key);
return key;
}
/**
* 根据名称查找已注册的属性键
*/
public static Optional<AttributeKey<?>> findByName(String name) {
return Optional.ofNullable(REGISTRY.get(name));
}
/**
* 获取或创建属性键延迟注册
* 如果键已存在则返回否则根据值自动推断类型并创建
*
* @param name 属性名称
* @param value 属性值
* @return 属性键
*/
public static AttributeKey<?> getOrCreate(String name, Object value) {
return REGISTRY.computeIfAbsent(name, k -> inferKeyFromValue(name, value));
}
/**
* 获取所有已注册的属性键集合
*
* @return 所有已注册的属性键
*/
public static Map<String, AttributeKey<?>> getAllRegisteredKeys() {
return new ConcurrentHashMap<>(REGISTRY);
}
/**
* 解析原始值为目标类型
*/
public T parse(Object rawValue) {
return parser.parse(rawValue);
}
public String getName() {
return name;
}
public Class<T> getType() {
return type;
}
@Override
public String toString() {
return "AttributeKey{" +
"name='" + name + '\'' +
", type=" + type.getSimpleName() +
'}';
}
/**
* 根据值自动推断类型并创建属性键
* 注意这个方法不能调用 of() 方法因为会导致递归更新
*/
@SuppressWarnings("unchecked")
private static <T> AttributeKey<T> inferKeyFromValue(String name, Object value) {
if (value == null) {
// 默认为 String 类型
return (AttributeKey<T>) new AttributeKey<>(name, String.class, v -> v != null ? v.toString() : null);
}
// 根据值的实际类型推断
if (value instanceof Boolean) {
return (AttributeKey<T>) new AttributeKey<>(name, Boolean.class, v -> {
if (v == null) return null;
if (v instanceof Boolean) return (Boolean) v;
return Boolean.parseBoolean(v.toString());
});
} else if (value instanceof Integer) {
// Integer 类型优先处理
return (AttributeKey<T>) new AttributeKey<>(name, Integer.class, v -> {
if (v == null) return null;
if (v instanceof Number) return ((Number) v).intValue();
return Integer.parseInt(v.toString());
});
} else if (value instanceof Long) {
// Long 类型
return (AttributeKey<T>) new AttributeKey<>(name, Long.class, v -> {
if (v == null) return null;
if (v instanceof Number) return ((Number) v).longValue();
return Long.parseLong(v.toString());
});
} else if (value instanceof Double) {
// Double 类型优先处理
return (AttributeKey<T>) new AttributeKey<>(name, Double.class, v -> {
if (v == null) return null;
if (v instanceof Number) return ((Number) v).doubleValue();
return Double.parseDouble(v.toString());
});
} else if (value instanceof Float) {
// Float 类型
return (AttributeKey<T>) new AttributeKey<>(name, Float.class, v -> {
if (v == null) return null;
if (v instanceof Number) return ((Number) v).floatValue();
return Float.parseFloat(v.toString());
});
} else {
// 默认为 String 类型
return (AttributeKey<T>) new AttributeKey<>(name, String.class, v -> v != null ? v.toString() : null);
}
}
/**
* 值解析器接口
*/
@FunctionalInterface
public interface ValueParser<T> {
T parse(Object rawValue);
}
}

View File

@ -0,0 +1,76 @@
package com.ruoyi.device.domain.model.thingsboard;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
/**
* 类型安全的属性映射
* 解决了使用Object作为返回值的问题
*/
public class AttributeMap {
private final Map<AttributeKey<?>, Object> data = new HashMap<>();
/**
* 添加属性值类型安全
*/
public <T> void put(AttributeKey<T> key, T value) {
data.put(key, value);
}
/**
* 获取属性值类型安全
* 返回Optional避免null问题
*/
@SuppressWarnings("unchecked")
public <T> Optional<T> get(AttributeKey<T> key) {
return Optional.ofNullable((T) data.get(key));
}
/**
* 获取属性值如果不存在返回默认值
*/
@SuppressWarnings("unchecked")
public <T> T getOrDefault(AttributeKey<T> key, T defaultValue) {
return (T) data.getOrDefault(key, defaultValue);
}
/**
* 检查是否包含某个键
*/
public boolean containsKey(AttributeKey<?> key) {
return data.containsKey(key);
}
/**
* 获取所有键
*/
public Set<AttributeKey<?>> keySet() {
return data.keySet();
}
/**
* 获取属性数量
*/
public int size() {
return data.size();
}
/**
* 是否为空
*/
public boolean isEmpty() {
return data.isEmpty();
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder("AttributeMap{\n");
data.forEach((key, value) ->
sb.append(" ").append(key.getName()).append(": ").append(value).append("\n")
);
sb.append("}");
return sb.toString();
}
}

View File

@ -0,0 +1,38 @@
package com.ruoyi.device.domain.model.thingsboard;
/**
* 类型安全的属性值包装类
* 避免使用Object作为返回值
*
* @param <T> 值的类型
*/
public class AttributeValue<T> {
private final AttributeKey<T> key;
private final T value;
public AttributeValue(AttributeKey<T> key, T value) {
this.key = key;
this.value = value;
}
public AttributeKey<T> getKey() {
return key;
}
public T getValue() {
return value;
}
public String getKeyName() {
return key.getName();
}
public Class<T> getType() {
return key.getType();
}
@Override
public String toString() {
return key.getName() + ": " + value;
}
}

View File

@ -0,0 +1,66 @@
package com.ruoyi.device.domain.model.thingsboard;
import com.fasterxml.jackson.databind.JsonNode;
import org.thingsboard.server.common.data.id.DeviceId;
/**
* 设备信息
*/
public class DeviceInfo {
private final String name;
private final String id;
private final String type;
private final DeviceId deviceId;
private final JsonNode additionalInfo;
public DeviceInfo(String name, String id, String type, DeviceId deviceId, JsonNode additionalInfo) {
this.name = name;
this.id = id;
this.type = type;
this.deviceId = deviceId;
this.additionalInfo = additionalInfo;
}
public String getName() {
return name;
}
public String getId() {
return id;
}
public String getType() {
return type;
}
public DeviceId getDeviceId() {
return deviceId;
}
public JsonNode getAdditionalInfo() {
return additionalInfo;
}
/**
* 判断设备是否为网关
* 根据 ThingsBoard 标准检查 additionalInfo 中的 "gateway" 字段
*
* @return true 如果是网关设备否则返回 false
*/
public boolean isGateway() {
if (additionalInfo == null) {
return false;
}
return additionalInfo.has("gateway") && additionalInfo.get("gateway").asBoolean();
}
@Override
public String toString() {
return "DeviceInfo{" +
"name='" + name + '\'' +
", id='" + id + '\'' +
", type='" + type + '\'' +
", isGateway=" + isGateway() +
'}';
}
}

View File

@ -0,0 +1,69 @@
package com.ruoyi.device.domain.model.thingsboard;
import org.thingsboard.rest.client.RestClient;
import org.thingsboard.server.common.data.Device;
import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
/**
* 设备迭代器
* 支持分页遍历所有设备
*/
public class DeviceIterator implements Iterable<List<DeviceInfo>> {
private final RestClient client;
private final int pageSize;
public DeviceIterator(RestClient client, int pageSize) {
this.client = client;
this.pageSize = pageSize;
}
@Override
public Iterator<List<DeviceInfo>> iterator() {
return new Iterator<List<DeviceInfo>>() {
private PageLink pageLink = new PageLink(pageSize);
private PageData<Device> currentPage = null;
private boolean hasNextPage = true;
@Override
public boolean hasNext() {
return hasNextPage;
}
@Override
public List<DeviceInfo> next() {
if (!hasNext()) {
throw new NoSuchElementException("No more devices");
}
// 获取当前页数据
currentPage = client.getTenantDevices("", pageLink);
// 转换为DeviceInfo列表
List<DeviceInfo> deviceInfoList = currentPage.getData().stream()
.map(device -> new DeviceInfo(
device.getName(),
device.getId().getId().toString(),
device.getType(),
device.getId(),
device.getAdditionalInfo()
))
.toList();
// 准备下一页
if (currentPage.hasNext()) {
pageLink = pageLink.nextPageLink();
} else {
hasNextPage = false;
}
return deviceInfoList;
}
};
}
}

View File

@ -0,0 +1,141 @@
package com.ruoyi.device.domain.model.thingsboard;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.thingsboard.rest.client.RestClient;
import org.thingsboard.server.common.data.Device;
import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.stream.Collectors;
/**
* 网关设备迭代器
* 支持分页遍历所有网关设备
* 优化策略自动跳过没有网关设备的页只返回包含网关设备的批次
*
* 注意由于ThingsBoard不支持服务端过滤网关设备
* 本迭代器会在客户端过滤并自动跳过空结果页
*/
public class GatewayDeviceIterator implements Iterable<List<DeviceInfo>> {
private static final Logger log = LoggerFactory.getLogger(GatewayDeviceIterator.class);
private final RestClient client;
private final int pageSize;
public GatewayDeviceIterator(RestClient client, int pageSize) {
this.client = client;
this.pageSize = pageSize;
log.debug("初始化网关设备迭代器,页大小: {}", pageSize);
}
@Override
public Iterator<List<DeviceInfo>> iterator() {
return new Iterator<List<DeviceInfo>>() {
private PageLink pageLink = new PageLink(pageSize);
private List<DeviceInfo> nextBatch = null;
private boolean hasMorePages = true;
@Override
public boolean hasNext() {
// 如果已经有预加载的数据直接返回true
if (nextBatch != null && !nextBatch.isEmpty()) {
return true;
}
// 尝试加载下一批网关设备
loadNextBatch();
// 检查是否成功加载到数据
return nextBatch != null && !nextBatch.isEmpty();
}
@Override
public List<DeviceInfo> next() {
if (!hasNext()) {
throw new NoSuchElementException("No more gateway devices");
}
// 返回预加载的数据
List<DeviceInfo> result = nextBatch;
nextBatch = null; // 清空下次调用hasNext时会重新加载
return result;
}
/**
* 加载下一批网关设备
* 会自动跳过没有网关设备的页直到找到至少一个网关设备或没有更多页
*/
private void loadNextBatch() {
nextBatch = null;
int skippedPages = 0;
int totalDevicesScanned = 0;
log.debug("开始加载下一批网关设备");
// 循环直到找到至少一个网关设备或者没有更多页
while (hasMorePages && (nextBatch == null || nextBatch.isEmpty())) {
int currentPageNumber = pageLink.getPage();
// 获取当前页数据
log.debug("正在获取第 {} 页设备数据,页大小: {}", currentPageNumber, pageSize);
PageData<Device> currentPage = client.getTenantDevices("", pageLink);
int pageDeviceCount = currentPage.getData().size();
totalDevicesScanned += pageDeviceCount;
log.debug("第 {} 页返回 {} 个设备", currentPageNumber, pageDeviceCount);
// 转换为DeviceInfo列表并过滤出网关设备
nextBatch = currentPage.getData().stream()
.filter(device -> {
// 检查 additionalInfo 中的 gateway 字段
if (device.getAdditionalInfo() == null) {
return false;
}
return device.getAdditionalInfo().has("gateway")
&& device.getAdditionalInfo().get("gateway").asBoolean();
})
.map(device -> new DeviceInfo(
device.getName(),
device.getId().getId().toString(),
device.getType(),
device.getId(),
device.getAdditionalInfo()
))
.collect(Collectors.toList());
int gatewayCount = nextBatch != null ? nextBatch.size() : 0;
log.debug("第 {} 页过滤后得到 {} 个网关设备", currentPageNumber, gatewayCount);
// 如果当前页没有网关设备记录跳过
if (gatewayCount == 0) {
skippedPages++;
log.debug("第 {} 页没有网关设备,继续查找下一页", currentPageNumber);
}
// 准备下一页
if (currentPage.hasNext()) {
pageLink = pageLink.nextPageLink();
} else {
hasMorePages = false;
log.debug("已到达最后一页,总共扫描 {} 个设备,跳过 {} 个空页", totalDevicesScanned, skippedPages);
}
}
// 输出最终结果日志
if (nextBatch != null && !nextBatch.isEmpty()) {
log.info("成功加载 {} 个网关设备,共扫描 {} 个设备,跳过 {} 个空页",
nextBatch.size(), totalDevicesScanned, skippedPages);
} else {
log.info("没有找到更多网关设备,共扫描 {} 个设备,跳过 {} 个空页",
totalDevicesScanned, skippedPages);
}
}
};
}
}

View File

@ -0,0 +1,90 @@
package com.ruoyi.device.domain.model.thingsboard;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.thingsboard.rest.client.RestClient;
/**
* RestClient管理器
* 提供全局唯一的RestClient实例避免重复创建连接
*
* 注意RestClient内部已经实现了token自动刷新和重新登录机制
* 本管理器主要用于全局共享同一个连接实例
*/
@Component
public class RestClientManager {
private static final Logger log = LoggerFactory.getLogger(RestClientManager.class);
private volatile RestClient client;
private final String url;
private final String username;
private final String password;
/**
* 构造函数 - Spring 自动装配
* @param url ThingsBoard服务器地址默认 http://thingsboard-ce:8080
* @param username 用户名默认 tenant@thingsboard.org
* @param password 密码默认 tenant
*/
public RestClientManager(@Value("${thingsboard.url:http://thingsboard-ce:8080}") String url,
@Value("${thingsboard.username:tenant@thingsboard.org}") String username,
@Value("${thingsboard.password:tenant}") String password) {
this.url = url;
this.username = username;
this.password = password;
}
/**
* 获取RestClient实例
* 懒加载第一次调用时才创建并登录
*
* 注意RestClient内部已实现token自动刷新机制
* 即使长时间不使用下次请求时也会自动处理过期问题
*/
public RestClient getClient() {
if (client == null) {
synchronized (this) {
if (client == null) {
initClient();
}
}
}
return client;
}
/**
* 初始化并登录客户端
*/
private void initClient() {
try {
log.info("正在连接到ThingsBoard: {}", url);
client = new RestClient(url);
client.login(username, password);
log.info("登录成功");
} catch (Exception e) {
log.error("登录失败: {}", e.getMessage(), e);
throw new RuntimeException("无法连接到ThingsBoard服务器", e);
}
}
/**
* 关闭客户端连接
* 注意关闭后需要重新获取实例才能使用
*/
public synchronized void close() {
if (client != null) {
try {
client.logout();
client.close();
log.info("客户端已关闭");
} catch (Exception e) {
log.error("关闭客户端时出错: {}", e.getMessage(), e);
} finally {
client = null;
}
}
}
}

View File

@ -0,0 +1,264 @@
package com.ruoyi.device.domain.model.thingsboard;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ruoyi.device.domain.model.thingsboard.attributes.psdk.PsdkDevice;
import com.ruoyi.device.domain.model.thingsboard.attributes.battery.BatteryData;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
/**
* 类型安全的遥测数据键
* 包含时间戳信息
*
* @param <T> 遥测值的类型
*/
public class TelemetryKey<T> {
private final String name;
private final Class<T> type;
private final ValueParser<T> parser;
private static final Map<String, TelemetryKey<?>> REGISTRY = new ConcurrentHashMap<>();
private TelemetryKey(String name, Class<T> type, ValueParser<T> parser) {
this.name = name;
this.type = type;
this.parser = parser;
}
/**
* 创建遥测键并注册
*/
public static <T> TelemetryKey<T> of(String name, Class<T> type, ValueParser<T> parser) {
TelemetryKey<T> key = new TelemetryKey<>(name, type, parser);
REGISTRY.put(name, key);
return key;
}
/**
* 根据名称查找已注册的遥测键
*/
public static Optional<TelemetryKey<?>> findByName(String name) {
return Optional.ofNullable(REGISTRY.get(name));
}
/**
* 获取或创建遥测键延迟注册
* 如果键已存在则返回否则根据值自动推断类型并创建
*
* @param name 遥测数据名称
* @param value 遥测数据值
* @return 遥测键
*/
public static TelemetryKey<?> getOrCreate(String name, Object value) {
return REGISTRY.computeIfAbsent(name, k -> inferKeyFromValue(name, value));
}
/**
* 获取所有已注册的遥测键集合
*
* @return 所有已注册的遥测键
*/
public static Map<String, TelemetryKey<?>> getAllRegisteredKeys() {
return new ConcurrentHashMap<>(REGISTRY);
}
/**
* 解析原始值为目标类型
*/
public T parse(Object rawValue) {
return parser.parse(rawValue);
}
public String getName() {
return name;
}
public Class<T> getType() {
return type;
}
@Override
public String toString() {
return "TelemetryKey{" +
"name='" + name + '\'' +
", type=" + type.getSimpleName() +
'}';
}
/**
* 根据值自动推断类型并创建遥测键
* 注意这个方法不能调用 of() 方法因为会导致递归更新
*/
@SuppressWarnings("unchecked")
private static <T> TelemetryKey<T> inferKeyFromValue(String name, Object value) {
if (value == null) {
// 默认为 String 类型
return (TelemetryKey<T>) new TelemetryKey<>(name, String.class, v -> v != null ? v.toString() : null);
}
// 特殊处理psdk_widget_values 字段
if ("psdk_widget_values".equals(name)) {
return (TelemetryKey<T>) createPsdkWidgetValuesKeyWithoutRegistering();
}
// 特殊处理battery 字段
if ("battery".equals(name)) {
return (TelemetryKey<T>) createBatteryKeyWithoutRegistering();
}
// 根据值的实际类型推断
if (value instanceof Boolean) {
return (TelemetryKey<T>) new TelemetryKey<>(name, Boolean.class, v -> {
if (v == null) return null;
if (v instanceof Boolean) return (Boolean) v;
return Boolean.parseBoolean(v.toString());
});
} else if (value instanceof Integer) {
// Integer 类型优先处理
return (TelemetryKey<T>) new TelemetryKey<>(name, Integer.class, v -> {
if (v == null) return null;
if (v instanceof Number) return ((Number) v).intValue();
return Integer.parseInt(v.toString());
});
} else if (value instanceof Long) {
// Long 类型
return (TelemetryKey<T>) new TelemetryKey<>(name, Long.class, v -> {
if (v == null) return null;
if (v instanceof Number) return ((Number) v).longValue();
return Long.parseLong(v.toString());
});
} else if (value instanceof Double) {
// Double 类型优先处理
return (TelemetryKey<T>) new TelemetryKey<>(name, Double.class, v -> {
if (v == null) return null;
if (v instanceof Number) return ((Number) v).doubleValue();
return Double.parseDouble(v.toString());
});
} else if (value instanceof Float) {
// Float 类型
return (TelemetryKey<T>) new TelemetryKey<>(name, Float.class, v -> {
if (v == null) return null;
if (v instanceof Number) return ((Number) v).floatValue();
return Float.parseFloat(v.toString());
});
} else {
// 默认为 String 类型
return (TelemetryKey<T>) new TelemetryKey<>(name, String.class, v -> v != null ? v.toString() : null);
}
}
/**
* 创建 psdk_widget_values 的遥测键不注册到 REGISTRY
* 用于解析 Python 风格的字典字符串为 List<PsdkDevice>
* 注意不能调用 of() 方法避免递归更新
*/
@SuppressWarnings("unchecked")
private static TelemetryKey<List<PsdkDevice>> createPsdkWidgetValuesKeyWithoutRegistering() {
ObjectMapper objectMapper = new ObjectMapper();
// 配置 ObjectMapper 忽略未知字段
objectMapper.configure(com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
return new TelemetryKey<>(
"psdk_widget_values",
(Class<List<PsdkDevice>>) (Class<?>) List.class,
value -> {
if (value == null) return null;
try {
// 如果已经是 List<PsdkDevice> 类型直接返回
if (value instanceof List) {
return (List<PsdkDevice>) value;
}
// 如果是字符串需要处理 Python 风格的字典格式
if (value instanceof String) {
String jsonStr = (String) value;
// Python 风格的字典转换为标准 JSON 格式
// 1. 将单引号替换为双引号
jsonStr = jsonStr.replace("'", "\"");
// 2. 处理 True/False/None (如果有的话)
jsonStr = jsonStr.replace(": True", ": true")
.replace(": False", ": false")
.replace(": None", ": null");
return objectMapper.readValue(
jsonStr,
new TypeReference<List<PsdkDevice>>() {}
);
}
// 如果是其他对象 JsonNode转换为 JSON 再解析
String json = objectMapper.writeValueAsString(value);
return objectMapper.readValue(
json,
new TypeReference<List<PsdkDevice>>() {}
);
} catch (Exception e) {
throw new RuntimeException("Failed to parse psdk_widget_values: " + e.getMessage(), e);
}
}
);
}
/**
* 创建 battery 的遥测键不注册到 REGISTRY
* 用于解析 Python 风格的字典字符串为 BatteryData
* 注意不能调用 of() 方法避免递归更新
*/
@SuppressWarnings("unchecked")
private static TelemetryKey<BatteryData> createBatteryKeyWithoutRegistering() {
ObjectMapper objectMapper = new ObjectMapper();
// 配置 ObjectMapper 忽略未知字段
objectMapper.configure(com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
return new TelemetryKey<>(
"battery",
BatteryData.class,
value -> {
if (value == null) return null;
try {
// 如果已经是 BatteryData 类型直接返回
if (value instanceof BatteryData) {
return (BatteryData) value;
}
// 如果是字符串需要处理 Python 风格的字典格式
if (value instanceof String) {
String jsonStr = (String) value;
// Python 风格的字典转换为标准 JSON 格式
// 1. 将单引号替换为双引号
jsonStr = jsonStr.replace("'", "\"");
// 2. 处理 True/False/None (如果有的话)
jsonStr = jsonStr.replace(": True", ": true")
.replace(": False", ": false")
.replace(": None", ": null");
return objectMapper.readValue(jsonStr, BatteryData.class);
}
// 如果是其他对象 JsonNode转换为 JSON 再解析
String json = objectMapper.writeValueAsString(value);
return objectMapper.readValue(json, BatteryData.class);
} catch (Exception e) {
throw new RuntimeException("Failed to parse battery: " + e.getMessage(), e);
}
}
);
}
/**
* 值解析器接口
*/
@FunctionalInterface
public interface ValueParser<T> {
T parse(Object rawValue);
}
}

View File

@ -0,0 +1,66 @@
package com.ruoyi.device.domain.model.thingsboard;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
/**
* 类型安全的遥测数据映射
*/
public class TelemetryMap {
private final Map<TelemetryKey<?>, TelemetryValue<?>> data = new HashMap<>();
/**
* 添加遥测值类型安全
*/
public <T> void put(TelemetryKey<T> key, T value, long timestamp) {
data.put(key, new TelemetryValue<>(key, value, timestamp));
}
/**
* 获取遥测值类型安全
*/
@SuppressWarnings("unchecked")
public <T> Optional<TelemetryValue<T>> get(TelemetryKey<T> key) {
return Optional.ofNullable((TelemetryValue<T>) data.get(key));
}
/**
* 检查是否包含某个键
*/
public boolean containsKey(TelemetryKey<?> key) {
return data.containsKey(key);
}
/**
* 获取所有键
*/
public Set<TelemetryKey<?>> keySet() {
return data.keySet();
}
/**
* 获取数据数量
*/
public int size() {
return data.size();
}
/**
* 是否为空
*/
public boolean isEmpty() {
return data.isEmpty();
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder("TelemetryMap{\n");
data.forEach((key, value) ->
sb.append(" ").append(value.toString()).append("\n")
);
sb.append("}");
return sb.toString();
}
}

View File

@ -0,0 +1,44 @@
package com.ruoyi.device.domain.model.thingsboard;
/**
* 类型安全的遥测数据值包装类
* 包含时间戳信息
*
* @param <T> 值的类型
*/
public class TelemetryValue<T> {
private final TelemetryKey<T> key;
private final T value;
private final long timestamp;
public TelemetryValue(TelemetryKey<T> key, T value, long timestamp) {
this.key = key;
this.value = value;
this.timestamp = timestamp;
}
public TelemetryKey<T> getKey() {
return key;
}
public T getValue() {
return value;
}
public long getTimestamp() {
return timestamp;
}
public String getKeyName() {
return key.getName();
}
public Class<T> getType() {
return key.getType();
}
@Override
public String toString() {
return key.getName() + ": " + value + " (timestamp: " + timestamp + ")";
}
}

View File

@ -0,0 +1,83 @@
package com.ruoyi.device.domain.model.thingsboard.attributes.battery;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.List;
/**
* 电池数据
* 包含电池列表和相关状态信息
*/
public class BatteryData {
@JsonProperty("batteries")
private List<BatteryInfo> batteries;
@JsonProperty("capacity_percent")
private Integer capacityPercent;
@JsonProperty("landing_power")
private Integer landingPower;
@JsonProperty("remain_flight_time")
private Integer remainFlightTime;
@JsonProperty("return_home_power")
private Integer returnHomePower;
// 构造方法
public BatteryData() {
}
// Getter和Setter方法
public List<BatteryInfo> getBatteries() {
return batteries;
}
public void setBatteries(List<BatteryInfo> batteries) {
this.batteries = batteries;
}
public Integer getCapacityPercent() {
return capacityPercent;
}
public void setCapacityPercent(Integer capacityPercent) {
this.capacityPercent = capacityPercent;
}
public Integer getLandingPower() {
return landingPower;
}
public void setLandingPower(Integer landingPower) {
this.landingPower = landingPower;
}
public Integer getRemainFlightTime() {
return remainFlightTime;
}
public void setRemainFlightTime(Integer remainFlightTime) {
this.remainFlightTime = remainFlightTime;
}
public Integer getReturnHomePower() {
return returnHomePower;
}
public void setReturnHomePower(Integer returnHomePower) {
this.returnHomePower = returnHomePower;
}
@Override
public String toString() {
return "BatteryData{" +
"batteries=" + batteries +
", capacityPercent=" + capacityPercent +
", landingPower=" + landingPower +
", remainFlightTime=" + remainFlightTime +
", returnHomePower=" + returnHomePower +
'}';
}
}

View File

@ -0,0 +1,46 @@
package com.ruoyi.device.domain.model.thingsboard.attributes.battery;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.v3.oas.models.security.SecurityScheme;
import lombok.Data;
/**
* 单个电池信息
*/
@Data
public class BatteryInfo {
@JsonProperty("capacity_percent")
private Integer capacityPercent;
@JsonProperty("firmware_version")
private String firmwareVersion;
@JsonProperty("high_voltage_storage_days")
private Integer highVoltageStorageDays;
@JsonProperty("index")
private Integer index;
@JsonProperty("loop_times")
private Integer loopTimes;
@JsonProperty("sn")
private String sn;
@JsonProperty("sub_type")
private Integer subType;
@JsonProperty("temperature")
private Double temperature;
@JsonProperty("type")
private Integer type;
@JsonProperty("voltage")
private Integer voltage;
@JsonProperty("remain_flight_time")
private Integer remainFlightTime;
}

View File

@ -0,0 +1,90 @@
package com.ruoyi.device.domain.model.thingsboard.attributes.psdk;
import java.util.List;
/**
* PSDK
*/
public class PsdkDevice {
private int psdk_index;
private String psdk_lib_version;
private String psdk_name;
private String psdk_sn;
private String psdk_version;
private Speaker speaker;
private List<ValueItem> values;
// 构造方法
public PsdkDevice() {
}
// Getter和Setter方法
public int getPsdk_index() {
return psdk_index;
}
public void setPsdk_index(int psdk_index) {
this.psdk_index = psdk_index;
}
public String getPsdk_lib_version() {
return psdk_lib_version;
}
public void setPsdk_lib_version(String psdk_lib_version) {
this.psdk_lib_version = psdk_lib_version;
}
public String getPsdk_name() {
return psdk_name;
}
public void setPsdk_name(String psdk_name) {
this.psdk_name = psdk_name;
}
public String getPsdk_sn() {
return psdk_sn;
}
public void setPsdk_sn(String psdk_sn) {
this.psdk_sn = psdk_sn;
}
public String getPsdk_version() {
return psdk_version;
}
public void setPsdk_version(String psdk_version) {
this.psdk_version = psdk_version;
}
public Speaker getSpeaker() {
return speaker;
}
public void setSpeaker(Speaker speaker) {
this.speaker = speaker;
}
public List<ValueItem> getValues() {
return values;
}
public void setValues(List<ValueItem> values) {
this.values = values;
}
@Override
public String toString() {
return "PsdkDevice{" +
"psdk_index=" + psdk_index +
", psdk_lib_version='" + psdk_lib_version + '\'' +
", psdk_name='" + psdk_name + '\'' +
", psdk_sn='" + psdk_sn + '\'' +
", psdk_version='" + psdk_version + '\'' +
", speaker=" + speaker +
", values=" + values +
'}';
}
}

View File

@ -0,0 +1,78 @@
package com.ruoyi.device.domain.model.thingsboard.attributes.psdk;
/**
* Speaker
*/
public class Speaker {
private String play_file_md5;
private String play_file_name;
private int play_mode;
private int play_volume;
private int system_state;
private int work_mode;
// 构造方法
public Speaker() {
}
// Getter和Setter方法
public String getPlay_file_md5() {
return play_file_md5;
}
public void setPlay_file_md5(String play_file_md5) {
this.play_file_md5 = play_file_md5;
}
public String getPlay_file_name() {
return play_file_name;
}
public void setPlay_file_name(String play_file_name) {
this.play_file_name = play_file_name;
}
public int getPlay_mode() {
return play_mode;
}
public void setPlay_mode(int play_mode) {
this.play_mode = play_mode;
}
public int getPlay_volume() {
return play_volume;
}
public void setPlay_volume(int play_volume) {
this.play_volume = play_volume;
}
public int getSystem_state() {
return system_state;
}
public void setSystem_state(int system_state) {
this.system_state = system_state;
}
public int getWork_mode() {
return work_mode;
}
public void setWork_mode(int work_mode) {
this.work_mode = work_mode;
}
@Override
public String toString() {
return "Speaker{" +
"play_file_md5='" + play_file_md5 + '\'' +
", play_file_name='" + play_file_name + '\'' +
", play_mode=" + play_mode +
", play_volume=" + play_volume +
", system_state=" + system_state +
", work_mode=" + work_mode +
'}';
}
}

View File

@ -0,0 +1,43 @@
package com.ruoyi.device.domain.model.thingsboard.attributes.psdk;
/**
* ValueItem
*/
public class ValueItem {
private int index;
private int value;
// 构造方法
public ValueItem() {
}
public ValueItem(int index, int value) {
this.index = index;
this.value = value;
}
// Getter和Setter方法
public int getIndex() {
return index;
}
public void setIndex(int index) {
this.index = index;
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
@Override
public String toString() {
return "ValueItem{" +
"index=" + index +
", value=" + value +
'}';
}
}

View File

@ -0,0 +1,221 @@
package com.ruoyi.device.domain.model.thingsboard.constants;
import com.ruoyi.device.domain.model.thingsboard.AttributeKey;
import com.ruoyi.device.domain.model.thingsboard.TelemetryKey;
import java.util.Arrays;
import java.util.List;
/**
* 预定义的设备属性键
* 使用类型安全的方式定义常用属性
*/
public class DeviceAttributes {
/**
* 公用服务端属性
*/
// 最后连接时间 - Long
public static final AttributeKey<Long> LAST_CONNECT_TIME = AttributeKey.of(
"lastConnectTime",
Long.class,
value -> {
if (value == null) return null;
if (value instanceof Number) {
return (Long) ((Number) value).longValue();
}
return (Long) Long.parseLong(value.toString());
}
);
// 是否激活 - Boolean
public static final AttributeKey<Boolean> ACTIVE = AttributeKey.of(
"active",
Boolean.class,
value -> {
if (value == null) return null;
if (value instanceof Boolean) {
return (Boolean) value;
}
return (Boolean) Boolean.parseBoolean(value.toString());
}
);
// 最后活动时间 - Long
public static final AttributeKey<Long> LAST_ACTIVITY_TIME = AttributeKey.of(
"lastActivityTime",
Long.class,
value -> {
if (value == null) return null;
if (value instanceof Number) {
return (Long) ((Number) value).longValue();
}
return (Long) Long.parseLong(value.toString());
}
);
// 最后断开连接时间 - Long
public static final AttributeKey<Long> LAST_DISCONNECT_TIME = AttributeKey.of(
"lastDisconnectTime",
Long.class,
value -> {
if (value == null) return null;
if (value instanceof Number) {
return (Long) ((Number) value).longValue();
}
return (Long) Long.parseLong(value.toString());
}
);
/**
* 公用客户端属性 无需配置
*/
// 连接器类型 - String
public static final AttributeKey<String> CONNECTOR_TYPE = AttributeKey.of(
"connectorType",
String.class,
value -> value != null ? value.toString() : null
);
// 连接器名称 - String
public static final AttributeKey<String> CONNECTOR_NAME = AttributeKey.of(
"connectorName",
String.class,
value -> value != null ? value.toString() : null
);
/**
* 公用客户端属性 需要配置
*/
// 机场SN号 - String
public static final AttributeKey<String> DOCK_SN = AttributeKey.of(
"dock_sn",
String.class,
value -> value != null ? value.toString() : null
);
/**
* 固件版本 需要配置 state中; 未收到过
*/
public static final AttributeKey<String> Firmware_Version = AttributeKey.of(
"firmware_version",
String.class,
value -> value != null ? value.toString() : null
);
/**
* 机场 {"0":"空闲中","1":"现场调试","2":"远程调试","3":"固件升级中","4":"作业中","5":"待标定"}
* 无人机 {"0":"待机","1":"起飞准备","2":"起飞准备完毕","3":"手动飞行","4":"自动起飞","5":"航线飞行","6":"全景拍照","7":"智能跟随","8":"ADS-B 躲避","9":"自动返航","10":"自动降落","11":"强制降落","12":"三桨叶降落","13":"升级中","14":"未连接","15":"APAS","16":"虚拟摇杆状态","17":"指令飞行","18":"空中 RTK 收敛模式","19":"机场选址中","20":"POI环绕"}
*/
public static final AttributeKey<Integer> MODE_CODE = AttributeKey.of(
"mode_code",
Integer.class,
value -> {
if (value == null) return null;
if (value instanceof Number) {
return (Integer) ((Number) value).intValue();
}
return (Integer) Integer.parseInt(value.toString());
}
);
/**
* 机场特有属性
*/
// 无人机SN号 - String
public static final AttributeKey<String> SUB_DEVICE_SN = AttributeKey.of(
"sub_device.device_sn",
String.class,
value -> value != null ? value.toString() : null
);
public static final AttributeKey<Double> Latitude = AttributeKey.of(
"latitude",
Double.class,
value -> {
if (value == null) return null;
if (value instanceof Number) {
return ((Number) value).doubleValue();
}
return Double.parseDouble(value.toString());
}
);
public static final AttributeKey<Double> Longitude = AttributeKey.of(
"longitude",
Double.class,
value -> {
if (value == null) return null;
if (value instanceof Number) {
return ((Number) value).doubleValue();
}
return Double.parseDouble(value.toString());
}
);
//
// // 空调状态 - Integer
// public static final TelemetryKey<Integer> AIR_CONDITIONER_STATE = TelemetryKey.of(
// "air_conditioner.air_conditioner_state",
// Integer.class,
// value -> {
// if (value == null) return null;
// if (value instanceof Number) {
// return ((Number) value).intValue();
// }
// return Integer.parseInt(value.toString());
// }
// );
//
// // 网关 - String
// public static final AttributeKey<String> GATEWAY = AttributeKey.of(
// "gateway",
// String.class,
// value -> value != null ? value.toString() : null
// );
private DeviceAttributes() {
// 工具类禁止实例化
}
/**
* 获取所有预定义的属性键
*
* @return 预定义的属性键列表
*/
public static List<AttributeKey<?>> getPredefinedKeys() {
return Arrays.asList(
CONNECTOR_TYPE,
CONNECTOR_NAME,
// GATEWAY,
LAST_CONNECT_TIME,
ACTIVE,
LAST_ACTIVITY_TIME,
LAST_DISCONNECT_TIME,
DOCK_SN,
SUB_DEVICE_SN,
MODE_CODE,
Firmware_Version,
Latitude,
Longitude
);
}
/**
* 初始化所有属性键
* 确保所有静态字段被加载和注册
*/
public static void init() {
// 这个方法的存在是为了触发类的静态初始化
// 当调用此方法时所有静态字段都会被初始化
}
}

View File

@ -0,0 +1,517 @@
package com.ruoyi.device.domain.model.thingsboard.constants;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ruoyi.device.domain.model.thingsboard.AttributeKey;
import com.ruoyi.device.domain.model.thingsboard.TelemetryKey;
import com.ruoyi.device.domain.model.thingsboard.attributes.battery.BatteryInfo;
import com.ruoyi.device.domain.model.thingsboard.attributes.psdk.PsdkDevice;
import com.ruoyi.device.domain.model.thingsboard.attributes.battery.BatteryData;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* 预定义的设备遥测数据键
* 使用类型安全的方式定义常用遥测数据
*/
public class DeviceTelemetry {
// Jackson ObjectMapper 用于 JSON 解析
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
/**
* 机场独有状态
*/
/**
* 备降点纬度
*/
public static final TelemetryKey<Double> Alternate_land_point_Latitude = TelemetryKey.of(
"alternate_land_point.latitude",
Double.class,
value -> {
if (value == null) return null;
if (value instanceof Number) {
return ((Number) value).doubleValue();
}
return Double.parseDouble(value.toString());
}
);
/**
* 环境温度 environment_temperature
*/
// 温度 - Double
public static final TelemetryKey<Double> Environment_Temperature = TelemetryKey.of(
"environment_temperature",
Double.class,
value -> {
if (value == null) return null;
if (value instanceof Number) {
return ((Number) value).doubleValue();
}
return Double.parseDouble(value.toString());
}
);
/**
* 备降点经度
*/
public static final TelemetryKey<Double> Alternate_land_point_Longitude = TelemetryKey.of(
"alternate_land_point.longitude",
Double.class,
value -> {
if (value == null) return null;
if (value instanceof Number) {
return ((Number) value).doubleValue();
}
return Double.parseDouble(value.toString());
}
);
/**
* 网络类型 {"1":"4G","2":"以太网"}
*/
public static final TelemetryKey<Integer> Network_State_Type = TelemetryKey.of(
"network_state.type",
Integer.class,
value -> {
if (value == null) return null;
if (value instanceof Number) {
return ((Number) value).intValue();
}
return Integer.parseInt(value.toString());
}
);
/**
* 舱门状态
* {"0":"关闭","1":"打开","2":"半开","3":"舱盖状态异常"}
*/
public static final TelemetryKey<Integer> Cover_State = TelemetryKey.of(
"cover_state",
Integer.class,
value -> {
if (value == null) return null;
if (value instanceof Number) {
return ((Number) value).intValue();
}
return Integer.parseInt(value.toString());
}
);
/**
* 网络速率 {"unit_name":"千字节每秒 / KB/s"}
*/
// 温度 - Double
public static final TelemetryKey<Double> Network_State_Rate = TelemetryKey.of(
"network_state.rate",
Double.class,
value -> {
if (value == null) return null;
if (value instanceof Number) {
return ((Number) value).doubleValue();
}
return Double.parseDouble(value.toString());
}
);
/**
* 运行时长 {"unit_name":"秒 / s"}
*/
public static final TelemetryKey<Integer> Acc_Time = TelemetryKey.of(
"acc_time",
Integer.class,
value -> {
if (value == null) return null;
if (value instanceof Number) {
return ((Number) value).intValue();
}
return Integer.parseInt(value.toString());
}
);
/**
* 舱内温度 temperature
*/
// 温度 - Double
public static final TelemetryKey<Double> TEMPERATURE = TelemetryKey.of(
"temperature",
Double.class,
value -> {
if (value == null) return null;
if (value instanceof Number) {
return ((Number) value).doubleValue();
}
return Double.parseDouble(value.toString());
}
);
/**
* 舱内湿度 humidity
*/
public static final TelemetryKey<Double> HUMIDITY = TelemetryKey.of(
"humidity",
Double.class,
value -> {
if (value == null) return null;
if (value instanceof Number) {
return ((Number) value).doubleValue();
}
return Double.parseDouble(value.toString());
}
);
/**
* 任务作业状态
* {"0":"作业准备中","1":"飞行作业中","2":"作业后状态恢复","3":"自定义飞行区更新中","4":"地形障碍物更新中","5":"任务空闲","255":"飞行器异常","256":"未知状态"}
*/
public static final TelemetryKey<Integer> FlightTask_Step_Code = TelemetryKey.of(
"flighttask_step_code",
Integer.class,
value -> {
if (value == null) return null;
if (value instanceof Number) {
return ((Number) value).intValue();
}
return Integer.parseInt(value.toString());
}
);
/**
* 无人机是否在舱
* {"0":"舱外","1":"舱内"}
*/
public static final TelemetryKey<Integer> Drone_In_Dock = TelemetryKey.of(
"drone_in_dock",
Integer.class,
value -> {
if (value == null) return null;
if (value instanceof Number) {
return ((Number) value).intValue();
}
return Integer.parseInt(value.toString());
}
);
/**
* 无人机是否开机状态
* {"0":"关机","1":"开机"}
*/
public static final TelemetryKey<Integer> Sub_Device_Online_Status = TelemetryKey.of(
"sub_device.device_online_status",
Integer.class,
value -> {
if (value == null) return null;
if (value instanceof Number) {
return ((Number) value).intValue();
}
return Integer.parseInt(value.toString());
}
);
/**
* 无人机充电状态
* {"0":"空闲","1":"充电中"}
*/
public static final TelemetryKey<Integer> Drone_Charge_State_State = TelemetryKey.of(
"drone_charge_state.state",
Integer.class,
value -> {
if (value == null) return null;
if (value instanceof Number) {
return ((Number) value).intValue();
}
return Integer.parseInt(value.toString());
}
);
/**
*
* {"0":"空闲模式(无制冷、制热、除湿等)","1":"制冷模式","2":"制热模式","3":"除湿模式","4":"制冷退出模式","5":"制热退出模式","6":"除湿退出模式","7":"制冷准备模式","8":"制热准备模式","9":"除湿准备模式"10":"风冷准备中"11":"风冷中"12":"风冷退出中"13":"除雾准备中"14":"除雾中"15":"除雾退出中"}
*/
public static final TelemetryKey<Integer> AIR_CONDITIONER_STATE = TelemetryKey.of(
"air_conditioner.air_conditioner_state",
Integer.class,
value -> {
if (value == null) return null;
if (value instanceof Number) {
return ((Number) value).intValue();
}
return Integer.parseInt(value.toString());
}
);
/**
* 无人机 position_state.rtk_number RTK 搜星数量
*/
public static final TelemetryKey<Integer> Position_State_Rtk_Number = TelemetryKey.of(
"position_state.rtk_number",
Integer.class,
value -> {
if (value == null) return null;
if (value instanceof Number) {
return ((Number) value).intValue();
}
return Integer.parseInt(value.toString());
}
);
/**
* 风速
*/
//wind_speed{"unit_name":"米每秒 / m/s"} float
public static final TelemetryKey<Double> Wind_Speed = TelemetryKey.of(
"wind_speed",
Double.class,
value -> {
if (value == null) return null;
if (value instanceof Number) {
return ((Number) value).doubleValue();
}
return Double.parseDouble(value.toString());
}
);
/**
* 降雨量
*/
//rainfall {"0":"无雨","1":"小雨","2":"中雨","3":"大雨"} enum_int
public static final TelemetryKey<Integer> Rainfall = TelemetryKey.of(
"rainfall",
Integer.class,
value -> {
if (value == null) return null;
if (value instanceof Number) {
return ((Number) value).intValue();
}
return Integer.parseInt(value.toString());
}
);
/**
* 无人机挂载信息
*/
@SuppressWarnings("unchecked")
public static final TelemetryKey<List<PsdkDevice>> PSDK_WIDGET_VALUES = TelemetryKey.of(
"psdk_widget_values",
(Class<List<PsdkDevice>>) (Class<?>) List.class,
value -> {
if (value == null) return null;
try {
// 如果已经是 List<PsdkDevice> 类型直接返回
if (value instanceof List) {
return (List<PsdkDevice>) value;
}
// 如果是字符串需要处理 Python 风格的字典格式
if (value instanceof String) {
String jsonStr = (String) value;
// Python 风格的字典转换为标准 JSON 格式
// 1. 将单引号替换为双引号
jsonStr = jsonStr.replace("'", "\"");
// 2. 处理 True/False/None (如果有的话)
jsonStr = jsonStr.replace(": True", ": true")
.replace(": False", ": false")
.replace(": None", ": null");
return OBJECT_MAPPER.readValue(
jsonStr,
new TypeReference<List<PsdkDevice>>() {}
);
}
// 如果是其他对象 JsonNode转换为 JSON 再解析
String json = OBJECT_MAPPER.writeValueAsString(value);
return OBJECT_MAPPER.readValue(
json,
new TypeReference<List<PsdkDevice>>() {}
);
} catch (Exception e) {
throw new RuntimeException("Failed to parse psdk_widget_values: " + e.getMessage(), e);
}
}
);
/**
* 电池信息
* 包含电池列表电量百分比降落电量剩余飞行时间返航电量等信息
*/
public static final TelemetryKey<BatteryData> BATTERY = TelemetryKey.of(
"battery",
BatteryData.class,
value -> {
if (value == null) return null;
try {
// 如果已经是 BatteryData 类型直接返回
if (value instanceof BatteryData) {
return (BatteryData) value;
}
// 如果是字符串需要处理 Python 风格的字典格式
if (value instanceof String) {
String jsonStr = (String) value;
// Python 风格的字典转换为标准 JSON 格式
// 1. 将单引号替换为双引号
jsonStr = jsonStr.replace("'", "\"");
// 2. 处理 True/False/None (如果有的话)
jsonStr = jsonStr.replace(": True", ": true")
.replace(": False", ": false")
.replace(": None", ": null");
return OBJECT_MAPPER.readValue(jsonStr, BatteryData.class);
}
// 如果是其他对象 JsonNode转换为 JSON 再解析
String json = OBJECT_MAPPER.writeValueAsString(value);
return OBJECT_MAPPER.readValue(json, BatteryData.class);
} catch (Exception e) {
throw new RuntimeException("Failed to parse battery: " + e.getMessage(), e);
}
}
);
/**
* 限高
*/
public static final TelemetryKey<Integer> Height_Limit = TelemetryKey.of(
"height_limit",
Integer.class,
value -> {
if (value == null) return null;
if (value instanceof Number) {
return ((Number) value).intValue();
}
return Integer.parseInt(value.toString());
}
);
/**
* 飞行器限远
* {"max":"8000","min":"15","step":"1","unit_name":"米 / m"}
*/
public static final TelemetryKey<Integer> Distance_Limit_Status_Distance_Limit = TelemetryKey.of(
"distance_limit_status.distance_limit",
Integer.class,
value -> {
if (value == null) return null;
if (value instanceof Number) {
return ((Number) value).intValue();
}
return Integer.parseInt(value.toString());
}
);
/**
* 飞行次数 作业架次
*/
public static final TelemetryKey<Integer> Total_Flight_Sorties = TelemetryKey.of(
"total_flight_sorties",
Integer.class,
value -> {
if (value == null) return null;
if (value instanceof Number) {
return ((Number) value).intValue();
}
return Integer.parseInt(value.toString());
}
);
/**
* 总飞行时长单位
*/
public static final TelemetryKey<Integer> Total_Flight_Time = TelemetryKey.of(
"total_flight_time",
Integer.class,
value -> {
if (value == null) return null;
if (value instanceof Number) {
return ((Number) value).intValue();
}
return Integer.parseInt(value.toString());
}
);
/**
* 以下尚未划分
*/
private DeviceTelemetry() {
// 工具类禁止实例化
}
/**
* 获取所有预定义的遥测键
*
* @return 预定义的遥测键列表
*/
public static List<TelemetryKey<?>> getPredefinedKeys() {
return Arrays.asList(
AIR_CONDITIONER_STATE,
TEMPERATURE,
HUMIDITY,
PSDK_WIDGET_VALUES,
BATTERY,
FlightTask_Step_Code,
Sub_Device_Online_Status,
Total_Flight_Sorties,
Total_Flight_Time,
Drone_Charge_State_State,
Drone_In_Dock,
Acc_Time,
Network_State_Type,
Wind_Speed,
Rainfall,
Position_State_Rtk_Number,
Height_Limit,
Distance_Limit_Status_Distance_Limit,
Alternate_land_point_Latitude,
Alternate_land_point_Longitude,
Environment_Temperature,
Network_State_Rate,
Cover_State
);
}
/**
* 初始化所有遥测键
* 确保所有静态字段被加载和注册
*/
public static void init() {
// 这个方法的存在是为了触发类的静态初始化
// 当调用此方法时所有静态字段都会被初始化
}
}

View File

@ -0,0 +1,77 @@
package com.ruoyi.device.mapper;
import com.ruoyi.device.mapper.entity.AircraftEntity;
import java.util.List;
/**
* 无人机表Mapper接口
*
* @author ruoyi
* @date 2026-01-16
*/
public interface AircraftMapper
{
/**
* 根据无人机主键查询无人机
*
* @param aircraftId 无人机主键
* @return 无人机信息
*/
AircraftEntity selectAircraftByAircraftId(Long aircraftId);
/**
* 根据设备主键查询无人机
*
* @param deviceId 设备主键
* @return 无人机信息
*/
AircraftEntity selectAircraftByDeviceId(Long deviceId);
/**
* 根据设备主键查询无人机列表
*
* @param deviceId 设备主键
* @return 无人机列表
*/
List<AircraftEntity> selectAircraftListByDeviceId(Long deviceId);
/**
* 查询无人机列表
*
* @param aircraft 无人机信息
* @return 无人机集合
*/
List<AircraftEntity> selectAircraftList(AircraftEntity aircraft);
/**
* 新增无人机
*
* @param aircraft 无人机信息
* @return 影响行数
*/
int insertAircraft(AircraftEntity aircraft);
/**
* 修改无人机
*
* @param aircraft 无人机信息
* @return 影响行数
*/
int updateAircraft(AircraftEntity aircraft);
/**
* 删除无人机
*
* @param aircraftId 无人机主键
* @return 影响行数
*/
int deleteAircraftByAircraftId(Long aircraftId);
/**
* 批量删除无人机
*
* @param aircraftIds 需要删除的无人机主键集合
* @return 影响行数
*/
int deleteAircraftByAircraftIds(Long[] aircraftIds);
}

View File

@ -0,0 +1,85 @@
package com.ruoyi.device.mapper;
import com.ruoyi.device.mapper.entity.AircraftPayloadEntity;
import java.util.List;
/**
* 无人机挂载关联表Mapper接口
*
* @author ruoyi
* @date 2026-01-16
*/
public interface AircraftPayloadMapper
{
/**
* 根据关联主键查询无人机挂载关联
*
* @param id 关联主键
* @return 无人机挂载关联信息
*/
AircraftPayloadEntity selectAircraftPayloadById(Long id);
/**
* 根据无人机主键查询无人机挂载关联列表
*
* @param aircraftId 无人机主键
* @return 无人机挂载关联列表
*/
List<AircraftPayloadEntity> selectAircraftPayloadListByAircraftId(Long aircraftId);
/**
* 根据挂载主键查询无人机挂载关联列表
*
* @param payloadId 挂载主键
* @return 无人机挂载关联列表
*/
List<AircraftPayloadEntity> selectAircraftPayloadListByPayloadId(Long payloadId);
/**
* 根据机场主键查询无人机挂载关联列表
*
* @param dockId 机场主键
* @return 无人机挂载关联列表
*/
List<AircraftPayloadEntity> selectAircraftPayloadListByDockId(Long dockId);
/**
* 查询无人机挂载关联列表
*
* @param aircraftPayload 无人机挂载关联信息
* @return 无人机挂载关联集合
*/
List<AircraftPayloadEntity> selectAircraftPayloadList(AircraftPayloadEntity aircraftPayload);
/**
* 新增无人机挂载关联
*
* @param aircraftPayload 无人机挂载关联信息
* @return 影响行数
*/
int insertAircraftPayload(AircraftPayloadEntity aircraftPayload);
/**
* 修改无人机挂载关联
*
* @param aircraftPayload 无人机挂载关联信息
* @return 影响行数
*/
int updateAircraftPayload(AircraftPayloadEntity aircraftPayload);
/**
* 删除无人机挂载关联
*
* @param id 关联主键
* @return 影响行数
*/
int deleteAircraftPayloadById(Long id);
/**
* 批量删除无人机挂载关联
*
* @param ids 需要删除的关联主键集合
* @return 影响行数
*/
int deleteAircraftPayloadByIds(Long[] ids);
}

View File

@ -0,0 +1,69 @@
package com.ruoyi.device.mapper;
import com.ruoyi.device.mapper.entity.DeviceEntity;
import java.util.List;
/**
* 设备表Mapper接口
*
* @author ruoyi
* @date 2026-01-16
*/
public interface DeviceMapper
{
/**
* 根据设备主键查询设备
*
* @param deviceId 设备主键
* @return 设备信息
*/
DeviceEntity selectDeviceByDeviceId(Long deviceId);
/**
* 根据IOT设备ID查询设备
*
* @param iotDeviceId IOT设备ID
* @return 设备信息
*/
DeviceEntity selectDeviceByIotDeviceId(String iotDeviceId);
/**
* 查询设备列表
*
* @param device 设备信息
* @return 设备集合
*/
List<DeviceEntity> selectDeviceList(DeviceEntity device);
/**
* 新增设备
*
* @param device 设备信息
* @return 影响行数
*/
int insertDevice(DeviceEntity device);
/**
* 修改设备
*
* @param device 设备信息
* @return 影响行数
*/
int updateDevice(DeviceEntity device);
/**
* 删除设备
*
* @param deviceId 设备主键
* @return 影响行数
*/
int deleteDeviceByDeviceId(Long deviceId);
/**
* 批量删除设备
*
* @param deviceIds 需要删除的设备主键集合
* @return 影响行数
*/
int deleteDeviceByDeviceIds(Long[] deviceIds);
}

View File

@ -0,0 +1,29 @@
package com.ruoyi.device.mapper;
import com.ruoyi.device.mapper.entity.DeviceTempEntity;
import java.util.List;
/**
* 设备临时表Mapper接口
*
* @author ruoyi
* @date 2026-01-15
*/
public interface DeviceTempMapper
{
/**
* 查询设备临时表列表
*
* @param deviceTempEntity 设备临时表
* @return 设备临时表集合
*/
public List<DeviceTempEntity> selectDeviceTempList(DeviceTempEntity deviceTempEntity);
/**
* 根据ID查询设备临时表
*
* @param id 主键ID
* @return 设备临时表
*/
public DeviceTempEntity selectDeviceTempById(String id);
}

View File

@ -0,0 +1,77 @@
package com.ruoyi.device.mapper;
import com.ruoyi.device.mapper.entity.DockAircraftEntity;
import java.util.List;
/**
* 机场无人机关联表Mapper接口
*
* @author ruoyi
* @date 2026-01-16
*/
public interface DockAircraftMapper
{
/**
* 根据关联主键查询机场无人机关联
*
* @param id 关联主键
* @return 机场无人机关联信息
*/
DockAircraftEntity selectDockAircraftById(Long id);
/**
* 根据机场主键查询机场无人机关联列表
*
* @param dockId 机场主键
* @return 机场无人机关联列表
*/
List<DockAircraftEntity> selectDockAircraftListByDockId(Long dockId);
/**
* 根据无人机主键查询机场无人机关联列表
*
* @param aircraftId 无人机主键
* @return 机场无人机关联列表
*/
List<DockAircraftEntity> selectDockAircraftListByAircraftId(Long aircraftId);
/**
* 查询机场无人机关联列表
*
* @param dockAircraft 机场无人机关联信息
* @return 机场无人机关联集合
*/
List<DockAircraftEntity> selectDockAircraftList(DockAircraftEntity dockAircraft);
/**
* 新增机场无人机关联
*
* @param dockAircraft 机场无人机关联信息
* @return 影响行数
*/
int insertDockAircraft(DockAircraftEntity dockAircraft);
/**
* 修改机场无人机关联
*
* @param dockAircraft 机场无人机关联信息
* @return 影响行数
*/
int updateDockAircraft(DockAircraftEntity dockAircraft);
/**
* 删除机场无人机关联
*
* @param id 关联主键
* @return 影响行数
*/
int deleteDockAircraftById(Long id);
/**
* 批量删除机场无人机关联
*
* @param ids 需要删除的关联主键集合
* @return 影响行数
*/
int deleteDockAircraftByIds(Long[] ids);
}

View File

@ -0,0 +1,77 @@
package com.ruoyi.device.mapper;
import com.ruoyi.device.mapper.entity.DockGroupEntity;
import java.util.List;
/**
* 机场分组关联表Mapper接口
*
* @author ruoyi
* @date 2026-01-16
*/
public interface DockGroupMapper
{
/**
* 根据关联主键查询机场分组关联
*
* @param id 关联主键
* @return 机场分组关联信息
*/
DockGroupEntity selectDockGroupById(Long id);
/**
* 根据机场主键查询机场分组关联列表
*
* @param dockId 机场主键
* @return 机场分组关联列表
*/
List<DockGroupEntity> selectDockGroupListByDockId(Long dockId);
/**
* 根据分组主键查询机场分组关联列表
*
* @param groupId 分组主键
* @return 机场分组关联列表
*/
List<DockGroupEntity> selectDockGroupListByGroupId(Long groupId);
/**
* 查询机场分组关联列表
*
* @param dockGroup 机场分组关联信息
* @return 机场分组关联集合
*/
List<DockGroupEntity> selectDockGroupList(DockGroupEntity dockGroup);
/**
* 新增机场分组关联
*
* @param dockGroup 机场分组关联信息
* @return 影响行数
*/
int insertDockGroup(DockGroupEntity dockGroup);
/**
* 修改机场分组关联
*
* @param dockGroup 机场分组关联信息
* @return 影响行数
*/
int updateDockGroup(DockGroupEntity dockGroup);
/**
* 删除机场分组关联
*
* @param id 关联主键
* @return 影响行数
*/
int deleteDockGroupById(Long id);
/**
* 批量删除机场分组关联
*
* @param ids 需要删除的关联主键集合
* @return 影响行数
*/
int deleteDockGroupByIds(Long[] ids);
}

View File

@ -0,0 +1,77 @@
package com.ruoyi.device.mapper;
import com.ruoyi.device.mapper.entity.DockEntity;
import java.util.List;
/**
* 机场表Mapper接口
*
* @author ruoyi
* @date 2026-01-16
*/
public interface DockMapper
{
/**
* 根据机场主键查询机场
*
* @param dockId 机场主键
* @return 机场信息
*/
DockEntity selectDockByDockId(Long dockId);
/**
* 根据设备主键查询机场
*
* @param deviceId 设备主键
* @return 机场信息
*/
DockEntity selectDockByDeviceId(Long deviceId);
/**
* 根据设备主键查询机场列表
*
* @param deviceId 设备主键
* @return 机场列表
*/
List<DockEntity> selectDockListByDeviceId(Long deviceId);
/**
* 查询机场列表
*
* @param dock 机场信息
* @return 机场集合
*/
List<DockEntity> selectDockList(DockEntity dock);
/**
* 新增机场
*
* @param dock 机场信息
* @return 影响行数
*/
int insertDock(DockEntity dock);
/**
* 修改机场
*
* @param dock 机场信息
* @return 影响行数
*/
int updateDock(DockEntity dock);
/**
* 删除机场
*
* @param dockId 机场主键
* @return 影响行数
*/
int deleteDockByDockId(Long dockId);
/**
* 批量删除机场
*
* @param dockIds 需要删除的机场主键集合
* @return 影响行数
*/
int deleteDockByDockIds(Long[] dockIds);
}

View File

@ -0,0 +1,61 @@
package com.ruoyi.device.mapper;
import com.ruoyi.device.mapper.entity.GroupEntity;
import java.util.List;
/**
* 分组表Mapper接口
*
* @author ruoyi
* @date 2026-01-16
*/
public interface GroupMapper
{
/**
* 根据分组主键查询分组
*
* @param groupId 分组主键
* @return 分组信息
*/
GroupEntity selectGroupByGroupId(Long groupId);
/**
* 查询分组列表
*
* @param group 分组信息
* @return 分组集合
*/
List<GroupEntity> selectGroupList(GroupEntity group);
/**
* 新增分组
*
* @param group 分组信息
* @return 影响行数
*/
int insertGroup(GroupEntity group);
/**
* 修改分组
*
* @param group 分组信息
* @return 影响行数
*/
int updateGroup(GroupEntity group);
/**
* 删除分组
*
* @param groupId 分组主键
* @return 影响行数
*/
int deleteGroupByGroupId(Long groupId);
/**
* 批量删除分组
*
* @param groupIds 需要删除的分组主键集合
* @return 影响行数
*/
int deleteGroupByGroupIds(Long[] groupIds);
}

View File

@ -0,0 +1,61 @@
package com.ruoyi.device.mapper;
import com.ruoyi.device.mapper.entity.PayloadEntity;
import java.util.List;
/**
* 挂载表Mapper接口
*
* @author ruoyi
* @date 2026-01-16
*/
public interface PayloadMapper
{
/**
* 根据挂载主键查询挂载
*
* @param payloadId 挂载主键
* @return 挂载信息
*/
PayloadEntity selectPayloadByPayloadId(Long payloadId);
/**
* 查询挂载列表
*
* @param payload 挂载信息
* @return 挂载集合
*/
List<PayloadEntity> selectPayloadList(PayloadEntity payload);
/**
* 新增挂载
*
* @param payload 挂载信息
* @return 影响行数
*/
int insertPayload(PayloadEntity payload);
/**
* 修改挂载
*
* @param payload 挂载信息
* @return 影响行数
*/
int updatePayload(PayloadEntity payload);
/**
* 删除挂载
*
* @param payloadId 挂载主键
* @return 影响行数
*/
int deletePayloadByPayloadId(Long payloadId);
/**
* 批量删除挂载
*
* @param payloadIds 需要删除的挂载主键集合
* @return 影响行数
*/
int deletePayloadByPayloadIds(Long[] payloadIds);
}

View File

@ -0,0 +1,64 @@
package com.ruoyi.device.mapper.entity;
import com.ruoyi.common.core.web.domain.BaseEntity;
/**
* 无人机表实体对象 device_aircraft
* Mapper 层实体对应数据库表
*
* @author ruoyi
* @date 2026-01-16
*/
public class AircraftEntity extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 无人机主键 */
private Long aircraftId;
/** 无人机名称 */
private String aircraftName;
/** 设备表主键 */
private Long deviceId;
public Long getAircraftId()
{
return aircraftId;
}
public void setAircraftId(Long aircraftId)
{
this.aircraftId = aircraftId;
}
public String getAircraftName()
{
return aircraftName;
}
public void setAircraftName(String aircraftName)
{
this.aircraftName = aircraftName;
}
public Long getDeviceId()
{
return deviceId;
}
public void setDeviceId(Long deviceId)
{
this.deviceId = deviceId;
}
@Override
public String toString()
{
return "AircraftEntity{" +
"aircraftId=" + aircraftId +
", aircraftName='" + aircraftName + '\'' +
", deviceId=" + deviceId +
'}';
}
}

View File

@ -0,0 +1,78 @@
package com.ruoyi.device.mapper.entity;
import com.ruoyi.common.core.web.domain.BaseEntity;
/**
* 无人机挂载关联表实体对象 device_aircraft_payload
* Mapper 层实体对应数据库表
*
* @author ruoyi
* @date 2026-01-16
*/
public class AircraftPayloadEntity extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 关联主键 */
private Long id;
/** 无人机主键 */
private Long aircraftId;
/** 挂载主键 */
private Long payloadId;
/** 机场主键 */
private Long dockId;
public Long getId()
{
return id;
}
public void setId(Long id)
{
this.id = id;
}
public Long getAircraftId()
{
return aircraftId;
}
public void setAircraftId(Long aircraftId)
{
this.aircraftId = aircraftId;
}
public Long getPayloadId()
{
return payloadId;
}
public void setPayloadId(Long payloadId)
{
this.payloadId = payloadId;
}
public Long getDockId()
{
return dockId;
}
public void setDockId(Long dockId)
{
this.dockId = dockId;
}
@Override
public String toString()
{
return "AircraftPayloadEntity{" +
"id=" + id +
", aircraftId=" + aircraftId +
", payloadId=" + payloadId +
", dockId=" + dockId +
'}';
}
}

View File

@ -0,0 +1,148 @@
package com.ruoyi.device.mapper.entity;
import com.ruoyi.common.core.web.domain.BaseEntity;
/**
* 设备表实体对象 device_device
* Mapper 层实体对应数据库表
*
* @author ruoyi
* @date 2026-01-16
*/
public class DeviceEntity extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 设备主键 */
private Long deviceId;
/** 设备名称 */
private String deviceName;
/** IOT中的设备ID */
private String iotDeviceId;
/** 设备类型 */
private String deviceType;
/** 设备厂商 */
private String deviceManufacturer;
/** 设备型号 */
private String deviceModel;
/** 设备SN号 */
private String deviceSn;
/** 所属部门主键 */
private Long deptId;
/** 网关 */
private String gateway;
public Long getDeviceId()
{
return deviceId;
}
public void setDeviceId(Long deviceId)
{
this.deviceId = deviceId;
}
public String getDeviceName()
{
return deviceName;
}
public void setDeviceName(String deviceName)
{
this.deviceName = deviceName;
}
public String getIotDeviceId()
{
return iotDeviceId;
}
public void setIotDeviceId(String iotDeviceId)
{
this.iotDeviceId = iotDeviceId;
}
public String getDeviceType()
{
return deviceType;
}
public void setDeviceType(String deviceType)
{
this.deviceType = deviceType;
}
public String getDeviceManufacturer()
{
return deviceManufacturer;
}
public void setDeviceManufacturer(String deviceManufacturer)
{
this.deviceManufacturer = deviceManufacturer;
}
public String getDeviceModel()
{
return deviceModel;
}
public void setDeviceModel(String deviceModel)
{
this.deviceModel = deviceModel;
}
public String getDeviceSn()
{
return deviceSn;
}
public void setDeviceSn(String deviceSn)
{
this.deviceSn = deviceSn;
}
public Long getDeptId()
{
return deptId;
}
public void setDeptId(Long deptId)
{
this.deptId = deptId;
}
public String getGateway()
{
return gateway;
}
public void setGateway(String gateway)
{
this.gateway = gateway;
}
@Override
public String toString()
{
return "DeviceEntity{" +
"deviceId=" + deviceId +
", deviceName='" + deviceName + '\'' +
", iotDeviceId='" + iotDeviceId + '\'' +
", deviceType='" + deviceType + '\'' +
", deviceManufacturer='" + deviceManufacturer + '\'' +
", deviceModel='" + deviceModel + '\'' +
", deviceSn='" + deviceSn + '\'' +
", deptId=" + deptId +
", gateway='" + gateway + '\'' +
'}';
}
}

View File

@ -0,0 +1,36 @@
package com.ruoyi.device.mapper.entity;
import com.ruoyi.common.core.web.domain.BaseEntity;
/**
* 设备临时表实体对象 tuoheng_device_temp
* Mapper 层实体对应数据库表
*
* @author ruoyi
* @date 2026-01-15
*/
public class DeviceTempEntity extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 主键ID */
private String id;
public String getId()
{
return id;
}
public void setId(String id)
{
this.id = id;
}
@Override
public String toString()
{
return "DeviceTempEntity{" +
"id='" + id + '\'' +
'}';
}
}

View File

@ -0,0 +1,64 @@
package com.ruoyi.device.mapper.entity;
import com.ruoyi.common.core.web.domain.BaseEntity;
/**
* 机场无人机关联表实体对象 device_dock_aircraft
* Mapper 层实体对应数据库表
*
* @author ruoyi
* @date 2026-01-16
*/
public class DockAircraftEntity extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 关联主键 */
private Long id;
/** 机场主键 */
private Long dockId;
/** 无人机主键 */
private Long aircraftId;
public Long getId()
{
return id;
}
public void setId(Long id)
{
this.id = id;
}
public Long getDockId()
{
return dockId;
}
public void setDockId(Long dockId)
{
this.dockId = dockId;
}
public Long getAircraftId()
{
return aircraftId;
}
public void setAircraftId(Long aircraftId)
{
this.aircraftId = aircraftId;
}
@Override
public String toString()
{
return "DockAircraftEntity{" +
"id=" + id +
", dockId=" + dockId +
", aircraftId=" + aircraftId +
'}';
}
}

View File

@ -0,0 +1,78 @@
package com.ruoyi.device.mapper.entity;
import com.ruoyi.common.core.web.domain.BaseEntity;
/**
* 机场表实体对象 device_dock
* Mapper 层实体对应数据库表
*
* @author ruoyi
* @date 2026-01-16
*/
public class DockEntity extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 机场主键 */
private Long dockId;
/** 机场名称 */
private String dockName;
/** 机场位置 */
private String dockLocation;
/** 设备表主键 */
private Long deviceId;
public Long getDockId()
{
return dockId;
}
public void setDockId(Long dockId)
{
this.dockId = dockId;
}
public String getDockName()
{
return dockName;
}
public void setDockName(String dockName)
{
this.dockName = dockName;
}
public String getDockLocation()
{
return dockLocation;
}
public void setDockLocation(String dockLocation)
{
this.dockLocation = dockLocation;
}
public Long getDeviceId()
{
return deviceId;
}
public void setDeviceId(Long deviceId)
{
this.deviceId = deviceId;
}
@Override
public String toString()
{
return "DockEntity{" +
"dockId=" + dockId +
", dockName='" + dockName + '\'' +
", dockLocation='" + dockLocation + '\'' +
", deviceId=" + deviceId +
'}';
}
}

View File

@ -0,0 +1,64 @@
package com.ruoyi.device.mapper.entity;
import com.ruoyi.common.core.web.domain.BaseEntity;
/**
* 机场分组关联表实体对象 device_dock_group
* Mapper 层实体对应数据库表
*
* @author ruoyi
* @date 2026-01-16
*/
public class DockGroupEntity extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 关联主键 */
private Long id;
/** 机场主键 */
private Long dockId;
/** 分组主键 */
private Long groupId;
public Long getId()
{
return id;
}
public void setId(Long id)
{
this.id = id;
}
public Long getDockId()
{
return dockId;
}
public void setDockId(Long dockId)
{
this.dockId = dockId;
}
public Long getGroupId()
{
return groupId;
}
public void setGroupId(Long groupId)
{
this.groupId = groupId;
}
@Override
public String toString()
{
return "DockGroupEntity{" +
"id=" + id +
", dockId=" + dockId +
", groupId=" + groupId +
'}';
}
}

View File

@ -0,0 +1,50 @@
package com.ruoyi.device.mapper.entity;
import com.ruoyi.common.core.web.domain.BaseEntity;
/**
* 分组表实体对象 device_group
* Mapper 层实体对应数据库表
*
* @author ruoyi
* @date 2026-01-16
*/
public class GroupEntity extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 分组主键 */
private Long groupId;
/** 分组名称 */
private String groupName;
public Long getGroupId()
{
return groupId;
}
public void setGroupId(Long groupId)
{
this.groupId = groupId;
}
public String getGroupName()
{
return groupName;
}
public void setGroupName(String groupName)
{
this.groupName = groupName;
}
@Override
public String toString()
{
return "GroupEntity{" +
"groupId=" + groupId +
", groupName='" + groupName + '\'' +
'}';
}
}

View File

@ -0,0 +1,120 @@
package com.ruoyi.device.mapper.entity;
import com.ruoyi.common.core.web.domain.BaseEntity;
/**
* 挂载表实体对象 device_payload
* Mapper 层实体对应数据库表
*
* @author ruoyi
* @date 2026-01-16
*/
public class PayloadEntity extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 挂载主键 */
private Long payloadId;
/** 挂载名称 */
private String payloadName;
/** 挂载类型 */
private String payloadType;
/** 挂载显示名称 */
private String payloadDisplayName;
/** 挂载动态信息 */
private String payloadDynamicInfo;
/** 挂载SN号 */
private String payloadSn;
/** IOT中的设备ID */
private String iotDeviceId;
public Long getPayloadId()
{
return payloadId;
}
public void setPayloadId(Long payloadId)
{
this.payloadId = payloadId;
}
public String getPayloadName()
{
return payloadName;
}
public void setPayloadName(String payloadName)
{
this.payloadName = payloadName;
}
public String getPayloadType()
{
return payloadType;
}
public void setPayloadType(String payloadType)
{
this.payloadType = payloadType;
}
public String getPayloadDisplayName()
{
return payloadDisplayName;
}
public void setPayloadDisplayName(String payloadDisplayName)
{
this.payloadDisplayName = payloadDisplayName;
}
public String getPayloadDynamicInfo()
{
return payloadDynamicInfo;
}
public void setPayloadDynamicInfo(String payloadDynamicInfo)
{
this.payloadDynamicInfo = payloadDynamicInfo;
}
public String getPayloadSn()
{
return payloadSn;
}
public void setPayloadSn(String payloadSn)
{
this.payloadSn = payloadSn;
}
public String getIotDeviceId()
{
return iotDeviceId;
}
public void setIotDeviceId(String iotDeviceId)
{
this.iotDeviceId = iotDeviceId;
}
@Override
public String toString()
{
return "PayloadEntity{" +
"payloadId=" + payloadId +
", payloadName='" + payloadName + '\'' +
", payloadType='" + payloadType + '\'' +
", payloadDisplayName='" + payloadDisplayName + '\'' +
", payloadDynamicInfo='" + payloadDynamicInfo + '\'' +
", payloadSn='" + payloadSn + '\'' +
", iotDeviceId='" + iotDeviceId + '\'' +
'}';
}
}

View File

@ -0,0 +1,53 @@
package com.ruoyi.device.service.api;
import com.ruoyi.device.service.dto.AircraftPayloadDTO;
import java.util.List;
/**
* 无人机挂载关联Service接口
*
* @author ruoyi
* @date 2026-01-16
*/
public interface IAircraftPayloadService
{
/**
* 查询无人机挂载关联列表
*
* @param aircraftPayloadDTO 无人机挂载关联
* @return 无人机挂载关联集合
*/
List<AircraftPayloadDTO> selectAircraftPayloadList(AircraftPayloadDTO aircraftPayloadDTO);
/**
* 根据关联主键查询无人机挂载关联
*
* @param id 关联主键
* @return 无人机挂载关联
*/
AircraftPayloadDTO selectAircraftPayloadById(Long id);
/**
* 根据无人机主键查询关联列表
*
* @param aircraftId 无人机主键
* @return 无人机挂载关联集合
*/
List<AircraftPayloadDTO> selectAircraftPayloadByAircraftId(Long aircraftId);
/**
* 根据挂载主键查询关联列表
*
* @param payloadId 挂载主键
* @return 无人机挂载关联集合
*/
List<AircraftPayloadDTO> selectAircraftPayloadByPayloadId(Long payloadId);
/**
* 根据机场主键查询关联列表
*
* @param dockId 机场主键
* @return 无人机挂载关联集合
*/
List<AircraftPayloadDTO> selectAircraftPayloadByDockId(Long dockId);
}

View File

@ -0,0 +1,46 @@
package com.ruoyi.device.service.api;
import com.ruoyi.device.api.domain.AircraftDetailVO;
import com.ruoyi.device.service.dto.AircraftDTO;
import java.util.List;
/**
* 无人机Service接口
*
* @author ruoyi
* @date 2026-01-16
*/
public interface IAircraftService
{
/**
* 查询无人机列表
*
* @param aircraftDTO 无人机
* @return 无人机集合
*/
List<AircraftDTO> selectAircraftList(AircraftDTO aircraftDTO);
/**
* 根据无人机主键查询无人机
*
* @param aircraftId 无人机主键
* @return 无人机
*/
AircraftDTO selectAircraftByAircraftId(Long aircraftId);
/**
* 查看无人机详情
*
* @param aircraftId 无人机ID
* @return 无人机详情
*/
AircraftDetailVO getAircraftDetail(Long aircraftId);
/**
* 更新无人机信息
*
* @param aircraftDTO 无人机信息
* @return 结果
*/
int updateAircraft(AircraftDTO aircraftDTO);
}

View File

@ -0,0 +1,30 @@
package com.ruoyi.device.service.api;
import com.ruoyi.device.service.dto.AircraftDetailDTO;
import com.ruoyi.device.service.dto.DockDetailDTO;
/**
* 设备缓冲服务接口
* 整合数据库数据和ThingsBoard数据
*
* @author ruoyi
* @date 2026-01-20
*/
public interface IBufferDeviceService
{
/**
* 通过ID获取机场详情
*
* @param dockId 机场ID
* @return 机场详情DTO
*/
DockDetailDTO getDockDetailById(Long dockId);
/**
* 通过ID获取无人机详情
*
* @param aircraftId 无人机ID
* @return 无人机详情DTO
*/
AircraftDetailDTO getAircraftDetailById(Long aircraftId);
}

View File

@ -0,0 +1,29 @@
package com.ruoyi.device.service.api;
import com.ruoyi.device.service.dto.DeviceDTO;
import java.util.List;
/**
* 设备Service接口
*
* @author ruoyi
* @date 2026-01-16
*/
public interface IDeviceService
{
/**
* 查询设备列表
*
* @param deviceDTO 设备
* @return 设备集合
*/
List<DeviceDTO> selectDeviceList(DeviceDTO deviceDTO);
/**
* 根据设备主键查询设备
*
* @param deviceId 设备主键
* @return 设备
*/
DeviceDTO selectDeviceByDeviceId(Long deviceId);
}

View File

@ -0,0 +1,29 @@
package com.ruoyi.device.service.api;
import com.ruoyi.device.service.dto.DeviceTempDTO;
import java.util.List;
/**
* 设备临时表Service接口
*
* @author ruoyi
* @date 2026-01-15
*/
public interface IDeviceTempService
{
/**
* 查询设备临时表列表
*
* @param deviceTempDTO 设备临时表
* @return 设备临时表集合
*/
List<DeviceTempDTO> selectDeviceTempList(DeviceTempDTO deviceTempDTO);
/**
* 根据ID查询设备临时表
*
* @param id 主键ID
* @return 设备临时表
*/
DeviceTempDTO selectDeviceTempById(String id);
}

View File

@ -0,0 +1,45 @@
package com.ruoyi.device.service.api;
import com.ruoyi.device.service.dto.DockAircraftDTO;
import java.util.List;
/**
* 机场无人机关联Service接口
*
* @author ruoyi
* @date 2026-01-16
*/
public interface IDockAircraftService
{
/**
* 查询机场无人机关联列表
*
* @param dockAircraftDTO 机场无人机关联
* @return 机场无人机关联集合
*/
List<DockAircraftDTO> selectDockAircraftList(DockAircraftDTO dockAircraftDTO);
/**
* 根据关联主键查询机场无人机关联
*
* @param id 关联主键
* @return 机场无人机关联
*/
DockAircraftDTO selectDockAircraftById(Long id);
/**
* 根据机场主键查询关联列表
*
* @param dockId 机场主键
* @return 机场无人机关联集合
*/
List<DockAircraftDTO> selectDockAircraftByDockId(Long dockId);
/**
* 根据无人机主键查询关联列表
*
* @param aircraftId 无人机主键
* @return 机场无人机关联集合
*/
List<DockAircraftDTO> selectDockAircraftByAircraftId(Long aircraftId);
}

View File

@ -0,0 +1,45 @@
package com.ruoyi.device.service.api;
import com.ruoyi.device.service.dto.DockGroupDTO;
import java.util.List;
/**
* 机场分组关联Service接口
*
* @author ruoyi
* @date 2026-01-16
*/
public interface IDockGroupService
{
/**
* 查询机场分组关联列表
*
* @param dockGroupDTO 机场分组关联
* @return 机场分组关联集合
*/
List<DockGroupDTO> selectDockGroupList(DockGroupDTO dockGroupDTO);
/**
* 根据关联主键查询机场分组关联
*
* @param id 关联主键
* @return 机场分组关联
*/
DockGroupDTO selectDockGroupById(Long id);
/**
* 根据机场主键查询关联列表
*
* @param dockId 机场主键
* @return 机场分组关联集合
*/
List<DockGroupDTO> selectDockGroupByDockId(Long dockId);
/**
* 根据分组主键查询关联列表
*
* @param groupId 分组主键
* @return 机场分组关联集合
*/
List<DockGroupDTO> selectDockGroupByGroupId(Long groupId);
}

View File

@ -0,0 +1,46 @@
package com.ruoyi.device.service.api;
import com.ruoyi.device.service.dto.DockDTO;
import java.util.List;
/**
* 机场Service接口
*
* @author ruoyi
* @date 2026-01-16
*/
public interface IDockService
{
/**
* 查询机场列表
*
* @param dockDTO 机场
* @return 机场集合
*/
List<DockDTO> selectDockList(DockDTO dockDTO);
/**
* 根据机场主键查询机场
*
* @param dockId 机场主键
* @return 机场
*/
DockDTO selectDockByDockId(Long dockId);
/**
* 搜索机场
*
* @param dockStatus 机场状态
* @param dockId 机场ID
* @return 机场列表
*/
List<DockDTO> searchDocks(String dockStatus, Long dockId);
/**
* 更新机场信息
*
* @param dockDTO 机场信息
* @return 结果
*/
int updateDock(DockDTO dockDTO);
}

View File

@ -0,0 +1,102 @@
package com.ruoyi.device.service.api;
import com.ruoyi.device.api.domain.GroupVO;
import com.ruoyi.device.service.dto.DockGroupDTO;
import com.ruoyi.device.service.dto.GroupDTO;
import com.ruoyi.device.service.dto.DockDTO;
import java.util.List;
/**
* 分组Service接口
*
* @author ruoyi
* @date 2026-01-16
*/
public interface IGroupService
{
/**
* 查询分组列表
*
* @param groupDTO 分组
* @return 分组集合
*/
List<GroupDTO> selectGroupList(GroupDTO groupDTO);
/**
* 根据分组主键查询分组
*
* @param groupId 分组主键
* @return 分组
*/
GroupDTO selectGroupByGroupId(Long groupId);
/**
* 新增分组
*
* @param groupDTO 分组
* @return 结果
*/
int insertGroup(GroupDTO groupDTO);
/**
* 修改分组
*
* @param groupDTO 分组
* @return 结果
*/
int updateGroup(GroupDTO groupDTO);
/**
* 删除分组
*
* @param groupId 分组主键
* @return 结果
*/
int deleteGroupByGroupId(Long groupId);
/**
* 批量删除分组
*
* @param groupIds 分组主键数组
* @return 结果
*/
int deleteGroupByGroupIds(Long[] groupIds);
/**
* 创建分组
*
* @param groupDTO 分组信息
* @return 分组ID
*/
Long createGroup(GroupDTO groupDTO);
/**
* 删除分组
*
* @param groupId 分组ID
*/
void deleteGroup(Long groupId);
/**
* 切换机场所在的分组
*
* @param dockId 机场ID
* @param groupId 分组ID
*/
void switchDockGroup(Long dockId, Long groupId);
/**
* 查看分组下的机场
*
* @param groupId 分组ID
* @return 机场列表
*/
List<DockGroupDTO> getDocksByGroupId(Long groupId);
/**
* 查看所有分组
*
* @return 分组ID列表
*/
List<GroupDTO> getAllGroupIds();
}

View File

@ -0,0 +1,29 @@
package com.ruoyi.device.service.api;
import com.ruoyi.device.service.dto.PayloadDTO;
import java.util.List;
/**
* 挂载Service接口
*
* @author ruoyi
* @date 2026-01-16
*/
public interface IPayloadService
{
/**
* 查询挂载列表
*
* @param payloadDTO 挂载
* @return 挂载集合
*/
List<PayloadDTO> selectPayloadList(PayloadDTO payloadDTO);
/**
* 根据挂载主键查询挂载
*
* @param payloadId 挂载主键
* @return 挂载
*/
PayloadDTO selectPayloadByPayloadId(Long payloadId);
}

View File

@ -0,0 +1,57 @@
package com.ruoyi.device.service.convert;
import com.ruoyi.common.core.utils.BaseConvert;
import com.ruoyi.device.domain.model.Aircraft;
import com.ruoyi.device.service.dto.AircraftDTO;
import java.util.List;
/**
* 无人机Service层转换器
* Service DTO Domain Model
*
* @author ruoyi
* @date 2026-01-16
*/
public class AircraftDTOConvert extends BaseConvert<Aircraft, AircraftDTO>
{
private static final AircraftDTOConvert INSTANCE = new AircraftDTOConvert();
private AircraftDTOConvert() {
super(Aircraft.class, AircraftDTO.class);
}
/**
* Model DTO
*/
public static AircraftDTO from(Aircraft model)
{
return INSTANCE.innerFrom(model);
}
/**
* DTO Model
*/
public static Aircraft to(AircraftDTO dto)
{
return INSTANCE.innerTo(dto);
}
/**
* Model List DTO List
*/
public static List<AircraftDTO> fromList(List<Aircraft> modelList)
{
return INSTANCE.innerFromList(modelList);
}
/**
* DTO List Model List
*/
public static List<Aircraft> toList(List<AircraftDTO> dtoList)
{
return INSTANCE.innerToList(dtoList);
}
}

View File

@ -0,0 +1,57 @@
package com.ruoyi.device.service.convert;
import com.ruoyi.common.core.utils.BaseConvert;
import com.ruoyi.device.domain.model.AircraftPayload;
import com.ruoyi.device.service.dto.AircraftPayloadDTO;
import java.util.List;
/**
* 无人机挂载关联Service层转换器
* Service DTO Domain Model
*
* @author ruoyi
* @date 2026-01-16
*/
public class AircraftPayloadDTOConvert extends BaseConvert<AircraftPayload, AircraftPayloadDTO>
{
private static final AircraftPayloadDTOConvert INSTANCE = new AircraftPayloadDTOConvert();
private AircraftPayloadDTOConvert() {
super(AircraftPayload.class, AircraftPayloadDTO.class);
}
/**
* Model DTO
*/
public static AircraftPayloadDTO from(AircraftPayload model)
{
return INSTANCE.innerFrom(model);
}
/**
* DTO Model
*/
public static AircraftPayload to(AircraftPayloadDTO dto)
{
return INSTANCE.innerTo(dto);
}
/**
* Model List DTO List
*/
public static List<AircraftPayloadDTO> fromList(List<AircraftPayload> modelList)
{
return INSTANCE.innerFromList(modelList);
}
/**
* DTO List Model List
*/
public static List<AircraftPayload> toList(List<AircraftPayloadDTO> dtoList)
{
return INSTANCE.innerToList(dtoList);
}
}

View File

@ -0,0 +1,57 @@
package com.ruoyi.device.service.convert;
import com.ruoyi.common.core.utils.BaseConvert;
import com.ruoyi.device.domain.model.Device;
import com.ruoyi.device.service.dto.DeviceDTO;
import java.util.List;
/**
* 设备Service层转换器
* Service DTO Domain Model
*
* @author ruoyi
* @date 2026-01-16
*/
public class DeviceDTOConvert extends BaseConvert<Device, DeviceDTO>
{
private static final DeviceDTOConvert INSTANCE = new DeviceDTOConvert();
private DeviceDTOConvert() {
super(Device.class, DeviceDTO.class);
}
/**
* Model DTO
*/
public static DeviceDTO from(Device model)
{
return INSTANCE.innerFrom(model);
}
/**
* DTO Model
*/
public static Device to(DeviceDTO dto)
{
return INSTANCE.innerTo(dto);
}
/**
* Model List DTO List
*/
public static List<DeviceDTO> fromList(List<Device> modelList)
{
return INSTANCE.innerFromList(modelList);
}
/**
* DTO List Model List
*/
public static List<Device> toList(List<DeviceDTO> dtoList)
{
return INSTANCE.innerToList(dtoList);
}
}

Some files were not shown because too many files have changed in this diff Show More