1. 统一包名修改
This commit is contained in:
212
zt-module-iot/zt-module-iot-biz/pom.xml
Normal file
212
zt-module-iot/zt-module-iot-biz/pom.xml
Normal file
@@ -0,0 +1,212 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>zt-module-iot</artifactId>
|
||||
<groupId>com.zt.plat</groupId>
|
||||
<version>${revision}</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<artifactId>zt-module-iot-biz</artifactId>
|
||||
|
||||
<name>${project.artifactId}</name>
|
||||
<description>
|
||||
物联网 模块,主要实现 产品管理、设备管理、协议管理等功能。
|
||||
<!-- TODO 芋艿:后续补充下 -->
|
||||
</description>
|
||||
|
||||
<dependencies>
|
||||
<!-- Spring Cloud 基础 -->
|
||||
<dependency>
|
||||
<groupId>com.zt.plat</groupId>
|
||||
<artifactId>zt-spring-boot-starter-env</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 依赖服务 -->
|
||||
<dependency>
|
||||
<groupId>com.zt.plat</groupId>
|
||||
<artifactId>zt-module-system-api</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.zt.plat</groupId>
|
||||
<artifactId>zt-module-iot-api</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.zt.plat</groupId>
|
||||
<artifactId>zt-spring-boot-starter-biz-tenant</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 业务组件 -->
|
||||
<dependency>
|
||||
<groupId>com.zt.plat</groupId>
|
||||
<artifactId>zt-spring-boot-starter-biz-tenant</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Web 相关 -->
|
||||
<dependency>
|
||||
<groupId>com.zt.plat</groupId>
|
||||
<artifactId>zt-spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.zt.plat</groupId>
|
||||
<artifactId>zt-spring-boot-starter-security</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- DB 相关 -->
|
||||
<dependency>
|
||||
<groupId>com.taosdata.jdbc</groupId>
|
||||
<artifactId>taos-jdbcdriver</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.zt.plat</groupId>
|
||||
<artifactId>zt-spring-boot-starter-mybatis</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.zt.plat</groupId>
|
||||
<artifactId>zt-spring-boot-starter-redis</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- RPC 远程调用相关 -->
|
||||
<dependency>
|
||||
<groupId>com.zt.plat</groupId>
|
||||
<artifactId>zt-spring-boot-starter-rpc</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Registry 注册中心相关 -->
|
||||
<dependency>
|
||||
<groupId>com.alibaba.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Config 配置中心相关 -->
|
||||
<dependency>
|
||||
<groupId>com.alibaba.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Job 定时任务相关 -->
|
||||
<dependency>
|
||||
<groupId>com.zt.plat</groupId>
|
||||
<artifactId>zt-spring-boot-starter-job</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- TODO @芋艿:引入下,看看情况 -->
|
||||
<dependency>
|
||||
<groupId>org.quartz-scheduler</groupId>
|
||||
<artifactId>quartz</artifactId>
|
||||
<version>2.3.2</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 消息队列相关 -->
|
||||
<dependency>
|
||||
<groupId>com.zt.plat</groupId>
|
||||
<artifactId>zt-spring-boot-starter-mq</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Test 测试相关 -->
|
||||
<dependency>
|
||||
<groupId>com.zt.plat</groupId>
|
||||
<artifactId>zt-spring-boot-starter-test</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 工具类相关 -->
|
||||
<dependency>
|
||||
<groupId>com.zt.plat</groupId>
|
||||
<artifactId>zt-spring-boot-starter-excel</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 监控相关 -->
|
||||
<dependency>
|
||||
<groupId>com.zt.plat</groupId>
|
||||
<artifactId>zt-spring-boot-starter-monitor</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 消息队列相关 TODO 芋艿:需要整理 -->
|
||||
<dependency>
|
||||
<groupId>org.apache.rocketmq</groupId>
|
||||
<artifactId>rocketmq-spring-boot-starter</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.kafka</groupId>
|
||||
<artifactId>spring-kafka</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-amqp</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.pf4j</groupId> <!-- PF4J:内置插件机制 -->
|
||||
<artifactId>pf4j-spring</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- TODO @芋艿:bom 管理 -->
|
||||
<dependency>
|
||||
<groupId>org.apache.groovy</groupId>
|
||||
<artifactId>groovy-all</artifactId>
|
||||
<version>4.0.25</version>
|
||||
<type>pom</type>
|
||||
</dependency>
|
||||
|
||||
<!-- TODO @芋艿:bom 管理 -->
|
||||
<dependency>
|
||||
<groupId>org.graalvm.js</groupId>
|
||||
<artifactId>js</artifactId>
|
||||
<version>24.1.2</version>
|
||||
<type>pom</type>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.graalvm.js</groupId>
|
||||
<artifactId>js-scriptengine</artifactId>
|
||||
<version>24.1.2</version>
|
||||
</dependency>
|
||||
|
||||
<!-- TODO @芋艿:合理注释 -->
|
||||
<!-- IoT 数据桥梁的执行器所需消息队列。如果您只需要使用 rocketmq 那么则注释掉其它消息队列即可 -->
|
||||
<!-- <dependency>-->
|
||||
<!-- <groupId>org.apache.rocketmq</groupId>-->
|
||||
<!-- <artifactId>rocketmq-spring-boot-starter</artifactId>-->
|
||||
<!-- </dependency>-->
|
||||
<!-- <dependency>-->
|
||||
<!-- <groupId>org.springframework.kafka</groupId>-->
|
||||
<!-- <artifactId>spring-kafka</artifactId>-->
|
||||
<!-- </dependency>-->
|
||||
<!-- <dependency>-->
|
||||
<!-- <groupId>org.springframework.boot</groupId>-->
|
||||
<!-- <artifactId>spring-boot-starter-amqp</artifactId>-->
|
||||
<!-- </dependency>-->
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<!-- 设置构建的 jar 包名 -->
|
||||
<finalName>${project.artifactId}</finalName>
|
||||
<plugins>
|
||||
<!-- 打包 -->
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<version>${spring.boot.version}</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>repackage</goal> <!-- 将引入的 jar 打入其中 -->
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.zt.plat.module.iot;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
/**
|
||||
* 项目的启动类
|
||||
*
|
||||
* 如果你碰到启动的问题,请认真阅读 https://cloud.iocoder.cn/quick-start/ 文章
|
||||
* 如果你碰到启动的问题,请认真阅读 https://cloud.iocoder.cn/quick-start/ 文章
|
||||
* 如果你碰到启动的问题,请认真阅读 https://cloud.iocoder.cn/quick-start/ 文章
|
||||
*
|
||||
* @author ZT
|
||||
*/
|
||||
@SpringBootApplication
|
||||
public class IoTServerApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
// 如果你碰到启动的问题,请认真阅读 https://cloud.iocoder.cn/quick-start/ 文章
|
||||
// 如果你碰到启动的问题,请认真阅读 https://cloud.iocoder.cn/quick-start/ 文章
|
||||
// 如果你碰到启动的问题,请认真阅读 https://cloud.iocoder.cn/quick-start/ 文章
|
||||
|
||||
SpringApplication.run(IoTServerApplication.class, args);
|
||||
|
||||
// 如果你碰到启动的问题,请认真阅读 https://cloud.iocoder.cn/quick-start/ 文章
|
||||
// 如果你碰到启动的问题,请认真阅读 https://cloud.iocoder.cn/quick-start/ 文章
|
||||
// 如果你碰到启动的问题,请认真阅读 https://cloud.iocoder.cn/quick-start/ 文章
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package com.zt.plat.module.iot;
|
||||
|
||||
import cn.hutool.script.ScriptUtil;
|
||||
import javax.script.Bindings;
|
||||
import javax.script.ScriptEngine;
|
||||
import javax.script.ScriptException;
|
||||
|
||||
/**
|
||||
* TODO 芋艿:测试脚本的接入
|
||||
*/
|
||||
public class ScriptTest {
|
||||
|
||||
public static void main2(String[] args) {
|
||||
// 创建一个 Groovy 脚本引擎
|
||||
ScriptEngine engine = ScriptUtil.createGroovyEngine();
|
||||
|
||||
// 创建绑定参数
|
||||
Bindings bindings = engine.createBindings();
|
||||
bindings.put("name", "Alice");
|
||||
bindings.put("age", 30);
|
||||
|
||||
// 定义一个稍微复杂的 Groovy 脚本
|
||||
String script = "def greeting = 'Hello, ' + name + '!';\n" +
|
||||
"def ageInFiveYears = age + 5;\n" +
|
||||
"def message = greeting + ' In five years, you will be ' + ageInFiveYears + ' years old.';\n" +
|
||||
"return message.toUpperCase();\n";
|
||||
|
||||
try {
|
||||
// 执行脚本并获取结果
|
||||
Object result = engine.eval(script, bindings);
|
||||
System.out.println(result); // 输出: HELLO, ALICE! IN FIVE YEARS, YOU WILL BE 35 YEARS OLD.
|
||||
} catch (ScriptException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
// 创建一个 JavaScript 脚本引擎
|
||||
ScriptEngine jsEngine = ScriptUtil.createJsEngine();
|
||||
|
||||
// 创建绑定参数
|
||||
Bindings jsBindings = jsEngine.createBindings();
|
||||
jsBindings.put("name", "Bob");
|
||||
jsBindings.put("age", 25);
|
||||
|
||||
// 定义一个简单的 JavaScript 脚本
|
||||
String jsScript = "var greeting = 'Hello, ' + name + '!';\n" +
|
||||
"var ageInTenYears = age + 10;\n" +
|
||||
"var message = greeting + ' In ten years, you will be ' + ageInTenYears + ' years old.';\n" +
|
||||
"message.toUpperCase();\n";
|
||||
|
||||
try {
|
||||
// 执行脚本并获取结果
|
||||
Object jsResult = jsEngine.eval(jsScript, jsBindings);
|
||||
System.out.println(jsResult); // 输出: HELLO, BOB! IN TEN YEARS, YOU WILL BE 35 YEARS OLD.
|
||||
} catch (ScriptException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
package com.zt.plat.module.iot.api.device;
|
||||
|
||||
import com.zt.plat.framework.common.pojo.CommonResult;
|
||||
import com.zt.plat.module.iot.api.device.dto.control.upstream.*;
|
||||
import com.zt.plat.module.iot.service.device.control.IotDeviceUpstreamService;
|
||||
import com.zt.plat.module.iot.service.plugin.IotPluginInstanceService;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import static com.zt.plat.framework.common.pojo.CommonResult.success;
|
||||
|
||||
/**
|
||||
* * 设备数据 Upstream 上行 API 实现类
|
||||
*/
|
||||
@RestController
|
||||
@Validated
|
||||
public class IoTDeviceUpstreamApiImpl implements IotDeviceUpstreamApi {
|
||||
|
||||
@Resource
|
||||
private IotDeviceUpstreamService deviceUpstreamService;
|
||||
@Resource
|
||||
private IotPluginInstanceService pluginInstanceService;
|
||||
|
||||
// ========== 设备相关 ==========
|
||||
|
||||
@Override
|
||||
public CommonResult<Boolean> updateDeviceState(IotDeviceStateUpdateReqDTO updateReqDTO) {
|
||||
deviceUpstreamService.updateDeviceState(updateReqDTO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommonResult<Boolean> reportDeviceProperty(IotDevicePropertyReportReqDTO reportReqDTO) {
|
||||
deviceUpstreamService.reportDeviceProperty(reportReqDTO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommonResult<Boolean> reportDeviceEvent(IotDeviceEventReportReqDTO reportReqDTO) {
|
||||
deviceUpstreamService.reportDeviceEvent(reportReqDTO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommonResult<Boolean> registerDevice(IotDeviceRegisterReqDTO registerReqDTO) {
|
||||
deviceUpstreamService.registerDevice(registerReqDTO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommonResult<Boolean> registerSubDevice(IotDeviceRegisterSubReqDTO registerReqDTO) {
|
||||
deviceUpstreamService.registerSubDevice(registerReqDTO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommonResult<Boolean> addDeviceTopology(IotDeviceTopologyAddReqDTO addReqDTO) {
|
||||
deviceUpstreamService.addDeviceTopology(addReqDTO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommonResult<Boolean> authenticateEmqxConnection(IotDeviceEmqxAuthReqDTO authReqDTO) {
|
||||
boolean result = deviceUpstreamService.authenticateEmqxConnection(authReqDTO);
|
||||
return success(result);
|
||||
}
|
||||
|
||||
// ========== 插件相关 ==========
|
||||
|
||||
@Override
|
||||
public CommonResult<Boolean> heartbeatPluginInstance(IotPluginInstanceHeartbeatReqDTO heartbeatReqDTO) {
|
||||
pluginInstanceService.heartbeatPluginInstance(heartbeatReqDTO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
/**
|
||||
* 占位
|
||||
*
|
||||
* TODO 芋艿:后续删除
|
||||
*/
|
||||
package com.zt.plat.module.iot.api;
|
||||
@@ -0,0 +1,75 @@
|
||||
### 请求 /iot/device/downstream 接口(服务调用) => 成功
|
||||
POST {{baseUrl}}/iot/device/downstream
|
||||
Content-Type: application/json
|
||||
tenant-id: {{adminTenentId}}
|
||||
Authorization: Bearer {{token}}
|
||||
|
||||
{
|
||||
"id": 25,
|
||||
"type": "service",
|
||||
"identifier": "temperature",
|
||||
"data": {
|
||||
"xx": "yy"
|
||||
}
|
||||
}
|
||||
|
||||
### 请求 /iot/device/downstream 接口(属性设置) => 成功
|
||||
POST {{baseUrl}}/iot/device/downstream
|
||||
Content-Type: application/json
|
||||
tenant-id: {{adminTenentId}}
|
||||
Authorization: Bearer {{token}}
|
||||
|
||||
{
|
||||
"id": 25,
|
||||
"type": "property",
|
||||
"identifier": "set",
|
||||
"data": {
|
||||
"xx": "yy"
|
||||
}
|
||||
}
|
||||
|
||||
### 请求 /iot/device/downstream 接口(属性获取) => 成功
|
||||
POST {{baseUrl}}/iot/device/downstream
|
||||
Content-Type: application/json
|
||||
tenant-id: {{adminTenentId}}
|
||||
Authorization: Bearer {{token}}
|
||||
|
||||
{
|
||||
"id": 25,
|
||||
"type": "property",
|
||||
"identifier": "get",
|
||||
"data": ["xx", "yy"]
|
||||
}
|
||||
|
||||
### 请求 /iot/device/downstream 接口(配置设置) => 成功
|
||||
POST {{baseUrl}}/iot/device/downstream
|
||||
Content-Type: application/json
|
||||
tenant-id: {{adminTenentId}}
|
||||
Authorization: Bearer {{token}}
|
||||
|
||||
{
|
||||
"id": 25,
|
||||
"type": "config",
|
||||
"identifier": "set"
|
||||
}
|
||||
|
||||
### 请求 /iot/device/downstream 接口(OTA 升级) => 成功
|
||||
POST {{baseUrl}}/iot/device/downstream
|
||||
Content-Type: application/json
|
||||
tenant-id: {{adminTenentId}}
|
||||
Authorization: Bearer {{token}}
|
||||
|
||||
{
|
||||
"id": 25,
|
||||
"type": "ota",
|
||||
"identifier": "upgrade",
|
||||
"data": {
|
||||
"firmwareId": 1,
|
||||
"version": "1.0.0",
|
||||
"signMethod": "MD5",
|
||||
"fileSign": "d41d8cd98f00b204e9800998ecf8427e",
|
||||
"fileSize": 1024,
|
||||
"fileUrl": "http://example.com/firmware.bin",
|
||||
"information": "{\"desc\":\"升级到最新版本\"}"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,188 @@
|
||||
package com.zt.plat.module.iot.controller.admin.device;
|
||||
|
||||
import com.zt.plat.framework.apilog.core.annotation.ApiAccessLog;
|
||||
import com.zt.plat.framework.common.pojo.CommonResult;
|
||||
import com.zt.plat.framework.common.pojo.PageParam;
|
||||
import com.zt.plat.framework.common.pojo.PageResult;
|
||||
import com.zt.plat.framework.common.util.object.BeanUtils;
|
||||
import com.zt.plat.framework.excel.core.util.ExcelUtils;
|
||||
import com.zt.plat.module.iot.controller.admin.device.vo.control.IotDeviceDownstreamReqVO;
|
||||
import com.zt.plat.module.iot.controller.admin.device.vo.control.IotDeviceUpstreamReqVO;
|
||||
import com.zt.plat.module.iot.controller.admin.device.vo.device.*;
|
||||
import com.zt.plat.module.iot.dal.dataobject.device.IotDeviceDO;
|
||||
import com.zt.plat.module.iot.service.device.IotDeviceService;
|
||||
import com.zt.plat.module.iot.service.device.control.IotDeviceDownstreamService;
|
||||
import com.zt.plat.module.iot.service.device.control.IotDeviceUpstreamService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import jakarta.validation.Valid;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import static com.zt.plat.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
|
||||
import static com.zt.plat.framework.common.pojo.CommonResult.success;
|
||||
import static com.zt.plat.framework.common.util.collection.CollectionUtils.convertList;
|
||||
|
||||
@Tag(name = "管理后台 - IoT 设备")
|
||||
@RestController
|
||||
@RequestMapping("/iot/device")
|
||||
@Validated
|
||||
public class IotDeviceController {
|
||||
|
||||
@Resource
|
||||
private IotDeviceService deviceService;
|
||||
@Resource
|
||||
private IotDeviceUpstreamService deviceUpstreamService;
|
||||
@Resource
|
||||
private IotDeviceDownstreamService deviceDownstreamService;
|
||||
|
||||
@PostMapping("/create")
|
||||
@Operation(summary = "创建设备")
|
||||
@PreAuthorize("@ss.hasPermission('iot:device:create')")
|
||||
public CommonResult<Long> createDevice(@Valid @RequestBody IotDeviceSaveReqVO createReqVO) {
|
||||
return success(deviceService.createDevice(createReqVO));
|
||||
}
|
||||
|
||||
@PutMapping("/update")
|
||||
@Operation(summary = "更新设备")
|
||||
@PreAuthorize("@ss.hasPermission('iot:device:update')")
|
||||
public CommonResult<Boolean> updateDevice(@Valid @RequestBody IotDeviceSaveReqVO updateReqVO) {
|
||||
deviceService.updateDevice(updateReqVO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
// TODO @芋艿:参考阿里云:1)绑定网关;2)解绑网关
|
||||
|
||||
@PutMapping("/update-group")
|
||||
@Operation(summary = "更新设备分组")
|
||||
@PreAuthorize("@ss.hasPermission('iot:device:update')")
|
||||
public CommonResult<Boolean> updateDeviceGroup(@Valid @RequestBody IotDeviceUpdateGroupReqVO updateReqVO) {
|
||||
deviceService.updateDeviceGroup(updateReqVO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@DeleteMapping("/delete")
|
||||
@Operation(summary = "删除单个设备")
|
||||
@Parameter(name = "id", description = "编号", required = true)
|
||||
@PreAuthorize("@ss.hasPermission('iot:device:delete')")
|
||||
public CommonResult<Boolean> deleteDevice(@RequestParam("id") Long id) {
|
||||
deviceService.deleteDevice(id);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@DeleteMapping("/delete-list")
|
||||
@Operation(summary = "删除多个设备")
|
||||
@Parameter(name = "ids", description = "编号数组", required = true)
|
||||
@PreAuthorize("@ss.hasPermission('iot:device:delete')")
|
||||
public CommonResult<Boolean> deleteDeviceList(@RequestParam("ids") Collection<Long> ids) {
|
||||
deviceService.deleteDeviceList(ids);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@GetMapping("/get")
|
||||
@Operation(summary = "获得设备")
|
||||
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
||||
@PreAuthorize("@ss.hasPermission('iot:device:query')")
|
||||
public CommonResult<IotDeviceRespVO> getDevice(@RequestParam("id") Long id) {
|
||||
IotDeviceDO device = deviceService.getDevice(id);
|
||||
return success(BeanUtils.toBean(device, IotDeviceRespVO.class));
|
||||
}
|
||||
|
||||
@GetMapping("/page")
|
||||
@Operation(summary = "获得设备分页")
|
||||
@PreAuthorize("@ss.hasPermission('iot:device:query')")
|
||||
public CommonResult<PageResult<IotDeviceRespVO>> getDevicePage(@Valid IotDevicePageReqVO pageReqVO) {
|
||||
PageResult<IotDeviceDO> pageResult = deviceService.getDevicePage(pageReqVO);
|
||||
return success(BeanUtils.toBean(pageResult, IotDeviceRespVO.class));
|
||||
}
|
||||
|
||||
@GetMapping("/export-excel")
|
||||
@Operation(summary = "导出设备 Excel")
|
||||
@PreAuthorize("@ss.hasPermission('iot:device:export')")
|
||||
@ApiAccessLog(operateType = EXPORT)
|
||||
public void exportDeviceExcel(@Valid IotDevicePageReqVO exportReqVO,
|
||||
HttpServletResponse response) throws IOException {
|
||||
exportReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
|
||||
CommonResult<PageResult<IotDeviceRespVO>> result = getDevicePage(exportReqVO);
|
||||
// 导出 Excel
|
||||
ExcelUtils.write(response, "设备.xls", "数据", IotDeviceRespVO.class,
|
||||
result.getData().getList());
|
||||
}
|
||||
|
||||
@GetMapping("/count")
|
||||
@Operation(summary = "获得设备数量")
|
||||
@Parameter(name = "productId", description = "产品编号", example = "1")
|
||||
@PreAuthorize("@ss.hasPermission('iot:device:query')")
|
||||
public CommonResult<Long> getDeviceCount(@RequestParam("productId") Long productId) {
|
||||
return success(deviceService.getDeviceCountByProductId(productId));
|
||||
}
|
||||
|
||||
@GetMapping("/simple-list")
|
||||
@Operation(summary = "获取设备的精简信息列表", description = "主要用于前端的下拉选项")
|
||||
@Parameter(name = "deviceType", description = "设备类型", example = "1")
|
||||
public CommonResult<List<IotDeviceRespVO>> getSimpleDeviceList(
|
||||
@RequestParam(value = "deviceType", required = false) Integer deviceType) {
|
||||
List<IotDeviceDO> list = deviceService.getDeviceListByDeviceType(deviceType);
|
||||
return success(convertList(list, device -> // 只返回 id、name 字段
|
||||
new IotDeviceRespVO().setId(device.getId()).setDeviceName(device.getDeviceName())));
|
||||
}
|
||||
|
||||
@PostMapping("/import")
|
||||
@Operation(summary = "导入设备")
|
||||
@PreAuthorize("@ss.hasPermission('iot:device:import')")
|
||||
public CommonResult<IotDeviceImportRespVO> importDevice(
|
||||
@RequestParam("file") MultipartFile file,
|
||||
@RequestParam(value = "updateSupport", required = false, defaultValue = "false") Boolean updateSupport)
|
||||
throws Exception {
|
||||
List<IotDeviceImportExcelVO> list = ExcelUtils.read(file, IotDeviceImportExcelVO.class);
|
||||
return success(deviceService.importDevice(list, updateSupport));
|
||||
}
|
||||
|
||||
@GetMapping("/get-import-template")
|
||||
@Operation(summary = "获得导入设备模板")
|
||||
public void importTemplate(HttpServletResponse response) throws IOException {
|
||||
// 手动创建导出 demo
|
||||
List<IotDeviceImportExcelVO> list = Arrays.asList(
|
||||
IotDeviceImportExcelVO.builder().deviceName("温度传感器001").parentDeviceName("gateway110")
|
||||
.productKey("1de24640dfe").groupNames("灰度分组,生产分组").build(),
|
||||
IotDeviceImportExcelVO.builder().deviceName("biubiu")
|
||||
.productKey("YzvHxd4r67sT4s2B").groupNames("").build());
|
||||
// 输出
|
||||
ExcelUtils.write(response, "设备导入模板.xls", "数据", IotDeviceImportExcelVO.class, list);
|
||||
}
|
||||
|
||||
@PostMapping("/upstream")
|
||||
@Operation(summary = "设备上行", description = "可用于设备模拟")
|
||||
@PreAuthorize("@ss.hasPermission('iot:device:upstream')")
|
||||
public CommonResult<Boolean> upstreamDevice(@Valid @RequestBody IotDeviceUpstreamReqVO upstreamReqVO) {
|
||||
deviceUpstreamService.upstreamDevice(upstreamReqVO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@PostMapping("/downstream")
|
||||
@Operation(summary = "设备下行", description = "可用于设备模拟")
|
||||
@PreAuthorize("@ss.hasPermission('iot:device:downstream')")
|
||||
public CommonResult<Boolean> downstreamDevice(@Valid @RequestBody IotDeviceDownstreamReqVO downstreamReqVO) {
|
||||
deviceDownstreamService.downstreamDevice(downstreamReqVO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
// TODO @haohao:是不是默认详情接口,不返回 secret,然后这个接口,用于统一返回。然后接口名可以更通用一点。
|
||||
@GetMapping("/mqtt-connection-params")
|
||||
@Operation(summary = "获取 MQTT 连接参数")
|
||||
@PreAuthorize("@ss.hasPermission('iot:device:mqtt-connection-params')")
|
||||
public CommonResult<IotDeviceMqttConnectionParamsRespVO> getMqttConnectionParams(@RequestParam("deviceId") Long deviceId) {
|
||||
return success(deviceService.getMqttConnectionParams(deviceId));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
package com.zt.plat.module.iot.controller.admin.device;
|
||||
|
||||
import com.zt.plat.framework.common.enums.CommonStatusEnum;
|
||||
import com.zt.plat.framework.common.pojo.CommonResult;
|
||||
import com.zt.plat.framework.common.pojo.PageResult;
|
||||
import com.zt.plat.framework.common.util.object.BeanUtils;
|
||||
import com.zt.plat.module.iot.controller.admin.device.vo.group.IotDeviceGroupPageReqVO;
|
||||
import com.zt.plat.module.iot.controller.admin.device.vo.group.IotDeviceGroupRespVO;
|
||||
import com.zt.plat.module.iot.controller.admin.device.vo.group.IotDeviceGroupSaveReqVO;
|
||||
import com.zt.plat.module.iot.dal.dataobject.device.IotDeviceGroupDO;
|
||||
import com.zt.plat.module.iot.service.device.IotDeviceGroupService;
|
||||
import com.zt.plat.module.iot.service.device.IotDeviceService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.validation.Valid;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static com.zt.plat.framework.common.pojo.CommonResult.success;
|
||||
import static com.zt.plat.framework.common.util.collection.CollectionUtils.convertList;
|
||||
|
||||
@Tag(name = "管理后台 - IoT 设备分组")
|
||||
@RestController
|
||||
@RequestMapping("/iot/device-group")
|
||||
@Validated
|
||||
public class IotDeviceGroupController {
|
||||
|
||||
@Resource
|
||||
private IotDeviceGroupService deviceGroupService;
|
||||
@Resource
|
||||
private IotDeviceService deviceService;
|
||||
|
||||
@PostMapping("/create")
|
||||
@Operation(summary = "创建设备分组")
|
||||
@PreAuthorize("@ss.hasPermission('iot:device-group:create')")
|
||||
public CommonResult<Long> createDeviceGroup(@Valid @RequestBody IotDeviceGroupSaveReqVO createReqVO) {
|
||||
return success(deviceGroupService.createDeviceGroup(createReqVO));
|
||||
}
|
||||
|
||||
@PutMapping("/update")
|
||||
@Operation(summary = "更新设备分组")
|
||||
@PreAuthorize("@ss.hasPermission('iot:device-group:update')")
|
||||
public CommonResult<Boolean> updateDeviceGroup(@Valid @RequestBody IotDeviceGroupSaveReqVO updateReqVO) {
|
||||
deviceGroupService.updateDeviceGroup(updateReqVO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@DeleteMapping("/delete")
|
||||
@Operation(summary = "删除设备分组")
|
||||
@Parameter(name = "id", description = "编号", required = true)
|
||||
@PreAuthorize("@ss.hasPermission('iot:device-group:delete')")
|
||||
public CommonResult<Boolean> deleteDeviceGroup(@RequestParam("id") Long id) {
|
||||
deviceGroupService.deleteDeviceGroup(id);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@GetMapping("/get")
|
||||
@Operation(summary = "获得设备分组")
|
||||
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
||||
@PreAuthorize("@ss.hasPermission('iot:device-group:query')")
|
||||
public CommonResult<IotDeviceGroupRespVO> getDeviceGroup(@RequestParam("id") Long id) {
|
||||
IotDeviceGroupDO deviceGroup = deviceGroupService.getDeviceGroup(id);
|
||||
return success(BeanUtils.toBean(deviceGroup, IotDeviceGroupRespVO.class));
|
||||
}
|
||||
|
||||
@GetMapping("/page")
|
||||
@Operation(summary = "获得设备分组分页")
|
||||
@PreAuthorize("@ss.hasPermission('iot:device-group:query')")
|
||||
public CommonResult<PageResult<IotDeviceGroupRespVO>> getDeviceGroupPage(@Valid IotDeviceGroupPageReqVO pageReqVO) {
|
||||
PageResult<IotDeviceGroupDO> pageResult = deviceGroupService.getDeviceGroupPage(pageReqVO);
|
||||
return success(BeanUtils.toBean(pageResult, IotDeviceGroupRespVO.class,
|
||||
group -> group.setDeviceCount(deviceService.getDeviceCountByGroupId(group.getId()))));
|
||||
}
|
||||
|
||||
@GetMapping("/simple-list")
|
||||
@Operation(summary = "获取设备分组的精简信息列表", description = "只包含被开启的分组,主要用于前端的下拉选项")
|
||||
public CommonResult<List<IotDeviceGroupRespVO>> getSimpleDeviceGroupList() {
|
||||
List<IotDeviceGroupDO> list = deviceGroupService.getDeviceGroupListByStatus(CommonStatusEnum.ENABLE.getStatus());
|
||||
return success(convertList(list, group -> // 只返回 id、name 字段
|
||||
new IotDeviceGroupRespVO().setId(group.getId()).setName(group.getName())));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package com.zt.plat.module.iot.controller.admin.device;
|
||||
|
||||
import com.zt.plat.framework.common.pojo.CommonResult;
|
||||
import com.zt.plat.framework.common.pojo.PageResult;
|
||||
import com.zt.plat.framework.common.util.object.BeanUtils;
|
||||
import com.zt.plat.module.iot.controller.admin.device.vo.data.IotDeviceLogPageReqVO;
|
||||
import com.zt.plat.module.iot.controller.admin.device.vo.data.IotDeviceLogRespVO;
|
||||
import com.zt.plat.module.iot.dal.dataobject.device.IotDeviceLogDO;
|
||||
import com.zt.plat.module.iot.service.device.data.IotDeviceLogService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.validation.Valid;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import static com.zt.plat.framework.common.pojo.CommonResult.success;
|
||||
|
||||
@Tag(name = "管理后台 - IoT 设备日志")
|
||||
@RestController
|
||||
@RequestMapping("/iot/device/log")
|
||||
@Validated
|
||||
public class IotDeviceLogController {
|
||||
|
||||
@Resource
|
||||
private IotDeviceLogService deviceLogService;
|
||||
|
||||
@GetMapping("/page")
|
||||
@Operation(summary = "获得设备日志分页")
|
||||
@PreAuthorize("@ss.hasPermission('iot:device:log-query')")
|
||||
public CommonResult<PageResult<IotDeviceLogRespVO>> getDeviceLogPage(@Valid IotDeviceLogPageReqVO pageReqVO) {
|
||||
PageResult<IotDeviceLogDO> pageResult = deviceLogService.getDeviceLogPage(pageReqVO);
|
||||
return success(BeanUtils.toBean(pageResult, IotDeviceLogRespVO.class));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
package com.zt.plat.module.iot.controller.admin.device;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.date.LocalDateTimeUtil;
|
||||
import cn.hutool.core.lang.Assert;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.zt.plat.framework.common.pojo.CommonResult;
|
||||
import com.zt.plat.framework.common.pojo.PageResult;
|
||||
import com.zt.plat.module.iot.controller.admin.device.vo.data.IotDevicePropertyHistoryPageReqVO;
|
||||
import com.zt.plat.module.iot.controller.admin.device.vo.data.IotDevicePropertyRespVO;
|
||||
import com.zt.plat.module.iot.dal.dataobject.device.IotDeviceDO;
|
||||
import com.zt.plat.module.iot.dal.dataobject.device.IotDevicePropertyDO;
|
||||
import com.zt.plat.module.iot.dal.dataobject.thingmodel.IotThingModelDO;
|
||||
import com.zt.plat.module.iot.service.device.IotDeviceService;
|
||||
import com.zt.plat.module.iot.service.device.data.IotDevicePropertyService;
|
||||
import com.zt.plat.module.iot.service.thingmodel.IotThingModelService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.Parameters;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.validation.Valid;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static com.zt.plat.framework.common.pojo.CommonResult.success;
|
||||
import static com.zt.plat.framework.common.util.collection.CollectionUtils.convertList;
|
||||
|
||||
@Tag(name = "管理后台 - IoT 设备属性")
|
||||
@RestController
|
||||
@RequestMapping("/iot/device/property")
|
||||
@Validated
|
||||
public class IotDevicePropertyController {
|
||||
|
||||
@Resource
|
||||
private IotDevicePropertyService devicePropertyService;
|
||||
@Resource
|
||||
private IotThingModelService thingModelService;
|
||||
@Resource
|
||||
private IotDeviceService deviceService;
|
||||
|
||||
@GetMapping("/latest")
|
||||
@Operation(summary = "获取设备属性最新属性")
|
||||
@Parameters({
|
||||
@Parameter(name = "deviceId", description = "设备编号", required = true),
|
||||
@Parameter(name = "identifier", description = "标识符"),
|
||||
@Parameter(name = "name", description = "名称")
|
||||
})
|
||||
@PreAuthorize("@ss.hasPermission('iot:device:property-query')")
|
||||
public CommonResult<List<IotDevicePropertyRespVO>> getLatestDeviceProperties(
|
||||
@RequestParam("deviceId") Long deviceId,
|
||||
@RequestParam(value = "identifier", required = false) String identifier,
|
||||
@RequestParam(value = "name", required = false) String name) {
|
||||
Map<String, IotDevicePropertyDO> properties = devicePropertyService.getLatestDeviceProperties(deviceId);
|
||||
|
||||
// 拼接数据
|
||||
IotDeviceDO device = deviceService.getDevice(deviceId);
|
||||
Assert.notNull(device, "设备不存在");
|
||||
List<IotThingModelDO> thingModels = thingModelService.getThingModelListByProductId(device.getProductId());
|
||||
return success(convertList(properties.entrySet(), entry -> {
|
||||
IotThingModelDO thingModel = CollUtil.findOne(thingModels,
|
||||
item -> item.getIdentifier().equals(entry.getKey()));
|
||||
if (thingModel == null || thingModel.getProperty() == null) {
|
||||
return null;
|
||||
}
|
||||
if (StrUtil.isNotEmpty(identifier) && !StrUtil.contains(thingModel.getIdentifier(), identifier)) {
|
||||
return null;
|
||||
}
|
||||
if (StrUtil.isNotEmpty(name) && !StrUtil.contains(thingModel.getName(), name)) {
|
||||
return null;
|
||||
}
|
||||
// 构建对象
|
||||
IotDevicePropertyDO property = entry.getValue();
|
||||
return new IotDevicePropertyRespVO().setProperty(thingModel.getProperty())
|
||||
.setValue(property.getValue()).setUpdateTime(LocalDateTimeUtil.toEpochMilli(property.getUpdateTime()));
|
||||
}));
|
||||
}
|
||||
|
||||
@GetMapping("/history-page")
|
||||
@Operation(summary = "获取设备属性历史数据")
|
||||
@PreAuthorize("@ss.hasPermission('iot:device:property-query')")
|
||||
public CommonResult<PageResult<IotDevicePropertyRespVO>> getHistoryDevicePropertyPage(
|
||||
@Valid IotDevicePropertyHistoryPageReqVO pageReqVO) {
|
||||
Assert.notEmpty(pageReqVO.getIdentifier(), "标识符不能为空");
|
||||
return success(devicePropertyService.getHistoryDevicePropertyPage(pageReqVO));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.zt.plat.module.iot.controller.admin.device.vo.control;
|
||||
|
||||
import com.zt.plat.framework.common.validation.InEnum;
|
||||
import com.zt.plat.module.iot.enums.device.IotDeviceMessageTypeEnum;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
|
||||
@Schema(description = "管理后台 - IoT 设备下行 Request VO") // 服务调用、属性设置、属性获取等
|
||||
@Data
|
||||
public class IotDeviceDownstreamReqVO {
|
||||
|
||||
@Schema(description = "设备编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "177")
|
||||
@NotNull(message = "设备编号不能为空")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "消息类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "property")
|
||||
@NotEmpty(message = "消息类型不能为空")
|
||||
@InEnum(IotDeviceMessageTypeEnum.class)
|
||||
private String type;
|
||||
|
||||
@Schema(description = "标识符", requiredMode = Schema.RequiredMode.REQUIRED, example = "report")
|
||||
@NotEmpty(message = "标识符不能为空")
|
||||
private String identifier; // 参见 IotDeviceMessageIdentifierEnum 枚举类
|
||||
|
||||
@Schema(description = "请求参数", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private Object data; // 例如说:服务调用的 params、属性设置的 properties
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.zt.plat.module.iot.controller.admin.device.vo.control;
|
||||
|
||||
import com.zt.plat.framework.common.validation.InEnum;
|
||||
import com.zt.plat.module.iot.enums.device.IotDeviceMessageTypeEnum;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
|
||||
@Schema(description = "管理后台 - IoT 设备上行 Request VO") // 属性上报、事件上报、状态变更等
|
||||
@Data
|
||||
public class IotDeviceUpstreamReqVO {
|
||||
|
||||
@Schema(description = "设备编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "177")
|
||||
@NotNull(message = "设备编号不能为空")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "消息类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "property")
|
||||
@NotEmpty(message = "消息类型不能为空")
|
||||
@InEnum(IotDeviceMessageTypeEnum.class)
|
||||
private String type;
|
||||
|
||||
@Schema(description = "标识符", requiredMode = Schema.RequiredMode.REQUIRED, example = "report")
|
||||
@NotEmpty(message = "标识符不能为空")
|
||||
private String identifier; // 参见 IotDeviceMessageIdentifierEnum 枚举类
|
||||
|
||||
@Schema(description = "请求参数", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private Object data; // 例如说:属性上报的 properties、事件上报的 params
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.zt.plat.module.iot.controller.admin.device.vo.data;
|
||||
|
||||
import com.zt.plat.framework.common.pojo.PageParam;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import lombok.Data;
|
||||
|
||||
@Schema(description = "管理后台 - IoT 设备日志分页查询 Request VO")
|
||||
@Data
|
||||
public class IotDeviceLogPageReqVO extends PageParam {
|
||||
|
||||
@Schema(description = "设备标识", requiredMode = Schema.RequiredMode.REQUIRED, example = "device123")
|
||||
@NotEmpty(message = "设备标识不能为空")
|
||||
private String deviceKey;
|
||||
|
||||
@Schema(description = "消息类型", example = "property")
|
||||
private String type; // 参见 IotDeviceMessageTypeEnum 枚举,精准匹配
|
||||
|
||||
@Schema(description = "标识符", example = "temperature")
|
||||
private String identifier; // 参见 IotDeviceMessageIdentifierEnum 枚举,模糊匹配
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package com.zt.plat.module.iot.controller.admin.device.vo.data;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Schema(description = "管理后台 - IoT 设备日志 Response VO")
|
||||
@Data
|
||||
public class IotDeviceLogRespVO {
|
||||
|
||||
@Schema(description = "日志编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
private String id;
|
||||
|
||||
@Schema(description = "产品标识", requiredMode = Schema.RequiredMode.REQUIRED, example = "product123")
|
||||
private String productKey;
|
||||
|
||||
@Schema(description = "设备标识", requiredMode = Schema.RequiredMode.REQUIRED, example = "device123")
|
||||
private String deviceKey;
|
||||
|
||||
@Schema(description = "消息类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "property")
|
||||
private String type;
|
||||
|
||||
@Schema(description = "标识符", requiredMode = Schema.RequiredMode.REQUIRED, example = "temperature")
|
||||
private String identifier;
|
||||
|
||||
@Schema(description = "日志内容", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private String content;
|
||||
|
||||
@Schema(description = "上报时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private LocalDateTime reportTime;
|
||||
|
||||
@Schema(description = "记录时间戳", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private LocalDateTime ts;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.zt.plat.module.iot.controller.admin.device.vo.data;
|
||||
|
||||
import com.zt.plat.framework.common.pojo.PageParam;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import lombok.Data;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import static com.zt.plat.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
||||
|
||||
@Schema(description = "管理后台 - IoT 设备属性历史分页 Request VO")
|
||||
@Data
|
||||
public class IotDevicePropertyHistoryPageReqVO extends PageParam {
|
||||
|
||||
@Schema(description = "设备编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "177")
|
||||
@NotNull(message = "设备编号不能为空")
|
||||
private Long deviceId;
|
||||
|
||||
@Schema(description = "设备 Key", hidden = true)
|
||||
private String deviceKey; // 非前端传递,后端自己查询设置
|
||||
|
||||
@Schema(description = "属性标识符", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotEmpty(message = "属性标识符不能为空")
|
||||
private String identifier;
|
||||
|
||||
@Schema(description = "时间范围", requiredMode = Schema.RequiredMode.NOT_REQUIRED)
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
@Size(min = 2, max = 2, message = "请选择时间范围")
|
||||
private LocalDateTime[] times;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.zt.plat.module.iot.controller.admin.device.vo.data;
|
||||
|
||||
import com.zt.plat.module.iot.controller.admin.thingmodel.model.ThingModelProperty;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
@Schema(description = "管理后台 - IoT 设备属性 Response VO")
|
||||
@Data
|
||||
public class IotDevicePropertyRespVO {
|
||||
|
||||
@Schema(description = "属性定义", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private ThingModelProperty property;
|
||||
|
||||
@Schema(description = "最新值", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private Object value;
|
||||
|
||||
@Schema(description = "更新时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private Long updateTime; // 由于从 TDengine 查询出来的是 Long 类型,所以这里也使用 Long 类型
|
||||
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package com.zt.plat.module.iot.controller.admin.device.vo.device;
|
||||
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* 设备 Excel 导入 VO
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Accessors(chain = false) // 设置 chain = false,避免设备导入有问题
|
||||
public class IotDeviceImportExcelVO {
|
||||
|
||||
@ExcelProperty("设备名称")
|
||||
@NotEmpty(message = "设备名称不能为空")
|
||||
private String deviceName;
|
||||
|
||||
@ExcelProperty("父设备名称")
|
||||
@Schema(description = "父设备名称", example = "网关001")
|
||||
private String parentDeviceName;
|
||||
|
||||
@ExcelProperty("产品标识")
|
||||
@NotEmpty(message = "产品标识不能为空")
|
||||
private String productKey;
|
||||
|
||||
@ExcelProperty("设备分组")
|
||||
private String groupNames;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.zt.plat.module.iot.controller.admin.device.vo.device;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Schema(description = "管理后台 - IoT 设备导入 Response VO")
|
||||
@Data
|
||||
@Builder
|
||||
public class IotDeviceImportRespVO {
|
||||
|
||||
@Schema(description = "创建成功的设备名称数组", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private List<String> createDeviceNames;
|
||||
|
||||
@Schema(description = "更新成功的设备名称数组", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private List<String> updateDeviceNames;
|
||||
|
||||
@Schema(description = "导入失败的设备集合,key为设备名称,value为失败原因", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private Map<String, String> failureDeviceNames;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.zt.plat.module.iot.controller.admin.device.vo.device;
|
||||
|
||||
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
@Schema(description = "管理后台 - IoT 设备 MQTT 连接参数 Response VO")
|
||||
@Data
|
||||
@ExcelIgnoreUnannotated
|
||||
public class IotDeviceMqttConnectionParamsRespVO {
|
||||
|
||||
@Schema(description = "MQTT 客户端 ID", example = "24602")
|
||||
@ExcelProperty("MQTT 客户端 ID")
|
||||
private String mqttClientId;
|
||||
|
||||
@Schema(description = "MQTT 用户名", example = "芋艿")
|
||||
@ExcelProperty("MQTT 用户名")
|
||||
private String mqttUsername;
|
||||
|
||||
@Schema(description = "MQTT 密码")
|
||||
@ExcelProperty("MQTT 密码")
|
||||
private String mqttPassword;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.zt.plat.module.iot.controller.admin.device.vo.device;
|
||||
|
||||
import com.zt.plat.framework.common.pojo.PageParam;
|
||||
import com.zt.plat.framework.common.validation.InEnum;
|
||||
import com.zt.plat.module.iot.enums.device.IotDeviceStateEnum;
|
||||
import com.zt.plat.module.iot.enums.product.IotProductDeviceTypeEnum;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
@Schema(description = "管理后台 - IoT 设备分页 Request VO")
|
||||
@Data
|
||||
public class IotDevicePageReqVO extends PageParam {
|
||||
|
||||
@Schema(description = "设备名称", example = "王五")
|
||||
private String deviceName;
|
||||
|
||||
@Schema(description = "备注名称", example = "张三")
|
||||
private String nickname;
|
||||
|
||||
@Schema(description = "产品编号", example = "26202")
|
||||
private Long productId;
|
||||
|
||||
@Schema(description = "设备类型", example = "1")
|
||||
@InEnum(IotProductDeviceTypeEnum.class)
|
||||
private Integer deviceType;
|
||||
|
||||
@Schema(description = "设备状态", example = "1")
|
||||
@InEnum(IotDeviceStateEnum.class)
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "设备分组编号", example = "1024")
|
||||
private Long groupId;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
package com.zt.plat.module.iot.controller.admin.device.vo.device;
|
||||
|
||||
import com.zt.plat.framework.excel.core.annotations.DictFormat;
|
||||
import com.zt.plat.framework.excel.core.convert.DictConvert;
|
||||
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Set;
|
||||
|
||||
import static com.zt.plat.module.iot.enums.DictTypeConstants.DEVICE_STATE;
|
||||
|
||||
@Schema(description = "管理后台 - IoT 设备 Response VO")
|
||||
@Data
|
||||
@ExcelIgnoreUnannotated
|
||||
public class IotDeviceRespVO {
|
||||
|
||||
@Schema(description = "设备编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "177")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "设备唯一标识符", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@ExcelProperty("设备唯一标识符")
|
||||
private String deviceKey;
|
||||
|
||||
@Schema(description = "设备名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "王五")
|
||||
@ExcelProperty("设备名称")
|
||||
private String deviceName;
|
||||
|
||||
@Schema(description = "设备备注名称", example = "张三")
|
||||
@ExcelProperty("设备备注名称")
|
||||
private String nickname;
|
||||
|
||||
@Schema(description = "设备序列号", example = "1024")
|
||||
@ExcelProperty("设备序列号")
|
||||
private String serialNumber;
|
||||
|
||||
@Schema(description = "设备图片", example = "我是一名码农")
|
||||
@ExcelProperty("设备图片")
|
||||
private String picUrl;
|
||||
|
||||
@Schema(description = "设备分组编号数组", example = "1,2")
|
||||
private Set<Long> groupIds;
|
||||
|
||||
@Schema(description = "产品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "26202")
|
||||
@ExcelProperty("产品编号")
|
||||
private Long productId;
|
||||
|
||||
@Schema(description = "产品标识", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@ExcelProperty("产品 Key")
|
||||
private String productKey;
|
||||
|
||||
@Schema(description = "设备类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
@ExcelProperty("设备类型")
|
||||
private Integer deviceType;
|
||||
|
||||
@Schema(description = "网关设备 ID", example = "16380")
|
||||
private Long gatewayId;
|
||||
|
||||
@Schema(description = "设备状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
@ExcelProperty(value = "设备状态", converter = DictConvert.class)
|
||||
@DictFormat(DEVICE_STATE)
|
||||
private Integer state;
|
||||
|
||||
@Schema(description = "最后上线时间")
|
||||
@ExcelProperty("最后上线时间")
|
||||
private LocalDateTime onlineTime;
|
||||
|
||||
@Schema(description = "最后离线时间")
|
||||
@ExcelProperty("最后离线时间")
|
||||
private LocalDateTime offlineTime;
|
||||
|
||||
@Schema(description = "设备激活时间")
|
||||
@ExcelProperty("设备激活时间")
|
||||
private LocalDateTime activeTime;
|
||||
|
||||
@Schema(description = "设备密钥,用于设备认证")
|
||||
@ExcelProperty("设备密钥")
|
||||
private String deviceSecret;
|
||||
|
||||
@Schema(description = "认证类型(如一机一密、动态注册)", example = "2")
|
||||
@ExcelProperty("认证类型(如一机一密、动态注册)")
|
||||
private String authType;
|
||||
|
||||
@Schema(description = "设备配置", example = "{\"abc\": \"efg\"}")
|
||||
private String config;
|
||||
|
||||
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@ExcelProperty("创建时间")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package com.zt.plat.module.iot.controller.admin.device.vo.device;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
@Schema(description = "管理后台 - IoT 设备新增/修改 Request VO")
|
||||
@Data
|
||||
public class IotDeviceSaveReqVO {
|
||||
|
||||
@Schema(description = "设备编号", example = "177")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "设备编号", requiredMode = Schema.RequiredMode.AUTO, example = "177")
|
||||
@Size(max = 50, message = "设备编号长度不能超过 50 个字符")
|
||||
private String deviceKey;
|
||||
|
||||
@Schema(description = "设备名称", requiredMode = Schema.RequiredMode.AUTO, example = "王五")
|
||||
private String deviceName;
|
||||
|
||||
@Schema(description = "备注名称", example = "张三")
|
||||
private String nickname;
|
||||
|
||||
@Schema(description = "设备序列号", example = "123456")
|
||||
private String serialNumber;
|
||||
|
||||
@Schema(description = "设备图片", example = "https://iocoder.cn/1.png")
|
||||
private String picUrl;
|
||||
|
||||
@Schema(description = "设备分组编号数组", example = "1,2")
|
||||
private Set<Long> groupIds;
|
||||
|
||||
@Schema(description = "产品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "26202")
|
||||
private Long productId;
|
||||
|
||||
@Schema(description = "网关设备 ID", example = "16380")
|
||||
private Long gatewayId;
|
||||
|
||||
@Schema(description = "设备配置", example = "{\"abc\": \"efg\"}")
|
||||
private String config;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.zt.plat.module.iot.controller.admin.device.vo.device;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
@Schema(description = "管理后台 - IoT 设备更新分组 Request VO")
|
||||
@Data
|
||||
public class IotDeviceUpdateGroupReqVO {
|
||||
|
||||
@Schema(description = "设备编号列表", requiredMode = Schema.RequiredMode.REQUIRED, example = "1,2,3")
|
||||
@NotEmpty(message = "设备编号列表不能为空")
|
||||
private Set<Long> ids;
|
||||
|
||||
@Schema(description = "分组编号列表", requiredMode = Schema.RequiredMode.REQUIRED, example = "1,2,3")
|
||||
@NotEmpty(message = "分组编号列表不能为空")
|
||||
private Set<Long> groupIds;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.zt.plat.module.iot.controller.admin.device.vo.group;
|
||||
|
||||
import com.zt.plat.framework.common.pojo.PageParam;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import static com.zt.plat.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
||||
|
||||
@Schema(description = "管理后台 - IoT 设备分组分页 Request VO")
|
||||
@Data
|
||||
public class IotDeviceGroupPageReqVO extends PageParam {
|
||||
|
||||
@Schema(description = "分组名字", example = "李四")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
private LocalDateTime[] createTime;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.zt.plat.module.iot.controller.admin.device.vo.group;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Schema(description = "管理后台 - IoT 设备分组 Response VO")
|
||||
@Data
|
||||
public class IotDeviceGroupRespVO {
|
||||
|
||||
@Schema(description = "分组 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "3583")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "分组名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "分组状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "分组描述", example = "你说的对")
|
||||
private String description;
|
||||
|
||||
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private LocalDateTime createTime;
|
||||
|
||||
@Schema(description = "设备数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
|
||||
private Long deviceCount;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.zt.plat.module.iot.controller.admin.device.vo.group;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
|
||||
@Schema(description = "管理后台 - IoT 设备分组新增/修改 Request VO")
|
||||
@Data
|
||||
public class IotDeviceGroupSaveReqVO {
|
||||
|
||||
@Schema(description = "分组 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "3583")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "分组名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四")
|
||||
@NotEmpty(message = "分组名字不能为空")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "分组状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
@NotNull(message = "分组状态不能为空")
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "分组描述", example = "你说的对")
|
||||
private String description;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
package com.zt.plat.module.iot.controller.admin.ota;
|
||||
|
||||
import com.zt.plat.framework.common.pojo.CommonResult;
|
||||
import com.zt.plat.framework.common.pojo.PageResult;
|
||||
import com.zt.plat.framework.common.util.object.BeanUtils;
|
||||
import com.zt.plat.module.iot.controller.admin.ota.vo.firmware.IotOtaFirmwarePageReqVO;
|
||||
import com.zt.plat.module.iot.controller.admin.ota.vo.firmware.IotOtaFirmwareRespVO;
|
||||
import com.zt.plat.module.iot.controller.admin.ota.vo.firmware.IotOtaFirmwareCreateReqVO;
|
||||
import com.zt.plat.module.iot.controller.admin.ota.vo.firmware.IotOtaFirmwareUpdateReqVO;
|
||||
import com.zt.plat.module.iot.dal.dataobject.ota.IotOtaFirmwareDO;
|
||||
import com.zt.plat.module.iot.service.ota.IotOtaFirmwareService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.validation.Valid;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import static com.zt.plat.framework.common.pojo.CommonResult.success;
|
||||
|
||||
@Tag(name = "管理后台 - IoT OTA 固件")
|
||||
@RestController
|
||||
@RequestMapping("/iot/ota-firmware")
|
||||
@Validated
|
||||
public class IotOtaFirmwareController {
|
||||
|
||||
@Resource
|
||||
private IotOtaFirmwareService otaFirmwareService;
|
||||
|
||||
@PostMapping("/create")
|
||||
@Operation(summary = "创建 OTA 固件")
|
||||
@PreAuthorize("@ss.hasPermission('iot:ota-firmware:create')")
|
||||
public CommonResult<Long> createOtaFirmware(@Valid @RequestBody IotOtaFirmwareCreateReqVO createReqVO) {
|
||||
return success(otaFirmwareService.createOtaFirmware(createReqVO));
|
||||
}
|
||||
|
||||
@PutMapping("/update")
|
||||
@Operation(summary = "更新 OTA 固件")
|
||||
@PreAuthorize("@ss.hasPermission('iot:ota-firmware:update')")
|
||||
public CommonResult<Boolean> updateOtaFirmware(@Valid @RequestBody IotOtaFirmwareUpdateReqVO updateReqVO) {
|
||||
otaFirmwareService.updateOtaFirmware(updateReqVO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@GetMapping("/get")
|
||||
@Operation(summary = "获得 OTA 固件")
|
||||
@PreAuthorize("@ss.hasPermission('iot:ota-firmware:query')")
|
||||
public CommonResult<IotOtaFirmwareRespVO> getOtaFirmware(@RequestParam("id") Long id) {
|
||||
IotOtaFirmwareDO otaFirmware = otaFirmwareService.getOtaFirmware(id);
|
||||
return success(BeanUtils.toBean(otaFirmware, IotOtaFirmwareRespVO.class));
|
||||
}
|
||||
|
||||
@GetMapping("/page")
|
||||
@Operation(summary = "获得 OTA 固件分页")
|
||||
@PreAuthorize("@ss.hasPermission('iot:ota-firmware:query')")
|
||||
public CommonResult<PageResult<IotOtaFirmwareRespVO>> getOtaFirmwarePage(@Valid IotOtaFirmwarePageReqVO pageReqVO) {
|
||||
PageResult<IotOtaFirmwareDO> pageResult = otaFirmwareService.getOtaFirmwarePage(pageReqVO);
|
||||
return success(BeanUtils.toBean(pageResult, IotOtaFirmwareRespVO.class));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
package com.zt.plat.module.iot.controller.admin.ota;
|
||||
|
||||
import com.zt.plat.framework.common.pojo.CommonResult;
|
||||
import com.zt.plat.framework.common.pojo.PageResult;
|
||||
import com.zt.plat.framework.common.util.object.BeanUtils;
|
||||
import com.zt.plat.module.iot.controller.admin.ota.vo.upgrade.record.IotOtaUpgradeRecordPageReqVO;
|
||||
import com.zt.plat.module.iot.controller.admin.ota.vo.upgrade.record.IotOtaUpgradeRecordRespVO;
|
||||
import com.zt.plat.module.iot.dal.dataobject.ota.IotOtaUpgradeRecordDO;
|
||||
import com.zt.plat.module.iot.service.ota.IotOtaUpgradeRecordService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.validation.Valid;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import static com.zt.plat.framework.common.pojo.CommonResult.success;
|
||||
|
||||
@Tag(name = "管理后台 - IoT OTA 升级记录")
|
||||
@RestController
|
||||
@RequestMapping("/iot/ota-upgrade-record")
|
||||
@Validated
|
||||
public class IotOtaUpgradeRecordController {
|
||||
|
||||
@Resource
|
||||
private IotOtaUpgradeRecordService upgradeRecordService;
|
||||
|
||||
@GetMapping("/get-statistics")
|
||||
@Operation(summary = "固件升级设备统计")
|
||||
@PreAuthorize("@ss.hasPermission('iot:ota-upgrade-record:query')")
|
||||
@Parameter(name = "firmwareId", description = "固件编号", required = true, example = "1024")
|
||||
public CommonResult<Map<Integer, Long>> getOtaUpgradeRecordStatistics(@RequestParam(value = "firmwareId") Long firmwareId) {
|
||||
return success(upgradeRecordService.getOtaUpgradeRecordStatistics(firmwareId));
|
||||
}
|
||||
|
||||
@GetMapping("/get-count")
|
||||
@Operation(summary = "获得升级记录分页 tab 数量")
|
||||
@PreAuthorize("@ss.hasPermission('iot:ota-upgrade-record:query')")
|
||||
public CommonResult<Map<Integer, Long>> getOtaUpgradeRecordCount(
|
||||
@Valid IotOtaUpgradeRecordPageReqVO pageReqVO) {
|
||||
return success(upgradeRecordService.getOtaUpgradeRecordCount(pageReqVO));
|
||||
}
|
||||
|
||||
@GetMapping("/page")
|
||||
@Operation(summary = "获得升级记录分页")
|
||||
@PreAuthorize("@ss.hasPermission('iot:ota-upgrade-record:query')")
|
||||
public CommonResult<PageResult<IotOtaUpgradeRecordRespVO>> getUpgradeRecordPage(
|
||||
@Valid IotOtaUpgradeRecordPageReqVO pageReqVO) {
|
||||
PageResult<IotOtaUpgradeRecordDO> pageResult = upgradeRecordService.getUpgradeRecordPage(pageReqVO);
|
||||
return success(BeanUtils.toBean(pageResult, IotOtaUpgradeRecordRespVO.class));
|
||||
}
|
||||
|
||||
@GetMapping("/get")
|
||||
@Operation(summary = "获得升级记录")
|
||||
@PreAuthorize("@ss.hasPermission('iot:ota-upgrade-record:query')")
|
||||
@Parameter(name = "id", description = "升级记录编号", required = true, example = "1024")
|
||||
public CommonResult<IotOtaUpgradeRecordRespVO> getUpgradeRecord(@RequestParam("id") Long id) {
|
||||
IotOtaUpgradeRecordDO upgradeRecord = upgradeRecordService.getUpgradeRecord(id);
|
||||
return success(BeanUtils.toBean(upgradeRecord, IotOtaUpgradeRecordRespVO.class));
|
||||
}
|
||||
|
||||
@PutMapping("/retry")
|
||||
@Operation(summary = "重试升级记录")
|
||||
@PreAuthorize("@ss.hasPermission('iot:ota-upgrade-record:retry')")
|
||||
@Parameter(name = "id", description = "升级记录编号", required = true, example = "1024")
|
||||
public CommonResult<Boolean> retryUpgradeRecord(@RequestParam("id") Long id) {
|
||||
upgradeRecordService.retryUpgradeRecord(id);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
package com.zt.plat.module.iot.controller.admin.ota;
|
||||
|
||||
import com.zt.plat.framework.common.pojo.CommonResult;
|
||||
import com.zt.plat.framework.common.pojo.PageResult;
|
||||
import com.zt.plat.framework.common.util.object.BeanUtils;
|
||||
import com.zt.plat.module.iot.controller.admin.ota.vo.upgrade.task.IotOtaUpgradeTaskPageReqVO;
|
||||
import com.zt.plat.module.iot.controller.admin.ota.vo.upgrade.task.IotOtaUpgradeTaskRespVO;
|
||||
import com.zt.plat.module.iot.controller.admin.ota.vo.upgrade.task.IotOtaUpgradeTaskSaveReqVO;
|
||||
import com.zt.plat.module.iot.dal.dataobject.ota.IotOtaUpgradeTaskDO;
|
||||
import com.zt.plat.module.iot.service.ota.IotOtaUpgradeTaskService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.validation.Valid;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import static com.zt.plat.framework.common.pojo.CommonResult.success;
|
||||
|
||||
@Tag(name = "管理后台 - IoT OTA 升级任务")
|
||||
@RestController
|
||||
@RequestMapping("/iot/ota-upgrade-task")
|
||||
@Validated
|
||||
public class IotOtaUpgradeTaskController {
|
||||
|
||||
@Resource
|
||||
private IotOtaUpgradeTaskService upgradeTaskService;
|
||||
|
||||
@PostMapping("/create")
|
||||
@Operation(summary = "创建升级任务")
|
||||
@PreAuthorize(value = "@ss.hasPermission('iot:ota-upgrade-task:create')")
|
||||
public CommonResult<Long> createUpgradeTask(@Valid @RequestBody IotOtaUpgradeTaskSaveReqVO createReqVO) {
|
||||
return success(upgradeTaskService.createUpgradeTask(createReqVO));
|
||||
}
|
||||
|
||||
@PostMapping("/cancel")
|
||||
@Operation(summary = "取消升级任务")
|
||||
@Parameter(name = "id", description = "升级任务编号", required = true)
|
||||
@PreAuthorize(value = "@ss.hasPermission('iot:ota-upgrade-task:cancel')")
|
||||
public CommonResult<Boolean> cancelUpgradeTask(@RequestParam("id") Long id) {
|
||||
upgradeTaskService.cancelUpgradeTask(id);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@GetMapping("/page")
|
||||
@Operation(summary = "获得升级任务分页")
|
||||
@PreAuthorize(value = "@ss.hasPermission('iot:ota-upgrade-task:query')")
|
||||
public CommonResult<PageResult<IotOtaUpgradeTaskRespVO>> getUpgradeTaskPage(@Valid IotOtaUpgradeTaskPageReqVO pageReqVO) {
|
||||
PageResult<IotOtaUpgradeTaskDO> pageResult = upgradeTaskService.getUpgradeTaskPage(pageReqVO);
|
||||
return success(BeanUtils.toBean(pageResult, IotOtaUpgradeTaskRespVO.class));
|
||||
}
|
||||
|
||||
@GetMapping("/get")
|
||||
@Operation(summary = "获得升级任务")
|
||||
@Parameter(name = "id", description = "升级任务编号", required = true, example = "1024")
|
||||
@PreAuthorize(value = "@ss.hasPermission('iot:ota-upgrade-task:query')")
|
||||
public CommonResult<IotOtaUpgradeTaskRespVO> getUpgradeTask(@RequestParam("id") Long id) {
|
||||
IotOtaUpgradeTaskDO upgradeTask = upgradeTaskService.getUpgradeTask(id);
|
||||
return success(BeanUtils.toBean(upgradeTask, IotOtaUpgradeTaskRespVO.class));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package com.zt.plat.module.iot.controller.admin.ota.vo.firmware;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
|
||||
import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.REQUIRED;
|
||||
|
||||
@Schema(description = "管理后台 - IoT OTA 固件创建 Request VO")
|
||||
@Data
|
||||
public class IotOtaFirmwareCreateReqVO {
|
||||
|
||||
@Schema(description = "固件名称", requiredMode = REQUIRED, example = "智能开关固件")
|
||||
@NotEmpty(message = "固件名称不能为空")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "固件描述", example = "某品牌型号固件,测试用")
|
||||
private String description;
|
||||
|
||||
@Schema(description = "版本号", requiredMode = REQUIRED, example = "1.0.0")
|
||||
@NotEmpty(message = "版本号不能为空")
|
||||
private String version;
|
||||
|
||||
@Schema(description = "产品编号", requiredMode = REQUIRED, example = "1024")
|
||||
@NotNull(message = "产品编号不能为空")
|
||||
private String productId;
|
||||
|
||||
@Schema(description = "签名方式", example = "MD5")
|
||||
// TODO @li:是不是必传哈
|
||||
private String signMethod;
|
||||
|
||||
@Schema(description = "固件文件 URL", requiredMode = REQUIRED, example = "https://www.iocoder.cn/cloud-firmware.zip")
|
||||
@NotEmpty(message = "固件文件 URL 不能为空")
|
||||
private String fileUrl;
|
||||
|
||||
@Schema(description = "自定义信息,建议使用 JSON 格式", example = "{\"key1\":\"value1\",\"key2\":\"value2\"}")
|
||||
private String information;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.zt.plat.module.iot.controller.admin.ota.vo.firmware;
|
||||
|
||||
import com.zt.plat.framework.common.pojo.PageParam;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
@Schema(description = "管理后台 - IoT OTA 固件分页 Request VO")
|
||||
public class IotOtaFirmwarePageReqVO extends PageParam {
|
||||
|
||||
/**
|
||||
* 固件名称
|
||||
*/
|
||||
@Schema(description = "固件名称", example = "智能开关固件")
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 产品标识
|
||||
*/
|
||||
@Schema(description = "产品标识", example = "1024")
|
||||
private String productId;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
package com.zt.plat.module.iot.controller.admin.ota.vo.firmware;
|
||||
|
||||
import com.zt.plat.module.iot.dal.dataobject.product.IotProductDO;
|
||||
import com.fhs.core.trans.anno.Trans;
|
||||
import com.fhs.core.trans.constant.TransType;
|
||||
import com.fhs.core.trans.vo.VO;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.REQUIRED;
|
||||
|
||||
@Data
|
||||
@Schema(description = "管理后台 - IoT OTA 固件 Response VO")
|
||||
public class IotOtaFirmwareRespVO implements VO {
|
||||
|
||||
/**
|
||||
* 固件编号
|
||||
*/
|
||||
@Schema(description = "固件编号", requiredMode = REQUIRED, example = "1024")
|
||||
private Long id;
|
||||
/**
|
||||
* 固件名称
|
||||
*/
|
||||
@Schema(description = "固件名称", requiredMode = REQUIRED, example = "OTA固件")
|
||||
private String name;
|
||||
/**
|
||||
* 固件描述
|
||||
*/
|
||||
@Schema(description = "固件描述")
|
||||
private String description;
|
||||
/**
|
||||
* 版本号
|
||||
*/
|
||||
@Schema(description = "版本号", requiredMode = REQUIRED, example = "1.0.0")
|
||||
private String version;
|
||||
|
||||
/**
|
||||
* 产品编号
|
||||
* <p>
|
||||
* 关联 {@link com.zt.plat.module.iot.dal.dataobject.product.IotProductDO#getId()}
|
||||
*/
|
||||
@Schema(description = "产品编号", requiredMode = REQUIRED, example = "1024")
|
||||
@Trans(type = TransType.SIMPLE, target = IotProductDO.class, fields = {"name"}, refs = {"productName"})
|
||||
private String productId;
|
||||
/**
|
||||
* 产品标识
|
||||
* <p>
|
||||
* 冗余 {@link com.zt.plat.module.iot.dal.dataobject.product.IotProductDO#getProductKey()}
|
||||
*/
|
||||
@Schema(description = "产品标识", requiredMode = REQUIRED, example = "iot-product-key")
|
||||
private String productKey;
|
||||
/**
|
||||
* 产品名称
|
||||
*/
|
||||
@Schema(description = "产品名称", requiredMode = REQUIRED, example = "OTA产品")
|
||||
private String productName;
|
||||
/**
|
||||
* 签名方式
|
||||
* <p>
|
||||
* 例如说:MD5、SHA256
|
||||
*/
|
||||
@Schema(description = "签名方式", example = "MD5")
|
||||
private String signMethod;
|
||||
/**
|
||||
* 固件文件签名
|
||||
*/
|
||||
@Schema(description = "固件文件签名", example = "1024")
|
||||
private String fileSign;
|
||||
/**
|
||||
* 固件文件大小
|
||||
*/
|
||||
@Schema(description = "固件文件大小", requiredMode = REQUIRED, example = "1024")
|
||||
private Long fileSize;
|
||||
/**
|
||||
* 固件文件 URL
|
||||
*/
|
||||
@Schema(description = "固件文件 URL", requiredMode = REQUIRED, example = "https://www.iocoder.cn")
|
||||
private String fileUrl;
|
||||
/**
|
||||
* 自定义信息,建议使用 JSON 格式
|
||||
*/
|
||||
@Schema(description = "自定义信息,建议使用 JSON 格式")
|
||||
private String information;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.zt.plat.module.iot.controller.admin.ota.vo.firmware;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
|
||||
import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.REQUIRED;
|
||||
|
||||
@Schema(description = "管理后台 - IoT OTA 固件更新 Request VO")
|
||||
@Data
|
||||
public class IotOtaFirmwareUpdateReqVO {
|
||||
|
||||
@Schema(description = "固件编号", requiredMode = REQUIRED, example = "1024")
|
||||
@NotNull(message = "固件编号不能为空")
|
||||
private Long id;
|
||||
|
||||
// TODO @li:name 是不是可以飞必传哈
|
||||
@Schema(description = "固件名称", requiredMode = REQUIRED, example = "智能开关固件")
|
||||
@NotEmpty(message = "固件名称不能为空")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "固件描述", example = "某品牌型号固件,测试用")
|
||||
private String description;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.zt.plat.module.iot.controller.admin.ota.vo.upgrade.record;
|
||||
|
||||
import com.zt.plat.framework.common.pojo.PageParam;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
|
||||
import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.REQUIRED;
|
||||
|
||||
@Data
|
||||
@Schema(description = "管理后台 - IoT OTA 升级记录分页 Request VO")
|
||||
public class IotOtaUpgradeRecordPageReqVO extends PageParam {
|
||||
|
||||
// TODO @li:已经有注解,不用重复注释
|
||||
/**
|
||||
* 升级任务编号字段。
|
||||
* <p>
|
||||
* 该字段用于标识升级任务的唯一编号,不能为空。
|
||||
*/
|
||||
@Schema(description = "升级任务编号", requiredMode = REQUIRED, example = "1024")
|
||||
@NotNull(message = "升级任务编号不能为空")
|
||||
private Long taskId;
|
||||
|
||||
/**
|
||||
* 设备标识字段。
|
||||
* <p>
|
||||
* 该字段用于标识设备的名称,通常用于区分不同的设备。
|
||||
*/
|
||||
@Schema(description = "设备标识", requiredMode = REQUIRED, example = "摄像头A1-1")
|
||||
private String deviceName;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
package com.zt.plat.module.iot.controller.admin.ota.vo.upgrade.record;
|
||||
|
||||
import com.zt.plat.module.iot.dal.dataobject.device.IotDeviceDO;
|
||||
import com.zt.plat.module.iot.dal.dataobject.ota.IotOtaFirmwareDO;
|
||||
import com.zt.plat.module.iot.dal.dataobject.ota.IotOtaUpgradeTaskDO;
|
||||
import com.fhs.core.trans.anno.Trans;
|
||||
import com.fhs.core.trans.constant.TransType;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.REQUIRED;
|
||||
|
||||
@Data
|
||||
@Schema(description = "管理后台 - IoT OTA 升级记录 Response VO")
|
||||
public class IotOtaUpgradeRecordRespVO {
|
||||
|
||||
/**
|
||||
* 升级记录编号
|
||||
*/
|
||||
@Schema(description = "升级记录编号", requiredMode = REQUIRED, example = "1024")
|
||||
private Long id;
|
||||
/**
|
||||
* 固件编号
|
||||
* <p>
|
||||
* 关联 {@link IotOtaFirmwareDO#getId()}
|
||||
*/
|
||||
@Schema(description = "固件编号", requiredMode = REQUIRED, example = "1024")
|
||||
@Trans(type = TransType.SIMPLE, target = IotOtaFirmwareDO.class, fields = {"version"}, refs = {"firmwareVersion"})
|
||||
private Long firmwareId;
|
||||
/**
|
||||
* 固件版本
|
||||
*/
|
||||
@Schema(description = "固件版本", requiredMode = REQUIRED, example = "v1.0.0")
|
||||
private String firmwareVersion;
|
||||
/**
|
||||
* 任务编号
|
||||
* <p>
|
||||
* 关联 {@link IotOtaUpgradeTaskDO#getId()}
|
||||
*/
|
||||
@Schema(description = "任务编号", requiredMode = REQUIRED, example = "1024")
|
||||
private Long taskId;
|
||||
/**
|
||||
* 产品标识
|
||||
* <p>
|
||||
* 关联 {@link com.zt.plat.module.iot.dal.dataobject.product.IotProductDO#getId()}
|
||||
*/
|
||||
@Schema(description = "产品标识", requiredMode = REQUIRED, example = "iot")
|
||||
private String productKey;
|
||||
/**
|
||||
* 设备名称
|
||||
* <p>
|
||||
* 关联 {@link com.zt.plat.module.iot.dal.dataobject.device.IotDeviceDO#getId()}
|
||||
*/
|
||||
@Schema(description = "设备名称", requiredMode = REQUIRED, example = "iot")
|
||||
private String deviceName;
|
||||
/**
|
||||
* 设备编号
|
||||
* <p>
|
||||
* 关联 {@link com.zt.plat.module.iot.dal.dataobject.device.IotDeviceDO#getId()}
|
||||
*/
|
||||
@Schema(description = "设备编号", requiredMode = REQUIRED, example = "1024")
|
||||
private String deviceId;
|
||||
/**
|
||||
* 来源的固件编号
|
||||
* <p>
|
||||
* 关联 {@link IotDeviceDO#getFirmwareId()}
|
||||
*/
|
||||
@Schema(description = "来源的固件编号", requiredMode = REQUIRED, example = "1024")
|
||||
@Trans(type = TransType.SIMPLE, target = IotOtaFirmwareDO.class, fields = {"version"}, refs = {"fromFirmwareVersion"})
|
||||
private Long fromFirmwareId;
|
||||
/**
|
||||
* 来源的固件版本
|
||||
*/
|
||||
@Schema(description = "来源的固件版本", requiredMode = REQUIRED, example = "v1.0.0")
|
||||
private String fromFirmwareVersion;
|
||||
/**
|
||||
* 升级状态
|
||||
* <p>
|
||||
* 关联 {@link com.zt.plat.module.iot.enums.ota.IotOtaUpgradeRecordStatusEnum}
|
||||
*/
|
||||
@Schema(description = "升级状态", requiredMode = REQUIRED, allowableValues = {"0", "10", "20", "30", "40", "50"})
|
||||
private Integer status;
|
||||
/**
|
||||
* 升级进度,百分比
|
||||
*/
|
||||
@Schema(description = "升级进度,百分比", requiredMode = REQUIRED, example = "10")
|
||||
private Integer progress;
|
||||
/**
|
||||
* 升级进度描述
|
||||
* <p>
|
||||
* 注意,只记录设备最后一次的升级进度描述
|
||||
* 如果想看历史记录,可以查看 {@link com.zt.plat.module.iot.dal.dataobject.device.IotDeviceLogDO} 设备日志
|
||||
*/
|
||||
@Schema(description = "升级进度描述", requiredMode = REQUIRED, example = "10")
|
||||
private String description;
|
||||
/**
|
||||
* 升级开始时间
|
||||
*/
|
||||
@Schema(description = "升级开始时间", requiredMode = REQUIRED, example = "2022-07-08 07:30:00")
|
||||
private LocalDateTime startTime;
|
||||
/**
|
||||
* 升级结束时间
|
||||
*/
|
||||
@Schema(description = "升级结束时间", requiredMode = REQUIRED, example = "2022-07-08 07:30:00")
|
||||
private LocalDateTime endTime;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.zt.plat.module.iot.controller.admin.ota.vo.upgrade.task;
|
||||
|
||||
import com.zt.plat.framework.common.pojo.PageParam;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
|
||||
import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.REQUIRED;
|
||||
|
||||
@Data
|
||||
@Schema(description = "管理后台 - IoT OTA 升级任务分页 Request VO")
|
||||
public class IotOtaUpgradeTaskPageReqVO extends PageParam {
|
||||
|
||||
/**
|
||||
* 任务名称字段,用于描述任务的名称
|
||||
*/
|
||||
@Schema(description = "任务名称", example = "升级任务")
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 固件编号字段,用于唯一标识固件,不能为空
|
||||
*/
|
||||
@NotNull(message = "固件编号不能为空")
|
||||
@Schema(description = "固件编号", requiredMode = REQUIRED, example = "1024")
|
||||
private Long firmwareId;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
package com.zt.plat.module.iot.controller.admin.ota.vo.upgrade.task;
|
||||
|
||||
import com.zt.plat.module.iot.dal.dataobject.device.IotDeviceDO;
|
||||
import com.zt.plat.module.iot.dal.dataobject.ota.IotOtaFirmwareDO;
|
||||
import com.fhs.core.trans.vo.VO;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.REQUIRED;
|
||||
|
||||
@Data
|
||||
@Schema(description = "管理后台 - IoT OTA 升级任务 Response VO")
|
||||
public class IotOtaUpgradeTaskRespVO implements VO {
|
||||
|
||||
/**
|
||||
* 任务编号
|
||||
*/
|
||||
@Schema(description = "任务编号", requiredMode = REQUIRED, example = "1024")
|
||||
private Long id;
|
||||
/**
|
||||
* 任务名称
|
||||
*/
|
||||
@Schema(description = "任务名称", requiredMode = REQUIRED, example = "升级任务")
|
||||
private String name;
|
||||
/**
|
||||
* 任务描述
|
||||
*/
|
||||
@Schema(description = "任务描述", example = "升级任务")
|
||||
private String description;
|
||||
/**
|
||||
* 固件编号
|
||||
* <p>
|
||||
* 关联 {@link IotOtaFirmwareDO#getId()}
|
||||
*/
|
||||
@Schema(description = "固件编号", requiredMode = REQUIRED, example = "1024")
|
||||
private Long firmwareId;
|
||||
/**
|
||||
* 任务状态
|
||||
* <p>
|
||||
* 关联 {@link com.zt.plat.module.iot.enums.ota.IotOtaUpgradeTaskStatusEnum}
|
||||
*/
|
||||
@Schema(description = "任务状态", requiredMode = REQUIRED, allowableValues = {"10", "20", "21", "30"})
|
||||
private Integer status;
|
||||
/**
|
||||
* 任务状态名称
|
||||
*/
|
||||
@Schema(description = "任务状态名称", requiredMode = REQUIRED, example = "进行中")
|
||||
private String statusName;
|
||||
/**
|
||||
* 升级范围
|
||||
* <p>
|
||||
* 关联 {@link com.zt.plat.module.iot.enums.ota.IotOtaUpgradeTaskScopeEnum}
|
||||
*/
|
||||
@Schema(description = "升级范围", requiredMode = REQUIRED, allowableValues = {"1", "2"})
|
||||
private Integer scope;
|
||||
/**
|
||||
* 设备数量
|
||||
*/
|
||||
@Schema(description = "设备数量", requiredMode = REQUIRED, example = "1024")
|
||||
private Long deviceCount;
|
||||
/**
|
||||
* 选中的设备编号数组
|
||||
* <p>
|
||||
* 关联 {@link IotDeviceDO#getId()}
|
||||
*/
|
||||
@Schema(description = "选中的设备编号数组", example = "1024")
|
||||
private List<Long> deviceIds;
|
||||
/**
|
||||
* 选中的设备名字数组
|
||||
* <p>
|
||||
* 关联 {@link IotDeviceDO#getDeviceName()}
|
||||
*/
|
||||
@Schema(description = "选中的设备名字数组", example = "1024")
|
||||
private List<String> deviceNames;
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@Schema(description = "创建时间", requiredMode = REQUIRED, example = "2022-07-08 07:30:00")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
package com.zt.plat.module.iot.controller.admin.ota.vo.upgrade.task;
|
||||
|
||||
import com.zt.plat.framework.common.validation.InEnum;
|
||||
import com.zt.plat.module.iot.dal.dataobject.device.IotDeviceDO;
|
||||
import com.zt.plat.module.iot.dal.dataobject.ota.IotOtaFirmwareDO;
|
||||
import com.zt.plat.module.iot.enums.ota.IotOtaUpgradeTaskScopeEnum;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.REQUIRED;
|
||||
|
||||
@Data
|
||||
@Schema(description = "管理后台 - IoT OTA 升级任务创建/修改 Request VO")
|
||||
public class IotOtaUpgradeTaskSaveReqVO {
|
||||
|
||||
// TODO @li:已经有注解,不用重复注释
|
||||
// TODO @li: @Schema 写在参数校验前面。先有定义;其他的,也检查下;
|
||||
|
||||
/**
|
||||
* 任务名称
|
||||
*/
|
||||
@NotEmpty(message = "任务名称不能为空")
|
||||
@Schema(description = "任务名称", requiredMode = REQUIRED, example = "升级任务")
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 任务描述
|
||||
*/
|
||||
@Schema(description = "任务描述", example = "升级任务")
|
||||
private String description;
|
||||
|
||||
/**
|
||||
* 固件编号
|
||||
* <p>
|
||||
* 关联 {@link IotOtaFirmwareDO#getId()}
|
||||
*/
|
||||
@NotNull(message = "固件编号不能为空")
|
||||
@Schema(description = "固件编号", requiredMode = REQUIRED, example = "1024")
|
||||
private Long firmwareId;
|
||||
|
||||
/**
|
||||
* 升级范围
|
||||
* <p>
|
||||
* 关联 {@link com.zt.plat.module.iot.enums.ota.IotOtaUpgradeTaskScopeEnum}
|
||||
*/
|
||||
@NotNull(message = "升级范围不能为空")
|
||||
@InEnum(value = IotOtaUpgradeTaskScopeEnum.class)
|
||||
@Schema(description = "升级范围", requiredMode = REQUIRED, example = "1")
|
||||
private Integer scope;
|
||||
|
||||
/**
|
||||
* 选中的设备编号数组
|
||||
* <p>
|
||||
* 关联 {@link IotDeviceDO#getId()}
|
||||
*/
|
||||
@Schema(description = "选中的设备编号数组", requiredMode = REQUIRED, example = "[1,2,3,4]")
|
||||
private List<Long> deviceIds;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
package com.zt.plat.module.iot.controller.admin.plugin;
|
||||
|
||||
import com.zt.plat.framework.common.pojo.CommonResult;
|
||||
import com.zt.plat.framework.common.pojo.PageResult;
|
||||
import com.zt.plat.framework.common.util.object.BeanUtils;
|
||||
import com.zt.plat.module.iot.controller.admin.plugin.vo.config.PluginConfigImportReqVO;
|
||||
import com.zt.plat.module.iot.controller.admin.plugin.vo.config.PluginConfigPageReqVO;
|
||||
import com.zt.plat.module.iot.controller.admin.plugin.vo.config.PluginConfigRespVO;
|
||||
import com.zt.plat.module.iot.controller.admin.plugin.vo.config.PluginConfigSaveReqVO;
|
||||
import com.zt.plat.module.iot.controller.admin.plugin.vo.config.PluginConfigStatusReqVO;
|
||||
import com.zt.plat.module.iot.dal.dataobject.plugin.IotPluginConfigDO;
|
||||
import com.zt.plat.module.iot.service.plugin.IotPluginConfigService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.validation.Valid;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import static com.zt.plat.framework.common.pojo.CommonResult.success;
|
||||
|
||||
@Tag(name = "管理后台 - IoT 插件配置")
|
||||
@RestController
|
||||
@RequestMapping("/iot/plugin-config")
|
||||
@Validated
|
||||
public class PluginConfigController {
|
||||
|
||||
@Resource
|
||||
private IotPluginConfigService pluginConfigService;
|
||||
|
||||
@PostMapping("/create")
|
||||
@Operation(summary = "创建插件配置")
|
||||
@PreAuthorize("@ss.hasPermission('iot:plugin-config:create')")
|
||||
public CommonResult<Long> createPluginConfig(@Valid @RequestBody PluginConfigSaveReqVO createReqVO) {
|
||||
return success(pluginConfigService.createPluginConfig(createReqVO));
|
||||
}
|
||||
|
||||
@PutMapping("/update")
|
||||
@Operation(summary = "更新插件配置")
|
||||
@PreAuthorize("@ss.hasPermission('iot:plugin-config:update')")
|
||||
public CommonResult<Boolean> updatePluginConfig(@Valid @RequestBody PluginConfigSaveReqVO updateReqVO) {
|
||||
pluginConfigService.updatePluginConfig(updateReqVO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@DeleteMapping("/delete")
|
||||
@Operation(summary = "删除插件配置")
|
||||
@Parameter(name = "id", description = "编号", required = true)
|
||||
@PreAuthorize("@ss.hasPermission('iot:plugin-config:delete')")
|
||||
public CommonResult<Boolean> deletePluginConfig(@RequestParam("id") Long id) {
|
||||
pluginConfigService.deletePluginConfig(id);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@GetMapping("/get")
|
||||
@Operation(summary = "获得插件配置")
|
||||
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
||||
@PreAuthorize("@ss.hasPermission('iot:plugin-config:query')")
|
||||
public CommonResult<PluginConfigRespVO> getPluginConfig(@RequestParam("id") Long id) {
|
||||
IotPluginConfigDO pluginConfig = pluginConfigService.getPluginConfig(id);
|
||||
return success(BeanUtils.toBean(pluginConfig, PluginConfigRespVO.class));
|
||||
}
|
||||
|
||||
@GetMapping("/page")
|
||||
@Operation(summary = "获得插件配置分页")
|
||||
@PreAuthorize("@ss.hasPermission('iot:plugin-config:query')")
|
||||
public CommonResult<PageResult<PluginConfigRespVO>> getPluginConfigPage(@Valid PluginConfigPageReqVO pageReqVO) {
|
||||
PageResult<IotPluginConfigDO> pageResult = pluginConfigService.getPluginConfigPage(pageReqVO);
|
||||
return success(BeanUtils.toBean(pageResult, PluginConfigRespVO.class));
|
||||
}
|
||||
|
||||
@PostMapping("/upload-file")
|
||||
@Operation(summary = "上传插件文件")
|
||||
@PreAuthorize("@ss.hasPermission('iot:plugin-config:update')")
|
||||
public CommonResult<Boolean> uploadFile(@Valid PluginConfigImportReqVO reqVO) {
|
||||
pluginConfigService.uploadFile(reqVO.getId(), reqVO.getFile());
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@PutMapping("/update-status")
|
||||
@Operation(summary = "修改插件状态")
|
||||
@PreAuthorize("@ss.hasPermission('iot:plugin-config:update')")
|
||||
public CommonResult<Boolean> updatePluginConfigStatus(@Valid @RequestBody PluginConfigStatusReqVO reqVO) {
|
||||
pluginConfigService.updatePluginStatus(reqVO.getId(), reqVO.getStatus());
|
||||
return success(true);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.zt.plat.module.iot.controller.admin.plugin.vo.config;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
@Schema(description = "管理后台 - IoT 插件上传 Request VO")
|
||||
@Data
|
||||
public class PluginConfigImportReqVO {
|
||||
|
||||
@Schema(description = "主键 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "11546")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "插件文件", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotNull(message = "插件文件不能为空")
|
||||
private MultipartFile file;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.zt.plat.module.iot.controller.admin.plugin.vo.config;
|
||||
|
||||
import com.zt.plat.framework.common.pojo.PageParam;
|
||||
import com.zt.plat.framework.common.validation.InEnum;
|
||||
import com.zt.plat.module.iot.enums.plugin.IotPluginStatusEnum;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
@Schema(description = "管理后台 - IoT 插件配置分页 Request VO")
|
||||
@Data
|
||||
public class PluginConfigPageReqVO extends PageParam {
|
||||
|
||||
@Schema(description = "插件名称", example = "http")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "状态", example = "1")
|
||||
@InEnum(IotPluginStatusEnum.class)
|
||||
private Integer status;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package com.zt.plat.module.iot.controller.admin.plugin.vo.config;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Schema(description = "管理后台 - IoT 插件配置 Response VO")
|
||||
@Data
|
||||
public class PluginConfigRespVO {
|
||||
|
||||
@Schema(description = "主键 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "11546")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "插件包标识符", requiredMode = Schema.RequiredMode.REQUIRED, example = "24627")
|
||||
private String pluginKey;
|
||||
|
||||
@Schema(description = "插件名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "赵六")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "描述", example = "你猜")
|
||||
private String description;
|
||||
|
||||
@Schema(description = "部署方式", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
|
||||
private Integer deployType;
|
||||
|
||||
@Schema(description = "插件包文件名", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private String fileName;
|
||||
|
||||
@Schema(description = "插件版本", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private String version;
|
||||
|
||||
@Schema(description = "插件类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
|
||||
private Integer type;
|
||||
|
||||
@Schema(description = "设备插件协议类型")
|
||||
private String protocol;
|
||||
|
||||
@Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "插件配置项描述信息")
|
||||
private String configSchema;
|
||||
|
||||
@Schema(description = "插件配置信息")
|
||||
private String config;
|
||||
|
||||
@Schema(description = "插件脚本")
|
||||
private String script;
|
||||
|
||||
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private LocalDateTime createTime;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package com.zt.plat.module.iot.controller.admin.plugin.vo.config;
|
||||
|
||||
import com.zt.plat.framework.common.validation.InEnum;
|
||||
import com.zt.plat.module.iot.enums.plugin.IotPluginStatusEnum;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
@Schema(description = "管理后台 - IoT 插件配置新增/修改 Request VO")
|
||||
@Data
|
||||
public class PluginConfigSaveReqVO {
|
||||
|
||||
// TODO @haohao:新增的字段有点多,每个都需要哇?
|
||||
|
||||
// TODO @haohao:一些枚举字段,需要加枚举校验。例如说,deployType、status、type 等
|
||||
|
||||
@Schema(description = "主键编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "11546")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "插件包标识符", requiredMode = Schema.RequiredMode.REQUIRED, example = "24627")
|
||||
private String pluginKey;
|
||||
|
||||
@Schema(description = "插件名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "赵六")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "描述", example = "你猜")
|
||||
private String description;
|
||||
|
||||
@Schema(description = "部署方式", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
|
||||
private Integer deployType;
|
||||
|
||||
@Schema(description = "插件包文件名", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private String fileName;
|
||||
|
||||
@Schema(description = "插件版本", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private String version;
|
||||
|
||||
@Schema(description = "插件类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
|
||||
private Integer type;
|
||||
|
||||
@Schema(description = "设备插件协议类型")
|
||||
private String protocol;
|
||||
|
||||
@Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@InEnum(IotPluginStatusEnum.class)
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "插件配置项描述信息")
|
||||
private String configSchema;
|
||||
|
||||
@Schema(description = "插件配置信息")
|
||||
private String config;
|
||||
|
||||
@Schema(description = "插件脚本")
|
||||
private String script;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.zt.plat.module.iot.controller.admin.plugin.vo.config;
|
||||
|
||||
import com.zt.plat.framework.common.validation.InEnum;
|
||||
import com.zt.plat.module.iot.enums.plugin.IotPluginStatusEnum;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
@Schema(description = "管理后台 - IoT 插件配置状态 Request VO")
|
||||
@Data
|
||||
public class PluginConfigStatusReqVO {
|
||||
|
||||
@Schema(description = "主键编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "11546")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@InEnum(IotPluginStatusEnum.class)
|
||||
private Integer status;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.zt.plat.module.iot.controller.admin.plugin.vo.instance;
|
||||
|
||||
import lombok.*;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import com.zt.plat.framework.common.pojo.PageParam;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import static com.zt.plat.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
||||
|
||||
// TODO @haohao:后续需要使用下
|
||||
@Schema(description = "管理后台 - IoT 插件实例分页 Request VO")
|
||||
@Data
|
||||
public class PluginInstancePageReqVO extends PageParam {
|
||||
|
||||
@Schema(description = "插件主程序编号", example = "23738")
|
||||
private String mainId;
|
||||
|
||||
@Schema(description = "插件id", example = "26498")
|
||||
private Long pluginId;
|
||||
|
||||
@Schema(description = "插件主程序所在ip")
|
||||
private String ip;
|
||||
|
||||
@Schema(description = "插件主程序端口")
|
||||
private Integer port;
|
||||
|
||||
@Schema(description = "心跳时间,心路时间超过30秒需要剔除")
|
||||
private Long heartbeatAt;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
private LocalDateTime[] createTime;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.zt.plat.module.iot.controller.admin.plugin.vo.instance;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
// TODO @haohao:后续需要使用下
|
||||
@Schema(description = "管理后台 - IoT 插件实例 Response VO")
|
||||
@Data
|
||||
public class PluginInstanceRespVO {
|
||||
|
||||
@Schema(description = "主键编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "23864")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "插件主程序id", requiredMode = Schema.RequiredMode.REQUIRED, example = "23738")
|
||||
private String mainId;
|
||||
|
||||
@Schema(description = "插件id", requiredMode = Schema.RequiredMode.REQUIRED, example = "26498")
|
||||
private Long pluginId;
|
||||
|
||||
@Schema(description = "插件主程序所在ip", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private String ip;
|
||||
|
||||
@Schema(description = "插件主程序端口", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private Integer port;
|
||||
|
||||
@Schema(description = "心跳时间,心路时间超过30秒需要剔除", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private Long heartbeatAt;
|
||||
|
||||
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private LocalDateTime createTime;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
package com.zt.plat.module.iot.controller.admin.product;
|
||||
|
||||
import com.zt.plat.framework.common.enums.CommonStatusEnum;
|
||||
import com.zt.plat.framework.common.pojo.CommonResult;
|
||||
import com.zt.plat.framework.common.pojo.PageResult;
|
||||
import com.zt.plat.framework.common.util.object.BeanUtils;
|
||||
import com.zt.plat.module.iot.controller.admin.product.vo.category.IotProductCategoryPageReqVO;
|
||||
import com.zt.plat.module.iot.controller.admin.product.vo.category.IotProductCategoryRespVO;
|
||||
import com.zt.plat.module.iot.controller.admin.product.vo.category.IotProductCategorySaveReqVO;
|
||||
import com.zt.plat.module.iot.dal.dataobject.product.IotProductCategoryDO;
|
||||
import com.zt.plat.module.iot.service.product.IotProductCategoryService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.validation.Valid;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static com.zt.plat.framework.common.pojo.CommonResult.success;
|
||||
import static com.zt.plat.framework.common.util.collection.CollectionUtils.convertList;
|
||||
|
||||
@Tag(name = "管理后台 - IoT 产品分类")
|
||||
@RestController
|
||||
@RequestMapping("/iot/product-category")
|
||||
@Validated
|
||||
public class IotProductCategoryController {
|
||||
|
||||
@Resource
|
||||
private IotProductCategoryService productCategoryService;
|
||||
|
||||
@PostMapping("/create")
|
||||
@Operation(summary = "创建产品分类")
|
||||
@PreAuthorize("@ss.hasPermission('iot:product-category:create')")
|
||||
public CommonResult<Long> createProductCategory(@Valid @RequestBody IotProductCategorySaveReqVO createReqVO) {
|
||||
return success(productCategoryService.createProductCategory(createReqVO));
|
||||
}
|
||||
|
||||
@PutMapping("/update")
|
||||
@Operation(summary = "更新产品分类")
|
||||
@PreAuthorize("@ss.hasPermission('iot:product-category:update')")
|
||||
public CommonResult<Boolean> updateProductCategory(@Valid @RequestBody IotProductCategorySaveReqVO updateReqVO) {
|
||||
productCategoryService.updateProductCategory(updateReqVO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@DeleteMapping("/delete")
|
||||
@Operation(summary = "删除产品分类")
|
||||
@Parameter(name = "id", description = "编号", required = true)
|
||||
@PreAuthorize("@ss.hasPermission('iot:product-category:delete')")
|
||||
public CommonResult<Boolean> deleteProductCategory(@RequestParam("id") Long id) {
|
||||
productCategoryService.deleteProductCategory(id);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@GetMapping("/get")
|
||||
@Operation(summary = "获得产品分类")
|
||||
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
||||
@PreAuthorize("@ss.hasPermission('iot:product-category:query')")
|
||||
public CommonResult<IotProductCategoryRespVO> getProductCategory(@RequestParam("id") Long id) {
|
||||
IotProductCategoryDO productCategory = productCategoryService.getProductCategory(id);
|
||||
return success(BeanUtils.toBean(productCategory, IotProductCategoryRespVO.class));
|
||||
}
|
||||
|
||||
@GetMapping("/page")
|
||||
@Operation(summary = "获得产品分类分页")
|
||||
@PreAuthorize("@ss.hasPermission('iot:product-category:query')")
|
||||
public CommonResult<PageResult<IotProductCategoryRespVO>> getProductCategoryPage(@Valid IotProductCategoryPageReqVO pageReqVO) {
|
||||
PageResult<IotProductCategoryDO> pageResult = productCategoryService.getProductCategoryPage(pageReqVO);
|
||||
return success(BeanUtils.toBean(pageResult, IotProductCategoryRespVO.class));
|
||||
}
|
||||
|
||||
@GetMapping("/simple-list")
|
||||
@Operation(summary = "获得所有产品分类列表")
|
||||
@PreAuthorize("@ss.hasPermission('iot:product-category:query')")
|
||||
public CommonResult<List<IotProductCategoryRespVO>> getSimpleProductCategoryList() {
|
||||
List<IotProductCategoryDO> list = productCategoryService.getProductCategoryListByStatus(
|
||||
CommonStatusEnum.ENABLE.getStatus());
|
||||
return success(convertList(list, category ->
|
||||
new IotProductCategoryRespVO().setId(category.getId()).setName(category.getName())));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
package com.zt.plat.module.iot.controller.admin.product;
|
||||
|
||||
import com.zt.plat.framework.apilog.core.annotation.ApiAccessLog;
|
||||
import com.zt.plat.framework.common.pojo.CommonResult;
|
||||
import com.zt.plat.framework.common.pojo.PageParam;
|
||||
import com.zt.plat.framework.common.pojo.PageResult;
|
||||
import com.zt.plat.framework.common.util.collection.MapUtils;
|
||||
import com.zt.plat.framework.common.util.object.BeanUtils;
|
||||
import com.zt.plat.framework.excel.core.util.ExcelUtils;
|
||||
import com.zt.plat.module.iot.controller.admin.product.vo.product.IotProductPageReqVO;
|
||||
import com.zt.plat.module.iot.controller.admin.product.vo.product.IotProductRespVO;
|
||||
import com.zt.plat.module.iot.controller.admin.product.vo.product.IotProductSaveReqVO;
|
||||
import com.zt.plat.module.iot.dal.dataobject.product.IotProductCategoryDO;
|
||||
import com.zt.plat.module.iot.dal.dataobject.product.IotProductDO;
|
||||
import com.zt.plat.module.iot.service.product.IotProductCategoryService;
|
||||
import com.zt.plat.module.iot.service.product.IotProductService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import jakarta.validation.Valid;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static com.zt.plat.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
|
||||
import static com.zt.plat.framework.common.pojo.CommonResult.success;
|
||||
import static com.zt.plat.framework.common.util.collection.CollectionUtils.convertList;
|
||||
|
||||
@Tag(name = "管理后台 - IoT 产品")
|
||||
@RestController
|
||||
@RequestMapping("/iot/product")
|
||||
@Validated
|
||||
public class IotProductController {
|
||||
|
||||
@Resource
|
||||
private IotProductService productService;
|
||||
@Resource
|
||||
private IotProductCategoryService categoryService;
|
||||
|
||||
@PostMapping("/create")
|
||||
@Operation(summary = "创建产品")
|
||||
@PreAuthorize("@ss.hasPermission('iot:product:create')")
|
||||
public CommonResult<Long> createProduct(@Valid @RequestBody IotProductSaveReqVO createReqVO) {
|
||||
return success(productService.createProduct(createReqVO));
|
||||
}
|
||||
|
||||
@PutMapping("/update")
|
||||
@Operation(summary = "更新产品")
|
||||
@PreAuthorize("@ss.hasPermission('iot:product:update')")
|
||||
public CommonResult<Boolean> updateProduct(@Valid @RequestBody IotProductSaveReqVO updateReqVO) {
|
||||
productService.updateProduct(updateReqVO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@PutMapping("/update-status")
|
||||
@Operation(summary = "更新产品状态")
|
||||
@Parameter(name = "id", description = "编号", required = true)
|
||||
@Parameter(name = "status", description = "状态", required = true)
|
||||
@PreAuthorize("@ss.hasPermission('iot:product:update')")
|
||||
public CommonResult<Boolean> updateProductStatus(@RequestParam("id") Long id,
|
||||
@RequestParam("status") Integer status) {
|
||||
productService.updateProductStatus(id, status);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@DeleteMapping("/delete")
|
||||
@Operation(summary = "删除产品")
|
||||
@Parameter(name = "id", description = "编号", required = true)
|
||||
@PreAuthorize("@ss.hasPermission('iot:product:delete')")
|
||||
public CommonResult<Boolean> deleteProduct(@RequestParam("id") Long id) {
|
||||
productService.deleteProduct(id);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@GetMapping("/get")
|
||||
@Operation(summary = "获得产品")
|
||||
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
||||
@PreAuthorize("@ss.hasPermission('iot:product:query')")
|
||||
public CommonResult<IotProductRespVO> getProduct(@RequestParam("id") Long id) {
|
||||
IotProductDO product = productService.getProduct(id);
|
||||
// 拼接数据
|
||||
IotProductCategoryDO category = categoryService.getProductCategory(product.getCategoryId());
|
||||
return success(BeanUtils.toBean(product, IotProductRespVO.class, bean -> {
|
||||
if (category != null) {
|
||||
bean.setCategoryName(category.getName());
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
@GetMapping("/page")
|
||||
@Operation(summary = "获得产品分页")
|
||||
@PreAuthorize("@ss.hasPermission('iot:product:query')")
|
||||
public CommonResult<PageResult<IotProductRespVO>> getProductPage(@Valid IotProductPageReqVO pageReqVO) {
|
||||
PageResult<IotProductDO> pageResult = productService.getProductPage(pageReqVO);
|
||||
// 拼接数据
|
||||
Map<Long, IotProductCategoryDO> categoryMap = categoryService.getProductCategoryMap(
|
||||
convertList(pageResult.getList(), IotProductDO::getCategoryId));
|
||||
return success(BeanUtils.toBean(pageResult, IotProductRespVO.class, bean -> {
|
||||
MapUtils.findAndThen(categoryMap, bean.getCategoryId(),
|
||||
category -> bean.setCategoryName(category.getName()));
|
||||
}));
|
||||
}
|
||||
|
||||
@GetMapping("/export-excel")
|
||||
@Operation(summary = "导出产品 Excel")
|
||||
@PreAuthorize("@ss.hasPermission('iot:product:export')")
|
||||
@ApiAccessLog(operateType = EXPORT)
|
||||
public void exportProductExcel(@Valid IotProductPageReqVO exportReqVO,
|
||||
HttpServletResponse response) throws IOException {
|
||||
exportReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
|
||||
CommonResult<PageResult<IotProductRespVO>> result = getProductPage(exportReqVO);
|
||||
// 导出 Excel
|
||||
ExcelUtils.write(response, "产品.xls", "数据", IotProductRespVO.class,
|
||||
result.getData().getList());
|
||||
}
|
||||
|
||||
@GetMapping("/simple-list")
|
||||
@Operation(summary = "获取产品的精简信息列表", description = "主要用于前端的下拉选项")
|
||||
public CommonResult<List<IotProductRespVO>> getSimpleProductList() {
|
||||
List<IotProductDO> list = productService.getProductList();
|
||||
return success(convertList(list, product -> // 只返回 id、name 字段
|
||||
new IotProductRespVO().setId(product.getId()).setName(product.getName())
|
||||
.setDeviceType(product.getDeviceType())));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.zt.plat.module.iot.controller.admin.product.vo.category;
|
||||
|
||||
import com.zt.plat.framework.common.pojo.PageParam;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import static com.zt.plat.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
||||
|
||||
@Schema(description = "管理后台 - IoT 产品分类分页 Request VO")
|
||||
@Data
|
||||
public class IotProductCategoryPageReqVO extends PageParam {
|
||||
|
||||
@Schema(description = "分类名字", example = "王五")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
private LocalDateTime[] createTime;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.zt.plat.module.iot.controller.admin.product.vo.category;
|
||||
|
||||
import com.zt.plat.framework.excel.core.annotations.DictFormat;
|
||||
import com.zt.plat.module.system.enums.DictTypeConstants;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Schema(description = "管理后台 - IoT 产品分类 Response VO")
|
||||
@Data
|
||||
public class IotProductCategoryRespVO {
|
||||
|
||||
@Schema(description = "分类 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "25284")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "分类名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "王五")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "分类排序")
|
||||
private Integer sort;
|
||||
|
||||
@Schema(description = "分类状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
@DictFormat(DictTypeConstants.COMMON_STATUS)
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "分类描述", example = "随便")
|
||||
private String description;
|
||||
|
||||
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private LocalDateTime createTime;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.zt.plat.module.iot.controller.admin.product.vo.category;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
|
||||
@Schema(description = "管理后台 - IoT 产品分类新增/修改 Request VO")
|
||||
@Data
|
||||
public class IotProductCategorySaveReqVO {
|
||||
|
||||
@Schema(description = "分类 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "25284")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "分类名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "王五")
|
||||
@NotEmpty(message = "分类名字不能为空")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "分类排序")
|
||||
private Integer sort;
|
||||
|
||||
@Schema(description = "分类状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
@NotNull(message = "分类状态不能为空")
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "分类描述", example = "随便")
|
||||
private String description;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.zt.plat.module.iot.controller.admin.product.vo.product;
|
||||
|
||||
import com.zt.plat.framework.common.pojo.PageParam;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
@Schema(description = "管理后台 - IoT 产品分页 Request VO")
|
||||
@Data
|
||||
public class IotProductPageReqVO extends PageParam {
|
||||
|
||||
@Schema(description = "产品名称", example = "李四")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "产品标识")
|
||||
private String productKey;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
package com.zt.plat.module.iot.controller.admin.product.vo.product;
|
||||
|
||||
import com.zt.plat.framework.excel.core.annotations.DictFormat;
|
||||
import com.zt.plat.framework.excel.core.convert.DictConvert;
|
||||
import com.zt.plat.module.iot.enums.DictTypeConstants;
|
||||
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Schema(description = "管理后台 - IoT 产品 Response VO")
|
||||
@Data
|
||||
@ExcelIgnoreUnannotated
|
||||
public class IotProductRespVO {
|
||||
|
||||
@Schema(description = "产品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "26087")
|
||||
@ExcelProperty("产品编号")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "产品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四")
|
||||
@ExcelProperty("产品名称")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "产品标识", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@ExcelProperty("产品标识")
|
||||
private String productKey;
|
||||
|
||||
@Schema(description = "产品分类编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
private Long categoryId;
|
||||
|
||||
@Schema(description = "产品分类名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
@ExcelProperty("产品分类")
|
||||
private String categoryName;
|
||||
|
||||
@Schema(description = "产品图标", example = "https://iocoder.cn/1.svg")
|
||||
@ExcelProperty("产品图标")
|
||||
private String icon;
|
||||
|
||||
@Schema(description = "产品图片", example = "https://iocoder.cn/1.png")
|
||||
@ExcelProperty("产品图片")
|
||||
private String picUrl;
|
||||
|
||||
@Schema(description = "产品描述", example = "你猜")
|
||||
@ExcelProperty("产品描述")
|
||||
private String description;
|
||||
|
||||
@Schema(description = "产品状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
@ExcelProperty(value = "产品状态", converter = DictConvert.class)
|
||||
@DictFormat(DictTypeConstants.PRODUCT_STATUS)
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "设备类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
|
||||
@ExcelProperty(value = "设备类型", converter = DictConvert.class)
|
||||
@DictFormat(DictTypeConstants.PRODUCT_DEVICE_TYPE)
|
||||
private Integer deviceType;
|
||||
|
||||
@Schema(description = "联网方式", example = "2")
|
||||
@ExcelProperty(value = "联网方式", converter = DictConvert.class)
|
||||
@DictFormat(DictTypeConstants.NET_TYPE)
|
||||
private Integer netType;
|
||||
|
||||
@Schema(description = "接入网关协议", example = "2")
|
||||
@ExcelProperty(value = "接入网关协议", converter = DictConvert.class)
|
||||
@DictFormat(DictTypeConstants.PROTOCOL_TYPE)
|
||||
private Integer protocolType;
|
||||
|
||||
@Schema(description = "协议编号(脚本解析 id)", requiredMode = Schema.RequiredMode.REQUIRED, example = "13177")
|
||||
@ExcelProperty("协议编号(脚本解析 id)")
|
||||
private Long protocolId;
|
||||
|
||||
@Schema(description = "数据格式")
|
||||
@ExcelProperty(value = "数据格式", converter = DictConvert.class)
|
||||
@DictFormat(DictTypeConstants.DATA_FORMAT)
|
||||
private Integer dataFormat;
|
||||
|
||||
@Schema(description = "数据校验级别", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
@ExcelProperty(value = "数据校验级别", converter = DictConvert.class)
|
||||
@DictFormat(DictTypeConstants.VALIDATE_TYPE)
|
||||
private Integer validateType;
|
||||
|
||||
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@ExcelProperty("创建时间")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package com.zt.plat.module.iot.controller.admin.product.vo.product;
|
||||
|
||||
import com.zt.plat.framework.common.validation.InEnum;
|
||||
import com.zt.plat.module.iot.enums.product.*;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
|
||||
@Schema(description = "管理后台 - IoT 产品新增/修改 Request VO")
|
||||
@Data
|
||||
public class IotProductSaveReqVO {
|
||||
|
||||
@Schema(description = "产品编号", requiredMode = Schema.RequiredMode.AUTO, example = "1")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "产品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "温湿度")
|
||||
@NotEmpty(message = "产品名称不能为空")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "产品 Key", requiredMode = Schema.RequiredMode.AUTO, example = "12345abc")
|
||||
private String productKey;
|
||||
|
||||
@Schema(description = "产品分类编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
@NotNull(message = "产品分类编号不能为空")
|
||||
private Long categoryId;
|
||||
|
||||
@Schema(description = "产品图标", example = "https://iocoder.cn/1.svg")
|
||||
private String icon;
|
||||
|
||||
@Schema(description = "产品图片", example = "https://iocoder.cn/1.png")
|
||||
private String picUrl;
|
||||
|
||||
@Schema(description = "产品描述", example = "描述")
|
||||
private String description;
|
||||
|
||||
@Schema(description = "设备类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
|
||||
@InEnum(value = IotProductDeviceTypeEnum.class, message = "设备类型必须是 {value}")
|
||||
@NotNull(message = "设备类型不能为空")
|
||||
private Integer deviceType;
|
||||
|
||||
@Schema(description = "联网方式", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
|
||||
@InEnum(value = IotNetTypeEnum.class, message = "联网方式必须是 {value}")
|
||||
private Integer netType;
|
||||
|
||||
@Schema(description = "接入网关协议", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
|
||||
@InEnum(value = IotProtocolTypeEnum.class, message = "接入网关协议必须是 {value}")
|
||||
private Integer protocolType;
|
||||
|
||||
@Schema(description = "数据格式", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
|
||||
@InEnum(value = IotDataFormatEnum.class, message = "数据格式必须是 {value}")
|
||||
@NotNull(message = "数据格式不能为空")
|
||||
private Integer dataFormat;
|
||||
|
||||
@Schema(description = "数据校验级别", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
|
||||
@InEnum(value = IotValidateTypeEnum.class, message = "数据校验级别必须是 {value}")
|
||||
@NotNull(message = "数据校验级别不能为空")
|
||||
private Integer validateType;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
package com.zt.plat.module.iot.controller.admin.rule;
|
||||
|
||||
import com.zt.plat.framework.common.pojo.CommonResult;
|
||||
import com.zt.plat.framework.common.pojo.PageResult;
|
||||
import com.zt.plat.framework.common.util.object.BeanUtils;
|
||||
import com.zt.plat.module.iot.controller.admin.rule.vo.databridge.IotDataBridgePageReqVO;
|
||||
import com.zt.plat.module.iot.controller.admin.rule.vo.databridge.IotDataBridgeRespVO;
|
||||
import com.zt.plat.module.iot.controller.admin.rule.vo.databridge.IotDataBridgeSaveReqVO;
|
||||
import com.zt.plat.module.iot.dal.dataobject.rule.IotDataBridgeDO;
|
||||
import com.zt.plat.module.iot.service.rule.IotDataBridgeService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.validation.Valid;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import static com.zt.plat.framework.common.pojo.CommonResult.success;
|
||||
|
||||
@Tag(name = "管理后台 - IoT 数据桥梁")
|
||||
@RestController
|
||||
@RequestMapping("/iot/data-bridge")
|
||||
@Validated
|
||||
public class IotDataBridgeController {
|
||||
|
||||
@Resource
|
||||
private IotDataBridgeService dataBridgeService;
|
||||
|
||||
@PostMapping("/create")
|
||||
@Operation(summary = "创建数据桥梁")
|
||||
@PreAuthorize("@ss.hasPermission('iot:data-bridge:create')")
|
||||
public CommonResult<Long> createDataBridge(@Valid @RequestBody IotDataBridgeSaveReqVO createReqVO) {
|
||||
return success(dataBridgeService.createDataBridge(createReqVO));
|
||||
}
|
||||
|
||||
@PutMapping("/update")
|
||||
@Operation(summary = "更新数据桥梁")
|
||||
@PreAuthorize("@ss.hasPermission('iot:data-bridge:update')")
|
||||
public CommonResult<Boolean> updateDataBridge(@Valid @RequestBody IotDataBridgeSaveReqVO updateReqVO) {
|
||||
dataBridgeService.updateDataBridge(updateReqVO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@DeleteMapping("/delete")
|
||||
@Operation(summary = "删除数据桥梁")
|
||||
@Parameter(name = "id", description = "编号", required = true)
|
||||
@PreAuthorize("@ss.hasPermission('iot:data-bridge:delete')")
|
||||
public CommonResult<Boolean> deleteDataBridge(@RequestParam("id") Long id) {
|
||||
dataBridgeService.deleteDataBridge(id);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@GetMapping("/get")
|
||||
@Operation(summary = "获得数据桥梁")
|
||||
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
||||
@PreAuthorize("@ss.hasPermission('iot:data-bridge:query')")
|
||||
public CommonResult<IotDataBridgeRespVO> getDataBridge(@RequestParam("id") Long id) {
|
||||
IotDataBridgeDO dataBridge = dataBridgeService.getDataBridge(id);
|
||||
return success(BeanUtils.toBean(dataBridge, IotDataBridgeRespVO.class));
|
||||
}
|
||||
|
||||
@GetMapping("/page")
|
||||
@Operation(summary = "获得数据桥梁分页")
|
||||
@PreAuthorize("@ss.hasPermission('iot:data-bridge:query')")
|
||||
public CommonResult<PageResult<IotDataBridgeRespVO>> getDataBridgePage(@Valid IotDataBridgePageReqVO pageReqVO) {
|
||||
PageResult<IotDataBridgeDO> pageResult = dataBridgeService.getDataBridgePage(pageReqVO);
|
||||
return success(BeanUtils.toBean(pageResult, IotDataBridgeRespVO.class));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.zt.plat.module.iot.controller.admin.rule;
|
||||
|
||||
import com.zt.plat.module.iot.service.rule.IotRuleSceneService;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.annotation.security.PermitAll;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@Tag(name = "管理后台 - IoT 规则场景")
|
||||
@RestController
|
||||
@RequestMapping("/iot/rule-scene")
|
||||
@Validated
|
||||
public class IotRuleSceneController {
|
||||
|
||||
@Resource
|
||||
private IotRuleSceneService ruleSceneService;
|
||||
|
||||
@GetMapping("/test")
|
||||
@PermitAll
|
||||
public void test() {
|
||||
ruleSceneService.test();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.zt.plat.module.iot.controller.admin.rule.vo.databridge;
|
||||
|
||||
import com.zt.plat.framework.common.enums.CommonStatusEnum;
|
||||
import com.zt.plat.framework.common.pojo.PageParam;
|
||||
import com.zt.plat.framework.common.validation.InEnum;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import static com.zt.plat.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
||||
|
||||
@Schema(description = "管理后台 - IoT 数据桥梁分页 Request VO")
|
||||
@Data
|
||||
public class IotDataBridgePageReqVO extends PageParam {
|
||||
|
||||
@Schema(description = "桥梁名称", example = "赵六")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "桥梁状态", example = "1")
|
||||
@InEnum(CommonStatusEnum.class)
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
private LocalDateTime[] createTime;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package com.zt.plat.module.iot.controller.admin.rule.vo.databridge;
|
||||
|
||||
import com.zt.plat.module.iot.controller.admin.rule.vo.databridge.config.IotDataBridgeAbstractConfig;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Schema(description = "管理后台 - IoT 数据桥梁 Response VO")
|
||||
@Data
|
||||
public class IotDataBridgeRespVO {
|
||||
|
||||
@Schema(description = "桥梁编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "18564")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "桥梁名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "赵六")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "桥梁描述", example = "随便")
|
||||
private String description;
|
||||
|
||||
@Schema(description = "桥梁状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "桥梁方向", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private Integer direction;
|
||||
|
||||
@Schema(description = "桥梁类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
private Integer type;
|
||||
|
||||
@Schema(description = "桥梁配置")
|
||||
private IotDataBridgeAbstractConfig config;
|
||||
|
||||
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private LocalDateTime createTime;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package com.zt.plat.module.iot.controller.admin.rule.vo.databridge;
|
||||
|
||||
import com.zt.plat.framework.common.enums.CommonStatusEnum;
|
||||
import com.zt.plat.framework.common.validation.InEnum;
|
||||
import com.zt.plat.module.iot.controller.admin.rule.vo.databridge.config.IotDataBridgeAbstractConfig;
|
||||
import com.zt.plat.module.iot.enums.rule.IotDataBridgeDirectionEnum;
|
||||
import com.zt.plat.module.iot.enums.rule.IotDataBridgeTypeEnum;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
|
||||
@Schema(description = "管理后台 - IoT 数据桥梁新增/修改 Request VO")
|
||||
@Data
|
||||
public class IotDataBridgeSaveReqVO {
|
||||
|
||||
@Schema(description = "桥梁编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "18564")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "桥梁名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "赵六")
|
||||
@NotEmpty(message = "桥梁名称不能为空")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "桥梁描述", example = "随便")
|
||||
private String description;
|
||||
|
||||
@Schema(description = "桥梁状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
|
||||
@NotNull(message = "桥梁状态不能为空")
|
||||
@InEnum(CommonStatusEnum.class)
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "桥梁方向", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotNull(message = "桥梁方向不能为空")
|
||||
@InEnum(IotDataBridgeDirectionEnum.class)
|
||||
private Integer direction;
|
||||
|
||||
@Schema(description = "桥梁类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
@NotNull(message = "桥梁类型不能为空")
|
||||
@InEnum(IotDataBridgeTypeEnum.class)
|
||||
private Integer type;
|
||||
|
||||
@Schema(description = "桥梁配置")
|
||||
@NotNull(message = "桥梁配置不能为空")
|
||||
private IotDataBridgeAbstractConfig config;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.zt.plat.module.iot.controller.admin.rule.vo.databridge.config;
|
||||
|
||||
import com.zt.plat.module.iot.enums.rule.IotDataBridgeTypeEnum;
|
||||
import com.fasterxml.jackson.annotation.JsonSubTypes;
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* IoT IotDataBridgeConfig 抽象类
|
||||
*
|
||||
* 用于表示数据桥梁配置数据的通用类型,根据具体的 "type" 字段动态映射到对应的子类
|
||||
* 提供多态支持,适用于不同类型的数据结构序列化和反序列化场景。
|
||||
*
|
||||
* @author HUIHUI
|
||||
*/
|
||||
@Data
|
||||
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type", visible = true)
|
||||
@JsonSubTypes({
|
||||
@JsonSubTypes.Type(value = IotDataBridgeHttpConfig.class, name = "1"),
|
||||
@JsonSubTypes.Type(value = IotDataBridgeMqttConfig.class, name = "10"),
|
||||
@JsonSubTypes.Type(value = IotDataBridgeRedisStreamMQConfig.class, name = "21"),
|
||||
@JsonSubTypes.Type(value = IotDataBridgeRocketMQConfig.class, name = "30"),
|
||||
@JsonSubTypes.Type(value = IotDataBridgeRabbitMQConfig.class, name = "31"),
|
||||
@JsonSubTypes.Type(value = IotDataBridgeKafkaMQConfig.class, name = "32"),
|
||||
})
|
||||
public abstract class IotDataBridgeAbstractConfig {
|
||||
|
||||
/**
|
||||
* 配置类型
|
||||
*
|
||||
* 枚举 {@link IotDataBridgeTypeEnum#getType()}
|
||||
*/
|
||||
private String type;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package com.zt.plat.module.iot.controller.admin.rule.vo.databridge.config;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* IoT HTTP 配置 {@link IotDataBridgeAbstractConfig} 实现类
|
||||
*
|
||||
* @author HUIHUI
|
||||
*/
|
||||
@Data
|
||||
public class IotDataBridgeHttpConfig extends IotDataBridgeAbstractConfig {
|
||||
|
||||
/**
|
||||
* 请求 URL
|
||||
*/
|
||||
private String url;
|
||||
/**
|
||||
* 请求方法
|
||||
*/
|
||||
private String method;
|
||||
/**
|
||||
* 请求头
|
||||
*/
|
||||
private Map<String, String> headers;
|
||||
/**
|
||||
* 请求参数
|
||||
*/
|
||||
private Map<String, String> query;
|
||||
/**
|
||||
* 请求体
|
||||
*/
|
||||
private String body;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.zt.plat.module.iot.controller.admin.rule.vo.databridge.config;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* IoT Kafka 配置 {@link IotDataBridgeAbstractConfig} 实现类
|
||||
*
|
||||
* @author HUIHUI
|
||||
*/
|
||||
@Data
|
||||
public class IotDataBridgeKafkaMQConfig extends IotDataBridgeAbstractConfig {
|
||||
|
||||
/**
|
||||
* Kafka 服务器地址
|
||||
*/
|
||||
private String bootstrapServers;
|
||||
/**
|
||||
* 用户名
|
||||
*/
|
||||
private String username;
|
||||
/**
|
||||
* 密码
|
||||
*/
|
||||
private String password;
|
||||
/**
|
||||
* 是否启用 SSL
|
||||
*/
|
||||
private Boolean ssl;
|
||||
|
||||
/**
|
||||
* 主题
|
||||
*/
|
||||
private String topic;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.zt.plat.module.iot.controller.admin.rule.vo.databridge.config;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* IoT MQTT 配置 {@link IotDataBridgeAbstractConfig} 实现类
|
||||
*
|
||||
* @author HUIHUI
|
||||
*/
|
||||
@Data
|
||||
public class IotDataBridgeMqttConfig extends IotDataBridgeAbstractConfig {
|
||||
|
||||
/**
|
||||
* MQTT 服务器地址
|
||||
*/
|
||||
private String url;
|
||||
/**
|
||||
* 用户名
|
||||
*/
|
||||
private String username;
|
||||
/**
|
||||
* 密码
|
||||
*/
|
||||
private String password;
|
||||
/**
|
||||
* 客户端编号
|
||||
*/
|
||||
private String clientId;
|
||||
/**
|
||||
* 主题
|
||||
*/
|
||||
private String topic;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package com.zt.plat.module.iot.controller.admin.rule.vo.databridge.config;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* IoT RabbitMQ 配置 {@link IotDataBridgeAbstractConfig} 实现类
|
||||
*
|
||||
* @author HUIHUI
|
||||
*/
|
||||
@Data
|
||||
public class IotDataBridgeRabbitMQConfig extends IotDataBridgeAbstractConfig {
|
||||
|
||||
/**
|
||||
* RabbitMQ 服务器地址
|
||||
*/
|
||||
private String host;
|
||||
/**
|
||||
* 端口
|
||||
*/
|
||||
private Integer port;
|
||||
/**
|
||||
* 虚拟主机
|
||||
*/
|
||||
private String virtualHost;
|
||||
/**
|
||||
* 用户名
|
||||
*/
|
||||
private String username;
|
||||
/**
|
||||
* 密码
|
||||
*/
|
||||
private String password;
|
||||
|
||||
/**
|
||||
* 交换机名称
|
||||
*/
|
||||
private String exchange;
|
||||
/**
|
||||
* 路由键
|
||||
*/
|
||||
private String routingKey;
|
||||
/**
|
||||
* 队列名称
|
||||
*/
|
||||
private String queue;
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.zt.plat.module.iot.controller.admin.rule.vo.databridge.config;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
// TODO @puhui999:MQ 可以去掉哈。stream 更精准
|
||||
/**
|
||||
* IoT Redis Stream 配置 {@link IotDataBridgeAbstractConfig} 实现类
|
||||
*
|
||||
* @author HUIHUI
|
||||
*/
|
||||
@Data
|
||||
public class IotDataBridgeRedisStreamMQConfig extends IotDataBridgeAbstractConfig {
|
||||
|
||||
/**
|
||||
* Redis 服务器地址
|
||||
*/
|
||||
private String host;
|
||||
/**
|
||||
* 端口
|
||||
*/
|
||||
private Integer port;
|
||||
/**
|
||||
* 密码
|
||||
*/
|
||||
private String password;
|
||||
/**
|
||||
* 数据库索引
|
||||
*/
|
||||
private Integer database;
|
||||
|
||||
/**
|
||||
* 主题
|
||||
*/
|
||||
private String topic;
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package com.zt.plat.module.iot.controller.admin.rule.vo.databridge.config;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* IoT RocketMQ 配置 {@link IotDataBridgeAbstractConfig} 实现类
|
||||
*
|
||||
* @author HUIHUI
|
||||
*/
|
||||
@Data
|
||||
public class IotDataBridgeRocketMQConfig extends IotDataBridgeAbstractConfig {
|
||||
|
||||
/**
|
||||
* RocketMQ 名称服务器地址
|
||||
*/
|
||||
private String nameServer;
|
||||
/**
|
||||
* 访问密钥
|
||||
*/
|
||||
private String accessKey;
|
||||
/**
|
||||
* 秘密钥匙
|
||||
*/
|
||||
private String secretKey;
|
||||
|
||||
/**
|
||||
* 生产者组
|
||||
*/
|
||||
private String group;
|
||||
/**
|
||||
* 主题
|
||||
*/
|
||||
private String topic;
|
||||
/**
|
||||
* 标签
|
||||
*/
|
||||
private String tags;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
// TODO @芋艿:占位
|
||||
package com.zt.plat.module.iot.controller.admin.rule.vo;
|
||||
@@ -0,0 +1,79 @@
|
||||
package com.zt.plat.module.iot.controller.admin.statistics;
|
||||
|
||||
import com.zt.plat.framework.common.pojo.CommonResult;
|
||||
import com.zt.plat.module.iot.controller.admin.statistics.vo.IotStatisticsDeviceMessageSummaryRespVO;
|
||||
import com.zt.plat.module.iot.controller.admin.statistics.vo.IotStatisticsReqVO;
|
||||
import com.zt.plat.module.iot.controller.admin.statistics.vo.IotStatisticsSummaryRespVO;
|
||||
import com.zt.plat.module.iot.enums.device.IotDeviceStateEnum;
|
||||
import com.zt.plat.module.iot.service.device.IotDeviceService;
|
||||
import com.zt.plat.module.iot.service.device.data.IotDeviceLogService;
|
||||
import com.zt.plat.module.iot.service.product.IotProductCategoryService;
|
||||
import com.zt.plat.module.iot.service.product.IotProductService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.validation.Valid;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Map;
|
||||
|
||||
import static com.zt.plat.framework.common.pojo.CommonResult.*;
|
||||
|
||||
@Tag(name = "管理后台 - IoT 数据统计")
|
||||
@RestController
|
||||
@RequestMapping("/iot/statistics")
|
||||
@Validated
|
||||
public class IotStatisticsController {
|
||||
|
||||
@Resource
|
||||
private IotDeviceService deviceService;
|
||||
@Resource
|
||||
private IotProductCategoryService productCategoryService;
|
||||
@Resource
|
||||
private IotProductService productService;
|
||||
@Resource
|
||||
private IotDeviceLogService deviceLogService;
|
||||
|
||||
@GetMapping("/get-summary")
|
||||
@Operation(summary = "获取 IoT 数据统计")
|
||||
public CommonResult<IotStatisticsSummaryRespVO> getIotStatisticsSummary(){
|
||||
IotStatisticsSummaryRespVO respVO = new IotStatisticsSummaryRespVO();
|
||||
// 1.1 获取总数
|
||||
respVO.setProductCategoryCount(productCategoryService.getProductCategoryCount(null));
|
||||
respVO.setProductCount(productService.getProductCount(null));
|
||||
respVO.setDeviceCount(deviceService.getDeviceCount(null));
|
||||
respVO.setDeviceMessageCount(deviceLogService.getDeviceLogCount(null));
|
||||
// 1.2 获取今日新增数量
|
||||
// TODO @super:使用 LocalDateTimeUtils.getToday()
|
||||
LocalDateTime todayStart = LocalDateTime.now().withHour(0).withMinute(0).withSecond(0);
|
||||
respVO.setProductCategoryTodayCount(productCategoryService.getProductCategoryCount(todayStart));
|
||||
respVO.setProductTodayCount(productService.getProductCount(todayStart));
|
||||
respVO.setDeviceTodayCount(deviceService.getDeviceCount(todayStart));
|
||||
respVO.setDeviceMessageTodayCount(deviceLogService.getDeviceLogCount(todayStart));
|
||||
|
||||
// 2. 获取各个品类下设备数量统计
|
||||
respVO.setProductCategoryDeviceCounts(productCategoryService.getProductCategoryDeviceCountMap());
|
||||
|
||||
// 3. 获取设备状态数量统计
|
||||
Map<Integer, Long> deviceCountMap = deviceService.getDeviceCountMapByState();
|
||||
respVO.setDeviceOnlineCount(deviceCountMap.getOrDefault(IotDeviceStateEnum.ONLINE.getState(), 0L));
|
||||
respVO.setDeviceOfflineCount(deviceCountMap.getOrDefault(IotDeviceStateEnum.OFFLINE.getState(), 0L));
|
||||
respVO.setDeviceInactiveCount(deviceCountMap.getOrDefault(IotDeviceStateEnum.INACTIVE.getState(), 0L));
|
||||
return success(respVO);
|
||||
}
|
||||
|
||||
// TODO @super:要不干掉 IotStatisticsReqVO 参数,直接使用 @RequestParam 接收,简单一些。
|
||||
@GetMapping("/get-log-summary")
|
||||
@Operation(summary = "获取 IoT 设备上下行消息数据统计")
|
||||
public CommonResult<IotStatisticsDeviceMessageSummaryRespVO> getIotStatisticsDeviceMessageSummary(
|
||||
@Valid IotStatisticsReqVO reqVO) {
|
||||
return success(new IotStatisticsDeviceMessageSummaryRespVO()
|
||||
.setDownstreamCounts(deviceLogService.getDeviceLogUpCountByHour(null, reqVO.getStartTime(), reqVO.getEndTime()))
|
||||
.setDownstreamCounts((deviceLogService.getDeviceLogDownCountByHour(null, reqVO.getStartTime(), reqVO.getEndTime()))));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.zt.plat.module.iot.controller.admin.statistics.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Schema(description = "管理后台 - IoT 设备上下行消息数量统计 Response VO")
|
||||
@Data
|
||||
public class IotStatisticsDeviceMessageSummaryRespVO {
|
||||
|
||||
@Schema(description = "每小时上行数据数量统计")
|
||||
private List<Map<Long, Integer>> upstreamCounts;
|
||||
|
||||
@Schema(description = "每小时下行数据数量统计")
|
||||
private List<Map<Long, Integer>> downstreamCounts;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.zt.plat.module.iot.controller.admin.statistics.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
|
||||
@Schema(description = "管理后台 - IoT 统计 Request VO")
|
||||
@Data
|
||||
public class IotStatisticsReqVO {
|
||||
|
||||
// TODO @super:前端传递的时候,还是通过 startTime 和 endTime 传递。后端转成 Long
|
||||
|
||||
@Schema(description = "查询起始时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "1658486600000")
|
||||
@NotNull(message = "查询起始时间不能为空")
|
||||
private Long startTime;
|
||||
|
||||
@Schema(description = "查询结束时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "1758486600000")
|
||||
@NotNull(message = "查询结束时间不能为空")
|
||||
private Long endTime;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package com.zt.plat.module.iot.controller.admin.statistics.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 管理后台 - IoT 统计 Response VO
|
||||
*/
|
||||
@Schema(description = "管理后台 - IoT 统计 Response VO")
|
||||
@Data
|
||||
public class IotStatisticsSummaryRespVO {
|
||||
|
||||
@Schema(description = "品类数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
|
||||
private Long productCategoryCount;
|
||||
|
||||
@Schema(description = "产品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "20")
|
||||
private Long productCount;
|
||||
|
||||
@Schema(description = "设备数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
|
||||
private Long deviceCount;
|
||||
|
||||
@Schema(description = "上报数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1000")
|
||||
private Long deviceMessageCount;
|
||||
|
||||
@Schema(description = "今日新增品类数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
|
||||
private Long productCategoryTodayCount;
|
||||
|
||||
@Schema(description = "今日新增产品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "20")
|
||||
private Long productTodayCount;
|
||||
|
||||
@Schema(description = "今日新增设备数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
|
||||
private Long deviceTodayCount;
|
||||
|
||||
@Schema(description = "今日新增上报数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1000")
|
||||
private Long deviceMessageTodayCount;
|
||||
|
||||
@Schema(description = "在线数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "80")
|
||||
private Long deviceOnlineCount;
|
||||
|
||||
@Schema(description = "离线数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "15")
|
||||
private Long deviceOfflineCount;
|
||||
|
||||
@Schema(description = "待激活设备数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "5")
|
||||
private Long deviceInactiveCount;
|
||||
|
||||
@Schema(description = "按品类统计的设备数量")
|
||||
private Map<String, Integer> productCategoryDeviceCounts;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,181 @@
|
||||
### 请求 /iot/product-thing-model/create 接口 => 成功
|
||||
POST {{baseUrl}}/iot/product-thing-model/create
|
||||
Content-Type: application/json
|
||||
tenant-id: {{adminTenentId}}
|
||||
Authorization: Bearer {{token}}
|
||||
|
||||
{
|
||||
"productId": 12,
|
||||
"productKey": "CJVS54fObwZJ9Qe5CJVS54fObwZJ9Qe5",
|
||||
"identifier": "Temperature",
|
||||
"name": "温度",
|
||||
"description": "当前温度值",
|
||||
"type": 1,
|
||||
"property": {
|
||||
"identifier": "Temperature",
|
||||
"name": "温度",
|
||||
"accessMode": "r",
|
||||
"required": true,
|
||||
"dataType": "int",
|
||||
"dataSpecs": {
|
||||
"dataType": "int",
|
||||
"max": "200",
|
||||
"min": "0",
|
||||
"step": "10",
|
||||
"defaultValue": "30",
|
||||
"unit": "%",
|
||||
"unitName": "百分比"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
### 请求 /iot/product-thing-model/create 接口 => 成功
|
||||
POST {{baseUrl}}/iot/product-thing-model/create
|
||||
Content-Type: application/json
|
||||
tenant-id: {{adminTenentId}}
|
||||
Authorization: Bearer {{token}}
|
||||
|
||||
{
|
||||
"productId": 12,
|
||||
"productKey": "CJVS54fObwZJ9Qe5CJVS54fObwZJ9Qe5",
|
||||
"identifier": "switch",
|
||||
"name": "开关",
|
||||
"description": "温度计开关",
|
||||
"type": 1,
|
||||
"property": {
|
||||
"identifier": "switch",
|
||||
"name": "开关",
|
||||
"accessMode": "rw",
|
||||
"required": true,
|
||||
"dataType": "bool",
|
||||
"dataSpecsList": [
|
||||
{
|
||||
"dataType": "bool",
|
||||
"name": "关",
|
||||
"value": 0
|
||||
},
|
||||
{
|
||||
"dataType": "bool",
|
||||
"name": "开",
|
||||
"value": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
### 请求 /iot/product-thing-model/create 接口 => 成功
|
||||
POST {{baseUrl}}/iot/product-thing-model/create
|
||||
Content-Type: application/json
|
||||
tenant-id: {{adminTenentId}}
|
||||
Authorization: Bearer {{token}}
|
||||
|
||||
{
|
||||
"productId": 12,
|
||||
"productKey": "CJVS54fObwZJ9Qe5CJVS54fObwZJ9Qe5",
|
||||
"identifier": "argb",
|
||||
"name": "温度计 argb 颜色",
|
||||
"description": "温度计 argb 颜色",
|
||||
"type": 1,
|
||||
"property": {
|
||||
"identifier": "argb",
|
||||
"name": "温度计 argb 颜色",
|
||||
"accessMode": "rw",
|
||||
"required": true,
|
||||
"dataType": "array",
|
||||
"dataSpecs": {
|
||||
"dataType": "array",
|
||||
"size": 10,
|
||||
"childDataType": "struct",
|
||||
"dataSpecsList": [
|
||||
{
|
||||
"identifier": "switch",
|
||||
"name": "开关",
|
||||
"accessMode": "rw",
|
||||
"required": true,
|
||||
"dataType": "struct",
|
||||
"childDataType": "bool",
|
||||
"dataSpecsList": [
|
||||
{
|
||||
"dataType": "bool",
|
||||
"name": "关",
|
||||
"value": 0
|
||||
},
|
||||
{
|
||||
"dataType": "bool",
|
||||
"name": "开",
|
||||
"value": 1
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"identifier": "Temperature",
|
||||
"name": "温度",
|
||||
"accessMode": "r",
|
||||
"required": true,
|
||||
"dataType": "struct",
|
||||
"childDataType": "int",
|
||||
"dataSpecs": {
|
||||
"dataType": "int",
|
||||
"max": "200",
|
||||
"min": "0",
|
||||
"step": "10",
|
||||
"defaultValue": "30",
|
||||
"unit": "%",
|
||||
"unitName": "百分比"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
### 请求 /iot/product-thing-model/update 接口 => 成功
|
||||
PUT {{baseUrl}}/iot/product-thing-model/update
|
||||
Content-Type: application/json
|
||||
tenant-id: {{adminTenentId}}
|
||||
Authorization: Bearer {{token}}
|
||||
|
||||
{
|
||||
"id": 33,
|
||||
"productId": 12,
|
||||
"productKey": "CJVS54fObwZJ9Qe5CJVS54fObwZJ9Qe5",
|
||||
"identifier": "switch",
|
||||
"name": "开关",
|
||||
"description": "温度计开关",
|
||||
"type": 1,
|
||||
"property": {
|
||||
"identifier": "switch",
|
||||
"name": "开关",
|
||||
"accessMode": "r",
|
||||
"required": true,
|
||||
"dataType": "bool",
|
||||
"dataSpecsList": [
|
||||
{
|
||||
"dataType": "bool",
|
||||
"name": "关",
|
||||
"value": 0
|
||||
},
|
||||
{
|
||||
"dataType": "bool",
|
||||
"name": "开",
|
||||
"value": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
### 请求 /iot/product-thing-model/delete 接口 => 成功
|
||||
DELETE {{baseUrl}}/iot/product-thing-model/delete?id=36
|
||||
tenant-id: {{adminTenentId}}
|
||||
Authorization: Bearer {{token}}
|
||||
|
||||
### 请求 /iot/product-thing-model/get 接口 => 成功
|
||||
GET {{baseUrl}}/iot/product-thing-model/get?id=67
|
||||
tenant-id: {{adminTenentId}}
|
||||
Authorization: Bearer {{token}}
|
||||
|
||||
|
||||
### 请求 /iot/product-thing-model/list-by-product-id 接口 => 成功
|
||||
GET {{baseUrl}}/iot/product-thing-model/list-by-product-id?productId=1001
|
||||
tenant-id: {{adminTenentId}}
|
||||
Authorization: Bearer {{token}}
|
||||
@@ -0,0 +1,93 @@
|
||||
package com.zt.plat.module.iot.controller.admin.thingmodel;
|
||||
|
||||
import com.zt.plat.framework.common.pojo.CommonResult;
|
||||
import com.zt.plat.framework.common.pojo.PageResult;
|
||||
import com.zt.plat.framework.common.util.object.BeanUtils;
|
||||
import com.zt.plat.module.iot.controller.admin.thingmodel.vo.IotThingModelListReqVO;
|
||||
import com.zt.plat.module.iot.controller.admin.thingmodel.vo.IotThingModelPageReqVO;
|
||||
import com.zt.plat.module.iot.controller.admin.thingmodel.vo.IotThingModelRespVO;
|
||||
import com.zt.plat.module.iot.controller.admin.thingmodel.vo.IotThingModelSaveReqVO;
|
||||
import com.zt.plat.module.iot.dal.dataobject.thingmodel.IotThingModelDO;
|
||||
import com.zt.plat.module.iot.service.thingmodel.IotThingModelService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.validation.Valid;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static com.zt.plat.framework.common.pojo.CommonResult.success;
|
||||
|
||||
@Tag(name = "管理后台 - IoT 产品物模型")
|
||||
@RestController
|
||||
@RequestMapping("/iot/thing-model")
|
||||
@Validated
|
||||
public class IotThingModelController {
|
||||
|
||||
@Resource
|
||||
private IotThingModelService thingModelService;
|
||||
|
||||
@PostMapping("/create")
|
||||
@Operation(summary = "创建产品物模型")
|
||||
@PreAuthorize("@ss.hasPermission('iot:thing-model:create')")
|
||||
public CommonResult<Long> createThingModel(@Valid @RequestBody IotThingModelSaveReqVO createReqVO) {
|
||||
return success(thingModelService.createThingModel(createReqVO));
|
||||
}
|
||||
|
||||
@PutMapping("/update")
|
||||
@Operation(summary = "更新产品物模型")
|
||||
@PreAuthorize("@ss.hasPermission('iot:thing-model:update')")
|
||||
public CommonResult<Boolean> updateThingModel(@Valid @RequestBody IotThingModelSaveReqVO updateReqVO) {
|
||||
thingModelService.updateThingModel(updateReqVO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@DeleteMapping("/delete")
|
||||
@Operation(summary = "删除产品物模型")
|
||||
@Parameter(name = "id", description = "编号", required = true)
|
||||
@PreAuthorize("@ss.hasPermission('iot:thing-model:delete')")
|
||||
public CommonResult<Boolean> deleteThingModel(@RequestParam("id") Long id) {
|
||||
thingModelService.deleteThingModel(id);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@GetMapping("/get")
|
||||
@Operation(summary = "获得产品物模型")
|
||||
@Parameter(name = "id", description = "编号", required = true)
|
||||
@PreAuthorize("@ss.hasPermission('iot:thing-model:query')")
|
||||
public CommonResult<IotThingModelRespVO> getThingModel(@RequestParam("id") Long id) {
|
||||
IotThingModelDO thingModel = thingModelService.getThingModel(id);
|
||||
return success(BeanUtils.toBean(thingModel, IotThingModelRespVO.class));
|
||||
}
|
||||
|
||||
@GetMapping("/list-by-product-id")
|
||||
@Operation(summary = "获得产品物模型")
|
||||
@Parameter(name = "productId", description = "产品ID", required = true, example = "1024")
|
||||
@PreAuthorize("@ss.hasPermission('iot:thing-model:query')")
|
||||
public CommonResult<List<IotThingModelRespVO>> getThingModelListByProductId(@RequestParam("productId") Long productId) {
|
||||
List<IotThingModelDO> list = thingModelService.getThingModelListByProductId(productId);
|
||||
return success(BeanUtils.toBean(list, IotThingModelRespVO.class));
|
||||
}
|
||||
|
||||
// TODO @puhui @super:getThingModelListByProductId 和 getThingModelListByProductId 可以融合么?
|
||||
@GetMapping("/list")
|
||||
@Operation(summary = "获得产品物模型列表")
|
||||
@PreAuthorize("@ss.hasPermission('iot:thing-model:query')")
|
||||
public CommonResult<List<IotThingModelRespVO>> getThingModelListByProductId(@Valid IotThingModelListReqVO reqVO) {
|
||||
List<IotThingModelDO> list = thingModelService.getThingModelList(reqVO);
|
||||
return success(BeanUtils.toBean(list, IotThingModelRespVO.class));
|
||||
}
|
||||
|
||||
@GetMapping("/page")
|
||||
@Operation(summary = "获得产品物模型分页")
|
||||
@PreAuthorize("@ss.hasPermission('iot:thing-model:query')")
|
||||
public CommonResult<PageResult<IotThingModelRespVO>> getThingModelPage(@Valid IotThingModelPageReqVO pageReqVO) {
|
||||
PageResult<IotThingModelDO> pageResult = thingModelService.getProductThingModelPage(pageReqVO);
|
||||
return success(BeanUtils.toBean(pageResult, IotThingModelRespVO.class));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package com.zt.plat.module.iot.controller.admin.thingmodel.model;
|
||||
|
||||
import com.zt.plat.framework.common.validation.InEnum;
|
||||
import com.zt.plat.module.iot.enums.thingmodel.IotThingModelServiceEventTypeEnum;
|
||||
import jakarta.validation.Valid;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import jakarta.validation.constraints.Pattern;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* IoT 物模型中的事件
|
||||
*
|
||||
* @author HUIHUI
|
||||
*/
|
||||
@Data
|
||||
public class ThingModelEvent {
|
||||
|
||||
/**
|
||||
* 事件标识符
|
||||
*/
|
||||
@NotEmpty(message = "事件标识符不能为空")
|
||||
@Pattern(regexp = "^[a-zA-Z][a-zA-Z0-9_]{0,31}$", message = "事件标识符只能由字母、数字和下划线组成,必须以字母开头,长度不超过 32 个字符")
|
||||
private String identifier;
|
||||
/**
|
||||
* 事件名称
|
||||
*/
|
||||
@NotEmpty(message = "事件名称不能为空")
|
||||
private String name;
|
||||
/**
|
||||
* 是否是标准品类的必选事件
|
||||
*/
|
||||
private Boolean required;
|
||||
/**
|
||||
* 事件类型
|
||||
*
|
||||
* 枚举 {@link IotThingModelServiceEventTypeEnum}
|
||||
*/
|
||||
@NotEmpty(message = "事件类型不能为空")
|
||||
@InEnum(IotThingModelServiceEventTypeEnum.class)
|
||||
private String type;
|
||||
/**
|
||||
* 事件的输出参数
|
||||
*
|
||||
* 输出参数定义事件调用后返回的结果或反馈信息,用于确认操作结果或提供额外的信息。
|
||||
*/
|
||||
@Valid
|
||||
private List<ThingModelParam> outputParams;
|
||||
/**
|
||||
* 标识设备需要执行的具体操作
|
||||
*/
|
||||
private String method;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
package com.zt.plat.module.iot.controller.admin.thingmodel.model;
|
||||
|
||||
import com.zt.plat.framework.common.validation.InEnum;
|
||||
import com.zt.plat.module.iot.controller.admin.thingmodel.model.dataType.ThingModelDataSpecs;
|
||||
import com.zt.plat.module.iot.enums.thingmodel.IotDataSpecsDataTypeEnum;
|
||||
import com.zt.plat.module.iot.enums.thingmodel.IotThingModelParamDirectionEnum;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import jakarta.validation.constraints.Pattern;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* IoT 产品物模型中的参数
|
||||
*
|
||||
* @author HUIHUI
|
||||
*/
|
||||
@Data
|
||||
public class ThingModelParam {
|
||||
|
||||
/**
|
||||
* 参数标识符
|
||||
*/
|
||||
@NotEmpty(message = "参数标识符不能为空")
|
||||
@Pattern(regexp = "^[a-zA-Z][a-zA-Z0-9_]{0,31}$", message = "参数标识符只能由字母、数字和下划线组成,必须以字母开头,长度不超过 32 个字符")
|
||||
private String identifier;
|
||||
/**
|
||||
* 参数名称
|
||||
*/
|
||||
@NotEmpty(message = "参数名称不能为空")
|
||||
private String name;
|
||||
/**
|
||||
* 用于区分输入或输出参数
|
||||
*
|
||||
* 枚举 {@link IotThingModelParamDirectionEnum}
|
||||
*/
|
||||
@NotEmpty(message = "参数方向不能为空")
|
||||
@InEnum(IotThingModelParamDirectionEnum.class)
|
||||
private String direction;
|
||||
/**
|
||||
* 参数的序号。从 0 开始排序,且不能重复。
|
||||
*
|
||||
* TODO 考虑要不要序号,感觉是要的, 先留一手看看
|
||||
*/
|
||||
private Integer paraOrder;
|
||||
/**
|
||||
* 参数值的数据类型,与 dataSpecs 的 dataType 保持一致
|
||||
*
|
||||
* 枚举 {@link IotDataSpecsDataTypeEnum}
|
||||
*/
|
||||
@NotEmpty(message = "数据类型不能为空")
|
||||
@InEnum(IotDataSpecsDataTypeEnum.class)
|
||||
private String dataType;
|
||||
/**
|
||||
* 参数值的数据类型(dataType)为非列表型(int、float、double、text、date、array)的数据规范存储在 dataSpecs 中
|
||||
*/
|
||||
private ThingModelDataSpecs dataSpecs;
|
||||
/**
|
||||
* 参数值的数据类型(dataType)为列表型(enum、bool、struct)的数据规范存储在 dataSpecsList 中
|
||||
*/
|
||||
private List<ThingModelDataSpecs> dataSpecsList;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
package com.zt.plat.module.iot.controller.admin.thingmodel.model;
|
||||
|
||||
import com.zt.plat.framework.common.validation.InEnum;
|
||||
import com.zt.plat.module.iot.controller.admin.thingmodel.model.dataType.ThingModelDataSpecs;
|
||||
import com.zt.plat.module.iot.enums.thingmodel.IotDataSpecsDataTypeEnum;
|
||||
import com.zt.plat.module.iot.enums.thingmodel.IotThingModelAccessModeEnum;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import jakarta.validation.constraints.Pattern;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* IoT 物模型中的属性
|
||||
*
|
||||
* dataSpecs 和 dataSpecsList 之中必须传入且只能传入一个
|
||||
*
|
||||
* @author HUIHUI
|
||||
*/
|
||||
@Data
|
||||
public class ThingModelProperty {
|
||||
|
||||
/**
|
||||
* 属性标识符
|
||||
*/
|
||||
@NotEmpty(message = "属性标识符不能为空")
|
||||
@Pattern(regexp = "^[a-zA-Z][a-zA-Z0-9_]{0,31}$", message = "属性标识符只能由字母、数字和下划线组成,必须以字母开头,长度不超过 32 个字符")
|
||||
private String identifier;
|
||||
/**
|
||||
* 属性名称
|
||||
*/
|
||||
@NotEmpty(message = "属性名称不能为空")
|
||||
private String name;
|
||||
/**
|
||||
* 云端可以对该属性进行的操作类型
|
||||
*
|
||||
* 枚举 {@link IotThingModelAccessModeEnum}
|
||||
*/
|
||||
@NotEmpty(message = "操作类型不能为空")
|
||||
@InEnum(IotThingModelAccessModeEnum.class)
|
||||
private String accessMode;
|
||||
/**
|
||||
* 是否是标准品类的必选服务
|
||||
*/
|
||||
private Boolean required;
|
||||
/**
|
||||
* 参数值的数据类型,与 dataSpecs 的 dataType 保持一致
|
||||
*
|
||||
* 枚举 {@link IotDataSpecsDataTypeEnum}
|
||||
*/
|
||||
@NotEmpty(message = "数据类型不能为空")
|
||||
@InEnum(IotDataSpecsDataTypeEnum.class)
|
||||
private String dataType;
|
||||
/**
|
||||
* 数据类型(dataType)为非列表型(int、float、double、text、date、array)的数据规范存储在 dataSpecs 中
|
||||
*/
|
||||
private ThingModelDataSpecs dataSpecs;
|
||||
/**
|
||||
* 数据类型(dataType)为列表型(enum、bool、struct)的数据规范存储在 dataSpecsList 中
|
||||
*/
|
||||
private List<ThingModelDataSpecs> dataSpecsList;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
package com.zt.plat.module.iot.controller.admin.thingmodel.model;
|
||||
|
||||
import com.zt.plat.framework.common.validation.InEnum;
|
||||
import com.zt.plat.module.iot.enums.thingmodel.IotThingModelServiceCallTypeEnum;
|
||||
import jakarta.validation.Valid;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import jakarta.validation.constraints.Pattern;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* IoT 物模型中的服务
|
||||
*
|
||||
* @author HUIHUI
|
||||
*/
|
||||
@Data
|
||||
public class ThingModelService {
|
||||
|
||||
/**
|
||||
* 服务标识符
|
||||
*/
|
||||
@NotEmpty(message = "服务标识符不能为空")
|
||||
@Pattern(regexp = "^[a-zA-Z][a-zA-Z0-9_]{0,31}$", message = "服务标识符只能由字母、数字和下划线组成,必须以字母开头,长度不超过 32 个字符")
|
||||
private String identifier;
|
||||
/**
|
||||
* 服务名称
|
||||
*/
|
||||
@NotEmpty(message = "服务名称不能为空")
|
||||
private String name;
|
||||
/**
|
||||
* 是否是标准品类的必选服务
|
||||
*/
|
||||
private Boolean required;
|
||||
/**
|
||||
* 调用类型
|
||||
*
|
||||
* 枚举 {@link IotThingModelServiceCallTypeEnum}
|
||||
*/
|
||||
@NotEmpty(message = "调用类型不能为空")
|
||||
@InEnum(IotThingModelServiceCallTypeEnum.class)
|
||||
private String callType;
|
||||
/**
|
||||
* 服务的输入参数
|
||||
*
|
||||
* 输入参数定义服务调用时所需提供的信息,用于控制设备行为或执行特定任务
|
||||
*/
|
||||
@Valid
|
||||
private List<ThingModelParam> inputParams;
|
||||
/**
|
||||
* 服务的输出参数
|
||||
*
|
||||
* 输出参数定义服务调用后返回的结果或反馈信息,用于确认操作结果或提供额外的信息。
|
||||
*/
|
||||
@Valid
|
||||
private List<ThingModelParam> outputParams;
|
||||
/**
|
||||
* 标识设备需要执行的具体操作
|
||||
*/
|
||||
private String method;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.zt.plat.module.iot.controller.admin.thingmodel.model.dataType;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* IoT 物模型数据类型为数组的 DataSpec 定义
|
||||
*
|
||||
* @author HUIHUI
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@JsonIgnoreProperties({"dataType"}) // 忽略子类中的 dataType 字段,从而避免重复
|
||||
public class ThingModelArrayDataSpecs extends ThingModelDataSpecs {
|
||||
|
||||
/**
|
||||
* 数组中的元素个数
|
||||
*/
|
||||
private Integer size;
|
||||
/**
|
||||
* 数组中的元素的数据类型。可选值:struct、int、float、double 或 text
|
||||
*/
|
||||
private String childDataType;
|
||||
/**
|
||||
* 数据类型(childDataType)为列表型 struct 的数据规范存储在 dataSpecsList 中
|
||||
* 此时 struct 取值范围为:int、float、double、text、date、enum、bool
|
||||
*/
|
||||
private List<ThingModelDataSpecs> dataSpecsList;
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.zt.plat.module.iot.controller.admin.thingmodel.model.dataType;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
/**
|
||||
* IoT 物模型数据类型为布尔型或枚举型的 DataSpec 定义
|
||||
*
|
||||
* 数据类型,取值为 bool 或 enum。
|
||||
*
|
||||
* @author HUIHUI
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@JsonIgnoreProperties({"dataType"}) // 忽略子类中的 dataType 字段,从而避免重复
|
||||
public class ThingModelBoolOrEnumDataSpecs extends ThingModelDataSpecs {
|
||||
|
||||
// TODO @puhui999:要不写下参数校验?这样,注释可以简洁一点
|
||||
/**
|
||||
* 枚举项的名称。
|
||||
* 可包含中文、大小写英文字母、数字、下划线(_)和短划线(-)
|
||||
* 必须以中文、英文字母或数字开头,长度不超过 20 个字符
|
||||
*/
|
||||
private String name;
|
||||
/**
|
||||
* 枚举值。
|
||||
*/
|
||||
private Integer value;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.zt.plat.module.iot.controller.admin.thingmodel.model.dataType;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonSubTypes;
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* IoT ThingModelDataSpecs 抽象类
|
||||
*
|
||||
* 用于表示物模型数据的通用类型,根据具体的 "dataType" 字段动态映射到对应的子类。
|
||||
* 提供多态支持,适用于不同类型的数据结构序列化和反序列化场景。
|
||||
*
|
||||
* @author HUIHUI
|
||||
*/
|
||||
@Data
|
||||
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "dataType", visible = true)
|
||||
@JsonSubTypes({
|
||||
@JsonSubTypes.Type(value = ThingModelNumericDataSpec.class, name = "int"),
|
||||
@JsonSubTypes.Type(value = ThingModelNumericDataSpec.class, name = "float"),
|
||||
@JsonSubTypes.Type(value = ThingModelNumericDataSpec.class, name = "double"),
|
||||
@JsonSubTypes.Type(value = ThingModelDateOrTextDataSpecs.class, name = "text"),
|
||||
@JsonSubTypes.Type(value = ThingModelDateOrTextDataSpecs.class, name = "date"),
|
||||
@JsonSubTypes.Type(value = ThingModelBoolOrEnumDataSpecs.class, name = "bool"),
|
||||
@JsonSubTypes.Type(value = ThingModelBoolOrEnumDataSpecs.class, name = "enum"),
|
||||
@JsonSubTypes.Type(value = ThingModelArrayDataSpecs.class, name = "array"),
|
||||
@JsonSubTypes.Type(value = ThingModelStructDataSpecs.class, name = "struct")
|
||||
})
|
||||
public abstract class ThingModelDataSpecs {
|
||||
|
||||
/**
|
||||
* 数据类型
|
||||
*/
|
||||
private String dataType;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.zt.plat.module.iot.controller.admin.thingmodel.model.dataType;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
/**
|
||||
* IoT 物模型数据类型为时间型或文本型的 DataSpec 定义
|
||||
*
|
||||
* 数据类型,取值为 date 或 text。
|
||||
*
|
||||
* @author HUIHUI
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@JsonIgnoreProperties({"dataType"}) // 忽略子类中的 dataType 字段,从而避免重复
|
||||
public class ThingModelDateOrTextDataSpecs extends ThingModelDataSpecs {
|
||||
|
||||
/**
|
||||
* 数据长度,单位为字节。取值不能超过 2048。
|
||||
* 当 dataType 为 text 时,需传入该参数。
|
||||
*/
|
||||
private Integer length;
|
||||
/**
|
||||
* 默认值,可选参数,用于存储默认值。
|
||||
*/
|
||||
private String defaultValue;
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
package com.zt.plat.module.iot.controller.admin.thingmodel.model.dataType;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
/**
|
||||
* IoT 物模型数据类型为数值的 DataSpec 定义
|
||||
*
|
||||
* 数据类型,取值为 int、float 或 double。
|
||||
*
|
||||
* @author HUIHUI
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@JsonIgnoreProperties({"dataType"}) // 忽略子类中的 dataType 字段,从而避免重复
|
||||
public class ThingModelNumericDataSpec extends ThingModelDataSpecs {
|
||||
|
||||
/**
|
||||
* 最大值,需转为字符串类型。值必须与 dataType 类型一致。
|
||||
* 例如,当 dataType 为 int 时,取值为 "200",而不是 200。
|
||||
*/
|
||||
private String max;
|
||||
/**
|
||||
* 最小值,需转为字符串类型。值必须与 dataType 类型一致。
|
||||
* 例如,当 dataType 为 int 时,取值为 "0",而不是 0。
|
||||
*/
|
||||
private String min;
|
||||
/**
|
||||
* 步长,需转为字符串类型。值必须与 dataType 类型一致。
|
||||
* 例如,当 dataType 为 int 时,取值为 "10",而不是 10。
|
||||
*/
|
||||
private String step;
|
||||
/**
|
||||
* 精度。当 dataType 为 float 或 double 时可选传入。
|
||||
*/
|
||||
private String precise;
|
||||
/**
|
||||
* 默认值,可传入用于存储的默认值。
|
||||
*/
|
||||
private String defaultValue;
|
||||
/**
|
||||
* 单位的符号。
|
||||
*/
|
||||
private String unit;
|
||||
/**
|
||||
* 单位的名称。
|
||||
*/
|
||||
private String unitName;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package com.zt.plat.module.iot.controller.admin.thingmodel.model.dataType;
|
||||
|
||||
import com.zt.plat.module.iot.enums.thingmodel.IotThingModelAccessModeEnum;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* IoT 物模型数据类型为 struct 的 DataSpec 定义
|
||||
*
|
||||
* @author HUIHUI
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@JsonIgnoreProperties({"dataType"}) // 忽略子类中的 dataType 字段,从而避免重复
|
||||
public class ThingModelStructDataSpecs extends ThingModelDataSpecs {
|
||||
|
||||
/**
|
||||
* 属性标识符
|
||||
*/
|
||||
private String identifier;
|
||||
/**
|
||||
* 属性名称
|
||||
*/
|
||||
private String name;
|
||||
/**
|
||||
* 云端可以对该属性进行的操作类型
|
||||
*
|
||||
* 枚举 {@link IotThingModelAccessModeEnum}
|
||||
*/
|
||||
private String accessMode;
|
||||
/**
|
||||
* 是否是标准品类的必选服务
|
||||
*/
|
||||
private Boolean required;
|
||||
/**
|
||||
* struct 数据的数据类型
|
||||
*/
|
||||
private String childDataType;
|
||||
/**
|
||||
* 数据类型(dataType)为非列表型(int、float、double、text、date、array)的数据规范存储在 dataSpecs 中
|
||||
*/
|
||||
private ThingModelDataSpecs dataSpecs;
|
||||
/**
|
||||
* 数据类型(dataType)为列表型(enum、bool、struct)的数据规范存储在 dataSpecsList 中
|
||||
*/
|
||||
private List<ThingModelDataSpecs> dataSpecsList;
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.zt.plat.module.iot.controller.admin.thingmodel.vo;
|
||||
|
||||
import com.zt.plat.framework.common.validation.InEnum;
|
||||
import com.zt.plat.module.iot.enums.thingmodel.IotThingModelTypeEnum;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
|
||||
@Schema(description = "管理后台 - IoT 产品物模型 List Request VO")
|
||||
@Data
|
||||
public class IotThingModelListReqVO {
|
||||
|
||||
@Schema(description = "产品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
@NotNull(message = "产品编号不能为空")
|
||||
private Long productId;
|
||||
|
||||
@Schema(description = "功能标识", example = "temperature")
|
||||
private String identifier;
|
||||
|
||||
@Schema(description = "功能名称", example = "温度")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "功能类型", example = "1")
|
||||
@InEnum(IotThingModelTypeEnum.class)
|
||||
private Integer type;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.zt.plat.module.iot.controller.admin.thingmodel.vo;
|
||||
|
||||
import com.zt.plat.framework.common.pojo.PageParam;
|
||||
import com.zt.plat.framework.common.validation.InEnum;
|
||||
import com.zt.plat.module.iot.enums.thingmodel.IotThingModelTypeEnum;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
|
||||
@Schema(description = "管理后台 - IoT 产品物模型分页 Request VO")
|
||||
@Data
|
||||
public class IotThingModelPageReqVO extends PageParam {
|
||||
|
||||
@Schema(description = "产品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
@NotNull(message = "产品编号不能为空")
|
||||
private Long productId;
|
||||
|
||||
@Schema(description = "功能标识", example = "temperature")
|
||||
private String identifier;
|
||||
|
||||
@Schema(description = "功能名称", example = "温度")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "功能类型", example = "1")
|
||||
@InEnum(IotThingModelTypeEnum.class)
|
||||
private Integer type;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package com.zt.plat.module.iot.controller.admin.thingmodel.vo;
|
||||
|
||||
import com.zt.plat.module.iot.controller.admin.thingmodel.model.ThingModelEvent;
|
||||
import com.zt.plat.module.iot.controller.admin.thingmodel.model.ThingModelProperty;
|
||||
import com.zt.plat.module.iot.controller.admin.thingmodel.model.ThingModelService;
|
||||
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Schema(description = "管理后台 - IoT 产品物模型 Response VO")
|
||||
@Data
|
||||
@ExcelIgnoreUnannotated
|
||||
public class IotThingModelRespVO {
|
||||
|
||||
@Schema(description = "产品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "21816")
|
||||
@ExcelProperty("产品ID")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "产品标识", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
private Long productId;
|
||||
|
||||
@Schema(description = "产品标识", requiredMode = Schema.RequiredMode.REQUIRED, example = "temperature_sensor")
|
||||
@ExcelProperty("产品标识")
|
||||
private String productKey;
|
||||
|
||||
@Schema(description = "功能标识", requiredMode = Schema.RequiredMode.REQUIRED, example = "temperature")
|
||||
private String identifier;
|
||||
|
||||
@Schema(description = "功能名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "温度")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "功能描述", requiredMode = Schema.RequiredMode.REQUIRED, example = "测量当前环境温度")
|
||||
private String description;
|
||||
|
||||
@Schema(description = "功能类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
private Integer type;
|
||||
|
||||
@Schema(description = "属性", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private ThingModelProperty property;
|
||||
|
||||
@Schema(description = "服务", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private ThingModelEvent event;
|
||||
|
||||
@Schema(description = "事件", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private ThingModelService service;
|
||||
|
||||
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@ExcelProperty("创建时间")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package com.zt.plat.module.iot.controller.admin.thingmodel.vo;
|
||||
|
||||
import com.zt.plat.framework.common.validation.InEnum;
|
||||
import com.zt.plat.module.iot.controller.admin.thingmodel.model.ThingModelEvent;
|
||||
import com.zt.plat.module.iot.controller.admin.thingmodel.model.ThingModelProperty;
|
||||
import com.zt.plat.module.iot.controller.admin.thingmodel.model.ThingModelService;
|
||||
import com.zt.plat.module.iot.enums.thingmodel.IotThingModelTypeEnum;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.Valid;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
|
||||
@Schema(description = "管理后台 - IoT 产品物模型新增/修改 Request VO")
|
||||
@Data
|
||||
public class IotThingModelSaveReqVO {
|
||||
|
||||
@Schema(description = "编号", example = "1")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "产品ID", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotNull(message = "产品ID不能为空")
|
||||
private Long productId;
|
||||
|
||||
@Schema(description = "产品标识", requiredMode = Schema.RequiredMode.REQUIRED, example = "temperature_001")
|
||||
@NotEmpty(message = "产品标识不能为空")
|
||||
private String productKey;
|
||||
|
||||
@Schema(description = "功能标识", requiredMode = Schema.RequiredMode.REQUIRED, example = "temp_monitor")
|
||||
@NotEmpty(message = "功能标识不能为空")
|
||||
private String identifier;
|
||||
|
||||
@Schema(description = "功能名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "温度监测器")
|
||||
@NotEmpty(message = "功能名称不能为空")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "功能描述", requiredMode = Schema.RequiredMode.REQUIRED, example = "用于监测环境温度的传感器")
|
||||
private String description;
|
||||
|
||||
@Schema(description = "功能类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
@NotNull(message = "功能类型不能为空")
|
||||
@InEnum(IotThingModelTypeEnum.class)
|
||||
private Integer type;
|
||||
|
||||
@Schema(description = "属性", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@Valid
|
||||
private ThingModelProperty property;
|
||||
|
||||
@Schema(description = "服务", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@Valid
|
||||
private ThingModelService service;
|
||||
|
||||
@Schema(description = "事件", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@Valid
|
||||
private ThingModelEvent event;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
### 请求 /iot/think-model-function/create 接口 => 成功
|
||||
POST {{baseUrl}}/iot/think-model-function/create
|
||||
Content-Type: application/json
|
||||
tenant-id: {{adminTenantId}}
|
||||
Authorization: Bearer {{token}}
|
||||
|
||||
{
|
||||
"productId": 1001,
|
||||
"productKey": "smart-sensor-001",
|
||||
"identifier": "Temperature",
|
||||
"name": "温度",
|
||||
"description": "当前温度值",
|
||||
"type": 1,
|
||||
"property": {
|
||||
"identifier": "Temperature",
|
||||
"name": "温度",
|
||||
"accessMode": "r",
|
||||
"required": true,
|
||||
"dataType": {
|
||||
"type": "float",
|
||||
"specs": {
|
||||
"min": -10.0,
|
||||
"max": 100.0,
|
||||
"step": 0.1,
|
||||
"unit": "℃"
|
||||
}
|
||||
},
|
||||
"description": "当前温度值"
|
||||
}
|
||||
}
|
||||
|
||||
### 请求 /iot/think-model-function/create 接口 => 成功
|
||||
POST {{baseUrl}}/iot/think-model-function/create
|
||||
Content-Type: application/json
|
||||
tenant-id: {{adminTenantId}}
|
||||
Authorization: Bearer {{token}}
|
||||
|
||||
{
|
||||
"productId": 1001,
|
||||
"productKey": "smart-sensor-001",
|
||||
"identifier": "Humidity",
|
||||
"name": "湿度",
|
||||
"description": "当前湿度值",
|
||||
"type": 1,
|
||||
"property": {
|
||||
"identifier": "Humidity",
|
||||
"name": "湿度",
|
||||
"accessMode": "r",
|
||||
"required": true,
|
||||
"dataType": {
|
||||
"type": "float",
|
||||
"specs": {
|
||||
"min": 0.0,
|
||||
"max": 100.0,
|
||||
"step": 0.1,
|
||||
"unit": "%"
|
||||
}
|
||||
},
|
||||
"description": "当前湿度值"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
### 请求 /iot/think-model-function/update 接口 => 成功
|
||||
PUT {{baseUrl}}/iot/think-model-function/update
|
||||
Content-Type: application/json
|
||||
tenant-id: {{adminTenantId}}
|
||||
Authorization: Bearer {{token}}
|
||||
|
||||
{
|
||||
"id": 11,
|
||||
"productId": 1001,
|
||||
"productKey": "smart-sensor-001",
|
||||
"identifier": "Temperature",
|
||||
"name": "温度",
|
||||
"description": "当前温度值",
|
||||
"type": 1,
|
||||
"property": {
|
||||
"identifier": "Temperature",
|
||||
"name": "温度",
|
||||
"accessMode": "r",
|
||||
"required": true,
|
||||
"dataType": {
|
||||
"type": "float",
|
||||
"specs": {
|
||||
"min": -111.0,
|
||||
"max": 222.0,
|
||||
"step": 0.1,
|
||||
"unit": "℃"
|
||||
}
|
||||
},
|
||||
"description": "当前温度值"
|
||||
}
|
||||
}
|
||||
|
||||
### 请求 /iot/think-model-function/delete 接口 => 成功
|
||||
DELETE {{baseUrl}}/iot/think-model-function/delete?id=7
|
||||
tenant-id: {{adminTenantId}}
|
||||
Authorization: Bearer {{token}}
|
||||
|
||||
### 请求 /iot/think-model-function/get 接口 => 成功
|
||||
GET {{baseUrl}}/iot/think-model-function/get?id=10
|
||||
tenant-id: {{adminTenantId}}
|
||||
Authorization: Bearer {{token}}
|
||||
|
||||
|
||||
### 请求 /iot/think-model-function/list-by-product-id 接口 => 成功
|
||||
GET {{baseUrl}}/iot/think-model-function/list-by-product-id?productId=1001
|
||||
tenant-id: {{adminTenantId}}
|
||||
Authorization: Bearer {{token}}
|
||||
@@ -0,0 +1,6 @@
|
||||
/**
|
||||
* 提供 RESTful API 给前端:
|
||||
* 1. admin 包:提供给管理后台 cloud-ui-admin 前端项目
|
||||
* 2. app 包:提供给用户 APP cloud-ui-app 前端项目,它的 Controller 和 VO 都要添加 App 前缀,用于和管理后台进行区分
|
||||
*/
|
||||
package com.zt.plat.module.iot.controller;
|
||||
@@ -0,0 +1,6 @@
|
||||
/**
|
||||
* 提供 POJO 类的实体转换
|
||||
*
|
||||
* 目前使用 MapStruct 框架
|
||||
*/
|
||||
package com.zt.plat.module.iot.convert;
|
||||
@@ -0,0 +1,50 @@
|
||||
package com.zt.plat.module.iot.convert.thingmodel;
|
||||
|
||||
import com.zt.plat.module.iot.controller.admin.thingmodel.model.ThingModelEvent;
|
||||
import com.zt.plat.module.iot.controller.admin.thingmodel.model.ThingModelProperty;
|
||||
import com.zt.plat.module.iot.controller.admin.thingmodel.model.ThingModelService;
|
||||
import com.zt.plat.module.iot.controller.admin.thingmodel.vo.IotThingModelSaveReqVO;
|
||||
import com.zt.plat.module.iot.dal.dataobject.thingmodel.IotThingModelDO;
|
||||
import com.zt.plat.module.iot.enums.thingmodel.IotThingModelTypeEnum;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.Mapping;
|
||||
import org.mapstruct.Named;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
@Mapper
|
||||
public interface IotThingModelConvert {
|
||||
|
||||
IotThingModelConvert INSTANCE = Mappers.getMapper(IotThingModelConvert.class);
|
||||
|
||||
@Mapping(target = "property", expression = "java(convertToProperty(bean))")
|
||||
@Mapping(target = "event", expression = "java(convertToEvent(bean))")
|
||||
@Mapping(target = "service", expression = "java(convertToService(bean))")
|
||||
IotThingModelDO convert(IotThingModelSaveReqVO bean);
|
||||
|
||||
@Named("convertToProperty")
|
||||
default ThingModelProperty convertToProperty(IotThingModelSaveReqVO bean) {
|
||||
if (Objects.equals(bean.getType(), IotThingModelTypeEnum.PROPERTY.getType())) {
|
||||
return bean.getProperty();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Named("convertToEvent")
|
||||
default ThingModelEvent convertToEvent(IotThingModelSaveReqVO bean) {
|
||||
if (Objects.equals(bean.getType(), IotThingModelTypeEnum.EVENT.getType())) {
|
||||
return bean.getEvent();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Named("convertToService")
|
||||
default ThingModelService convertToService(IotThingModelSaveReqVO bean) {
|
||||
if (Objects.equals(bean.getType(), IotThingModelTypeEnum.SERVICE.getType())) {
|
||||
return bean.getService();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,173 @@
|
||||
package com.zt.plat.module.iot.dal.dataobject.device;
|
||||
|
||||
import com.zt.plat.framework.mybatis.core.type.LongSetTypeHandler;
|
||||
import com.zt.plat.framework.tenant.core.db.TenantBaseDO;
|
||||
import com.zt.plat.module.iot.dal.dataobject.ota.IotOtaFirmwareDO;
|
||||
import com.zt.plat.module.iot.dal.dataobject.product.IotProductDO;
|
||||
import com.zt.plat.module.iot.enums.device.IotDeviceStateEnum;
|
||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.*;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* IoT 设备 DO
|
||||
*
|
||||
* @author haohao
|
||||
*/
|
||||
@TableName(value = "iot_device", autoResultMap = true)
|
||||
@KeySequence("iot_device_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class IotDeviceDO extends TenantBaseDO {
|
||||
|
||||
/**
|
||||
* 设备 ID,主键,自增
|
||||
*/
|
||||
@TableId
|
||||
private Long id;
|
||||
/**
|
||||
* 设备唯一标识符,全局唯一,用于识别设备
|
||||
*
|
||||
* 类似阿里云 <a href="https://help.aliyun.com/zh/iot/developer-reference/api-querydeviceinfo">QueryDeviceInfo</a> 的 IotInstanceId
|
||||
*/
|
||||
private String deviceKey;
|
||||
/**
|
||||
* 设备名称,在产品内唯一,用于标识设备
|
||||
*/
|
||||
private String deviceName;
|
||||
/**
|
||||
* 设备备注名称
|
||||
*/
|
||||
private String nickname;
|
||||
/**
|
||||
* 设备序列号
|
||||
*/
|
||||
private String serialNumber;
|
||||
/**
|
||||
* 设备图片
|
||||
*/
|
||||
private String picUrl;
|
||||
/**
|
||||
* 设备分组编号集合
|
||||
*
|
||||
* 关联 {@link IotDeviceGroupDO#getId()}
|
||||
*/
|
||||
@TableField(typeHandler = LongSetTypeHandler.class)
|
||||
private Set<Long> groupIds;
|
||||
|
||||
/**
|
||||
* 产品编号
|
||||
* <p>
|
||||
* 关联 {@link IotProductDO#getId()}
|
||||
*/
|
||||
private Long productId;
|
||||
/**
|
||||
* 产品标识
|
||||
* <p>
|
||||
* 冗余 {@link IotProductDO#getProductKey()}
|
||||
*/
|
||||
private String productKey;
|
||||
/**
|
||||
* 设备类型
|
||||
* <p>
|
||||
* 冗余 {@link IotProductDO#getDeviceType()}
|
||||
*/
|
||||
private Integer deviceType;
|
||||
/**
|
||||
* 网关设备编号
|
||||
* <p>
|
||||
* 子设备需要关联的网关设备 ID
|
||||
* <p>
|
||||
* 关联 {@link IotDeviceDO#getId()}
|
||||
*/
|
||||
private Long gatewayId;
|
||||
|
||||
/**
|
||||
* 设备状态
|
||||
* <p>
|
||||
* 枚举 {@link IotDeviceStateEnum}
|
||||
*/
|
||||
private Integer state;
|
||||
/**
|
||||
* 最后上线时间
|
||||
*/
|
||||
private LocalDateTime onlineTime;
|
||||
/**
|
||||
* 最后离线时间
|
||||
*/
|
||||
private LocalDateTime offlineTime;
|
||||
/**
|
||||
* 设备激活时间
|
||||
*/
|
||||
private LocalDateTime activeTime;
|
||||
|
||||
/**
|
||||
* 设备的 IP 地址
|
||||
*/
|
||||
private String ip;
|
||||
/**
|
||||
* 固件编号
|
||||
*
|
||||
* 关联 {@link IotOtaFirmwareDO#getId()}
|
||||
*/
|
||||
private String firmwareId;
|
||||
|
||||
// TODO @芋艿:【待定 003】:要不要增加 username?目前 tl 有,阿里云之类的没有
|
||||
/**
|
||||
* 设备密钥,用于设备认证,需安全存储
|
||||
*/
|
||||
private String deviceSecret;
|
||||
/**
|
||||
* MQTT 客户端 ID
|
||||
*/
|
||||
private String mqttClientId;
|
||||
/**
|
||||
* MQTT 用户名
|
||||
*/
|
||||
private String mqttUsername;
|
||||
/**
|
||||
* MQTT 密码
|
||||
*/
|
||||
private String mqttPassword;
|
||||
/**
|
||||
* 认证类型(如一机一密、动态注册)
|
||||
*/
|
||||
// TODO @haohao:是不是要枚举哈
|
||||
private String authType;
|
||||
|
||||
// TODO @芋艿:【待定 002】:1)设备维护的时候,设置位置?类似 tl?;2)设备上传的时候,设置位置,类似 it?
|
||||
/**
|
||||
* 设备位置的纬度
|
||||
*/
|
||||
private BigDecimal latitude;
|
||||
/**
|
||||
* 设备位置的经度
|
||||
*/
|
||||
private BigDecimal longitude;
|
||||
/**
|
||||
* 地区编码
|
||||
* <p>
|
||||
* 关联 Area 的 id
|
||||
*/
|
||||
private Integer areaId;
|
||||
/**
|
||||
* 设备详细地址
|
||||
*/
|
||||
private String address;
|
||||
|
||||
/**
|
||||
* 设备配置
|
||||
*
|
||||
* JSON 格式,可下发给 device 进行自定义配置
|
||||
*/
|
||||
private String config;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package com.zt.plat.module.iot.dal.dataobject.device;
|
||||
|
||||
import com.zt.plat.framework.mybatis.core.dataobject.BaseDO;
|
||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.*;
|
||||
|
||||
/**
|
||||
* IoT 设备分组 DO
|
||||
*
|
||||
* @author ZT
|
||||
*/
|
||||
@TableName("iot_device_group")
|
||||
@KeySequence("iot_device_group_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class IotDeviceGroupDO extends BaseDO {
|
||||
|
||||
/**
|
||||
* 分组 ID
|
||||
*/
|
||||
@TableId
|
||||
private Long id;
|
||||
/**
|
||||
* 分组名字
|
||||
*/
|
||||
private String name;
|
||||
/**
|
||||
* 分组状态
|
||||
*
|
||||
* 枚举 {@link com.zt.plat.framework.common.enums.CommonStatusEnum}
|
||||
*/
|
||||
private Integer status;
|
||||
/**
|
||||
* 分组描述
|
||||
*/
|
||||
private String description;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
package com.zt.plat.module.iot.dal.dataobject.device;
|
||||
|
||||
import cn.hutool.core.util.IdUtil;
|
||||
import com.zt.plat.module.iot.dal.dataobject.product.IotProductDO;
|
||||
import com.zt.plat.module.iot.enums.device.IotDeviceMessageIdentifierEnum;
|
||||
import com.zt.plat.module.iot.enums.device.IotDeviceMessageTypeEnum;
|
||||
import com.zt.plat.module.iot.mq.message.IotDeviceMessage;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* IoT 设备日志数据 DO
|
||||
*
|
||||
* 目前使用 TDengine 存储
|
||||
*
|
||||
* @author alwayssuper
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class IotDeviceLogDO {
|
||||
|
||||
/**
|
||||
* 日志编号
|
||||
*
|
||||
* 通过 {@link IdUtil#fastSimpleUUID()} 生成
|
||||
*/
|
||||
private String id;
|
||||
|
||||
/**
|
||||
* 请求编号
|
||||
*
|
||||
* 对应 {@link IotDeviceMessage#getRequestId()} 字段
|
||||
*/
|
||||
private String requestId;
|
||||
|
||||
/**
|
||||
* 产品标识
|
||||
* <p>
|
||||
* 关联 {@link IotProductDO#getProductKey()}
|
||||
*/
|
||||
private String productKey;
|
||||
/**
|
||||
* 设备名称
|
||||
*
|
||||
* 关联 {@link IotDeviceDO#getDeviceName()}
|
||||
*/
|
||||
private String deviceName;
|
||||
/**
|
||||
* 设备标识
|
||||
* <p>
|
||||
* 关联 {@link IotDeviceDO#getDeviceKey()}}
|
||||
*/
|
||||
private String deviceKey; // 非存储字段,用于 TDengine 的 TAG
|
||||
|
||||
/**
|
||||
* 日志类型
|
||||
*
|
||||
* 枚举 {@link IotDeviceMessageTypeEnum}
|
||||
*/
|
||||
private String type;
|
||||
/**
|
||||
* 标识符
|
||||
*
|
||||
* 枚举 {@link IotDeviceMessageIdentifierEnum}
|
||||
*/
|
||||
private String identifier;
|
||||
|
||||
/**
|
||||
* 数据内容
|
||||
*
|
||||
* 存储具体的消息数据内容,通常是 JSON 格式
|
||||
*/
|
||||
private String content;
|
||||
/**
|
||||
* 响应码
|
||||
*
|
||||
* 目前只有 server 下行消息给 device 设备时,才会有响应码
|
||||
*/
|
||||
private Integer code;
|
||||
|
||||
/**
|
||||
* 上报时间戳
|
||||
*/
|
||||
private Long reportTime;
|
||||
|
||||
/**
|
||||
* 时序时间
|
||||
*/
|
||||
private Long ts;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.zt.plat.module.iot.dal.dataobject.device;
|
||||
|
||||
import com.zt.plat.module.iot.dal.redis.device.DevicePropertyRedisDAO;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* IoT 设备属性项 Redis DO
|
||||
*
|
||||
* @see com.zt.plat.module.iot.dal.redis.RedisKeyConstants#DEVICE_PROPERTY
|
||||
* @see DevicePropertyRedisDAO
|
||||
*
|
||||
* @author haohao
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class IotDevicePropertyDO {
|
||||
|
||||
/**
|
||||
* 属性值(最新)
|
||||
*/
|
||||
private Object value;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
package com.zt.plat.module.iot.dal.dataobject.ota;
|
||||
|
||||
import com.zt.plat.framework.mybatis.core.dataobject.BaseDO;
|
||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.*;
|
||||
|
||||
/**
|
||||
* IoT OTA 固件 DO
|
||||
*
|
||||
* @see <a href="阿里云 IoT - OTA 升级">https://help.aliyun.com/zh/iot/user-guide/ota-upgrade-overview</a>
|
||||
*
|
||||
* @author ZT
|
||||
*/
|
||||
@TableName(value = "iot_ota_firmware", autoResultMap = true)
|
||||
@KeySequence("iot_ota_firmware_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class IotOtaFirmwareDO extends BaseDO {
|
||||
|
||||
/**
|
||||
* 固件编号
|
||||
*/
|
||||
@TableField
|
||||
private Long id;
|
||||
/**
|
||||
* 固件名称
|
||||
*/
|
||||
private String name;
|
||||
/**
|
||||
* 固件版本
|
||||
*/
|
||||
private String description;
|
||||
/**
|
||||
* 版本号
|
||||
*/
|
||||
private String version;
|
||||
|
||||
/**
|
||||
* 产品编号
|
||||
*
|
||||
* 关联 {@link com.zt.plat.module.iot.dal.dataobject.product.IotProductDO#getId()}
|
||||
*/
|
||||
// TODO @li:帮我改成 Long 哈,写错了
|
||||
private String productId;
|
||||
/**
|
||||
* 产品标识
|
||||
*
|
||||
* 冗余 {@link com.zt.plat.module.iot.dal.dataobject.product.IotProductDO#getProductKey()}
|
||||
*/
|
||||
private String productKey;
|
||||
|
||||
/**
|
||||
* 签名方式
|
||||
*
|
||||
* 例如说:MD5、SHA256
|
||||
*/
|
||||
private String signMethod;
|
||||
/**
|
||||
* 固件文件签名
|
||||
*/
|
||||
private String fileSign;
|
||||
/**
|
||||
* 固件文件大小
|
||||
*/
|
||||
private Long fileSize;
|
||||
/**
|
||||
* 固件文件 URL
|
||||
*/
|
||||
private String fileUrl;
|
||||
|
||||
/**
|
||||
* 自定义信息,建议使用 JSON 格式
|
||||
*/
|
||||
private String information;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
package com.zt.plat.module.iot.dal.dataobject.ota;
|
||||
|
||||
import com.zt.plat.framework.mybatis.core.dataobject.BaseDO;
|
||||
import com.zt.plat.module.iot.dal.dataobject.device.IotDeviceDO;
|
||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.*;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* IoT OTA 升级记录 DO
|
||||
*
|
||||
* @author ZT
|
||||
*/
|
||||
@TableName(value = "iot_ota_upgrade_record", autoResultMap = true)
|
||||
@KeySequence("iot_ota_upgrade_record_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class IotOtaUpgradeRecordDO extends BaseDO {
|
||||
|
||||
@TableId
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 固件编号
|
||||
*
|
||||
* 关联 {@link IotOtaFirmwareDO#getId()}
|
||||
*/
|
||||
private Long firmwareId;
|
||||
/**
|
||||
* 任务编号
|
||||
*
|
||||
* 关联 {@link IotOtaUpgradeTaskDO#getId()}
|
||||
*/
|
||||
private Long taskId;
|
||||
|
||||
/**
|
||||
* 产品标识
|
||||
*
|
||||
* 关联 {@link com.zt.plat.module.iot.dal.dataobject.product.IotProductDO#getId()}
|
||||
*/
|
||||
private String productKey;
|
||||
/**
|
||||
* 设备名称
|
||||
*
|
||||
* 关联 {@link com.zt.plat.module.iot.dal.dataobject.device.IotDeviceDO#getId()}
|
||||
*/
|
||||
private String deviceName;
|
||||
/**
|
||||
* 设备编号
|
||||
*
|
||||
* 关联 {@link com.zt.plat.module.iot.dal.dataobject.device.IotDeviceDO#getId()}
|
||||
*/
|
||||
private String deviceId;
|
||||
/**
|
||||
* 来源的固件编号
|
||||
*
|
||||
* 关联 {@link IotDeviceDO#getFirmwareId()}
|
||||
*/
|
||||
private Long fromFirmwareId;
|
||||
|
||||
/**
|
||||
* 升级状态
|
||||
*
|
||||
* 关联 {@link com.zt.plat.module.iot.enums.ota.IotOtaUpgradeRecordStatusEnum}
|
||||
*/
|
||||
private Integer status;
|
||||
/**
|
||||
* 升级进度,百分比
|
||||
*/
|
||||
private Integer progress;
|
||||
/**
|
||||
* 升级进度描述
|
||||
*
|
||||
* 注意,只记录设备最后一次的升级进度描述
|
||||
* 如果想看历史记录,可以查看 {@link com.zt.plat.module.iot.dal.dataobject.device.IotDeviceLogDO} 设备日志
|
||||
*/
|
||||
private String description;
|
||||
/**
|
||||
* 升级开始时间
|
||||
*/
|
||||
private LocalDateTime startTime;
|
||||
/**
|
||||
* 升级结束时间
|
||||
*/
|
||||
private LocalDateTime endTime;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
package com.zt.plat.module.iot.dal.dataobject.ota;
|
||||
|
||||
import com.zt.plat.framework.mybatis.core.dataobject.BaseDO;
|
||||
import com.zt.plat.module.iot.dal.dataobject.device.IotDeviceDO;
|
||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
|
||||
import lombok.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* IoT OTA 升级任务 DO
|
||||
*
|
||||
* @author ZT
|
||||
*/
|
||||
@TableName(value = "iot_ota_upgrade_task", autoResultMap = true)
|
||||
@KeySequence("iot_ota_upgrade_task_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class IotOtaUpgradeTaskDO extends BaseDO {
|
||||
|
||||
/**
|
||||
* 任务编号
|
||||
*/
|
||||
@TableField
|
||||
private Long id;
|
||||
/**
|
||||
* 任务名称
|
||||
*/
|
||||
private String name;
|
||||
/**
|
||||
* 任务描述
|
||||
*/
|
||||
private String description;
|
||||
|
||||
/**
|
||||
* 固件编号
|
||||
* <p>
|
||||
* 关联 {@link IotOtaFirmwareDO#getId()}
|
||||
*/
|
||||
private Long firmwareId;
|
||||
|
||||
/**
|
||||
* 任务状态
|
||||
* <p>
|
||||
* 关联 {@link com.zt.plat.module.iot.enums.ota.IotOtaUpgradeTaskStatusEnum}
|
||||
*/
|
||||
private Integer status;
|
||||
|
||||
/**
|
||||
* 升级范围
|
||||
* <p>
|
||||
* 关联 {@link com.zt.plat.module.iot.enums.ota.IotOtaUpgradeTaskScopeEnum}
|
||||
*/
|
||||
private Integer scope;
|
||||
/**
|
||||
* 设备数量
|
||||
*/
|
||||
private Long deviceCount;
|
||||
/**
|
||||
* 选中的设备编号数组
|
||||
* <p>
|
||||
* 关联 {@link IotDeviceDO#getId()}
|
||||
*/
|
||||
@TableField(typeHandler = JacksonTypeHandler.class)
|
||||
private List<Long> deviceIds;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
package com.zt.plat.module.iot.dal.dataobject.plugin;
|
||||
|
||||
import com.zt.plat.framework.common.enums.CommonStatusEnum;
|
||||
import com.zt.plat.framework.tenant.core.db.TenantBaseDO;
|
||||
import com.zt.plat.module.iot.enums.plugin.IotPluginDeployTypeEnum;
|
||||
import com.zt.plat.module.iot.enums.plugin.IotPluginTypeEnum;
|
||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.*;
|
||||
|
||||
/**
|
||||
* IoT 插件配置 DO
|
||||
*
|
||||
* @author ZT
|
||||
*/
|
||||
@TableName("iot_plugin_config")
|
||||
@KeySequence("iot_plugin_config_seq")
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class IotPluginConfigDO extends TenantBaseDO {
|
||||
|
||||
/**
|
||||
* 主键 ID
|
||||
*/
|
||||
@TableId
|
||||
private Long id;
|
||||
/**
|
||||
* 插件包标识符
|
||||
*/
|
||||
private String pluginKey;
|
||||
/**
|
||||
* 插件名称
|
||||
*/
|
||||
private String name;
|
||||
/**
|
||||
* 插件描述
|
||||
*/
|
||||
private String description;
|
||||
/**
|
||||
* 部署方式
|
||||
* <p>
|
||||
* 枚举 {@link IotPluginDeployTypeEnum}
|
||||
*/
|
||||
private Integer deployType;
|
||||
// TODO @芋艿:如果是外置的插件,fileName 和 version 的选择~
|
||||
/**
|
||||
* 插件包文件名
|
||||
*/
|
||||
private String fileName;
|
||||
/**
|
||||
* 插件版本
|
||||
*/
|
||||
private String version;
|
||||
// TODO @芋艿:type 字典的定义
|
||||
/**
|
||||
* 插件类型
|
||||
* <p>
|
||||
* 枚举 {@link IotPluginTypeEnum}
|
||||
*/
|
||||
private Integer type;
|
||||
/**
|
||||
* 设备插件协议类型
|
||||
*/
|
||||
// TODO @芋艿:枚举字段
|
||||
private String protocol;
|
||||
// TODO @haohao:这个字段,是不是直接用 CommonStatus,开启、禁用;然后插件实例那,online 是否在线
|
||||
/**
|
||||
* 状态
|
||||
* <p>
|
||||
* 枚举 {@link CommonStatusEnum}
|
||||
*/
|
||||
private Integer status;
|
||||
|
||||
// TODO @芋艿:configSchema、config 示例字段
|
||||
/**
|
||||
* 插件配置项描述信息
|
||||
*/
|
||||
private String configSchema;
|
||||
/**
|
||||
* 插件配置信息
|
||||
*/
|
||||
private String config;
|
||||
|
||||
// TODO @芋艿:script 后续的使用
|
||||
/**
|
||||
* 插件脚本
|
||||
*/
|
||||
private String script;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
package com.zt.plat.module.iot.dal.dataobject.plugin;
|
||||
|
||||
import com.zt.plat.framework.tenant.core.db.TenantBaseDO;
|
||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.*;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* IoT 插件实例 DO
|
||||
*
|
||||
* @author ZT
|
||||
*/
|
||||
@TableName("iot_plugin_instance")
|
||||
@KeySequence("iot_plugin_instance_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class IotPluginInstanceDO extends TenantBaseDO {
|
||||
|
||||
/**
|
||||
* 主键
|
||||
*/
|
||||
@TableId
|
||||
private Long id;
|
||||
/**
|
||||
* 插件编号
|
||||
* <p>
|
||||
* 关联 {@link IotPluginConfigDO#getId()}
|
||||
*/
|
||||
private Long pluginId;
|
||||
/**
|
||||
* 插件进程编号
|
||||
*
|
||||
* 一般格式是:hostIp@processId@${uuid}
|
||||
*/
|
||||
private String processId;
|
||||
|
||||
/**
|
||||
* 插件实例所在 IP
|
||||
*/
|
||||
private String hostIp;
|
||||
/**
|
||||
* 设备下行端口
|
||||
*/
|
||||
private Integer downstreamPort;
|
||||
|
||||
/**
|
||||
* 是否在线
|
||||
*/
|
||||
private Boolean online;
|
||||
/**
|
||||
* 在线时间
|
||||
*/
|
||||
private LocalDateTime onlineTime;
|
||||
/**
|
||||
* 离线时间
|
||||
*/
|
||||
private LocalDateTime offlineTime;
|
||||
/**
|
||||
* 心跳时间
|
||||
*
|
||||
* 目的:心路时间超过一定时间后,会被进行下线处理
|
||||
*/
|
||||
private LocalDateTime heartbeatTime;
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user