mirror of
https://gitee.com/huangge1199_admin/vue-pro.git
synced 2024-11-25 08:41:52 +08:00
Merge branch 'feature/iot' of https://gitee.com/zhijiantianya/ruoyi-vue-pro into master-jdk17
# Conflicts: # pom.xml # yudao-dependencies/pom.xml # yudao-server/pom.xml
This commit is contained in:
commit
44b466c678
7
pom.xml
7
pom.xml
@ -15,15 +15,16 @@
|
|||||||
<!-- 各种 module 拓展 -->
|
<!-- 各种 module 拓展 -->
|
||||||
<module>yudao-module-system</module>
|
<module>yudao-module-system</module>
|
||||||
<module>yudao-module-infra</module>
|
<module>yudao-module-infra</module>
|
||||||
<module>yudao-module-member</module>
|
<!-- <module>yudao-module-member</module>-->
|
||||||
<!-- <module>yudao-module-bpm</module>-->
|
<!-- <module>yudao-module-bpm</module>-->
|
||||||
<!-- <module>yudao-module-report</module>-->
|
<!-- <module>yudao-module-report</module>-->
|
||||||
<!-- <module>yudao-module-mp</module>-->
|
<!-- <module>yudao-module-mp</module>-->
|
||||||
<module>yudao-module-pay</module>
|
<!-- <module>yudao-module-pay</module>-->
|
||||||
<module>yudao-module-mall</module>
|
<!-- <module>yudao-module-mall</module>-->
|
||||||
<!-- <module>yudao-module-crm</module>-->
|
<!-- <module>yudao-module-crm</module>-->
|
||||||
<!-- <module>yudao-module-erp</module>-->
|
<!-- <module>yudao-module-erp</module>-->
|
||||||
<!-- <module>yudao-module-ai</module>-->
|
<!-- <module>yudao-module-ai</module>-->
|
||||||
|
<!-- <module>yudao-module-iot</module>-->
|
||||||
</modules>
|
</modules>
|
||||||
|
|
||||||
<name>${project.artifactId}</name>
|
<name>${project.artifactId}</name>
|
||||||
|
@ -64,6 +64,7 @@
|
|||||||
<ip2region.version>2.7.0</ip2region.version>
|
<ip2region.version>2.7.0</ip2region.version>
|
||||||
<bizlog-sdk.version>3.0.6</bizlog-sdk.version>
|
<bizlog-sdk.version>3.0.6</bizlog-sdk.version>
|
||||||
<netty.version>4.1.113.Final</netty.version>
|
<netty.version>4.1.113.Final</netty.version>
|
||||||
|
<mqtt.version>1.2.5</mqtt.version>
|
||||||
<!-- 三方云服务相关 -->
|
<!-- 三方云服务相关 -->
|
||||||
<okio.version>3.5.0</okio.version>
|
<okio.version>3.5.0</okio.version>
|
||||||
<okhttp3.version>4.11.0</okhttp3.version>
|
<okhttp3.version>4.11.0</okhttp3.version>
|
||||||
@ -596,6 +597,13 @@
|
|||||||
</exclusion>
|
</exclusion>
|
||||||
</exclusions>
|
</exclusions>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!-- MQTT -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.paho</groupId>
|
||||||
|
<artifactId>org.eclipse.paho.client.mqttv3</artifactId>
|
||||||
|
<version>${mqtt.version}</version>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</dependencyManagement>
|
</dependencyManagement>
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ import java.util.Set;
|
|||||||
/**
|
/**
|
||||||
* 基于 MyBatis Plus 多租户的功能,实现 DB 层面的多租户的功能
|
* 基于 MyBatis Plus 多租户的功能,实现 DB 层面的多租户的功能
|
||||||
*
|
*
|
||||||
* @author 芋道源码
|
* @author
|
||||||
*/
|
*/
|
||||||
public class TenantDatabaseInterceptor implements TenantLineHandler {
|
public class TenantDatabaseInterceptor implements TenantLineHandler {
|
||||||
|
|
||||||
|
@ -62,6 +62,10 @@ public class BannerApplicationRunner implements ApplicationRunner {
|
|||||||
if (isNotPresent("cn.iocoder.yudao.module.ai.framework.web.config.AiWebConfiguration")) {
|
if (isNotPresent("cn.iocoder.yudao.module.ai.framework.web.config.AiWebConfiguration")) {
|
||||||
System.out.println("[AI 大模型 yudao-module-ai - 已禁用][参考 https://doc.iocoder.cn/ai/build/ 开启]");
|
System.out.println("[AI 大模型 yudao-module-ai - 已禁用][参考 https://doc.iocoder.cn/ai/build/ 开启]");
|
||||||
}
|
}
|
||||||
|
// IOT 物联网
|
||||||
|
if (isNotPresent("cn.iocoder.yudao.module.iot.framework.web.config.IotWebConfiguration")) {
|
||||||
|
System.out.println("[IOT 物联网 yudao-module-iot - 已禁用][参考 https://doc.iocoder.cn/iot/build/ 开启]");
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -378,6 +378,12 @@ public class GlobalExceptionHandler {
|
|||||||
return CommonResult.error(NOT_IMPLEMENTED.getCode(),
|
return CommonResult.error(NOT_IMPLEMENTED.getCode(),
|
||||||
"[AI 大模型 yudao-module-ai - 表结构未导入][参考 https://cloud.iocoder.cn/ai/build/ 开启]");
|
"[AI 大模型 yudao-module-ai - 表结构未导入][参考 https://cloud.iocoder.cn/ai/build/ 开启]");
|
||||||
}
|
}
|
||||||
|
// 9. IOT 物联网
|
||||||
|
if (message.contains("iot_")) {
|
||||||
|
log.error("[IOT 物联网 yudao-module-iot - 表结构未导入][参考 https://doc.iocoder.cn/iot/build/ 开启]");
|
||||||
|
return CommonResult.error(NOT_IMPLEMENTED.getCode(),
|
||||||
|
"[IOT 物联网 yudao-module-iot - 表结构未导入][参考 https://doc.iocoder.cn/iot/build/ 开启]");
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
25
yudao-module-iot/pom.xml
Normal file
25
yudao-module-iot/pom.xml
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<parent>
|
||||||
|
<artifactId>yudao</artifactId>
|
||||||
|
<groupId>cn.iocoder.boot</groupId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</parent>
|
||||||
|
<modules>
|
||||||
|
<module>yudao-module-iot-api</module>
|
||||||
|
<module>yudao-module-iot-biz</module>
|
||||||
|
</modules>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<artifactId>yudao-module-iot</artifactId>
|
||||||
|
<packaging>pom</packaging>
|
||||||
|
|
||||||
|
<name>${project.artifactId}</name>
|
||||||
|
<description>
|
||||||
|
物联网模块
|
||||||
|
<!-- TODO 芋艿:需要补充下说明! -->
|
||||||
|
</description>
|
||||||
|
|
||||||
|
</project>
|
26
yudao-module-iot/yudao-module-iot-api/pom.xml
Normal file
26
yudao-module-iot/yudao-module-iot-api/pom.xml
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
<?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>yudao-module-iot</artifactId>
|
||||||
|
<groupId>cn.iocoder.boot</groupId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</parent>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<artifactId>yudao-module-iot-api</artifactId>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
|
<name>${project.artifactId}</name>
|
||||||
|
<description>
|
||||||
|
物联网 模块 API,暴露给其它模块调用
|
||||||
|
</description>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>cn.iocoder.boot</groupId>
|
||||||
|
<artifactId>yudao-common</artifactId>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
</project>
|
@ -0,0 +1,6 @@
|
|||||||
|
/**
|
||||||
|
* 占位
|
||||||
|
*
|
||||||
|
* TODO 芋艿:后续删除
|
||||||
|
*/
|
||||||
|
package cn.iocoder.yudao.module.iot.api;
|
@ -0,0 +1,32 @@
|
|||||||
|
package cn.iocoder.yudao.module.iot.enums;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.framework.common.exception.ErrorCode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* iot 错误码枚举类
|
||||||
|
* <p>
|
||||||
|
* iot 系统,使用 1-050-000-000 段
|
||||||
|
*/
|
||||||
|
public interface ErrorCodeConstants {
|
||||||
|
|
||||||
|
// ========== IoT 产品相关 1-050-001-000 ============
|
||||||
|
ErrorCode PRODUCT_NOT_EXISTS = new ErrorCode(1_050_001_000, "产品不存在");
|
||||||
|
ErrorCode PRODUCT_IDENTIFICATION_EXISTS = new ErrorCode(1_050_001_001, "产品标识已经存在");
|
||||||
|
ErrorCode PRODUCT_STATUS_NOT_DELETE = new ErrorCode(1_050_001_002, "产品状是发布状态,不允许删除");
|
||||||
|
|
||||||
|
// ========== IoT 产品物模型 1-050-002-000 ============
|
||||||
|
ErrorCode THINK_MODEL_FUNCTION_NOT_EXISTS = new ErrorCode(1_050_002_000, "产品物模型不存在");
|
||||||
|
ErrorCode THINK_MODEL_FUNCTION_EXISTS_BY_PRODUCT_KEY = new ErrorCode(1_050_002_001, "ProductKey 对应的产品物模型已存在");
|
||||||
|
ErrorCode THINK_MODEL_FUNCTION_IDENTIFIER_EXISTS = new ErrorCode(1_050_002_002, "存在重复的功能标识符。");
|
||||||
|
ErrorCode THINK_MODEL_FUNCTION_NAME_EXISTS = new ErrorCode(1_050_002_003, "存在重复的功能名称。");
|
||||||
|
ErrorCode THINK_MODEL_FUNCTION_IDENTIFIER_INVALID = new ErrorCode(1_050_002_003, "产品物模型标识无效");
|
||||||
|
|
||||||
|
// ========== IoT 设备 1-050-003-000 ============
|
||||||
|
ErrorCode DEVICE_NOT_EXISTS = new ErrorCode(1_050_003_000, "设备不存在");
|
||||||
|
ErrorCode DEVICE_NAME_EXISTS = new ErrorCode(1_050_003_001, "设备名称在同一产品下必须唯一");
|
||||||
|
ErrorCode DEVICE_HAS_CHILDREN = new ErrorCode(1_050_003_002, "有子设备,不允许删除");
|
||||||
|
ErrorCode DEVICE_NAME_CANNOT_BE_MODIFIED = new ErrorCode(1_050_003_003, "设备名称不能修改");
|
||||||
|
ErrorCode DEVICE_PRODUCT_CANNOT_BE_MODIFIED = new ErrorCode(1_050_003_004, "产品不能修改");
|
||||||
|
ErrorCode DEVICE_INVALID_DEVICE_STATUS = new ErrorCode(1_050_003_005, "无效的设备状态");
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,55 @@
|
|||||||
|
package cn.iocoder.yudao.module.iot.enums.device;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IoT 设备状态枚举
|
||||||
|
*
|
||||||
|
* @author haohao
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
public enum IotDeviceStatusEnum implements IntArrayValuable {
|
||||||
|
|
||||||
|
INACTIVE(0, "未激活"),
|
||||||
|
ONLINE(1, "在线"),
|
||||||
|
OFFLINE(2, "离线"),
|
||||||
|
DISABLED(3, "已禁用");
|
||||||
|
|
||||||
|
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(IotDeviceStatusEnum::getStatus).toArray();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 状态
|
||||||
|
*/
|
||||||
|
private final Integer status;
|
||||||
|
/**
|
||||||
|
* 状态名
|
||||||
|
*/
|
||||||
|
private final String name;
|
||||||
|
|
||||||
|
IotDeviceStatusEnum(Integer status, String name) {
|
||||||
|
this.status = status;
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IotDeviceStatusEnum fromStatus(Integer status) {
|
||||||
|
for (IotDeviceStatusEnum value : values()) {
|
||||||
|
if (value.getStatus().equals(status)) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isValidStatus(Integer status) {
|
||||||
|
return fromStatus(status) != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int[] array() {
|
||||||
|
return ARRAYS;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
package cn.iocoder.yudao.module.iot.enums.product;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IOT 访问方式枚举类
|
||||||
|
*
|
||||||
|
* @author ahh
|
||||||
|
*/
|
||||||
|
@AllArgsConstructor
|
||||||
|
@Getter
|
||||||
|
public enum IotAccessModeEnum {
|
||||||
|
|
||||||
|
READ("r"),
|
||||||
|
WRITE("w"),
|
||||||
|
READ_WRITE("rw");
|
||||||
|
|
||||||
|
private final String mode;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,38 @@
|
|||||||
|
package cn.iocoder.yudao.module.iot.enums.product;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 产品数据格式枚举类
|
||||||
|
*
|
||||||
|
* @author ahh
|
||||||
|
* @see <a href="https://help.aliyun.com/zh/iot/user-guide/message-parsing">阿里云 - 什么是消息解析</a>
|
||||||
|
*/
|
||||||
|
@AllArgsConstructor
|
||||||
|
@Getter
|
||||||
|
public enum IotDataFormatEnum implements IntArrayValuable {
|
||||||
|
|
||||||
|
JSON(0, "标准数据格式(JSON)"),
|
||||||
|
CUSTOMIZE(1, "透传/自定义");
|
||||||
|
|
||||||
|
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(IotDataFormatEnum::getType).toArray();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 类型
|
||||||
|
*/
|
||||||
|
private final Integer type;
|
||||||
|
/**
|
||||||
|
* 描述
|
||||||
|
*/
|
||||||
|
private final String description;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int[] array() {
|
||||||
|
return ARRAYS;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,39 @@
|
|||||||
|
package cn.iocoder.yudao.module.iot.enums.product;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IOT 联网方式枚举类
|
||||||
|
*
|
||||||
|
* @author ahh
|
||||||
|
*/
|
||||||
|
@AllArgsConstructor
|
||||||
|
@Getter
|
||||||
|
public enum IotNetTypeEnum implements IntArrayValuable {
|
||||||
|
|
||||||
|
WIFI(0, "Wi-Fi"),
|
||||||
|
CELLULAR(1, "Cellular"),
|
||||||
|
ETHERNET(2, "Ethernet"),
|
||||||
|
OTHER(3, "其他");
|
||||||
|
|
||||||
|
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(IotNetTypeEnum::getType).toArray();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 类型
|
||||||
|
*/
|
||||||
|
private final Integer type;
|
||||||
|
/**
|
||||||
|
* 描述
|
||||||
|
*/
|
||||||
|
private final String description;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int[] array() {
|
||||||
|
return ARRAYS;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,39 @@
|
|||||||
|
package cn.iocoder.yudao.module.iot.enums.product;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IOT 产品的设备类型
|
||||||
|
*
|
||||||
|
* @author ahh
|
||||||
|
*/
|
||||||
|
@AllArgsConstructor
|
||||||
|
@Getter
|
||||||
|
public enum IotProductDeviceTypeEnum implements IntArrayValuable {
|
||||||
|
|
||||||
|
DIRECT(0, "直连设备"),
|
||||||
|
GATEWAY_CHILD(1, "网关子设备"),
|
||||||
|
GATEWAY(2, "网关设备");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 类型
|
||||||
|
*/
|
||||||
|
private final Integer type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 描述
|
||||||
|
*/
|
||||||
|
private final String description;
|
||||||
|
|
||||||
|
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(IotProductDeviceTypeEnum::getType).toArray();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int[] array() {
|
||||||
|
return ARRAYS;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,38 @@
|
|||||||
|
package cn.iocoder.yudao.module.iot.enums.product;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IOT 产品功能(物模型)类型枚举类
|
||||||
|
*
|
||||||
|
* @author ahh
|
||||||
|
*/
|
||||||
|
@AllArgsConstructor
|
||||||
|
@Getter
|
||||||
|
public enum IotProductFunctionTypeEnum implements IntArrayValuable {
|
||||||
|
|
||||||
|
PROPERTY(1, "属性"),
|
||||||
|
SERVICE(2, "服务"),
|
||||||
|
EVENT(3, "事件");
|
||||||
|
|
||||||
|
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(IotProductFunctionTypeEnum::getType).toArray();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 类型
|
||||||
|
*/
|
||||||
|
private final Integer type;
|
||||||
|
/**
|
||||||
|
* 描述
|
||||||
|
*/
|
||||||
|
private final String description;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int[] array() {
|
||||||
|
return ARRAYS;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,37 @@
|
|||||||
|
package cn.iocoder.yudao.module.iot.enums.product;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IOT 产品的状态枚举类
|
||||||
|
*
|
||||||
|
* @author ahh
|
||||||
|
*/
|
||||||
|
@AllArgsConstructor
|
||||||
|
@Getter
|
||||||
|
public enum IotProductStatusEnum implements IntArrayValuable {
|
||||||
|
|
||||||
|
UNPUBLISHED(0, "开发中"),
|
||||||
|
PUBLISHED(1, "已发布");
|
||||||
|
|
||||||
|
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(IotProductStatusEnum::getType).toArray();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 类型
|
||||||
|
*/
|
||||||
|
private final Integer type;
|
||||||
|
/**
|
||||||
|
* 描述
|
||||||
|
*/
|
||||||
|
private final String description;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int[] array() {
|
||||||
|
return ARRAYS;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,40 @@
|
|||||||
|
package cn.iocoder.yudao.module.iot.enums.product;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IOT 接入网关协议枚举类
|
||||||
|
*
|
||||||
|
* @author ahh
|
||||||
|
*/
|
||||||
|
@AllArgsConstructor
|
||||||
|
@Getter
|
||||||
|
public enum IotProtocolTypeEnum implements IntArrayValuable {
|
||||||
|
|
||||||
|
CUSTOM(0, "自定义"),
|
||||||
|
MODBUS(1, "Modbus"),
|
||||||
|
OPC_UA(2, "OPC UA"),
|
||||||
|
ZIGBEE(3, "ZigBee"),
|
||||||
|
BLE(4, "BLE");
|
||||||
|
|
||||||
|
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(IotProtocolTypeEnum::getType).toArray();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 类型
|
||||||
|
*/
|
||||||
|
private final Integer type;
|
||||||
|
/**
|
||||||
|
* 描述
|
||||||
|
*/
|
||||||
|
private final String description;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int[] array() {
|
||||||
|
return ARRAYS;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,37 @@
|
|||||||
|
package cn.iocoder.yudao.module.iot.enums.product;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IOT 数据校验级别枚举类
|
||||||
|
*
|
||||||
|
* @author ahh
|
||||||
|
*/
|
||||||
|
@AllArgsConstructor
|
||||||
|
@Getter
|
||||||
|
public enum IotValidateTypeEnum implements IntArrayValuable {
|
||||||
|
|
||||||
|
WEAK(0, "弱校验"),
|
||||||
|
NONE(1, "免校验");
|
||||||
|
|
||||||
|
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(IotValidateTypeEnum::getType).toArray();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 类型
|
||||||
|
*/
|
||||||
|
private final Integer type;
|
||||||
|
/**
|
||||||
|
* 描述
|
||||||
|
*/
|
||||||
|
private final String description;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int[] array() {
|
||||||
|
return ARRAYS;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
64
yudao-module-iot/yudao-module-iot-biz/pom.xml
Normal file
64
yudao-module-iot/yudao-module-iot-biz/pom.xml
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
<?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>yudao-module-iot</artifactId>
|
||||||
|
<groupId>cn.iocoder.boot</groupId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</parent>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
|
<artifactId>yudao-module-iot-biz</artifactId>
|
||||||
|
|
||||||
|
<name>${project.artifactId}</name>
|
||||||
|
<description>
|
||||||
|
物联网 模块,主要实现 产品管理、设备管理、协议管理等功能。
|
||||||
|
<!-- TODO 芋艿:后续补充下 -->
|
||||||
|
</description>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>cn.iocoder.boot</groupId>
|
||||||
|
<artifactId>yudao-module-iot-api</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Web 相关 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>cn.iocoder.boot</groupId>
|
||||||
|
<artifactId>yudao-spring-boot-starter-web</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>cn.iocoder.boot</groupId>
|
||||||
|
<artifactId>yudao-spring-boot-starter-security</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- DB 相关 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>cn.iocoder.boot</groupId>
|
||||||
|
<artifactId>yudao-spring-boot-starter-mybatis</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Test 测试相关 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>cn.iocoder.boot</groupId>
|
||||||
|
<artifactId>yudao-spring-boot-starter-test</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- 工具类相关 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>cn.iocoder.boot</groupId>
|
||||||
|
<artifactId>yudao-spring-boot-starter-excel</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- MQTT -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.paho</groupId>
|
||||||
|
<artifactId>org.eclipse.paho.client.mqttv3</artifactId>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
</project>
|
@ -0,0 +1,89 @@
|
|||||||
|
package cn.iocoder.yudao.module.iot.controller.admin.device;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||||
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
|
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||||
|
import cn.iocoder.yudao.module.iot.controller.admin.device.vo.IotDevicePageReqVO;
|
||||||
|
import cn.iocoder.yudao.module.iot.controller.admin.device.vo.IotDeviceRespVO;
|
||||||
|
import cn.iocoder.yudao.module.iot.controller.admin.device.vo.IotDeviceSaveReqVO;
|
||||||
|
import cn.iocoder.yudao.module.iot.controller.admin.device.vo.IotDeviceStatusUpdateReqVO;
|
||||||
|
import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO;
|
||||||
|
import cn.iocoder.yudao.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 static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||||
|
|
||||||
|
@Tag(name = "管理后台 - IoT 设备")
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/iot/device")
|
||||||
|
@Validated
|
||||||
|
public class IotDeviceController {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private IotDeviceService deviceService;
|
||||||
|
|
||||||
|
@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-status")
|
||||||
|
@Operation(summary = "更新设备状态")
|
||||||
|
@PreAuthorize("@ss.hasPermission('iot:device:update')")
|
||||||
|
public CommonResult<Boolean> updateDeviceStatus(@Valid @RequestBody IotDeviceStatusUpdateReqVO updateReqVO) {
|
||||||
|
deviceService.updateDeviceStatus(updateReqVO);
|
||||||
|
return success(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PutMapping("/update")
|
||||||
|
@Operation(summary = "更新设备")
|
||||||
|
@PreAuthorize("@ss.hasPermission('iot:device:update')")
|
||||||
|
public CommonResult<Boolean> updateDevice(@Valid @RequestBody IotDeviceSaveReqVO updateReqVO) {
|
||||||
|
deviceService.updateDevice(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);
|
||||||
|
}
|
||||||
|
|
||||||
|
@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("/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));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,87 @@
|
|||||||
|
package cn.iocoder.yudao.module.iot.controller.admin.device.vo;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||||
|
import cn.iocoder.yudao.framework.common.validation.InEnum;
|
||||||
|
import cn.iocoder.yudao.module.iot.enums.device.IotDeviceStatusEnum;
|
||||||
|
import cn.iocoder.yudao.module.iot.enums.product.IotProductDeviceTypeEnum;
|
||||||
|
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.math.BigDecimal;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
||||||
|
|
||||||
|
@Schema(description = "管理后台 - IoT 设备分页 Request VO")
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@ToString(callSuper = true)
|
||||||
|
public class IotDevicePageReqVO extends PageParam {
|
||||||
|
|
||||||
|
// TODO @芋艿:需要去掉一些多余的字段;
|
||||||
|
|
||||||
|
@Schema(description = "设备唯一标识符", example = "24602")
|
||||||
|
private String deviceKey;
|
||||||
|
|
||||||
|
@Schema(description = "设备名称", example = "王五")
|
||||||
|
private String deviceName;
|
||||||
|
|
||||||
|
@Schema(description = "备注名称", example = "张三")
|
||||||
|
private String nickname;
|
||||||
|
|
||||||
|
@Schema(description = "产品编号", example = "26202")
|
||||||
|
private Long productId;
|
||||||
|
|
||||||
|
@Schema(description = "产品标识")
|
||||||
|
private String productKey;
|
||||||
|
|
||||||
|
@Schema(description = "设备类型", example = "1")
|
||||||
|
@InEnum(IotProductDeviceTypeEnum.class)
|
||||||
|
private Integer deviceType;
|
||||||
|
|
||||||
|
@Schema(description = "网关设备 ID", example = "16380")
|
||||||
|
private Long gatewayId;
|
||||||
|
|
||||||
|
@Schema(description = "设备状态", example = "1")
|
||||||
|
@InEnum(IotDeviceStatusEnum.class)
|
||||||
|
private Integer status;
|
||||||
|
|
||||||
|
@Schema(description = "设备状态最后更新时间")
|
||||||
|
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||||
|
private LocalDateTime[] statusLastUpdateTime;
|
||||||
|
|
||||||
|
@Schema(description = "最后上线时间")
|
||||||
|
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||||
|
private LocalDateTime[] lastOnlineTime;
|
||||||
|
|
||||||
|
@Schema(description = "最后离线时间")
|
||||||
|
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||||
|
private LocalDateTime[] lastOfflineTime;
|
||||||
|
|
||||||
|
@Schema(description = "设备激活时间")
|
||||||
|
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||||
|
private LocalDateTime[] activeTime;
|
||||||
|
|
||||||
|
@Schema(description = "设备密钥,用于设备认证,需安全存储")
|
||||||
|
private String deviceSecret;
|
||||||
|
|
||||||
|
@Schema(description = "MQTT 客户端 ID", example = "24602")
|
||||||
|
private String mqttClientId;
|
||||||
|
|
||||||
|
@Schema(description = "MQTT 用户名", example = "芋艿")
|
||||||
|
private String mqttUsername;
|
||||||
|
|
||||||
|
@Schema(description = "MQTT 密码")
|
||||||
|
private String mqttPassword;
|
||||||
|
|
||||||
|
@Schema(description = "认证类型(如一机一密、动态注册)", example = "2")
|
||||||
|
private String authType;
|
||||||
|
|
||||||
|
@Schema(description = "创建时间")
|
||||||
|
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||||
|
private LocalDateTime[] createTime;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,90 @@
|
|||||||
|
package cn.iocoder.yudao.module.iot.controller.admin.device.vo;
|
||||||
|
|
||||||
|
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.math.BigDecimal;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
@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 = "产品编号", 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 = "设备备注名称", example = "张三")
|
||||||
|
@ExcelProperty("设备备注名称")
|
||||||
|
private String nickname;
|
||||||
|
|
||||||
|
@Schema(description = "网关设备 ID", example = "16380")
|
||||||
|
private Long gatewayId;
|
||||||
|
|
||||||
|
@Schema(description = "设备状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||||
|
@ExcelProperty("设备状态")
|
||||||
|
private Integer status;
|
||||||
|
|
||||||
|
@Schema(description = "设备状态最后更新时间")
|
||||||
|
@ExcelProperty("设备状态最后更新时间")
|
||||||
|
private LocalDateTime statusLastUpdateTime;
|
||||||
|
|
||||||
|
@Schema(description = "最后上线时间")
|
||||||
|
@ExcelProperty("最后上线时间")
|
||||||
|
private LocalDateTime lastOnlineTime;
|
||||||
|
|
||||||
|
@Schema(description = "最后离线时间")
|
||||||
|
@ExcelProperty("最后离线时间")
|
||||||
|
private LocalDateTime lastOfflineTime;
|
||||||
|
|
||||||
|
@Schema(description = "设备激活时间")
|
||||||
|
@ExcelProperty("设备激活时间")
|
||||||
|
private LocalDateTime activeTime;
|
||||||
|
|
||||||
|
@Schema(description = "设备密钥,用于设备认证")
|
||||||
|
@ExcelProperty("设备密钥")
|
||||||
|
private String deviceSecret;
|
||||||
|
|
||||||
|
@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;
|
||||||
|
|
||||||
|
@Schema(description = "认证类型(如一机一密、动态注册)", example = "2")
|
||||||
|
@ExcelProperty("认证类型(如一机一密、动态注册)")
|
||||||
|
private String authType;
|
||||||
|
|
||||||
|
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||||
|
@ExcelProperty("创建时间")
|
||||||
|
private LocalDateTime createTime;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,22 @@
|
|||||||
|
package cn.iocoder.yudao.module.iot.controller.admin.device.vo;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Schema(description = "管理后台 - IoT 设备新增/修改 Request VO")
|
||||||
|
@Data
|
||||||
|
public class IotDeviceSaveReqVO {
|
||||||
|
|
||||||
|
@Schema(description = "设备编号", example = "177")
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@Schema(description = "设备名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "王五")
|
||||||
|
private String deviceName;
|
||||||
|
|
||||||
|
@Schema(description = "备注名称", example = "张三")
|
||||||
|
private String nickname;
|
||||||
|
|
||||||
|
@Schema(description = "产品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "26202")
|
||||||
|
private Long productId;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
package cn.iocoder.yudao.module.iot.controller.admin.device.vo;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.framework.common.validation.InEnum;
|
||||||
|
import cn.iocoder.yudao.module.iot.enums.device.IotDeviceStatusEnum;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Schema(description = "管理后台 - IoT 设备状态更新 Request VO")
|
||||||
|
@Data
|
||||||
|
public class IotDeviceStatusUpdateReqVO {
|
||||||
|
|
||||||
|
@Schema(description = "设备编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||||
|
@NotNull(message = "设备编号不能为空")
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@Schema(description = "设备状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||||
|
@NotNull(message = "设备状态不能为空")
|
||||||
|
@InEnum(IotDeviceStatusEnum.class)
|
||||||
|
private Integer status;
|
||||||
|
}
|
@ -0,0 +1,95 @@
|
|||||||
|
package cn.iocoder.yudao.module.iot.controller.admin.product;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||||
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
|
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||||
|
import cn.iocoder.yudao.module.iot.controller.admin.product.vo.IotProductPageReqVO;
|
||||||
|
import cn.iocoder.yudao.module.iot.controller.admin.product.vo.IotProductRespVO;
|
||||||
|
import cn.iocoder.yudao.module.iot.controller.admin.product.vo.IotProductSaveReqVO;
|
||||||
|
import cn.iocoder.yudao.module.iot.controller.admin.product.vo.IotProductSimpleRespVO;
|
||||||
|
import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO;
|
||||||
|
import cn.iocoder.yudao.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.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 cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||||
|
|
||||||
|
@Tag(name = "管理后台 - IoT 产品")
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/iot/product")
|
||||||
|
@Validated
|
||||||
|
public class IotProductController {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private IotProductService productService;
|
||||||
|
|
||||||
|
@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);
|
||||||
|
return success(BeanUtils.toBean(product, IotProductRespVO.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/page")
|
||||||
|
@Operation(summary = "获得产品分页")
|
||||||
|
@PreAuthorize("@ss.hasPermission('iot:product:query')")
|
||||||
|
public CommonResult<PageResult<IotProductRespVO>> getProductPage(@Valid IotProductPageReqVO pageReqVO) {
|
||||||
|
PageResult<IotProductDO> pageResult = productService.getProductPage(pageReqVO);
|
||||||
|
return success(BeanUtils.toBean(pageResult, IotProductRespVO.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO @haohao:改成 simple-list 哈
|
||||||
|
@GetMapping("/list-all-simple")
|
||||||
|
@Operation(summary = "获得所有产品列表")
|
||||||
|
@PreAuthorize("@ss.hasPermission('iot:product:query')")
|
||||||
|
public CommonResult<List<IotProductSimpleRespVO>> listAllSimpleProducts() {
|
||||||
|
List<IotProductDO> list = productService.getProductList();
|
||||||
|
return success(BeanUtils.toBean(list, IotProductSimpleRespVO.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
package cn.iocoder.yudao.module.iot.controller.admin.product.vo;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.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
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@ToString(callSuper = true)
|
||||||
|
public class IotProductPageReqVO extends PageParam {
|
||||||
|
|
||||||
|
@Schema(description = "产品名称", example = "李四")
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@Schema(description = "产品标识")
|
||||||
|
private String productKey;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,67 @@
|
|||||||
|
package cn.iocoder.yudao.module.iot.controller.admin.product.vo;
|
||||||
|
|
||||||
|
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 LocalDateTime createTime;
|
||||||
|
|
||||||
|
@Schema(description = "产品标识", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||||
|
@ExcelProperty("产品标识")
|
||||||
|
private String productKey;
|
||||||
|
|
||||||
|
@Schema(description = "接入网关协议", example = "2")
|
||||||
|
@ExcelProperty("接入网关协议")
|
||||||
|
private Integer protocolType;
|
||||||
|
|
||||||
|
@Schema(description = "协议编号(脚本解析 id)", requiredMode = Schema.RequiredMode.REQUIRED, example = "13177")
|
||||||
|
@ExcelProperty("协议编号(脚本解析 id)")
|
||||||
|
private Long protocolId;
|
||||||
|
|
||||||
|
@Schema(description = "产品所属品类标识符", example = "14237")
|
||||||
|
@ExcelProperty("产品所属品类标识符")
|
||||||
|
private Long categoryId;
|
||||||
|
|
||||||
|
@Schema(description = "产品描述", example = "你猜")
|
||||||
|
@ExcelProperty("产品描述")
|
||||||
|
private String description;
|
||||||
|
|
||||||
|
@Schema(description = "数据校验级别", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||||
|
@ExcelProperty("数据校验级别")
|
||||||
|
private Integer validateType;
|
||||||
|
|
||||||
|
@Schema(description = "产品状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||||
|
@ExcelProperty("产品状态")
|
||||||
|
private Integer status;
|
||||||
|
|
||||||
|
@Schema(description = "设备类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
|
||||||
|
@ExcelProperty("设备类型")
|
||||||
|
private Integer deviceType;
|
||||||
|
|
||||||
|
@Schema(description = "联网方式", example = "2")
|
||||||
|
@ExcelProperty("联网方式")
|
||||||
|
private Integer netType;
|
||||||
|
|
||||||
|
@Schema(description = "数据格式")
|
||||||
|
@ExcelProperty("数据格式")
|
||||||
|
private Integer dataFormat;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,50 @@
|
|||||||
|
package cn.iocoder.yudao.module.iot.controller.admin.product.vo;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.framework.common.validation.InEnum;
|
||||||
|
import cn.iocoder.yudao.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 = "产品Key", requiredMode = Schema.RequiredMode.AUTO, example = "12345abc")
|
||||||
|
private String productKey;
|
||||||
|
|
||||||
|
@Schema(description = "产品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "温湿度")
|
||||||
|
@NotEmpty(message = "产品名称不能为空")
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@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;
|
||||||
|
|
||||||
|
@Schema(description = "产品描述", example = "描述")
|
||||||
|
private String description;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,16 @@
|
|||||||
|
package cn.iocoder.yudao.module.iot.controller.admin.product.vo;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Schema(description = "管理后台 - IoT 产品 Response VO")
|
||||||
|
@Data
|
||||||
|
public class IotProductSimpleRespVO {
|
||||||
|
|
||||||
|
@Schema(description = "产品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "26087")
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@Schema(description = "产品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四")
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,112 @@
|
|||||||
|
### 请求 /iot/think-model-function/create 接口 => 成功
|
||||||
|
POST {{baseUrl}}/iot/think-model-function/create
|
||||||
|
Content-Type: application/json
|
||||||
|
tenant-id: {{adminTenentId}}
|
||||||
|
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: {{adminTenentId}}
|
||||||
|
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: {{adminTenentId}}
|
||||||
|
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: {{adminTenentId}}
|
||||||
|
Authorization: Bearer {{token}}
|
||||||
|
|
||||||
|
### 请求 /iot/think-model-function/get 接口 => 成功
|
||||||
|
GET {{baseUrl}}/iot/think-model-function/get?id=10
|
||||||
|
tenant-id: {{adminTenentId}}
|
||||||
|
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: {{adminTenentId}}
|
||||||
|
Authorization: Bearer {{token}}
|
@ -0,0 +1,84 @@
|
|||||||
|
package cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||||
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
|
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||||
|
import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.vo.IotThinkModelFunctionPageReqVO;
|
||||||
|
import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.vo.IotThinkModelFunctionRespVO;
|
||||||
|
import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.vo.IotThinkModelFunctionSaveReqVO;
|
||||||
|
import cn.iocoder.yudao.module.iot.convert.thinkmodelfunction.IotThinkModelFunctionConvert;
|
||||||
|
import cn.iocoder.yudao.module.iot.dal.dataobject.thinkmodelfunction.IotThinkModelFunctionDO;
|
||||||
|
import cn.iocoder.yudao.module.iot.service.thinkmodelfunction.IotThinkModelFunctionService;
|
||||||
|
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 cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||||
|
|
||||||
|
@Tag(name = "管理后台 - IoT 产品物模型")
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/iot/think-model-function")
|
||||||
|
@Validated
|
||||||
|
public class IotThinkModelFunctionController {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private IotThinkModelFunctionService thinkModelFunctionService;
|
||||||
|
|
||||||
|
@PostMapping("/create")
|
||||||
|
@Operation(summary = "创建产品物模型")
|
||||||
|
@PreAuthorize("@ss.hasPermission('iot:think-model-function:create')")
|
||||||
|
public CommonResult<Long> createThinkModelFunction(@Valid @RequestBody IotThinkModelFunctionSaveReqVO createReqVO) {
|
||||||
|
return success(thinkModelFunctionService.createThinkModelFunction(createReqVO));
|
||||||
|
}
|
||||||
|
|
||||||
|
@PutMapping("/update")
|
||||||
|
@Operation(summary = "更新产品物模型")
|
||||||
|
@PreAuthorize("@ss.hasPermission('iot:think-model-function:update')")
|
||||||
|
public CommonResult<Boolean> updateThinkModelFunction(@Valid @RequestBody IotThinkModelFunctionSaveReqVO updateReqVO) {
|
||||||
|
thinkModelFunctionService.updateThinkModelFunction(updateReqVO);
|
||||||
|
return success(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@DeleteMapping("/delete")
|
||||||
|
@Operation(summary = "删除产品物模型")
|
||||||
|
@Parameter(name = "id", description = "编号", required = true)
|
||||||
|
@PreAuthorize("@ss.hasPermission('iot:think-model-function:delete')")
|
||||||
|
public CommonResult<Boolean> deleteThinkModelFunction(@RequestParam("id") Long id) {
|
||||||
|
thinkModelFunctionService.deleteThinkModelFunction(id);
|
||||||
|
return success(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/get")
|
||||||
|
@Operation(summary = "获得产品物模型")
|
||||||
|
@Parameter(name = "id", description = "编号", required = true)
|
||||||
|
@PreAuthorize("@ss.hasPermission('iot:think-model-function:query')")
|
||||||
|
public CommonResult<IotThinkModelFunctionRespVO> getThinkModelFunction(@RequestParam("id") Long id) {
|
||||||
|
IotThinkModelFunctionDO function = thinkModelFunctionService.getThinkModelFunction(id);
|
||||||
|
return success(IotThinkModelFunctionConvert.INSTANCE.convert(function));
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/list-by-product-id")
|
||||||
|
@Operation(summary = "获得产品物模型")
|
||||||
|
@Parameter(name = "productId", description = "产品ID", required = true, example = "1024")
|
||||||
|
@PreAuthorize("@ss.hasPermission('iot:think-model-function:query')")
|
||||||
|
public CommonResult<List<IotThinkModelFunctionRespVO>> getThinkModelFunctionListByProductId(@RequestParam("productId") Long productId) {
|
||||||
|
List<IotThinkModelFunctionDO> list = thinkModelFunctionService.getThinkModelFunctionListByProductId(productId);
|
||||||
|
return success(IotThinkModelFunctionConvert.INSTANCE.convertList(list));
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/page")
|
||||||
|
@Operation(summary = "获得产品物模型分页")
|
||||||
|
@PreAuthorize("@ss.hasPermission('iot:think-model-function:query')")
|
||||||
|
public CommonResult<PageResult<IotThinkModelFunctionRespVO>> getThinkModelFunctionPage(@Valid IotThinkModelFunctionPageReqVO pageReqVO) {
|
||||||
|
PageResult<IotThinkModelFunctionDO> pageResult = thinkModelFunctionService.getThinkModelFunctionPage(pageReqVO);
|
||||||
|
return success(BeanUtils.toBean(pageResult, IotThinkModelFunctionRespVO.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
package cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.dataType.ThingModelArgument;
|
||||||
|
import lombok.Data;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class ThingModelEvent {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 事件标识符
|
||||||
|
*/
|
||||||
|
private String identifier;
|
||||||
|
/**
|
||||||
|
* 事件名称
|
||||||
|
*/
|
||||||
|
private String name;
|
||||||
|
/**
|
||||||
|
* 事件描述
|
||||||
|
*/
|
||||||
|
private String description;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 事件类型
|
||||||
|
*
|
||||||
|
* "info"、"alert"、"error"
|
||||||
|
*/
|
||||||
|
private String type;
|
||||||
|
private List<ThingModelArgument> outputData;
|
||||||
|
private String method;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
package cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.dataType.ThingModelDataType;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class ThingModelProperty {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 属性标识符
|
||||||
|
*/
|
||||||
|
private String identifier;
|
||||||
|
/**
|
||||||
|
* 属性名称
|
||||||
|
*/
|
||||||
|
private String name;
|
||||||
|
/**
|
||||||
|
* 属性描述
|
||||||
|
*/
|
||||||
|
private String description;
|
||||||
|
|
||||||
|
private String accessMode; // "rw"、"r"、"w"
|
||||||
|
private Boolean required;
|
||||||
|
// TODO @haohao:这个是不是 dataSpecs 和 dataSpecsList?https://help.aliyun.com/zh/iot/developer-reference/api-a99t11
|
||||||
|
private ThingModelDataType dataType;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,33 @@
|
|||||||
|
package cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.dataType.ThingModelArgument;
|
||||||
|
import lombok.Data;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class ThingModelService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 服务标识符
|
||||||
|
*/
|
||||||
|
private String identifier;
|
||||||
|
/**
|
||||||
|
* 服务名称
|
||||||
|
*/
|
||||||
|
private String name;
|
||||||
|
/**
|
||||||
|
* 服务描述
|
||||||
|
*/
|
||||||
|
private String description;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 调用类型
|
||||||
|
*
|
||||||
|
* "sync"、"async"
|
||||||
|
*/
|
||||||
|
private String callType;
|
||||||
|
private List<ThingModelArgument> inputData;
|
||||||
|
private List<ThingModelArgument> outputData;
|
||||||
|
private String method;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
package cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.dataType;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class ThingModelArgument {
|
||||||
|
|
||||||
|
private String identifier;
|
||||||
|
private String name;
|
||||||
|
private ThingModelDataType dataType;
|
||||||
|
/**
|
||||||
|
* 用于区分输入或输出参数,"input" 或 "output"
|
||||||
|
*/
|
||||||
|
private String direction;
|
||||||
|
private String description;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
package cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.dataType;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class ThingModelArraySpecs {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数组长度
|
||||||
|
*/
|
||||||
|
private int size;
|
||||||
|
/**
|
||||||
|
* 数组元素的类型
|
||||||
|
*/
|
||||||
|
private ThingModelDataType item;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
package cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.dataType;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
// TODO @haohao:这个是不是和别的类,不太统一哈
|
||||||
|
@Data
|
||||||
|
public class ThingModelArrayType extends ThingModelDataType {
|
||||||
|
|
||||||
|
private ThingModelArraySpecs specs;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,12 @@
|
|||||||
|
package cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.dataType;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
public class ThingModelBoolType extends ThingModelDataType {
|
||||||
|
|
||||||
|
// Bool 类型一般不需要额外的 specs
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,24 @@
|
|||||||
|
package cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.dataType;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonSubTypes;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type", visible = true)
|
||||||
|
@JsonSubTypes({
|
||||||
|
@JsonSubTypes.Type(value = ThingModelIntType.class, name = "int"),
|
||||||
|
@JsonSubTypes.Type(value = ThingModelFloatType.class, name = "float"),
|
||||||
|
@JsonSubTypes.Type(value = ThingModelDoubleType.class, name = "double"),
|
||||||
|
@JsonSubTypes.Type(value = ThingModelTextType.class, name = "text"),
|
||||||
|
@JsonSubTypes.Type(value = ThingModelDateType.class, name = "date"),
|
||||||
|
@JsonSubTypes.Type(value = ThingModelBoolType.class, name = "bool"),
|
||||||
|
@JsonSubTypes.Type(value = ThingModelEnumType.class, name = "enum"),
|
||||||
|
@JsonSubTypes.Type(value = ThingModelStructType.class, name = "struct"),
|
||||||
|
@JsonSubTypes.Type(value = ThingModelArrayType.class, name = "array")
|
||||||
|
})
|
||||||
|
public abstract class ThingModelDataType {
|
||||||
|
|
||||||
|
private String type;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
package cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.dataType;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class ThingModelDateType extends ThingModelDataType {
|
||||||
|
|
||||||
|
// Date 类型一般不需要额外的 specs
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
package cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.dataType;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class ThingModelDoubleType extends ThingModelDataType {
|
||||||
|
private ThingModelDoubleSpecs specs;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
class ThingModelDoubleSpecs {
|
||||||
|
|
||||||
|
private Double min;
|
||||||
|
private Double max;
|
||||||
|
private Double step;
|
||||||
|
private String unit;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,15 @@
|
|||||||
|
package cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.dataType;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class ThingModelEnumType extends ThingModelDataType {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 枚举值和描述的键值对
|
||||||
|
*/
|
||||||
|
private Map<String, String> specs;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,20 @@
|
|||||||
|
package cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.dataType;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
public class ThingModelFloatType extends ThingModelDataType {
|
||||||
|
private ThingModelFloatSpecs specs;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
class ThingModelFloatSpecs {
|
||||||
|
|
||||||
|
private Float min;
|
||||||
|
private Float max;
|
||||||
|
private Float step;
|
||||||
|
private String unit;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
package cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.dataType;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class ThingModelIntType extends ThingModelDataType {
|
||||||
|
private ThingModelIntSpecs specs;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
class ThingModelIntSpecs {
|
||||||
|
|
||||||
|
private Integer min;
|
||||||
|
private Integer max;
|
||||||
|
private Integer step;
|
||||||
|
private String unit;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
package cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.dataType;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class ThingModelStructField {
|
||||||
|
|
||||||
|
private String identifier;
|
||||||
|
private String name;
|
||||||
|
private ThingModelDataType dataType;
|
||||||
|
private String description;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
package cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.dataType;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class ThingModelStructType extends ThingModelDataType {
|
||||||
|
|
||||||
|
private List<ThingModelStructField> specs;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,20 @@
|
|||||||
|
package cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.dataType;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class ThingModelTextType extends ThingModelDataType {
|
||||||
|
|
||||||
|
private ThingModelTextSpecs specs;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
class ThingModelTextSpecs {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 最大长度
|
||||||
|
*/
|
||||||
|
private Integer length;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
package cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.vo;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||||
|
import cn.iocoder.yudao.framework.common.validation.InEnum;
|
||||||
|
import cn.iocoder.yudao.module.iot.enums.product.IotProductFunctionTypeEnum;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.ToString;
|
||||||
|
|
||||||
|
@Schema(description = "管理后台 - IoT 产品物模型分页 Request VO")
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@ToString(callSuper = true)
|
||||||
|
public class IotThinkModelFunctionPageReqVO extends PageParam {
|
||||||
|
|
||||||
|
@Schema(description = "功能标识")
|
||||||
|
private String identifier;
|
||||||
|
|
||||||
|
@Schema(description = "功能名称", example = "张三")
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@Schema(description = "功能类型", example = "1")
|
||||||
|
@InEnum(IotProductFunctionTypeEnum.class)
|
||||||
|
private Integer type;
|
||||||
|
|
||||||
|
@Schema(description = "产品ID", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||||
|
@NotNull(message = "产品ID不能为空")
|
||||||
|
private Long productId;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,55 @@
|
|||||||
|
package cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.vo;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.ThingModelEvent;
|
||||||
|
import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.ThingModelProperty;
|
||||||
|
import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.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;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Schema(description = "管理后台 - IoT 产品物模型 Response VO")
|
||||||
|
@Data
|
||||||
|
@ExcelIgnoreUnannotated
|
||||||
|
public class IotThinkModelFunctionRespVO {
|
||||||
|
|
||||||
|
@Schema(description = "产品ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "21816")
|
||||||
|
@ExcelProperty("产品ID")
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@Schema(description = "产品标识", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||||
|
private Long productId;
|
||||||
|
|
||||||
|
@Schema(description = "产品标识", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||||
|
@ExcelProperty("产品标识")
|
||||||
|
private String productKey;
|
||||||
|
|
||||||
|
@Schema(description = "功能标识", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||||
|
private String identifier;
|
||||||
|
|
||||||
|
@Schema(description = "功能名称", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@Schema(description = "功能描述", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||||
|
private String description;
|
||||||
|
|
||||||
|
@Schema(description = "功能类型", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||||
|
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,53 @@
|
|||||||
|
package cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.vo;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.framework.common.validation.InEnum;
|
||||||
|
import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.ThingModelEvent;
|
||||||
|
import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.ThingModelProperty;
|
||||||
|
import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.ThingModelService;
|
||||||
|
import cn.iocoder.yudao.module.iot.enums.product.IotProductFunctionTypeEnum;
|
||||||
|
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 IotThinkModelFunctionSaveReqVO {
|
||||||
|
|
||||||
|
@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)
|
||||||
|
@NotEmpty(message = "产品标识不能为空")
|
||||||
|
private String productKey;
|
||||||
|
|
||||||
|
@Schema(description = "功能标识", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||||
|
@NotEmpty(message = "功能标识不能为空")
|
||||||
|
private String identifier;
|
||||||
|
|
||||||
|
@Schema(description = "功能名称", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||||
|
@NotEmpty(message = "功能名称不能为空")
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@Schema(description = "功能描述", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||||
|
private String description;
|
||||||
|
|
||||||
|
@Schema(description = "功能类型", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||||
|
@NotNull(message = "功能类型不能为空")
|
||||||
|
@InEnum(IotProductFunctionTypeEnum.class)
|
||||||
|
private Integer type;
|
||||||
|
|
||||||
|
@Schema(description = "属性", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||||
|
private ThingModelProperty property;
|
||||||
|
|
||||||
|
@Schema(description = "服务", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||||
|
private ThingModelService service;
|
||||||
|
|
||||||
|
@Schema(description = "事件", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||||
|
private ThingModelEvent event;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,6 @@
|
|||||||
|
/**
|
||||||
|
* 提供 RESTful API 给前端:
|
||||||
|
* 1. admin 包:提供给管理后台 yudao-ui-admin 前端项目
|
||||||
|
* 2. app 包:提供给用户 APP yudao-ui-app 前端项目,它的 Controller 和 VO 都要添加 App 前缀,用于和管理后台进行区分
|
||||||
|
*/
|
||||||
|
package cn.iocoder.yudao.module.iot.controller;
|
@ -0,0 +1 @@
|
|||||||
|
package cn.iocoder.yudao.module.iot.convert;
|
@ -0,0 +1,57 @@
|
|||||||
|
package cn.iocoder.yudao.module.iot.convert.thinkmodelfunction;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.ThingModelEvent;
|
||||||
|
import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.ThingModelProperty;
|
||||||
|
import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.ThingModelService;
|
||||||
|
import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.vo.IotThinkModelFunctionRespVO;
|
||||||
|
import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.vo.IotThinkModelFunctionSaveReqVO;
|
||||||
|
import cn.iocoder.yudao.module.iot.dal.dataobject.thinkmodelfunction.IotThinkModelFunctionDO;
|
||||||
|
import cn.iocoder.yudao.module.iot.enums.product.IotProductFunctionTypeEnum;
|
||||||
|
import org.mapstruct.Mapper;
|
||||||
|
import org.mapstruct.Mapping;
|
||||||
|
import org.mapstruct.factory.Mappers;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
@Mapper
|
||||||
|
public interface IotThinkModelFunctionConvert {
|
||||||
|
|
||||||
|
IotThinkModelFunctionConvert INSTANCE = Mappers.getMapper(IotThinkModelFunctionConvert.class);
|
||||||
|
|
||||||
|
// 将 SaveReqVO 转换为 DO
|
||||||
|
@Mapping(target = "property", expression = "java(convertToProperty(bean))")
|
||||||
|
@Mapping(target = "event", expression = "java(convertToEvent(bean))")
|
||||||
|
@Mapping(target = "service", expression = "java(convertToService(bean))")
|
||||||
|
IotThinkModelFunctionDO convert(IotThinkModelFunctionSaveReqVO bean);
|
||||||
|
|
||||||
|
default ThingModelProperty convertToProperty(IotThinkModelFunctionSaveReqVO bean) {
|
||||||
|
if (Objects.equals(bean.getType(), IotProductFunctionTypeEnum.PROPERTY.getType())) {
|
||||||
|
return bean.getProperty();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
default ThingModelEvent convertToEvent(IotThinkModelFunctionSaveReqVO bean) {
|
||||||
|
if (Objects.equals(bean.getType(), IotProductFunctionTypeEnum.EVENT.getType())) {
|
||||||
|
return bean.getEvent();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
default ThingModelService convertToService(IotThinkModelFunctionSaveReqVO bean) {
|
||||||
|
if (Objects.equals(bean.getType(), IotProductFunctionTypeEnum.SERVICE.getType())) {
|
||||||
|
return bean.getService();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 将 DO 转换为 RespVO
|
||||||
|
@Mapping(target = "property", source = "property")
|
||||||
|
@Mapping(target = "event", source = "event")
|
||||||
|
@Mapping(target = "service", source = "service")
|
||||||
|
IotThinkModelFunctionRespVO convert(IotThinkModelFunctionDO bean);
|
||||||
|
|
||||||
|
// 批量转换
|
||||||
|
List<IotThinkModelFunctionRespVO> convertList(List<IotThinkModelFunctionDO> list);
|
||||||
|
}
|
@ -0,0 +1,152 @@
|
|||||||
|
package cn.iocoder.yudao.module.iot.dal.dataobject.device;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||||
|
import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO;
|
||||||
|
import cn.iocoder.yudao.module.iot.enums.device.IotDeviceStatusEnum;
|
||||||
|
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import lombok.*;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IoT 设备 DO
|
||||||
|
*
|
||||||
|
* @author haohao
|
||||||
|
*/
|
||||||
|
@TableName("iot_device")
|
||||||
|
@KeySequence("iot_device_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@ToString(callSuper = true)
|
||||||
|
@Builder
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class IotDeviceDO extends BaseDO {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设备 ID,主键,自增
|
||||||
|
*/
|
||||||
|
@TableId
|
||||||
|
private Long id;
|
||||||
|
/**
|
||||||
|
* 设备唯一标识符,全局唯一,用于识别设备
|
||||||
|
*/
|
||||||
|
private String deviceKey;
|
||||||
|
/**
|
||||||
|
* 设备名称,在产品内唯一,用于标识设备
|
||||||
|
*/
|
||||||
|
private String deviceName;
|
||||||
|
/**
|
||||||
|
* 设备备注名称
|
||||||
|
*/
|
||||||
|
private String nickname;
|
||||||
|
/**
|
||||||
|
* 设备序列号
|
||||||
|
*/
|
||||||
|
private String serialNumber;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 产品编号
|
||||||
|
* <p>
|
||||||
|
* 关联 {@link IotProductDO#getId()}
|
||||||
|
*/
|
||||||
|
private Long productId;
|
||||||
|
/**
|
||||||
|
* 产品标识
|
||||||
|
* <p>
|
||||||
|
* 冗余 {@link IotProductDO#getProductKey()}
|
||||||
|
*/
|
||||||
|
private String productKey;
|
||||||
|
/**
|
||||||
|
* 设备类型
|
||||||
|
* <p>
|
||||||
|
* 冗余 {@link IotProductDO#getDeviceType()}
|
||||||
|
*/
|
||||||
|
private Integer deviceType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设备状态
|
||||||
|
* <p>
|
||||||
|
* 枚举 {@link IotDeviceStatusEnum}
|
||||||
|
*/
|
||||||
|
private Integer status;
|
||||||
|
/**
|
||||||
|
* 网关设备编号
|
||||||
|
* <p>
|
||||||
|
* 子设备需要关联的网关设备 ID
|
||||||
|
* <p>
|
||||||
|
* 关联 {@link IotDeviceDO#getId()}
|
||||||
|
*/
|
||||||
|
private Long gatewayId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设备状态最后更新时间
|
||||||
|
*/
|
||||||
|
private LocalDateTime statusLastUpdateTime;
|
||||||
|
/**
|
||||||
|
* 最后上线时间
|
||||||
|
*/
|
||||||
|
private LocalDateTime lastOnlineTime;
|
||||||
|
/**
|
||||||
|
* 最后离线时间
|
||||||
|
*/
|
||||||
|
private LocalDateTime lastOfflineTime;
|
||||||
|
/**
|
||||||
|
* 设备激活时间
|
||||||
|
*/
|
||||||
|
private LocalDateTime activeTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设备的 IP 地址
|
||||||
|
*/
|
||||||
|
private String ip;
|
||||||
|
/**
|
||||||
|
* 设备的固件版本
|
||||||
|
*/
|
||||||
|
private String firmwareVersion;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设备密钥,用于设备认证,需安全存储
|
||||||
|
*/
|
||||||
|
private String deviceSecret;
|
||||||
|
/**
|
||||||
|
* MQTT 客户端 ID
|
||||||
|
*/
|
||||||
|
private String mqttClientId;
|
||||||
|
/**
|
||||||
|
* MQTT 用户名
|
||||||
|
*/
|
||||||
|
private String mqttUsername;
|
||||||
|
/**
|
||||||
|
* MQTT 密码
|
||||||
|
*/
|
||||||
|
private String mqttPassword;
|
||||||
|
/**
|
||||||
|
* 认证类型(如一机一密、动态注册)
|
||||||
|
*/
|
||||||
|
// TODO @haohao:是不是要枚举哈
|
||||||
|
private String authType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设备位置的纬度
|
||||||
|
*/
|
||||||
|
private BigDecimal latitude;
|
||||||
|
/**
|
||||||
|
* 设备位置的经度
|
||||||
|
*/
|
||||||
|
private BigDecimal longitude;
|
||||||
|
/**
|
||||||
|
* 地区编码
|
||||||
|
* <p>
|
||||||
|
* 关联 Area 的 id
|
||||||
|
*/
|
||||||
|
private Integer areaId;
|
||||||
|
/**
|
||||||
|
* 设备详细地址
|
||||||
|
*/
|
||||||
|
private String address;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,93 @@
|
|||||||
|
package cn.iocoder.yudao.module.iot.dal.dataobject.product;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.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 ahh
|
||||||
|
*/
|
||||||
|
@TableName("iot_product")
|
||||||
|
@KeySequence("iot_product_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@ToString(callSuper = true)
|
||||||
|
@Builder
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class IotProductDO extends BaseDO {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 产品ID
|
||||||
|
*/
|
||||||
|
@TableId
|
||||||
|
private Long id;
|
||||||
|
/**
|
||||||
|
* 产品名称
|
||||||
|
*/
|
||||||
|
private String name;
|
||||||
|
// TODO @haohao:这个字段,要不改成 identifier,和阿里云更统一些
|
||||||
|
/**
|
||||||
|
* 产品标识
|
||||||
|
*/
|
||||||
|
private String productKey;
|
||||||
|
/**
|
||||||
|
* 产品所属品类编号
|
||||||
|
* <p>
|
||||||
|
* TODO 外键:后续加
|
||||||
|
*/
|
||||||
|
private Long categoryId;
|
||||||
|
/**
|
||||||
|
* 产品描述
|
||||||
|
*/
|
||||||
|
private String description;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 产品状态
|
||||||
|
* <p>
|
||||||
|
* 枚举 {@link cn.iocoder.yudao.module.iot.enums.product.IotProductStatusEnum}
|
||||||
|
*/
|
||||||
|
private Integer status;
|
||||||
|
/**
|
||||||
|
* 设备类型
|
||||||
|
* <p>
|
||||||
|
* 枚举 {@link cn.iocoder.yudao.module.iot.enums.product.IotProductDeviceTypeEnum}
|
||||||
|
*/
|
||||||
|
private Integer deviceType;
|
||||||
|
/**
|
||||||
|
* 联网方式
|
||||||
|
* <p>
|
||||||
|
* 枚举 {@link cn.iocoder.yudao.module.iot.enums.product.IotNetTypeEnum}
|
||||||
|
*/
|
||||||
|
private Integer netType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 接入网关协议
|
||||||
|
* <p>
|
||||||
|
* 枚举 {@link cn.iocoder.yudao.module.iot.enums.product.IotProtocolTypeEnum}
|
||||||
|
*/
|
||||||
|
private Integer protocolType;
|
||||||
|
/**
|
||||||
|
* 协议编号
|
||||||
|
* <p>
|
||||||
|
* TODO 外键:后续加
|
||||||
|
*/
|
||||||
|
private Long protocolId;
|
||||||
|
/**
|
||||||
|
* 数据格式
|
||||||
|
* <p>
|
||||||
|
* 枚举 {@link cn.iocoder.yudao.module.iot.enums.product.IotDataFormatEnum}
|
||||||
|
*/
|
||||||
|
private Integer dataFormat;
|
||||||
|
/**
|
||||||
|
* 数据校验级别
|
||||||
|
* <p>
|
||||||
|
* 枚举 {@link cn.iocoder.yudao.module.iot.enums.product.IotValidateTypeEnum}
|
||||||
|
*/
|
||||||
|
private Integer validateType;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,91 @@
|
|||||||
|
package cn.iocoder.yudao.module.iot.dal.dataobject.thinkmodelfunction;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||||
|
import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.ThingModelEvent;
|
||||||
|
import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.ThingModelProperty;
|
||||||
|
import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.ThingModelService;
|
||||||
|
import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO;
|
||||||
|
import cn.iocoder.yudao.module.iot.enums.product.IotProductFunctionTypeEnum;
|
||||||
|
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 com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IoT 产品物模型功能 DO
|
||||||
|
* <p>
|
||||||
|
* 每个 {@link IotProductDO} 和 {@link IotThinkModelFunctionDO} 是“一对多”的关系,它的每个属性、事件、服务都对应一条记录
|
||||||
|
*
|
||||||
|
* @author 芋道源码
|
||||||
|
*/
|
||||||
|
@TableName(value = "iot_think_model_function", autoResultMap = true)
|
||||||
|
@KeySequence("iot_think_model_function_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class IotThinkModelFunctionDO extends BaseDO {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 物模型功能编号
|
||||||
|
*/
|
||||||
|
@TableId
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 功能标识
|
||||||
|
*/
|
||||||
|
private String identifier;
|
||||||
|
/**
|
||||||
|
* 功能名称
|
||||||
|
*/
|
||||||
|
private String name;
|
||||||
|
/**
|
||||||
|
* 功能描述
|
||||||
|
*/
|
||||||
|
private String description;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 产品标识
|
||||||
|
* <p>
|
||||||
|
* 关联 {@link IotProductDO#getId()}
|
||||||
|
*/
|
||||||
|
private Long productId;
|
||||||
|
/**
|
||||||
|
* 产品标识
|
||||||
|
* <p>
|
||||||
|
* 关联 {@link IotProductDO#getProductKey()}
|
||||||
|
*/
|
||||||
|
private String productKey;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 功能类型
|
||||||
|
* <p>
|
||||||
|
* 枚举 {@link IotProductFunctionTypeEnum}
|
||||||
|
*/
|
||||||
|
private Integer type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 属性
|
||||||
|
*/
|
||||||
|
@TableField(typeHandler = JacksonTypeHandler.class)
|
||||||
|
private ThingModelProperty property;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 事件
|
||||||
|
*/
|
||||||
|
@TableField(typeHandler = JacksonTypeHandler.class)
|
||||||
|
private ThingModelEvent event;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 服务
|
||||||
|
*/
|
||||||
|
@TableField(typeHandler = JacksonTypeHandler.class)
|
||||||
|
private ThingModelService service;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,53 @@
|
|||||||
|
package cn.iocoder.yudao.module.iot.dal.mysql.device;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
|
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||||
|
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||||
|
import cn.iocoder.yudao.module.iot.controller.admin.device.vo.IotDevicePageReqVO;
|
||||||
|
import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IoT 设备 Mapper
|
||||||
|
*
|
||||||
|
* @author 芋道源码
|
||||||
|
*/
|
||||||
|
@Mapper
|
||||||
|
public interface IotDeviceMapper extends BaseMapperX<IotDeviceDO> {
|
||||||
|
|
||||||
|
default PageResult<IotDeviceDO> selectPage(IotDevicePageReqVO reqVO) {
|
||||||
|
return selectPage(reqVO, new LambdaQueryWrapperX<IotDeviceDO>()
|
||||||
|
.eqIfPresent(IotDeviceDO::getDeviceKey, reqVO.getDeviceKey())
|
||||||
|
.likeIfPresent(IotDeviceDO::getDeviceName, reqVO.getDeviceName())
|
||||||
|
.eqIfPresent(IotDeviceDO::getProductId, reqVO.getProductId())
|
||||||
|
.eqIfPresent(IotDeviceDO::getProductKey, reqVO.getProductKey())
|
||||||
|
.eqIfPresent(IotDeviceDO::getDeviceType, reqVO.getDeviceType())
|
||||||
|
.likeIfPresent(IotDeviceDO::getNickname, reqVO.getNickname())
|
||||||
|
.eqIfPresent(IotDeviceDO::getGatewayId, reqVO.getGatewayId())
|
||||||
|
.eqIfPresent(IotDeviceDO::getStatus, reqVO.getStatus())
|
||||||
|
.betweenIfPresent(IotDeviceDO::getStatusLastUpdateTime, reqVO.getStatusLastUpdateTime())
|
||||||
|
.betweenIfPresent(IotDeviceDO::getLastOnlineTime, reqVO.getLastOnlineTime())
|
||||||
|
.betweenIfPresent(IotDeviceDO::getLastOfflineTime, reqVO.getLastOfflineTime())
|
||||||
|
.betweenIfPresent(IotDeviceDO::getActiveTime, reqVO.getActiveTime())
|
||||||
|
.eqIfPresent(IotDeviceDO::getDeviceSecret, reqVO.getDeviceSecret())
|
||||||
|
.eqIfPresent(IotDeviceDO::getMqttClientId, reqVO.getMqttClientId())
|
||||||
|
.likeIfPresent(IotDeviceDO::getMqttUsername, reqVO.getMqttUsername())
|
||||||
|
.eqIfPresent(IotDeviceDO::getMqttPassword, reqVO.getMqttPassword())
|
||||||
|
.eqIfPresent(IotDeviceDO::getAuthType, reqVO.getAuthType())
|
||||||
|
.betweenIfPresent(IotDeviceDO::getCreateTime, reqVO.getCreateTime())
|
||||||
|
.orderByDesc(IotDeviceDO::getId));
|
||||||
|
}
|
||||||
|
|
||||||
|
default IotDeviceDO selectByProductKeyAndDeviceName(String productKey, String deviceName) {
|
||||||
|
return selectOne(IotDeviceDO::getProductKey, productKey,
|
||||||
|
IotDeviceDO::getDeviceName, deviceName);
|
||||||
|
}
|
||||||
|
|
||||||
|
default long selectCountByGatewayId(Long id) {
|
||||||
|
return selectCount(IotDeviceDO::getGatewayId, id);
|
||||||
|
}
|
||||||
|
|
||||||
|
default Long selectCountByProductId(Long productId) {
|
||||||
|
return selectCount(IotDeviceDO::getProductId, productId);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,29 @@
|
|||||||
|
package cn.iocoder.yudao.module.iot.dal.mysql.product;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
|
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||||
|
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||||
|
import cn.iocoder.yudao.module.iot.controller.admin.product.vo.IotProductPageReqVO;
|
||||||
|
import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IoT 产品 Mapper
|
||||||
|
*
|
||||||
|
* @author ahh
|
||||||
|
*/
|
||||||
|
@Mapper
|
||||||
|
public interface IotProductMapper extends BaseMapperX<IotProductDO> {
|
||||||
|
|
||||||
|
default PageResult<IotProductDO> selectPage(IotProductPageReqVO reqVO) {
|
||||||
|
return selectPage(reqVO, new LambdaQueryWrapperX<IotProductDO>()
|
||||||
|
.likeIfPresent(IotProductDO::getName, reqVO.getName())
|
||||||
|
.likeIfPresent(IotProductDO::getProductKey, reqVO.getProductKey())
|
||||||
|
.orderByDesc(IotProductDO::getId));
|
||||||
|
}
|
||||||
|
|
||||||
|
default IotProductDO selectByProductKey(String productKey) {
|
||||||
|
return selectOne(new LambdaQueryWrapperX<IotProductDO>().eq(IotProductDO::getProductKey, productKey));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,58 @@
|
|||||||
|
package cn.iocoder.yudao.module.iot.dal.mysql.thinkmodelfunction;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
|
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||||
|
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||||
|
import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.vo.IotThinkModelFunctionPageReqVO;
|
||||||
|
import cn.iocoder.yudao.module.iot.dal.dataobject.thinkmodelfunction.IotThinkModelFunctionDO;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IoT 产品物模型 Mapper
|
||||||
|
*
|
||||||
|
* @author 芋道源码
|
||||||
|
*/
|
||||||
|
@Mapper
|
||||||
|
public interface IotThinkModelFunctionMapper extends BaseMapperX<IotThinkModelFunctionDO> {
|
||||||
|
|
||||||
|
default PageResult<IotThinkModelFunctionDO> selectPage(IotThinkModelFunctionPageReqVO reqVO) {
|
||||||
|
return selectPage(reqVO, new LambdaQueryWrapperX<IotThinkModelFunctionDO>()
|
||||||
|
.eqIfPresent(IotThinkModelFunctionDO::getIdentifier, reqVO.getIdentifier())
|
||||||
|
.likeIfPresent(IotThinkModelFunctionDO::getName, reqVO.getName())
|
||||||
|
.eqIfPresent(IotThinkModelFunctionDO::getType, reqVO.getType())
|
||||||
|
.eqIfPresent(IotThinkModelFunctionDO::getProductId, reqVO.getProductId())
|
||||||
|
.notIn(IotThinkModelFunctionDO::getIdentifier, "get", "set", "post")
|
||||||
|
.orderByDesc(IotThinkModelFunctionDO::getId));
|
||||||
|
}
|
||||||
|
|
||||||
|
default IotThinkModelFunctionDO selectByProductIdAndIdentifier(Long productId, String identifier) {
|
||||||
|
return selectOne(IotThinkModelFunctionDO::getProductId, productId,
|
||||||
|
IotThinkModelFunctionDO::getIdentifier, identifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
default List<IotThinkModelFunctionDO> selectListByProductId(Long productId) {
|
||||||
|
return selectList(IotThinkModelFunctionDO::getProductId, productId);
|
||||||
|
}
|
||||||
|
|
||||||
|
default List<IotThinkModelFunctionDO> selectListByProductIdAndType(Long productId, Integer type) {
|
||||||
|
return selectList(IotThinkModelFunctionDO::getProductId, productId,
|
||||||
|
IotThinkModelFunctionDO::getType, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
default List<IotThinkModelFunctionDO> selectListByProductIdAndIdentifiersAndTypes(Long productId,
|
||||||
|
List<String> identifiers,
|
||||||
|
List<Integer> types){
|
||||||
|
return selectList(new LambdaQueryWrapperX<IotThinkModelFunctionDO>()
|
||||||
|
.eq(IotThinkModelFunctionDO::getProductId, productId)
|
||||||
|
.in(IotThinkModelFunctionDO::getIdentifier, identifiers)
|
||||||
|
.in(IotThinkModelFunctionDO::getType, types));
|
||||||
|
}
|
||||||
|
|
||||||
|
default IotThinkModelFunctionDO selectByProductIdAndName(Long productId, String name) {
|
||||||
|
return selectOne(IotThinkModelFunctionDO::getProductId, productId,
|
||||||
|
IotThinkModelFunctionDO::getName, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,54 @@
|
|||||||
|
package cn.iocoder.yudao.module.iot.emq.callback;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.module.iot.emq.client.EmqxClient;
|
||||||
|
import cn.iocoder.yudao.module.iot.emq.service.EmqxService;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
|
||||||
|
import org.eclipse.paho.client.mqttv3.MqttCallbackExtended;
|
||||||
|
import org.eclipse.paho.client.mqttv3.MqttMessage;
|
||||||
|
import org.springframework.context.annotation.Lazy;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
// TODO @芋艿:详细再瞅瞅
|
||||||
|
/**
|
||||||
|
* 用于处理MQTT连接的回调,如连接断开、消息到达、消息发布完成、连接完成等事件。
|
||||||
|
*
|
||||||
|
* @author ahh
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Component
|
||||||
|
public class EmqxCallback implements MqttCallbackExtended {
|
||||||
|
|
||||||
|
@Lazy
|
||||||
|
@Resource
|
||||||
|
private EmqxService emqxService;
|
||||||
|
|
||||||
|
@Lazy
|
||||||
|
@Resource
|
||||||
|
private EmqxClient emqxClient;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void connectionLost(Throwable throwable) {
|
||||||
|
log.info("MQTT 连接断开", throwable);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void messageArrived(String topic, MqttMessage mqttMessage) {
|
||||||
|
emqxService.subscribeCallback(topic, mqttMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void deliveryComplete(IMqttDeliveryToken iMqttDeliveryToken) {
|
||||||
|
log.info("消息发送成功: {}", iMqttDeliveryToken.getMessageId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void connectComplete(boolean reconnect, String serverURI) {
|
||||||
|
log.info("MQTT 已连接到服务器: {}", serverURI);
|
||||||
|
emqxService.subscribe(emqxClient.getMqttClient());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,86 @@
|
|||||||
|
package cn.iocoder.yudao.module.iot.emq.client;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.module.iot.emq.callback.EmqxCallback;
|
||||||
|
import cn.iocoder.yudao.module.iot.emq.config.MqttConfig;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.eclipse.paho.client.mqttv3.MqttClient;
|
||||||
|
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
|
||||||
|
import org.eclipse.paho.client.mqttv3.MqttException;
|
||||||
|
import org.eclipse.paho.client.mqttv3.MqttMessage;
|
||||||
|
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MQTT客户端类,负责建立与MQTT服务器的连接,提供发布消息和订阅主题的功能
|
||||||
|
*
|
||||||
|
* @author ahh
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Data
|
||||||
|
@Component
|
||||||
|
public class EmqxClient {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private EmqxCallback emqxCallback;
|
||||||
|
@Resource
|
||||||
|
private MqttConfig mqttConfig;
|
||||||
|
|
||||||
|
private MqttClient mqttClient;
|
||||||
|
|
||||||
|
public void connect() {
|
||||||
|
if (mqttClient == null) {
|
||||||
|
createMqttClient();
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
mqttClient.connect(createMqttOptions());
|
||||||
|
log.info("MQTT客户端连接成功");
|
||||||
|
} catch (MqttException e) {
|
||||||
|
log.error("MQTT客户端连接失败", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createMqttClient() {
|
||||||
|
try {
|
||||||
|
mqttClient = new MqttClient(mqttConfig.getHostUrl(), "yudao" + mqttConfig.getClientId(), new MemoryPersistence());
|
||||||
|
mqttClient.setCallback(emqxCallback);
|
||||||
|
} catch (MqttException e) {
|
||||||
|
log.error("创建MQTT客户端失败", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private MqttConnectOptions createMqttOptions() {
|
||||||
|
MqttConnectOptions options = new MqttConnectOptions();
|
||||||
|
options.setUserName(mqttConfig.getUsername());
|
||||||
|
options.setPassword(mqttConfig.getPassword().toCharArray());
|
||||||
|
options.setConnectionTimeout(mqttConfig.getTimeout());
|
||||||
|
options.setKeepAliveInterval(mqttConfig.getKeepalive());
|
||||||
|
options.setCleanSession(mqttConfig.isClearSession());
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void publish(String topic, String message) {
|
||||||
|
try {
|
||||||
|
if (mqttClient == null || !mqttClient.isConnected()) {
|
||||||
|
connect();
|
||||||
|
}
|
||||||
|
mqttClient.publish(topic, new MqttMessage(message.getBytes()));
|
||||||
|
log.info("消息已发布到主题: {}", topic);
|
||||||
|
} catch (MqttException e) {
|
||||||
|
log.error("消息发布失败", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void subscribe(String topic) {
|
||||||
|
try {
|
||||||
|
if (mqttClient == null || !mqttClient.isConnected()) {
|
||||||
|
connect();
|
||||||
|
}
|
||||||
|
mqttClient.subscribe(topic);
|
||||||
|
log.info("订阅了主题: {}", topic);
|
||||||
|
} catch (MqttException e) {
|
||||||
|
log.error("订阅主题失败", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,68 @@
|
|||||||
|
package cn.iocoder.yudao.module.iot.emq.config;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
// TODO @芋艿:详细再瞅瞅
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 配置类,用于读取MQTT连接的配置信息,如用户名、密码、连接地址等
|
||||||
|
*
|
||||||
|
* @author ahh
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Component
|
||||||
|
@ConfigurationProperties("iot.emq")
|
||||||
|
public class MqttConfig {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户名
|
||||||
|
*/
|
||||||
|
private String username;
|
||||||
|
/**
|
||||||
|
* 密码
|
||||||
|
*/
|
||||||
|
private String password;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 连接地址
|
||||||
|
*/
|
||||||
|
private String hostUrl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 客户Id
|
||||||
|
*/
|
||||||
|
private String clientId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 默认连接话题
|
||||||
|
*/
|
||||||
|
private String defaultTopic;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 超时时间
|
||||||
|
*/
|
||||||
|
private int timeout;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保持连接数
|
||||||
|
*/
|
||||||
|
private int keepalive;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否清除session
|
||||||
|
*/
|
||||||
|
private boolean clearSession;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否共享订阅
|
||||||
|
*/
|
||||||
|
private boolean isShared;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分组共享订阅
|
||||||
|
*/
|
||||||
|
private boolean isSharedGroup;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,28 @@
|
|||||||
|
package cn.iocoder.yudao.module.iot.emq.service;
|
||||||
|
|
||||||
|
import org.eclipse.paho.client.mqttv3.MqttClient;
|
||||||
|
import org.eclipse.paho.client.mqttv3.MqttMessage;
|
||||||
|
|
||||||
|
// TODO @芋艿:在瞅瞅
|
||||||
|
/**
|
||||||
|
* 用于处理MQTT消息的具体业务逻辑,如订阅回调
|
||||||
|
*
|
||||||
|
* @author ahh
|
||||||
|
*/
|
||||||
|
public interface EmqxService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 订阅回调
|
||||||
|
*
|
||||||
|
* @param topic 主题
|
||||||
|
* @param mqttMessage 消息
|
||||||
|
*/
|
||||||
|
void subscribeCallback(String topic, MqttMessage mqttMessage);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 订阅主题
|
||||||
|
*
|
||||||
|
* @param client MQTT 客户端
|
||||||
|
*/
|
||||||
|
void subscribe(MqttClient client);
|
||||||
|
}
|
@ -0,0 +1,39 @@
|
|||||||
|
package cn.iocoder.yudao.module.iot.emq.service;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.eclipse.paho.client.mqttv3.MqttClient;
|
||||||
|
import org.eclipse.paho.client.mqttv3.MqttMessage;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
// TODO @芋艿:在瞅瞅
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用于处理MQTT消息的具体业务逻辑,如订阅回调
|
||||||
|
*
|
||||||
|
* @author ahh
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
public class EmqxServiceImpl implements EmqxService {
|
||||||
|
|
||||||
|
// TODO 多线程处理消息
|
||||||
|
@Override
|
||||||
|
public void subscribeCallback(String topic, MqttMessage mqttMessage) {
|
||||||
|
log.info("收到消息,主题: {}, 内容: {}", topic, new String(mqttMessage.getPayload()));
|
||||||
|
// 根据不同的主题,处理不同的业务逻辑
|
||||||
|
if (topic.contains("/property/post")) {
|
||||||
|
// 设备上报数据
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void subscribe(MqttClient client) {
|
||||||
|
try {
|
||||||
|
// 订阅默认主题,可以根据需要修改
|
||||||
|
// client.subscribe("$share/yudao/+/+/#", 1);
|
||||||
|
log.info("订阅默认主题成功");
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("订阅默认主题失败", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
package cn.iocoder.yudao.module.iot.emq.start;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.module.iot.emq.client.EmqxClient;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import org.springframework.boot.ApplicationArguments;
|
||||||
|
import org.springframework.boot.ApplicationRunner;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
// TODO @芋艿:在瞅瞅
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用于在应用启动时自动连接MQTT服务器
|
||||||
|
*
|
||||||
|
* @author ahh
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class EmqxStart implements ApplicationRunner {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private EmqxClient emqxClient;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run(ApplicationArguments applicationArguments) {
|
||||||
|
emqxClient.connect();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,6 @@
|
|||||||
|
/**
|
||||||
|
* 属于 iot 模块的 framework 封装
|
||||||
|
*
|
||||||
|
* @author ahh
|
||||||
|
*/
|
||||||
|
package cn.iocoder.yudao.module.iot.framework;
|
@ -0,0 +1,24 @@
|
|||||||
|
package cn.iocoder.yudao.module.iot.framework.web.config;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.framework.swagger.config.YudaoSwaggerAutoConfiguration;
|
||||||
|
import org.springdoc.core.models.GroupedOpenApi;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* iot 模块的 web 组件的 Configuration
|
||||||
|
*
|
||||||
|
* @author ahh
|
||||||
|
*/
|
||||||
|
@Configuration(proxyBeanMethods = false)
|
||||||
|
public class IotWebConfiguration {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* iot 模块的 API 分组
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public GroupedOpenApi iotGroupedOpenApi() {
|
||||||
|
return YudaoSwaggerAutoConfiguration.buildGroupedOpenApi("iot");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,4 @@
|
|||||||
|
/**
|
||||||
|
* iot 模块的 web 拓展封装
|
||||||
|
*/
|
||||||
|
package cn.iocoder.yudao.module.iot.framework.web;
|
@ -0,0 +1,227 @@
|
|||||||
|
package cn.iocoder.yudao.module.iot.service.device;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.IdUtil;
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
|
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||||
|
import cn.iocoder.yudao.module.iot.controller.admin.device.vo.IotDevicePageReqVO;
|
||||||
|
import cn.iocoder.yudao.module.iot.controller.admin.device.vo.IotDeviceSaveReqVO;
|
||||||
|
import cn.iocoder.yudao.module.iot.controller.admin.device.vo.IotDeviceStatusUpdateReqVO;
|
||||||
|
import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO;
|
||||||
|
import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO;
|
||||||
|
import cn.iocoder.yudao.module.iot.dal.mysql.device.IotDeviceMapper;
|
||||||
|
import cn.iocoder.yudao.module.iot.enums.device.IotDeviceStatusEnum;
|
||||||
|
import cn.iocoder.yudao.module.iot.service.product.IotProductService;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||||
|
import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IoT 设备 Service 实现类
|
||||||
|
*
|
||||||
|
* @author 芋道源码
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
@Validated
|
||||||
|
@Slf4j
|
||||||
|
public class DeviceServiceImpl implements IotDeviceService {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private IotDeviceMapper deviceMapper;
|
||||||
|
@Resource
|
||||||
|
private IotProductService productService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建 IoT 设备
|
||||||
|
*
|
||||||
|
* @param createReqVO 创建请求 VO
|
||||||
|
* @return 设备 ID
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public Long createDevice(IotDeviceSaveReqVO createReqVO) {
|
||||||
|
// 1.1 校验产品是否存在
|
||||||
|
IotProductDO product = productService.getProduct(createReqVO.getProductId());
|
||||||
|
if (product == null) {
|
||||||
|
throw exception(PRODUCT_NOT_EXISTS);
|
||||||
|
}
|
||||||
|
// 1.2 校验设备名称在同一产品下是否唯一
|
||||||
|
if (StrUtil.isBlank(createReqVO.getDeviceName())) {
|
||||||
|
createReqVO.setDeviceName(generateUniqueDeviceName(product.getProductKey()));
|
||||||
|
} else {
|
||||||
|
validateDeviceNameUnique(product.getProductKey(), createReqVO.getDeviceName());
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2.1 转换 VO 为 DO
|
||||||
|
IotDeviceDO device = BeanUtils.toBean(createReqVO, IotDeviceDO.class)
|
||||||
|
.setProductKey(product.getProductKey())
|
||||||
|
.setDeviceType(product.getDeviceType());
|
||||||
|
// 2.2 生成并设置必要的字段
|
||||||
|
device.setDeviceKey(generateUniqueDeviceKey());
|
||||||
|
device.setDeviceSecret(generateDeviceSecret());
|
||||||
|
device.setMqttClientId(generateMqttClientId());
|
||||||
|
device.setMqttUsername(generateMqttUsername(device.getDeviceName(), device.getProductKey()));
|
||||||
|
device.setMqttPassword(generateMqttPassword());
|
||||||
|
// 2.3 设置设备状态为未激活
|
||||||
|
device.setStatus(IotDeviceStatusEnum.INACTIVE.getStatus());
|
||||||
|
device.setStatusLastUpdateTime(LocalDateTime.now());
|
||||||
|
// 2.4 插入到数据库
|
||||||
|
deviceMapper.insert(device);
|
||||||
|
return device.getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验设备名称在同一产品下是否唯一
|
||||||
|
*
|
||||||
|
* @param productKey 产品 Key
|
||||||
|
* @param deviceName 设备名称
|
||||||
|
*/
|
||||||
|
private void validateDeviceNameUnique(String productKey, String deviceName) {
|
||||||
|
IotDeviceDO existingDevice = deviceMapper.selectByProductKeyAndDeviceName(productKey, deviceName);
|
||||||
|
if (existingDevice != null) {
|
||||||
|
throw exception(DEVICE_NAME_EXISTS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成唯一的 deviceKey
|
||||||
|
*
|
||||||
|
* @return 生成的 deviceKey
|
||||||
|
*/
|
||||||
|
private String generateUniqueDeviceKey() {
|
||||||
|
return UUID.randomUUID().toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成 deviceSecret
|
||||||
|
*
|
||||||
|
* @return 生成的 deviceSecret
|
||||||
|
*/
|
||||||
|
private String generateDeviceSecret() {
|
||||||
|
return IdUtil.fastSimpleUUID();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成 MQTT Client ID
|
||||||
|
*
|
||||||
|
* @return 生成的 MQTT Client ID
|
||||||
|
*/
|
||||||
|
private String generateMqttClientId() {
|
||||||
|
return UUID.randomUUID().toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成 MQTT Username
|
||||||
|
*
|
||||||
|
* @param deviceName 设备名称
|
||||||
|
* @param productKey 产品 Key
|
||||||
|
* @return 生成的 MQTT Username
|
||||||
|
*/
|
||||||
|
private String generateMqttUsername(String deviceName, String productKey) {
|
||||||
|
return deviceName + "&" + productKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成 MQTT Password
|
||||||
|
*
|
||||||
|
* @return 生成的 MQTT Password
|
||||||
|
*/
|
||||||
|
private String generateMqttPassword() {
|
||||||
|
// TODO @haohao:【后续优化】在实际应用中,建议使用更安全的方法生成 MQTT Password,如加密或哈希
|
||||||
|
return UUID.randomUUID().toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成唯一的 DeviceName
|
||||||
|
*
|
||||||
|
* @param productKey 产品标识
|
||||||
|
* @return 生成的唯一 DeviceName
|
||||||
|
*/
|
||||||
|
private String generateUniqueDeviceName(String productKey) {
|
||||||
|
for (int i = 0; i < Short.MAX_VALUE; i++) {
|
||||||
|
String deviceName = IdUtil.fastSimpleUUID().substring(0, 20);
|
||||||
|
if (deviceMapper.selectByProductKeyAndDeviceName(productKey, deviceName) != null) {
|
||||||
|
return deviceName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new IllegalArgumentException("生成 DeviceName 失败");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public void updateDevice(IotDeviceSaveReqVO updateReqVO) {
|
||||||
|
// 1. 校验存在
|
||||||
|
validateDeviceExists(updateReqVO.getId());
|
||||||
|
|
||||||
|
// 2. 更新到数据库
|
||||||
|
IotDeviceDO updateObj = BeanUtils.toBean(updateReqVO, IotDeviceDO.class)
|
||||||
|
.setDeviceName(null).setProductId(null); // 设备名称 和 产品 ID 不能修改
|
||||||
|
deviceMapper.updateById(updateObj);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public void deleteDevice(Long id) {
|
||||||
|
// 1.1 校验存在
|
||||||
|
IotDeviceDO device = validateDeviceExists(id);
|
||||||
|
// 1.2 如果是网关设备,检查是否有子设备
|
||||||
|
if (device.getGatewayId() != null && deviceMapper.selectCountByGatewayId(id) > 0) {
|
||||||
|
throw exception(DEVICE_HAS_CHILDREN);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 删除设备
|
||||||
|
deviceMapper.deleteById(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验设备是否存在
|
||||||
|
*
|
||||||
|
* @param id 设备 ID
|
||||||
|
* @return 设备对象
|
||||||
|
*/
|
||||||
|
private IotDeviceDO validateDeviceExists(Long id) {
|
||||||
|
IotDeviceDO device = deviceMapper.selectById(id);
|
||||||
|
if (device == null) {
|
||||||
|
throw exception(DEVICE_NOT_EXISTS);
|
||||||
|
}
|
||||||
|
return device;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IotDeviceDO getDevice(Long id) {
|
||||||
|
IotDeviceDO device = deviceMapper.selectById(id);
|
||||||
|
if (device == null) {
|
||||||
|
throw exception(DEVICE_NOT_EXISTS);
|
||||||
|
}
|
||||||
|
return device;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PageResult<IotDeviceDO> getDevicePage(IotDevicePageReqVO pageReqVO) {
|
||||||
|
return deviceMapper.selectPage(pageReqVO);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateDeviceStatus(IotDeviceStatusUpdateReqVO updateReqVO) {
|
||||||
|
// 校验存在
|
||||||
|
validateDeviceExists(updateReqVO.getId());
|
||||||
|
|
||||||
|
// 更新状态和更新时间
|
||||||
|
IotDeviceDO updateObj = BeanUtils.toBean(updateReqVO, IotDeviceDO.class);
|
||||||
|
deviceMapper.updateById(updateObj);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Long getDeviceCountByProductId(Long productId) {
|
||||||
|
return deviceMapper.selectCountByProductId(productId);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,67 @@
|
|||||||
|
package cn.iocoder.yudao.module.iot.service.device;
|
||||||
|
|
||||||
|
import jakarta.validation.*;
|
||||||
|
import cn.iocoder.yudao.module.iot.controller.admin.device.vo.*;
|
||||||
|
import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO;
|
||||||
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IoT 设备 Service 接口
|
||||||
|
*
|
||||||
|
* @author 芋道源码
|
||||||
|
*/
|
||||||
|
public interface IotDeviceService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建设备
|
||||||
|
*
|
||||||
|
* @param createReqVO 创建信息
|
||||||
|
* @return 编号
|
||||||
|
*/
|
||||||
|
Long createDevice(@Valid IotDeviceSaveReqVO createReqVO);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新设备
|
||||||
|
*
|
||||||
|
* @param updateReqVO 更新信息
|
||||||
|
*/
|
||||||
|
void updateDevice(@Valid IotDeviceSaveReqVO updateReqVO);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除设备
|
||||||
|
*
|
||||||
|
* @param id 编号
|
||||||
|
*/
|
||||||
|
void deleteDevice(Long id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得设备
|
||||||
|
*
|
||||||
|
* @param id 编号
|
||||||
|
* @return IoT 设备
|
||||||
|
*/
|
||||||
|
IotDeviceDO getDevice(Long id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得设备分页
|
||||||
|
*
|
||||||
|
* @param pageReqVO 分页查询
|
||||||
|
* @return IoT 设备分页
|
||||||
|
*/
|
||||||
|
PageResult<IotDeviceDO> getDevicePage(IotDevicePageReqVO pageReqVO);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新设备状态
|
||||||
|
*
|
||||||
|
* @param updateReqVO 更新信息
|
||||||
|
*/
|
||||||
|
void updateDeviceStatus(IotDeviceStatusUpdateReqVO updateReqVO);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得设备数量
|
||||||
|
*
|
||||||
|
* @param productId 产品编号
|
||||||
|
* @return 设备数量
|
||||||
|
*/
|
||||||
|
Long getDeviceCountByProductId(Long productId);
|
||||||
|
}
|
@ -0,0 +1,71 @@
|
|||||||
|
package cn.iocoder.yudao.module.iot.service.product;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
|
import cn.iocoder.yudao.module.iot.controller.admin.product.vo.IotProductPageReqVO;
|
||||||
|
import cn.iocoder.yudao.module.iot.controller.admin.product.vo.IotProductSaveReqVO;
|
||||||
|
import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO;
|
||||||
|
import jakarta.validation.Valid;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IoT 产品 Service 接口
|
||||||
|
*
|
||||||
|
* @author ahh
|
||||||
|
*/
|
||||||
|
public interface IotProductService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建产品
|
||||||
|
*
|
||||||
|
* @param createReqVO 创建信息
|
||||||
|
* @return 编号
|
||||||
|
*/
|
||||||
|
Long createProduct(@Valid IotProductSaveReqVO createReqVO);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新产品
|
||||||
|
*
|
||||||
|
* @param updateReqVO 更新信息
|
||||||
|
*/
|
||||||
|
void updateProduct(@Valid IotProductSaveReqVO updateReqVO);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除产品
|
||||||
|
*
|
||||||
|
* @param id 编号
|
||||||
|
*/
|
||||||
|
void deleteProduct(Long id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得产品
|
||||||
|
*
|
||||||
|
* @param id 编号
|
||||||
|
* @return 产品
|
||||||
|
*/
|
||||||
|
IotProductDO getProduct(Long id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得产品分页
|
||||||
|
*
|
||||||
|
* @param pageReqVO 分页查询
|
||||||
|
* @return 产品分页
|
||||||
|
*/
|
||||||
|
PageResult<IotProductDO> getProductPage(IotProductPageReqVO pageReqVO);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新产品状态
|
||||||
|
*
|
||||||
|
* @param id 编号
|
||||||
|
* @param status 状态
|
||||||
|
*/
|
||||||
|
void updateProductStatus(Long id, Integer status);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得所有产品
|
||||||
|
*
|
||||||
|
* @return 产品列表
|
||||||
|
*/
|
||||||
|
List<IotProductDO> getProductList();
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,122 @@
|
|||||||
|
package cn.iocoder.yudao.module.iot.service.product;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
|
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||||
|
import cn.iocoder.yudao.module.iot.controller.admin.product.vo.IotProductPageReqVO;
|
||||||
|
import cn.iocoder.yudao.module.iot.controller.admin.product.vo.IotProductSaveReqVO;
|
||||||
|
import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO;
|
||||||
|
import cn.iocoder.yudao.module.iot.dal.mysql.product.IotProductMapper;
|
||||||
|
import cn.iocoder.yudao.module.iot.enums.product.IotProductStatusEnum;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||||
|
import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IoT 产品 Service 实现类
|
||||||
|
*
|
||||||
|
* @author ahh
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
@Validated
|
||||||
|
public class IotProductServiceImpl implements IotProductService {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private IotProductMapper productMapper;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Long createProduct(IotProductSaveReqVO createReqVO) {
|
||||||
|
// 1. 生成 ProductKey
|
||||||
|
createProductKey(createReqVO);
|
||||||
|
// 2. 插入
|
||||||
|
IotProductDO product = BeanUtils.toBean(createReqVO, IotProductDO.class);
|
||||||
|
productMapper.insert(product);
|
||||||
|
return product.getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建 ProductKey
|
||||||
|
*
|
||||||
|
* @param createReqVO 创建信息
|
||||||
|
*/
|
||||||
|
private void createProductKey(IotProductSaveReqVO createReqVO) {
|
||||||
|
String productKey = createReqVO.getProductKey();
|
||||||
|
// 1. productKey为空,生成随机的 11 位字符串
|
||||||
|
if (StrUtil.isEmpty(productKey)) {
|
||||||
|
productKey = UUID.randomUUID().toString().replace("-", "").substring(0, 11);
|
||||||
|
}
|
||||||
|
// 2. 校验唯一性
|
||||||
|
if (productMapper.selectByProductKey(productKey) != null) {
|
||||||
|
throw exception(PRODUCT_IDENTIFICATION_EXISTS);
|
||||||
|
}
|
||||||
|
createReqVO.setProductKey(productKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateProduct(IotProductSaveReqVO updateReqVO) {
|
||||||
|
updateReqVO.setProductKey(null); // 不更新产品标识
|
||||||
|
// 1.1 校验存在
|
||||||
|
IotProductDO iotProductDO = validateProductExists(updateReqVO.getId());
|
||||||
|
// 1.2 发布状态不可更新
|
||||||
|
validateProductStatus(iotProductDO);
|
||||||
|
// 2. 更新
|
||||||
|
IotProductDO updateObj = BeanUtils.toBean(updateReqVO, IotProductDO.class);
|
||||||
|
productMapper.updateById(updateObj);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void deleteProduct(Long id) {
|
||||||
|
// 1.1 校验存在
|
||||||
|
IotProductDO iotProductDO = validateProductExists(id);
|
||||||
|
// 1.2 发布状态不可删除
|
||||||
|
validateProductStatus(iotProductDO);
|
||||||
|
// 2. 删除
|
||||||
|
productMapper.deleteById(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
private IotProductDO validateProductExists(Long id) {
|
||||||
|
IotProductDO iotProductDO = productMapper.selectById(id);
|
||||||
|
if (iotProductDO == null) {
|
||||||
|
throw exception(PRODUCT_NOT_EXISTS);
|
||||||
|
}
|
||||||
|
return iotProductDO;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void validateProductStatus(IotProductDO iotProductDO) {
|
||||||
|
if (Objects.equals(iotProductDO.getStatus(), IotProductStatusEnum.PUBLISHED.getType())) {
|
||||||
|
throw exception(PRODUCT_STATUS_NOT_DELETE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IotProductDO getProduct(Long id) {
|
||||||
|
return productMapper.selectById(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PageResult<IotProductDO> getProductPage(IotProductPageReqVO pageReqVO) {
|
||||||
|
return productMapper.selectPage(pageReqVO);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateProductStatus(Long id, Integer status) {
|
||||||
|
// 1. 校验存在
|
||||||
|
validateProductExists(id);
|
||||||
|
// 2. 更新
|
||||||
|
IotProductDO updateObj = IotProductDO.builder().id(id).status(status).build();
|
||||||
|
productMapper.updateById(updateObj);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<IotProductDO> getProductList() {
|
||||||
|
return productMapper.selectList();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,65 @@
|
|||||||
|
package cn.iocoder.yudao.module.iot.service.thinkmodelfunction;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
|
import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.vo.IotThinkModelFunctionPageReqVO;
|
||||||
|
import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.vo.IotThinkModelFunctionSaveReqVO;
|
||||||
|
import cn.iocoder.yudao.module.iot.dal.dataobject.thinkmodelfunction.IotThinkModelFunctionDO;
|
||||||
|
import jakarta.validation.Valid;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IoT 产品物模型 Service 接口
|
||||||
|
*
|
||||||
|
* @author 芋道源码
|
||||||
|
*/
|
||||||
|
public interface IotThinkModelFunctionService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建产品物模型
|
||||||
|
*
|
||||||
|
* @param createReqVO 创建信息
|
||||||
|
* @return 编号
|
||||||
|
*/
|
||||||
|
Long createThinkModelFunction(@Valid IotThinkModelFunctionSaveReqVO createReqVO);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新产品物模型
|
||||||
|
*
|
||||||
|
* @param updateReqVO 更新信息
|
||||||
|
*/
|
||||||
|
void updateThinkModelFunction(@Valid IotThinkModelFunctionSaveReqVO updateReqVO);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除产品物模型
|
||||||
|
*
|
||||||
|
* @param id 编号
|
||||||
|
*/
|
||||||
|
void deleteThinkModelFunction(Long id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得产品物模型
|
||||||
|
*
|
||||||
|
* @param id 编号
|
||||||
|
* @return 产品物模型
|
||||||
|
*/
|
||||||
|
IotThinkModelFunctionDO getThinkModelFunction(Long id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得产品物模型列表
|
||||||
|
*
|
||||||
|
* @param productId 产品编号
|
||||||
|
* @return 产品物模型列表
|
||||||
|
*/
|
||||||
|
List<IotThinkModelFunctionDO> getThinkModelFunctionListByProductId(Long productId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得产品物模型分页
|
||||||
|
*
|
||||||
|
* @param pageReqVO 分页查询
|
||||||
|
* @return 产品物模型分页
|
||||||
|
*/
|
||||||
|
PageResult<IotThinkModelFunctionDO> getThinkModelFunctionPage(IotThinkModelFunctionPageReqVO pageReqVO);
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,404 @@
|
|||||||
|
package cn.iocoder.yudao.module.iot.service.thinkmodelfunction;
|
||||||
|
|
||||||
|
import cn.hutool.core.collection.CollUtil;
|
||||||
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
|
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
|
||||||
|
import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
|
||||||
|
import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.ThingModelEvent;
|
||||||
|
import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.ThingModelProperty;
|
||||||
|
import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.ThingModelService;
|
||||||
|
import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.dataType.ThingModelArgument;
|
||||||
|
import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.dataType.ThingModelArraySpecs;
|
||||||
|
import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.dataType.ThingModelArrayType;
|
||||||
|
import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.dataType.ThingModelTextType;
|
||||||
|
import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.vo.IotThinkModelFunctionPageReqVO;
|
||||||
|
import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.vo.IotThinkModelFunctionSaveReqVO;
|
||||||
|
import cn.iocoder.yudao.module.iot.convert.thinkmodelfunction.IotThinkModelFunctionConvert;
|
||||||
|
import cn.iocoder.yudao.module.iot.dal.dataobject.thinkmodelfunction.IotThinkModelFunctionDO;
|
||||||
|
import cn.iocoder.yudao.module.iot.dal.mysql.thinkmodelfunction.IotThinkModelFunctionMapper;
|
||||||
|
import cn.iocoder.yudao.module.iot.enums.product.IotAccessModeEnum;
|
||||||
|
import cn.iocoder.yudao.module.iot.enums.product.IotProductFunctionTypeEnum;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||||
|
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.diffList;
|
||||||
|
import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IoT 产品物模型 Service 实现类
|
||||||
|
*
|
||||||
|
* @author 芋道源码
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
@Validated
|
||||||
|
@Slf4j
|
||||||
|
public class IotThinkModelFunctionServiceImpl implements IotThinkModelFunctionService {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private IotThinkModelFunctionMapper thinkModelFunctionMapper;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public Long createThinkModelFunction(IotThinkModelFunctionSaveReqVO createReqVO) {
|
||||||
|
// 1. 校验功能标识符在同一产品下是否唯一
|
||||||
|
validateIdentifierUnique(createReqVO.getProductId(), createReqVO.getIdentifier());
|
||||||
|
|
||||||
|
// 2. 功能名称在同一产品下是否唯一
|
||||||
|
validateNameUnique(createReqVO.getProductId(), createReqVO.getName());
|
||||||
|
|
||||||
|
// 3. 系统保留字段,不能用于标识符定义
|
||||||
|
validateNotDefaultEventAndService(createReqVO.getIdentifier());
|
||||||
|
|
||||||
|
// 3. 插入数据库
|
||||||
|
IotThinkModelFunctionDO function = IotThinkModelFunctionConvert.INSTANCE.convert(createReqVO);
|
||||||
|
thinkModelFunctionMapper.insert(function);
|
||||||
|
|
||||||
|
// 4. 如果创建的是属性,需要更新默认的事件和服务
|
||||||
|
if (Objects.equals(createReqVO.getType(), IotProductFunctionTypeEnum.PROPERTY.getType())) {
|
||||||
|
createDefaultEventsAndServices(createReqVO.getProductId(), createReqVO.getProductKey());
|
||||||
|
}
|
||||||
|
return function.getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void validateNotDefaultEventAndService(String identifier) {
|
||||||
|
// set, get, post, property, event, time, value 是系统保留字段,不能用于标识符定义
|
||||||
|
if (CollUtil.containsAny(Arrays.asList("set", "get", "post", "property", "event", "time", "value"), Collections.singletonList(identifier))) {
|
||||||
|
throw exception(THINK_MODEL_FUNCTION_IDENTIFIER_INVALID);
|
||||||
|
}
|
||||||
|
// if (CollUtil.containsAny(Arrays.asList("post", "set", "get"), identifier)) {
|
||||||
|
// throw exception(THINK_MODEL_FUNCTION_IDENTIFIER_INVALID);
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
private void validateNameUnique(Long productId, String name) {
|
||||||
|
IotThinkModelFunctionDO function = thinkModelFunctionMapper.selectByProductIdAndName(productId, name);
|
||||||
|
if (function != null) {
|
||||||
|
throw exception(THINK_MODEL_FUNCTION_NAME_EXISTS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void validateIdentifierUnique(Long productId, String identifier) {
|
||||||
|
IotThinkModelFunctionDO function = thinkModelFunctionMapper.selectByProductIdAndIdentifier(productId, identifier);
|
||||||
|
if (function != null) {
|
||||||
|
throw exception(THINK_MODEL_FUNCTION_IDENTIFIER_EXISTS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public void updateThinkModelFunction(IotThinkModelFunctionSaveReqVO updateReqVO) {
|
||||||
|
// 1. 校验功能是否存在
|
||||||
|
validateThinkModelFunctionExists(updateReqVO.getId());
|
||||||
|
|
||||||
|
// 2. 校验功能标识符是否唯一
|
||||||
|
validateIdentifierUniqueForUpdate(updateReqVO.getId(), updateReqVO.getProductId(), updateReqVO.getIdentifier());
|
||||||
|
|
||||||
|
// 3. 更新数据库
|
||||||
|
IotThinkModelFunctionDO thinkModelFunction = IotThinkModelFunctionConvert.INSTANCE.convert(updateReqVO);
|
||||||
|
thinkModelFunctionMapper.updateById(thinkModelFunction);
|
||||||
|
|
||||||
|
// 4. 如果更新的是属性,需要更新默认的事件和服务
|
||||||
|
if (Objects.equals(updateReqVO.getType(), IotProductFunctionTypeEnum.PROPERTY.getType())) {
|
||||||
|
createDefaultEventsAndServices(updateReqVO.getProductId(), updateReqVO.getProductKey());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void validateIdentifierUniqueForUpdate(Long id, Long productId, String identifier) {
|
||||||
|
IotThinkModelFunctionDO function = thinkModelFunctionMapper.selectByProductIdAndIdentifier(productId, identifier);
|
||||||
|
if (function != null && ObjectUtil.notEqual(function.getId(), id)) {
|
||||||
|
throw exception(THINK_MODEL_FUNCTION_IDENTIFIER_EXISTS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public void deleteThinkModelFunction(Long id) {
|
||||||
|
// 1. 校验功能是否存在
|
||||||
|
IotThinkModelFunctionDO functionDO = thinkModelFunctionMapper.selectById(id);
|
||||||
|
if (functionDO == null) {
|
||||||
|
throw exception(THINK_MODEL_FUNCTION_NOT_EXISTS);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 删除功能
|
||||||
|
thinkModelFunctionMapper.deleteById(id);
|
||||||
|
|
||||||
|
// 3. 如果删除的是属性,需要更新默认的事件和服务
|
||||||
|
if (Objects.equals(functionDO.getType(), IotProductFunctionTypeEnum.PROPERTY.getType())) {
|
||||||
|
createDefaultEventsAndServices(functionDO.getProductId(), functionDO.getProductKey());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验功能是否存在
|
||||||
|
*
|
||||||
|
* @param id 功能编号
|
||||||
|
*/
|
||||||
|
private void validateThinkModelFunctionExists(Long id) {
|
||||||
|
if (thinkModelFunctionMapper.selectById(id) == null) {
|
||||||
|
throw exception(THINK_MODEL_FUNCTION_NOT_EXISTS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IotThinkModelFunctionDO getThinkModelFunction(Long id) {
|
||||||
|
return thinkModelFunctionMapper.selectById(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<IotThinkModelFunctionDO> getThinkModelFunctionListByProductId(Long productId) {
|
||||||
|
return thinkModelFunctionMapper.selectListByProductId(productId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PageResult<IotThinkModelFunctionDO> getThinkModelFunctionPage(IotThinkModelFunctionPageReqVO pageReqVO) {
|
||||||
|
return thinkModelFunctionMapper.selectPage(pageReqVO);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建默认的事件和服务
|
||||||
|
*/
|
||||||
|
public void createDefaultEventsAndServices(Long productId, String productKey) {
|
||||||
|
// 1. 获取当前属性列表
|
||||||
|
List<IotThinkModelFunctionDO> propertyList = thinkModelFunctionMapper
|
||||||
|
.selectListByProductIdAndType(productId, IotProductFunctionTypeEnum.PROPERTY.getType());
|
||||||
|
|
||||||
|
// 2. 生成新的事件和服务列表
|
||||||
|
List<IotThinkModelFunctionDO> newFunctionList = new ArrayList<>();
|
||||||
|
// 生成属性上报事件
|
||||||
|
ThingModelEvent propertyPostEvent = generatePropertyPostEvent(propertyList);
|
||||||
|
if (propertyPostEvent != null) {
|
||||||
|
IotThinkModelFunctionDO eventFunction = buildEventFunctionDO(productId, productKey, propertyPostEvent);
|
||||||
|
newFunctionList.add(eventFunction);
|
||||||
|
}
|
||||||
|
// 生成属性设置服务
|
||||||
|
ThingModelService propertySetService = generatePropertySetService(propertyList);
|
||||||
|
if (propertySetService != null) {
|
||||||
|
IotThinkModelFunctionDO setServiceFunction = buildServiceFunctionDO(productId, productKey, propertySetService);
|
||||||
|
newFunctionList.add(setServiceFunction);
|
||||||
|
}
|
||||||
|
// 生成属性获取服务
|
||||||
|
ThingModelService propertyGetService = generatePropertyGetService(propertyList);
|
||||||
|
if (propertyGetService != null) {
|
||||||
|
IotThinkModelFunctionDO getServiceFunction = buildServiceFunctionDO(productId, productKey, propertyGetService);
|
||||||
|
newFunctionList.add(getServiceFunction);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 获取数据库中的默认的旧事件和服务列表
|
||||||
|
List<IotThinkModelFunctionDO> oldFunctionList = thinkModelFunctionMapper.selectListByProductIdAndIdentifiersAndTypes(
|
||||||
|
productId,
|
||||||
|
Arrays.asList("post", "set", "get"),
|
||||||
|
Arrays.asList(IotProductFunctionTypeEnum.EVENT.getType(), IotProductFunctionTypeEnum.SERVICE.getType())
|
||||||
|
);
|
||||||
|
|
||||||
|
// 3.1 使用 diffList 方法比较新旧列表
|
||||||
|
List<List<IotThinkModelFunctionDO>> diffResult = diffList(oldFunctionList, newFunctionList,
|
||||||
|
// 继续使用 identifier 和 type 进行比较:这样可以准确地匹配对应的功能对象。
|
||||||
|
(oldFunc, newFunc) -> Objects.equals(oldFunc.getIdentifier(), newFunc.getIdentifier())
|
||||||
|
&& Objects.equals(oldFunc.getType(), newFunc.getType()));
|
||||||
|
List<IotThinkModelFunctionDO> createList = diffResult.get(0); // 需要新增的
|
||||||
|
List<IotThinkModelFunctionDO> updateList = diffResult.get(1); // 需要更新的
|
||||||
|
List<IotThinkModelFunctionDO> deleteList = diffResult.get(2); // 需要删除的
|
||||||
|
|
||||||
|
// 3.2 批量执行数据库操作
|
||||||
|
// 新增数据库中的新事件和服务列表
|
||||||
|
if (CollUtil.isNotEmpty(createList)) {
|
||||||
|
thinkModelFunctionMapper.insertBatch(createList);
|
||||||
|
}
|
||||||
|
// 更新数据库中的事件和服务列表
|
||||||
|
if (CollUtil.isNotEmpty(updateList)) {
|
||||||
|
// 首先,为每个需要更新的对象设置其对应的 ID
|
||||||
|
updateList.forEach(updateFunc -> {
|
||||||
|
IotThinkModelFunctionDO oldFunc = findFunctionByIdentifierAndType(
|
||||||
|
oldFunctionList, updateFunc.getIdentifier(), updateFunc.getType());
|
||||||
|
if (oldFunc != null) {
|
||||||
|
updateFunc.setId(oldFunc.getId());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// 过滤掉没有设置 ID 的对象
|
||||||
|
List<IotThinkModelFunctionDO> validUpdateList = updateList.stream()
|
||||||
|
.filter(func -> func.getId() != null)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
// 执行批量更新
|
||||||
|
if (CollUtil.isNotEmpty(validUpdateList)) {
|
||||||
|
thinkModelFunctionMapper.updateBatch(validUpdateList);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除数据库中的旧事件和服务列表
|
||||||
|
if (CollUtil.isNotEmpty(deleteList)) {
|
||||||
|
Set<Long> idsToDelete = CollectionUtils.convertSet(deleteList, IotThinkModelFunctionDO::getId);
|
||||||
|
thinkModelFunctionMapper.deleteByIds(idsToDelete);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据标识符和类型查找功能对象
|
||||||
|
*/
|
||||||
|
private IotThinkModelFunctionDO findFunctionByIdentifierAndType(List<IotThinkModelFunctionDO> functionList,
|
||||||
|
String identifier, Integer type) {
|
||||||
|
return CollUtil.findOne(functionList, func ->
|
||||||
|
Objects.equals(func.getIdentifier(), identifier) && Objects.equals(func.getType(), type));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构建事件功能对象
|
||||||
|
*/
|
||||||
|
private IotThinkModelFunctionDO buildEventFunctionDO(Long productId, String productKey, ThingModelEvent event) {
|
||||||
|
return new IotThinkModelFunctionDO()
|
||||||
|
.setProductId(productId)
|
||||||
|
.setProductKey(productKey)
|
||||||
|
.setIdentifier(event.getIdentifier())
|
||||||
|
.setName(event.getName())
|
||||||
|
.setDescription(event.getDescription())
|
||||||
|
.setType(IotProductFunctionTypeEnum.EVENT.getType())
|
||||||
|
.setEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构建服务功能对象
|
||||||
|
*/
|
||||||
|
private IotThinkModelFunctionDO buildServiceFunctionDO(Long productId, String productKey, ThingModelService service) {
|
||||||
|
return new IotThinkModelFunctionDO()
|
||||||
|
.setProductId(productId)
|
||||||
|
.setProductKey(productKey)
|
||||||
|
.setIdentifier(service.getIdentifier())
|
||||||
|
.setName(service.getName())
|
||||||
|
.setDescription(service.getDescription())
|
||||||
|
.setType(IotProductFunctionTypeEnum.SERVICE.getType())
|
||||||
|
.setService(service);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成属性上报事件
|
||||||
|
*/
|
||||||
|
private ThingModelEvent generatePropertyPostEvent(List<IotThinkModelFunctionDO> propertyList) {
|
||||||
|
if (CollUtil.isEmpty(propertyList)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
ThingModelEvent event = new ThingModelEvent()
|
||||||
|
.setIdentifier("post")
|
||||||
|
.setName("属性上报")
|
||||||
|
.setType("info")
|
||||||
|
.setDescription("属性上报事件")
|
||||||
|
.setMethod("thing.event.property.post");
|
||||||
|
|
||||||
|
// 将属性列表转换为事件的输出参数
|
||||||
|
List<ThingModelArgument> outputData = new ArrayList<>();
|
||||||
|
for (IotThinkModelFunctionDO functionDO : propertyList) {
|
||||||
|
ThingModelProperty property = functionDO.getProperty();
|
||||||
|
ThingModelArgument arg = new ThingModelArgument()
|
||||||
|
.setIdentifier(property.getIdentifier())
|
||||||
|
.setName(property.getName())
|
||||||
|
.setDataType(property.getDataType())
|
||||||
|
.setDescription(property.getDescription())
|
||||||
|
.setDirection("output"); // 设置为输出参数
|
||||||
|
outputData.add(arg);
|
||||||
|
}
|
||||||
|
event.setOutputData(outputData);
|
||||||
|
return event;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成属性设置服务
|
||||||
|
*/
|
||||||
|
private ThingModelService generatePropertySetService(List<IotThinkModelFunctionDO> propertyList) {
|
||||||
|
if (propertyList == null || propertyList.isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<ThingModelArgument> inputData = new ArrayList<>();
|
||||||
|
for (IotThinkModelFunctionDO functionDO : propertyList) {
|
||||||
|
ThingModelProperty property = functionDO.getProperty();
|
||||||
|
if (IotAccessModeEnum.WRITE.getMode().equals(property.getAccessMode()) || IotAccessModeEnum.READ_WRITE.getMode().equals(property.getAccessMode())) {
|
||||||
|
ThingModelArgument arg = new ThingModelArgument()
|
||||||
|
.setIdentifier(property.getIdentifier())
|
||||||
|
.setName(property.getName())
|
||||||
|
.setDataType(property.getDataType())
|
||||||
|
.setDescription(property.getDescription())
|
||||||
|
.setDirection("input"); // 设置为输入参数
|
||||||
|
inputData.add(arg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (inputData.isEmpty()) {
|
||||||
|
// 如果没有可写属性,不生成属性设置服务
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 属性设置服务一般不需要输出参数
|
||||||
|
return new ThingModelService()
|
||||||
|
.setIdentifier("set")
|
||||||
|
.setName("属性设置")
|
||||||
|
.setCallType("async")
|
||||||
|
.setDescription("属性设置服务")
|
||||||
|
.setMethod("thing.service.property.set")
|
||||||
|
.setInputData(inputData)
|
||||||
|
// 属性设置服务一般不需要输出参数
|
||||||
|
.setOutputData(new ArrayList<>());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成属性获取服务
|
||||||
|
*/
|
||||||
|
private ThingModelService generatePropertyGetService(List<IotThinkModelFunctionDO> propertyList) {
|
||||||
|
if (propertyList == null || propertyList.isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<ThingModelArgument> outputData = new ArrayList<>();
|
||||||
|
for (IotThinkModelFunctionDO functionDO : propertyList) {
|
||||||
|
ThingModelProperty property = functionDO.getProperty();
|
||||||
|
if (ObjectUtils.equalsAny(property.getAccessMode(),
|
||||||
|
IotAccessModeEnum.READ.getMode(), IotAccessModeEnum.READ_WRITE.getMode())) {
|
||||||
|
ThingModelArgument arg = new ThingModelArgument()
|
||||||
|
.setIdentifier(property.getIdentifier())
|
||||||
|
.setName(property.getName())
|
||||||
|
.setDataType(property.getDataType())
|
||||||
|
.setDescription(property.getDescription())
|
||||||
|
.setDirection("output"); // 设置为输出参数
|
||||||
|
outputData.add(arg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (outputData.isEmpty()) {
|
||||||
|
// 如果没有可读属性,不生成属性获取服务
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
ThingModelService service = new ThingModelService()
|
||||||
|
.setIdentifier("get")
|
||||||
|
.setName("属性获取")
|
||||||
|
.setCallType("async")
|
||||||
|
.setDescription("属性获取服务")
|
||||||
|
.setMethod("thing.service.property.get");
|
||||||
|
|
||||||
|
// 定义输入参数:属性标识符列表
|
||||||
|
ThingModelArgument inputArg = new ThingModelArgument()
|
||||||
|
.setIdentifier("properties")
|
||||||
|
.setName("属性标识符列表")
|
||||||
|
.setDescription("需要获取的属性标识符列表")
|
||||||
|
.setDirection("input"); // 设置为输入参数
|
||||||
|
|
||||||
|
// 创建数组类型,元素类型为文本类型(字符串)
|
||||||
|
ThingModelArrayType arrayType = new ThingModelArrayType();
|
||||||
|
arrayType.setType("array");
|
||||||
|
ThingModelArraySpecs arraySpecs = new ThingModelArraySpecs();
|
||||||
|
ThingModelTextType textType = new ThingModelTextType();
|
||||||
|
textType.setType("text");
|
||||||
|
arraySpecs.setItem(textType);
|
||||||
|
arrayType.setSpecs(arraySpecs);
|
||||||
|
inputArg.setDataType(arrayType);
|
||||||
|
|
||||||
|
service.setInputData(Collections.singletonList(inputArg));
|
||||||
|
service.setOutputData(outputData);
|
||||||
|
return service;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -33,11 +33,11 @@
|
|||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- 会员中心。默认注释,保证编译速度 -->
|
<!-- 会员中心。默认注释,保证编译速度 -->
|
||||||
<dependency>
|
<!-- <dependency>-->
|
||||||
<groupId>cn.iocoder.boot</groupId>
|
<!-- <groupId>cn.iocoder.boot</groupId>-->
|
||||||
<artifactId>yudao-module-member-biz</artifactId>
|
<!-- <artifactId>yudao-module-member-biz</artifactId>-->
|
||||||
<version>${revision}</version>
|
<!-- <version>${revision}</version>-->
|
||||||
</dependency>
|
<!-- </dependency>-->
|
||||||
|
|
||||||
<!-- 数据报表。默认注释,保证编译速度 -->
|
<!-- 数据报表。默认注释,保证编译速度 -->
|
||||||
<!-- <dependency>-->
|
<!-- <dependency>-->
|
||||||
@ -52,11 +52,11 @@
|
|||||||
<!-- <version>${revision}</version>-->
|
<!-- <version>${revision}</version>-->
|
||||||
<!-- </dependency>-->
|
<!-- </dependency>-->
|
||||||
<!-- 支付服务。默认注释,保证编译速度 -->
|
<!-- 支付服务。默认注释,保证编译速度 -->
|
||||||
<dependency>
|
<!-- <dependency>-->
|
||||||
<groupId>cn.iocoder.boot</groupId>
|
<!-- <groupId>cn.iocoder.boot</groupId>-->
|
||||||
<artifactId>yudao-module-pay-biz</artifactId>
|
<!-- <artifactId>yudao-module-pay-biz</artifactId>-->
|
||||||
<version>${revision}</version>
|
<!-- <version>${revision}</version>-->
|
||||||
</dependency>
|
<!-- </dependency>-->
|
||||||
|
|
||||||
<!-- 微信公众号模块。默认注释,保证编译速度 -->
|
<!-- 微信公众号模块。默认注释,保证编译速度 -->
|
||||||
<!-- <dependency>-->
|
<!-- <dependency>-->
|
||||||
@ -66,26 +66,26 @@
|
|||||||
<!-- </dependency>-->
|
<!-- </dependency>-->
|
||||||
|
|
||||||
<!-- 商城相关模块。默认注释,保证编译速度-->
|
<!-- 商城相关模块。默认注释,保证编译速度-->
|
||||||
<dependency>
|
<!-- <dependency>-->
|
||||||
<groupId>cn.iocoder.boot</groupId>
|
<!-- <groupId>cn.iocoder.boot</groupId>-->
|
||||||
<artifactId>yudao-module-promotion-biz</artifactId>
|
<!-- <artifactId>yudao-module-promotion-biz</artifactId>-->
|
||||||
<version>${revision}</version>
|
<!-- <version>${revision}</version>-->
|
||||||
</dependency>
|
<!-- </dependency>-->
|
||||||
<dependency>
|
<!-- <dependency>-->
|
||||||
<groupId>cn.iocoder.boot</groupId>
|
<!-- <groupId>cn.iocoder.boot</groupId>-->
|
||||||
<artifactId>yudao-module-product-biz</artifactId>
|
<!-- <artifactId>yudao-module-product-biz</artifactId>-->
|
||||||
<version>${revision}</version>
|
<!-- <version>${revision}</version>-->
|
||||||
</dependency>
|
<!-- </dependency>-->
|
||||||
<dependency>
|
<!-- <dependency>-->
|
||||||
<groupId>cn.iocoder.boot</groupId>
|
<!-- <groupId>cn.iocoder.boot</groupId>-->
|
||||||
<artifactId>yudao-module-trade-biz</artifactId>
|
<!-- <artifactId>yudao-module-trade-biz</artifactId>-->
|
||||||
<version>${revision}</version>
|
<!-- <version>${revision}</version>-->
|
||||||
</dependency>
|
<!-- </dependency>-->
|
||||||
<dependency>
|
<!-- <dependency>-->
|
||||||
<groupId>cn.iocoder.boot</groupId>
|
<!-- <groupId>cn.iocoder.boot</groupId>-->
|
||||||
<artifactId>yudao-module-statistics-biz</artifactId>
|
<!-- <artifactId>yudao-module-statistics-biz</artifactId>-->
|
||||||
<version>${revision}</version>
|
<!-- <version>${revision}</version>-->
|
||||||
</dependency>
|
<!-- </dependency>-->
|
||||||
|
|
||||||
<!-- CRM 相关模块。默认注释,保证编译速度 -->
|
<!-- CRM 相关模块。默认注释,保证编译速度 -->
|
||||||
<!-- <dependency>-->
|
<!-- <dependency>-->
|
||||||
@ -106,6 +106,13 @@
|
|||||||
<!-- <groupId>cn.iocoder.boot</groupId>-->
|
<!-- <groupId>cn.iocoder.boot</groupId>-->
|
||||||
<!-- <artifactId>yudao-module-ai-biz</artifactId>-->
|
<!-- <artifactId>yudao-module-ai-biz</artifactId>-->
|
||||||
<!-- <version>${revision}</version>-->
|
<!-- <version>${revision}</version>-->
|
||||||
|
<!-- </dependency>-->
|
||||||
|
|
||||||
|
<!-- IoT 物联网相关模块。默认注释,保证编译速度 -->
|
||||||
|
<!-- <dependency>-->
|
||||||
|
<!-- <groupId>cn.iocoder.boot</groupId>-->
|
||||||
|
<!-- <artifactId>yudao-module-iot-biz</artifactId>-->
|
||||||
|
<!-- <version>${revision}</version>-->
|
||||||
<!-- </dependency>-->
|
<!-- </dependency>-->
|
||||||
|
|
||||||
<!-- spring boot 配置所需依赖 -->
|
<!-- spring boot 配置所需依赖 -->
|
||||||
|
@ -65,4 +65,10 @@ public class DefaultController {
|
|||||||
"[AI 大模型 yudao-module-ai - 已禁用][参考 https://doc.iocoder.cn/ai/build/ 开启]");
|
"[AI 大模型 yudao-module-ai - 已禁用][参考 https://doc.iocoder.cn/ai/build/ 开启]");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@RequestMapping(value = {"/admin-api/iot/**"})
|
||||||
|
public CommonResult<Boolean> iot404() {
|
||||||
|
return CommonResult.error(NOT_IMPLEMENTED.getCode(),
|
||||||
|
"[IOT 物联网 yudao-module-iot - 已禁用][参考 https://doc.iocoder.cn/iot/build/ 开启]");
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -194,3 +194,22 @@ justauth:
|
|||||||
type: REDIS
|
type: REDIS
|
||||||
prefix: 'social_auth_state:' # 缓存前缀,目前只对 Redis 缓存生效,默认 JUSTAUTH::STATE::
|
prefix: 'social_auth_state:' # 缓存前缀,目前只对 Redis 缓存生效,默认 JUSTAUTH::STATE::
|
||||||
timeout: 24h # 超时时长,目前只对 Redis 缓存生效,默认 3 分钟
|
timeout: 24h # 超时时长,目前只对 Redis 缓存生效,默认 3 分钟
|
||||||
|
|
||||||
|
|
||||||
|
--- #################### iot相关配置 TODO 芋艿:再瞅瞅 ####################
|
||||||
|
iot:
|
||||||
|
emq:
|
||||||
|
# 账号
|
||||||
|
username: anhaohao
|
||||||
|
# 密码
|
||||||
|
password: ahh@123456
|
||||||
|
# 主机地址
|
||||||
|
hostUrl: tcp://chaojiniu.top:1883
|
||||||
|
# 客户端Id,不能相同,采用随机数 ${random.value}
|
||||||
|
client-id: ${random.int}
|
||||||
|
# 默认主题
|
||||||
|
default-topic: test
|
||||||
|
# 保持连接
|
||||||
|
keepalive: 60
|
||||||
|
# 清除会话(设置为false,断开连接,重连后使用原来的会话 保留订阅的主题,能接收离线期间的消息)
|
||||||
|
clearSession: true
|
@ -45,8 +45,8 @@ spring:
|
|||||||
primary: master
|
primary: master
|
||||||
datasource:
|
datasource:
|
||||||
master:
|
master:
|
||||||
url: jdbc:mysql://127.0.0.1:3306/ruoyi-vue-pro?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true&rewriteBatchedStatements=true # MySQL Connector/J 8.X 连接的示例
|
url: jdbc:mysql://127.0.0.1:3307/ruoyi-vue-pro?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true # MySQL Connector/J 8.X 连接的示例
|
||||||
# url: jdbc:mysql://127.0.0.1:3306/ruoyi-vue-pro?useSSL=true&allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true # MySQL Connector/J 5.X 连接的示例
|
# url: jdbc:mysql://127.0.0.1:3306/ruoyi-vue-pro?useSSL=true&allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai # MySQL Connector/J 5.X 连接的示例
|
||||||
# url: jdbc:postgresql://127.0.0.1:5432/ruoyi-vue-pro # PostgreSQL 连接的示例
|
# url: jdbc:postgresql://127.0.0.1:5432/ruoyi-vue-pro # PostgreSQL 连接的示例
|
||||||
# url: jdbc:oracle:thin:@127.0.0.1:1521:xe # Oracle 连接的示例
|
# url: jdbc:oracle:thin:@127.0.0.1:1521:xe # Oracle 连接的示例
|
||||||
# url: jdbc:sqlserver://127.0.0.1:1433;DatabaseName=ruoyi-vue-pro;SelectMethod=cursor;encrypt=false;rewriteBatchedStatements=true;useUnicode=true;characterEncoding=utf-8 # SQLServer 连接的示例
|
# url: jdbc:sqlserver://127.0.0.1:1433;DatabaseName=ruoyi-vue-pro;SelectMethod=cursor;encrypt=false;rewriteBatchedStatements=true;useUnicode=true;characterEncoding=utf-8 # SQLServer 连接的示例
|
||||||
@ -54,7 +54,7 @@ spring:
|
|||||||
# url: jdbc:kingbase8://127.0.0.1:54321/test # 人大金仓 KingbaseES 连接的示例
|
# url: jdbc:kingbase8://127.0.0.1:54321/test # 人大金仓 KingbaseES 连接的示例
|
||||||
# url: jdbc:postgresql://127.0.0.1:5432/postgres # OpenGauss 连接的示例
|
# url: jdbc:postgresql://127.0.0.1:5432/postgres # OpenGauss 连接的示例
|
||||||
username: root
|
username: root
|
||||||
password: 123456
|
password: ahh@123456
|
||||||
# username: sa # SQL Server 连接的示例
|
# username: sa # SQL Server 连接的示例
|
||||||
# password: Yudao@2024 # SQL Server 连接的示例
|
# password: Yudao@2024 # SQL Server 连接的示例
|
||||||
# username: SYSDBA # DM 连接的示例
|
# username: SYSDBA # DM 连接的示例
|
||||||
@ -63,9 +63,9 @@ spring:
|
|||||||
# password: Yudao@2024 # OpenGauss 连接的示例
|
# password: Yudao@2024 # OpenGauss 连接的示例
|
||||||
slave: # 模拟从库,可根据自己需要修改
|
slave: # 模拟从库,可根据自己需要修改
|
||||||
lazy: true # 开启懒加载,保证启动速度
|
lazy: true # 开启懒加载,保证启动速度
|
||||||
url: jdbc:mysql://127.0.0.1:3306/ruoyi-vue-pro?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&rewriteBatchedStatements=true&nullCatalogMeansCurrent=true
|
url: jdbc:mysql://127.0.0.1:3307/ruoyi-vue-pro?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true
|
||||||
username: root
|
username: root
|
||||||
password: 123456
|
password: ahh@123456
|
||||||
|
|
||||||
# Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优
|
# Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优
|
||||||
data:
|
data:
|
||||||
@ -174,6 +174,7 @@ logging:
|
|||||||
cn.iocoder.yudao.module.statistics.dal.mysql: debug
|
cn.iocoder.yudao.module.statistics.dal.mysql: debug
|
||||||
cn.iocoder.yudao.module.crm.dal.mysql: debug
|
cn.iocoder.yudao.module.crm.dal.mysql: debug
|
||||||
cn.iocoder.yudao.module.erp.dal.mysql: debug
|
cn.iocoder.yudao.module.erp.dal.mysql: debug
|
||||||
|
cn.iocoder.yudao.module.iot.dal.mysql: debug
|
||||||
cn.iocoder.yudao.module.ai.dal.mysql: debug
|
cn.iocoder.yudao.module.ai.dal.mysql: debug
|
||||||
org.springframework.context.support.PostProcessorRegistrationDelegate: ERROR # TODO 芋艿:先禁用,Spring Boot 3.X 存在部分错误的 WARN 提示
|
org.springframework.context.support.PostProcessorRegistrationDelegate: ERROR # TODO 芋艿:先禁用,Spring Boot 3.X 存在部分错误的 WARN 提示
|
||||||
|
|
||||||
@ -254,3 +255,20 @@ justauth:
|
|||||||
prefix: 'social_auth_state:' # 缓存前缀,目前只对 Redis 缓存生效,默认 JUSTAUTH::STATE::
|
prefix: 'social_auth_state:' # 缓存前缀,目前只对 Redis 缓存生效,默认 JUSTAUTH::STATE::
|
||||||
timeout: 24h # 超时时长,目前只对 Redis 缓存生效,默认 3 分钟
|
timeout: 24h # 超时时长,目前只对 Redis 缓存生效,默认 3 分钟
|
||||||
|
|
||||||
|
--- #################### iot相关配置 TODO 芋艿:再瞅瞅 ####################
|
||||||
|
iot:
|
||||||
|
emq:
|
||||||
|
# 账号
|
||||||
|
username: anhaohao
|
||||||
|
# 密码
|
||||||
|
password: ahh@123456
|
||||||
|
# 主机地址
|
||||||
|
hostUrl: tcp://chaojiniu.top:1883
|
||||||
|
# 客户端Id,不能相同,采用随机数 ${random.value}
|
||||||
|
client-id: ${random.int}
|
||||||
|
# 默认主题
|
||||||
|
default-topic: test
|
||||||
|
# 保持连接
|
||||||
|
keepalive: 60
|
||||||
|
# 清除会话(设置为false,断开连接,重连后使用原来的会话 保留订阅的主题,能接收离线期间的消息)
|
||||||
|
clearSession: true
|
Loading…
Reference in New Issue
Block a user