Commit 6abd67a38c671219f138a52a50d4d4ceda632af3
1 parent
d718f801
【代码优化】IoT: 物模型
Showing
14 changed files
with
148 additions
and
56 deletions
yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/thingmodel/IotDataSpecsDataTypeEnum.java
| 1 | 1 | package cn.iocoder.yudao.module.iot.enums.thingmodel; |
| 2 | 2 | |
| 3 | +import cn.iocoder.yudao.framework.common.core.ArrayValuable; | |
| 3 | 4 | import lombok.AllArgsConstructor; |
| 4 | 5 | import lombok.Getter; |
| 5 | 6 | |
| 6 | -// TODO @puhui999:加个 ArrayValuable | |
| 7 | +import java.util.Arrays; | |
| 8 | + | |
| 7 | 9 | /** |
| 8 | 10 | * IoT 数据定义的数据类型枚举类 |
| 9 | 11 | * |
| ... | ... | @@ -11,7 +13,7 @@ import lombok.Getter; |
| 11 | 13 | */ |
| 12 | 14 | @AllArgsConstructor |
| 13 | 15 | @Getter |
| 14 | -public enum IotDataSpecsDataTypeEnum { | |
| 16 | +public enum IotDataSpecsDataTypeEnum implements ArrayValuable<String> { | |
| 15 | 17 | |
| 16 | 18 | INT("int"), |
| 17 | 19 | FLOAT("float"), |
| ... | ... | @@ -23,6 +25,13 @@ public enum IotDataSpecsDataTypeEnum { |
| 23 | 25 | STRUCT("struct"), |
| 24 | 26 | ARRAY("array"); |
| 25 | 27 | |
| 28 | + public static final String[] ARRAYS = Arrays.stream(values()).map(IotDataSpecsDataTypeEnum::getDataType).toArray(String[]::new); | |
| 29 | + | |
| 26 | 30 | private final String dataType; |
| 27 | 31 | |
| 32 | + @Override | |
| 33 | + public String[] array() { | |
| 34 | + return ARRAYS; | |
| 35 | + } | |
| 36 | + | |
| 28 | 37 | } | ... | ... |
yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/thingmodel/IotThingModelAccessModeEnum.java
| 1 | 1 | package cn.iocoder.yudao.module.iot.enums.thingmodel; |
| 2 | 2 | |
| 3 | +import cn.iocoder.yudao.framework.common.core.ArrayValuable; | |
| 3 | 4 | import lombok.AllArgsConstructor; |
| 4 | 5 | import lombok.Getter; |
| 5 | 6 | |
| 6 | -// TODO @puhui999:加个 ArrayValuable | |
| 7 | +import java.util.Arrays; | |
| 8 | + | |
| 7 | 9 | /** |
| 8 | 10 | * IOT 产品物模型属性读取类型枚举 |
| 9 | 11 | * |
| ... | ... | @@ -11,11 +13,18 @@ import lombok.Getter; |
| 11 | 13 | */ |
| 12 | 14 | @AllArgsConstructor |
| 13 | 15 | @Getter |
| 14 | -public enum IotThingModelAccessModeEnum { | |
| 16 | +public enum IotThingModelAccessModeEnum implements ArrayValuable<String> { | |
| 15 | 17 | |
| 16 | 18 | READ_ONLY("r"), |
| 17 | 19 | READ_WRITE("rw"); |
| 18 | 20 | |
| 21 | + public static final String[] ARRAYS = Arrays.stream(values()).map(IotThingModelAccessModeEnum::getMode).toArray(String[]::new); | |
| 22 | + | |
| 19 | 23 | private final String mode; |
| 20 | 24 | |
| 25 | + @Override | |
| 26 | + public String[] array() { | |
| 27 | + return ARRAYS; | |
| 28 | + } | |
| 29 | + | |
| 21 | 30 | } | ... | ... |
yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/thingmodel/IotThingModelParamDirectionEnum.java
| 1 | 1 | package cn.iocoder.yudao.module.iot.enums.thingmodel; |
| 2 | 2 | |
| 3 | +import cn.iocoder.yudao.framework.common.core.ArrayValuable; | |
| 3 | 4 | import lombok.AllArgsConstructor; |
| 4 | 5 | import lombok.Getter; |
| 5 | 6 | |
| 6 | -// TODO @puhui999:加个 ArrayValuable | |
| 7 | +import java.util.Arrays; | |
| 8 | + | |
| 9 | + | |
| 7 | 10 | /** |
| 8 | 11 | * IOT 产品物模型参数是输入参数还是输出参数枚举 |
| 9 | 12 | * |
| ... | ... | @@ -11,11 +14,18 @@ import lombok.Getter; |
| 11 | 14 | */ |
| 12 | 15 | @AllArgsConstructor |
| 13 | 16 | @Getter |
| 14 | -public enum IotThingModelParamDirectionEnum { | |
| 17 | +public enum IotThingModelParamDirectionEnum implements ArrayValuable<String> { | |
| 15 | 18 | |
| 16 | 19 | INPUT("input"), // 输入参数 |
| 17 | 20 | OUTPUT("output"); // 输出参数 |
| 18 | 21 | |
| 22 | + public static final String[] ARRAYS = Arrays.stream(values()).map(IotThingModelParamDirectionEnum::getDirection).toArray(String[]::new); | |
| 23 | + | |
| 19 | 24 | private final String direction; |
| 20 | 25 | |
| 26 | + @Override | |
| 27 | + public String[] array() { | |
| 28 | + return ARRAYS; | |
| 29 | + } | |
| 30 | + | |
| 21 | 31 | } | ... | ... |
yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/thingmodel/IotThingModelServiceCallTypeEnum.java
| 1 | 1 | package cn.iocoder.yudao.module.iot.enums.thingmodel; |
| 2 | 2 | |
| 3 | +import cn.iocoder.yudao.framework.common.core.ArrayValuable; | |
| 3 | 4 | import lombok.AllArgsConstructor; |
| 4 | 5 | import lombok.Getter; |
| 5 | 6 | |
| 6 | -// TODO @puhui999:加个 ArrayValuable | |
| 7 | +import java.util.Arrays; | |
| 8 | + | |
| 7 | 9 | /** |
| 8 | 10 | * IOT 产品物模型服务调用方式枚举 |
| 9 | 11 | * |
| ... | ... | @@ -11,11 +13,18 @@ import lombok.Getter; |
| 11 | 13 | */ |
| 12 | 14 | @AllArgsConstructor |
| 13 | 15 | @Getter |
| 14 | -public enum IotThingModelServiceCallTypeEnum { | |
| 16 | +public enum IotThingModelServiceCallTypeEnum implements ArrayValuable<String> { | |
| 15 | 17 | |
| 16 | 18 | ASYNC("async"), // 异步调用 |
| 17 | 19 | SYNC("sync"); // 同步调用 |
| 18 | 20 | |
| 21 | + public static final String[] ARRAYS = Arrays.stream(values()).map(IotThingModelServiceCallTypeEnum::getType).toArray(String[]::new); | |
| 22 | + | |
| 19 | 23 | private final String type; |
| 20 | 24 | |
| 25 | + @Override | |
| 26 | + public String[] array() { | |
| 27 | + return ARRAYS; | |
| 28 | + } | |
| 29 | + | |
| 21 | 30 | } | ... | ... |
yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/thingmodel/IotThingModelServiceEventTypeEnum.java
| 1 | 1 | package cn.iocoder.yudao.module.iot.enums.thingmodel; |
| 2 | 2 | |
| 3 | +import cn.iocoder.yudao.framework.common.core.ArrayValuable; | |
| 3 | 4 | import lombok.AllArgsConstructor; |
| 4 | 5 | import lombok.Getter; |
| 5 | 6 | |
| 6 | -// TODO @puhui999:加个 ArrayValuable | |
| 7 | +import java.util.Arrays; | |
| 8 | + | |
| 7 | 9 | /** |
| 8 | 10 | * IOT 产品物模型事件类型枚举 |
| 9 | 11 | * |
| ... | ... | @@ -11,12 +13,19 @@ import lombok.Getter; |
| 11 | 13 | */ |
| 12 | 14 | @AllArgsConstructor |
| 13 | 15 | @Getter |
| 14 | -public enum IotThingModelServiceEventTypeEnum { | |
| 16 | +public enum IotThingModelServiceEventTypeEnum implements ArrayValuable<String> { | |
| 15 | 17 | |
| 16 | 18 | INFO("info"), // 信息 |
| 17 | 19 | ALERT("alert"), // 告警 |
| 18 | 20 | ERROR("error"); // 故障 |
| 19 | 21 | |
| 22 | + public static final String[] ARRAYS = Arrays.stream(values()).map(IotThingModelServiceEventTypeEnum::getType).toArray(String[]::new); | |
| 23 | + | |
| 20 | 24 | private final String type; |
| 21 | 25 | |
| 26 | + @Override | |
| 27 | + public String[] array() { | |
| 28 | + return ARRAYS; | |
| 29 | + } | |
| 30 | + | |
| 22 | 31 | } | ... | ... |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thingmodel/model/ThingModelEvent.java
| 1 | 1 | package cn.iocoder.yudao.module.iot.controller.admin.thingmodel.model; |
| 2 | 2 | |
| 3 | +import cn.iocoder.yudao.framework.common.validation.InEnum; | |
| 3 | 4 | import cn.iocoder.yudao.module.iot.enums.thingmodel.IotThingModelServiceEventTypeEnum; |
| 5 | +import jakarta.validation.Valid; | |
| 6 | +import jakarta.validation.constraints.NotEmpty; | |
| 7 | +import jakarta.validation.constraints.Pattern; | |
| 4 | 8 | import lombok.Data; |
| 5 | 9 | |
| 6 | 10 | import java.util.List; |
| 7 | 11 | |
| 8 | -// TODO @puhui999:必要的参数校验 | |
| 9 | 12 | /** |
| 10 | 13 | * 物模型中的事件 |
| 11 | 14 | * |
| ... | ... | @@ -17,10 +20,13 @@ public class ThingModelEvent { |
| 17 | 20 | /** |
| 18 | 21 | * 事件标识符 |
| 19 | 22 | */ |
| 23 | + @NotEmpty(message = "事件标识符不能为空") | |
| 24 | + @Pattern(regexp = "^[a-zA-Z][a-zA-Z0-9_]{0,31}$", message = "事件标识符只能由字母、数字和下划线组成,必须以字母开头,长度不超过32个字符") | |
| 20 | 25 | private String identifier; |
| 21 | 26 | /** |
| 22 | 27 | * 事件名称 |
| 23 | 28 | */ |
| 29 | + @NotEmpty(message = "事件名称不能为空") | |
| 24 | 30 | private String name; |
| 25 | 31 | /** |
| 26 | 32 | * 是否是标准品类的必选事件 |
| ... | ... | @@ -31,12 +37,15 @@ public class ThingModelEvent { |
| 31 | 37 | * |
| 32 | 38 | * 枚举 {@link IotThingModelServiceEventTypeEnum} |
| 33 | 39 | */ |
| 40 | + @NotEmpty(message = "事件类型不能为空") | |
| 41 | + @InEnum(IotThingModelServiceEventTypeEnum.class) | |
| 34 | 42 | private String type; |
| 35 | 43 | /** |
| 36 | 44 | * 事件的输出参数 |
| 37 | 45 | * |
| 38 | 46 | * 输出参数定义事件调用后返回的结果或反馈信息,用于确认操作结果或提供额外的信息。 |
| 39 | 47 | */ |
| 48 | + @Valid | |
| 40 | 49 | private List<ThingModelParam> outputParams; |
| 41 | 50 | /** |
| 42 | 51 | * 标识设备需要执行的具体操作 | ... | ... |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thingmodel/model/ThingModelParam.java
| 1 | 1 | package cn.iocoder.yudao.module.iot.controller.admin.thingmodel.model; |
| 2 | 2 | |
| 3 | +import cn.iocoder.yudao.framework.common.validation.InEnum; | |
| 3 | 4 | import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.model.dataType.ThingModelDataSpecs; |
| 5 | +import cn.iocoder.yudao.module.iot.enums.thingmodel.IotDataSpecsDataTypeEnum; | |
| 4 | 6 | import cn.iocoder.yudao.module.iot.enums.thingmodel.IotThingModelParamDirectionEnum; |
| 7 | +import jakarta.validation.constraints.NotEmpty; | |
| 8 | +import jakarta.validation.constraints.Pattern; | |
| 5 | 9 | import lombok.Data; |
| 6 | 10 | |
| 7 | 11 | import java.util.List; |
| 8 | 12 | |
| 9 | -// TODO @puhui999:必要的参数校验 | |
| 10 | 13 | /** |
| 11 | 14 | * IOT 产品物模型中的参数 |
| 12 | 15 | * |
| ... | ... | @@ -18,16 +21,21 @@ public class ThingModelParam { |
| 18 | 21 | /** |
| 19 | 22 | * 参数标识符 |
| 20 | 23 | */ |
| 24 | + @NotEmpty(message = "参数标识符不能为空") | |
| 25 | + @Pattern(regexp = "^[a-zA-Z][a-zA-Z0-9_]{0,31}$", message = "参数标识符只能由字母、数字和下划线组成,必须以字母开头,长度不超过32个字符") | |
| 21 | 26 | private String identifier; |
| 22 | 27 | /** |
| 23 | 28 | * 参数名称 |
| 24 | 29 | */ |
| 30 | + @NotEmpty(message = "参数名称不能为空") | |
| 25 | 31 | private String name; |
| 26 | 32 | /** |
| 27 | 33 | * 用于区分输入或输出参数 |
| 28 | 34 | * |
| 29 | 35 | * 枚举 {@link IotThingModelParamDirectionEnum} |
| 30 | 36 | */ |
| 37 | + @NotEmpty(message = "参数方向不能为空") | |
| 38 | + @InEnum(IotThingModelParamDirectionEnum.class) | |
| 31 | 39 | private String direction; |
| 32 | 40 | /** |
| 33 | 41 | * 参数的序号。从 0 开始排序,且不能重复。 |
| ... | ... | @@ -37,7 +45,11 @@ public class ThingModelParam { |
| 37 | 45 | private Integer paraOrder; |
| 38 | 46 | /** |
| 39 | 47 | * 参数值的数据类型,与 dataSpecs 的 dataType 保持一致 |
| 48 | + * | |
| 49 | + * 枚举 {@link IotDataSpecsDataTypeEnum} | |
| 40 | 50 | */ |
| 51 | + @NotEmpty(message = "数据类型不能为空") | |
| 52 | + @InEnum(IotDataSpecsDataTypeEnum.class) | |
| 41 | 53 | private String dataType; |
| 42 | 54 | /** |
| 43 | 55 | * 参数值的数据类型(dataType)为非列表型(int、float、double、text、date、array)的数据规范存储在 dataSpecs 中 | ... | ... |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thingmodel/model/ThingModelProperty.java
| 1 | 1 | package cn.iocoder.yudao.module.iot.controller.admin.thingmodel.model; |
| 2 | 2 | |
| 3 | +import cn.iocoder.yudao.framework.common.validation.InEnum; | |
| 3 | 4 | import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.model.dataType.ThingModelDataSpecs; |
| 5 | +import cn.iocoder.yudao.module.iot.enums.thingmodel.IotDataSpecsDataTypeEnum; | |
| 4 | 6 | import cn.iocoder.yudao.module.iot.enums.thingmodel.IotThingModelAccessModeEnum; |
| 7 | +import jakarta.validation.constraints.NotEmpty; | |
| 8 | +import jakarta.validation.constraints.Pattern; | |
| 5 | 9 | import lombok.Data; |
| 6 | 10 | |
| 7 | 11 | import java.util.List; |
| 8 | 12 | |
| 9 | -// TODO @puhui999:必要的参数校验 | |
| 10 | 13 | /** |
| 11 | 14 | * 物模型中的属性 |
| 12 | 15 | * |
| ... | ... | @@ -20,26 +23,33 @@ public class ThingModelProperty { |
| 20 | 23 | /** |
| 21 | 24 | * 属性标识符 |
| 22 | 25 | */ |
| 26 | + @NotEmpty(message = "属性标识符不能为空") | |
| 27 | + @Pattern(regexp = "^[a-zA-Z][a-zA-Z0-9_]{0,31}$", message = "属性标识符只能由字母、数字和下划线组成,必须以字母开头,长度不超过32个字符") | |
| 23 | 28 | private String identifier; |
| 24 | 29 | /** |
| 25 | 30 | * 属性名称 |
| 26 | 31 | */ |
| 32 | + @NotEmpty(message = "属性名称不能为空") | |
| 27 | 33 | private String name; |
| 28 | 34 | /** |
| 29 | 35 | * 云端可以对该属性进行的操作类型 |
| 30 | 36 | * |
| 31 | 37 | * 枚举 {@link IotThingModelAccessModeEnum} |
| 32 | 38 | */ |
| 39 | + @NotEmpty(message = "操作类型不能为空") | |
| 40 | + @InEnum(IotThingModelAccessModeEnum.class) | |
| 33 | 41 | private String accessMode; |
| 34 | 42 | /** |
| 35 | 43 | * 是否是标准品类的必选服务 |
| 36 | 44 | */ |
| 37 | 45 | private Boolean required; |
| 38 | 46 | /** |
| 39 | - * 数据类型,与 dataSpecs 的 dataType 保持一致 | |
| 47 | + * 参数值的数据类型,与 dataSpecs 的 dataType 保持一致 | |
| 40 | 48 | * |
| 41 | - * 枚举 {@link cn.iocoder.yudao.module.iot.enums.thingmodel.IotDataSpecsDataTypeEnum} | |
| 49 | + * 枚举 {@link IotDataSpecsDataTypeEnum} | |
| 42 | 50 | */ |
| 51 | + @NotEmpty(message = "数据类型不能为空") | |
| 52 | + @InEnum(IotDataSpecsDataTypeEnum.class) | |
| 43 | 53 | private String dataType; |
| 44 | 54 | /** |
| 45 | 55 | * 数据类型(dataType)为非列表型(int、float、double、text、date、array)的数据规范存储在 dataSpecs 中 | ... | ... |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thingmodel/model/ThingModelService.java
| 1 | 1 | package cn.iocoder.yudao.module.iot.controller.admin.thingmodel.model; |
| 2 | 2 | |
| 3 | +import cn.iocoder.yudao.framework.common.validation.InEnum; | |
| 3 | 4 | import cn.iocoder.yudao.module.iot.enums.thingmodel.IotThingModelServiceCallTypeEnum; |
| 5 | +import jakarta.validation.Valid; | |
| 6 | +import jakarta.validation.constraints.NotEmpty; | |
| 7 | +import jakarta.validation.constraints.Pattern; | |
| 4 | 8 | import lombok.Data; |
| 5 | 9 | |
| 6 | 10 | import java.util.List; |
| 7 | 11 | |
| 8 | -// TODO @puhui999:必要的参数校验 | |
| 9 | 12 | /** |
| 10 | 13 | * 物模型中的服务 |
| 11 | 14 | * |
| ... | ... | @@ -17,10 +20,13 @@ public class ThingModelService { |
| 17 | 20 | /** |
| 18 | 21 | * 服务标识符 |
| 19 | 22 | */ |
| 23 | + @NotEmpty(message = "服务标识符不能为空") | |
| 24 | + @Pattern(regexp = "^[a-zA-Z][a-zA-Z0-9_]{0,31}$", message = "服务标识符只能由字母、数字和下划线组成,必须以字母开头,长度不超过32个字符") | |
| 20 | 25 | private String identifier; |
| 21 | 26 | /** |
| 22 | 27 | * 服务名称 |
| 23 | 28 | */ |
| 29 | + @NotEmpty(message = "服务名称不能为空") | |
| 24 | 30 | private String name; |
| 25 | 31 | /** |
| 26 | 32 | * 是否是标准品类的必选服务 |
| ... | ... | @@ -31,18 +37,22 @@ public class ThingModelService { |
| 31 | 37 | * |
| 32 | 38 | * 枚举 {@link IotThingModelServiceCallTypeEnum} |
| 33 | 39 | */ |
| 40 | + @NotEmpty(message = "调用类型不能为空") | |
| 41 | + @InEnum(IotThingModelServiceCallTypeEnum.class) | |
| 34 | 42 | private String callType; |
| 35 | 43 | /** |
| 36 | 44 | * 服务的输入参数 |
| 37 | 45 | * |
| 38 | 46 | * 输入参数定义服务调用时所需提供的信息,用于控制设备行为或执行特定任务 |
| 39 | 47 | */ |
| 48 | + @Valid | |
| 40 | 49 | private List<ThingModelParam> inputParams; |
| 41 | 50 | /** |
| 42 | 51 | * 服务的输出参数 |
| 43 | 52 | * |
| 44 | 53 | * 输出参数定义服务调用后返回的结果或反馈信息,用于确认操作结果或提供额外的信息。 |
| 45 | 54 | */ |
| 55 | + @Valid | |
| 46 | 56 | private List<ThingModelParam> outputParams; |
| 47 | 57 | /** |
| 48 | 58 | * 标识设备需要执行的具体操作 | ... | ... |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thingmodel/vo/IotThingModelListReqVO.java
| ... | ... | @@ -6,19 +6,18 @@ import io.swagger.v3.oas.annotations.media.Schema; |
| 6 | 6 | import jakarta.validation.constraints.NotNull; |
| 7 | 7 | import lombok.Data; |
| 8 | 8 | |
| 9 | -// TODO @puhui999:部分字段,可以用 cursor 加上 example | |
| 10 | 9 | @Schema(description = "管理后台 - IoT 产品物模型 List Request VO") |
| 11 | 10 | @Data |
| 12 | 11 | public class IotThingModelListReqVO { |
| 13 | 12 | |
| 14 | - @Schema(description = "产品编号", requiredMode = Schema.RequiredMode.REQUIRED) | |
| 13 | + @Schema(description = "产品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | |
| 15 | 14 | @NotNull(message = "产品编号不能为空") |
| 16 | 15 | private Long productId; |
| 17 | 16 | |
| 18 | - @Schema(description = "功能标识") | |
| 17 | + @Schema(description = "功能标识", example = "temperature") | |
| 19 | 18 | private String identifier; |
| 20 | 19 | |
| 21 | - @Schema(description = "功能名称", example = "张三") | |
| 20 | + @Schema(description = "功能名称", example = "温度") | |
| 22 | 21 | private String name; |
| 23 | 22 | |
| 24 | 23 | @Schema(description = "功能类型", example = "1") | ... | ... |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thingmodel/vo/IotThingModelPageReqVO.java
| ... | ... | @@ -9,21 +9,20 @@ import lombok.Data; |
| 9 | 9 | import lombok.EqualsAndHashCode; |
| 10 | 10 | import lombok.ToString; |
| 11 | 11 | |
| 12 | -// TODO @puhui999:部分字段,可以用 cursor 加上 example | |
| 13 | 12 | @Schema(description = "管理后台 - IoT 产品物模型分页 Request VO") |
| 14 | 13 | @Data |
| 15 | 14 | @EqualsAndHashCode(callSuper = true) |
| 16 | 15 | @ToString(callSuper = true) |
| 17 | 16 | public class IotThingModelPageReqVO extends PageParam { |
| 18 | 17 | |
| 19 | - @Schema(description = "产品编号", requiredMode = Schema.RequiredMode.REQUIRED) | |
| 18 | + @Schema(description = "产品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | |
| 20 | 19 | @NotNull(message = "产品编号不能为空") |
| 21 | 20 | private Long productId; |
| 22 | 21 | |
| 23 | - @Schema(description = "功能标识") | |
| 22 | + @Schema(description = "功能标识", example = "temperature") | |
| 24 | 23 | private String identifier; |
| 25 | 24 | |
| 26 | - @Schema(description = "功能名称", example = "张三") | |
| 25 | + @Schema(description = "功能名称", example = "温度") | |
| 27 | 26 | private String name; |
| 28 | 27 | |
| 29 | 28 | @Schema(description = "功能类型", example = "1") | ... | ... |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thingmodel/vo/IotThingModelRespVO.java
| ... | ... | @@ -10,7 +10,6 @@ import lombok.Data; |
| 10 | 10 | |
| 11 | 11 | import java.time.LocalDateTime; |
| 12 | 12 | |
| 13 | -// TODO @puhui999:部分字段,可以用 cursor 加上 example | |
| 14 | 13 | @Schema(description = "管理后台 - IoT 产品物模型 Response VO") |
| 15 | 14 | @Data |
| 16 | 15 | @ExcelIgnoreUnannotated |
| ... | ... | @@ -20,23 +19,23 @@ public class IotThingModelRespVO { |
| 20 | 19 | @ExcelProperty("产品ID") |
| 21 | 20 | private Long id; |
| 22 | 21 | |
| 23 | - @Schema(description = "产品标识", requiredMode = Schema.RequiredMode.REQUIRED) | |
| 22 | + @Schema(description = "产品标识", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | |
| 24 | 23 | private Long productId; |
| 25 | 24 | |
| 26 | - @Schema(description = "产品标识", requiredMode = Schema.RequiredMode.REQUIRED) | |
| 25 | + @Schema(description = "产品标识", requiredMode = Schema.RequiredMode.REQUIRED, example = "temperature_sensor") | |
| 27 | 26 | @ExcelProperty("产品标识") |
| 28 | 27 | private String productKey; |
| 29 | 28 | |
| 30 | - @Schema(description = "功能标识", requiredMode = Schema.RequiredMode.REQUIRED) | |
| 29 | + @Schema(description = "功能标识", requiredMode = Schema.RequiredMode.REQUIRED, example = "temperature") | |
| 31 | 30 | private String identifier; |
| 32 | 31 | |
| 33 | - @Schema(description = "功能名称", requiredMode = Schema.RequiredMode.REQUIRED) | |
| 32 | + @Schema(description = "功能名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "温度") | |
| 34 | 33 | private String name; |
| 35 | 34 | |
| 36 | - @Schema(description = "功能描述", requiredMode = Schema.RequiredMode.REQUIRED) | |
| 35 | + @Schema(description = "功能描述", requiredMode = Schema.RequiredMode.REQUIRED, example = "测量当前环境温度") | |
| 37 | 36 | private String description; |
| 38 | 37 | |
| 39 | - @Schema(description = "功能类型", requiredMode = Schema.RequiredMode.REQUIRED) | |
| 38 | + @Schema(description = "功能类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | |
| 40 | 39 | private Integer type; |
| 41 | 40 | |
| 42 | 41 | @Schema(description = "属性", requiredMode = Schema.RequiredMode.REQUIRED) | ... | ... |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thingmodel/vo/IotThingModelSaveReqVO.java
| ... | ... | @@ -6,11 +6,11 @@ import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.model.ThingModelP |
| 6 | 6 | import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.model.ThingModelService; |
| 7 | 7 | import cn.iocoder.yudao.module.iot.enums.thingmodel.IotThingModelTypeEnum; |
| 8 | 8 | import io.swagger.v3.oas.annotations.media.Schema; |
| 9 | +import jakarta.validation.Valid; | |
| 9 | 10 | import jakarta.validation.constraints.NotEmpty; |
| 10 | 11 | import jakarta.validation.constraints.NotNull; |
| 11 | 12 | import lombok.Data; |
| 12 | 13 | |
| 13 | -// TODO @puhui999:部分字段,可以用 cursor 加上 example | |
| 14 | 14 | @Schema(description = "管理后台 - IoT 产品物模型新增/修改 Request VO") |
| 15 | 15 | @Data |
| 16 | 16 | public class IotThingModelSaveReqVO { |
| ... | ... | @@ -22,33 +22,36 @@ public class IotThingModelSaveReqVO { |
| 22 | 22 | @NotNull(message = "产品ID不能为空") |
| 23 | 23 | private Long productId; |
| 24 | 24 | |
| 25 | - @Schema(description = "产品标识", requiredMode = Schema.RequiredMode.REQUIRED) | |
| 25 | + @Schema(description = "产品标识", requiredMode = Schema.RequiredMode.REQUIRED, example = "temperature_001") | |
| 26 | 26 | @NotEmpty(message = "产品标识不能为空") |
| 27 | 27 | private String productKey; |
| 28 | 28 | |
| 29 | - @Schema(description = "功能标识", requiredMode = Schema.RequiredMode.REQUIRED) | |
| 29 | + @Schema(description = "功能标识", requiredMode = Schema.RequiredMode.REQUIRED, example = "temp_monitor") | |
| 30 | 30 | @NotEmpty(message = "功能标识不能为空") |
| 31 | 31 | private String identifier; |
| 32 | 32 | |
| 33 | - @Schema(description = "功能名称", requiredMode = Schema.RequiredMode.REQUIRED) | |
| 33 | + @Schema(description = "功能名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "温度监测器") | |
| 34 | 34 | @NotEmpty(message = "功能名称不能为空") |
| 35 | 35 | private String name; |
| 36 | 36 | |
| 37 | - @Schema(description = "功能描述", requiredMode = Schema.RequiredMode.REQUIRED) | |
| 37 | + @Schema(description = "功能描述", requiredMode = Schema.RequiredMode.REQUIRED, example = "用于监测环境温度的传感器") | |
| 38 | 38 | private String description; |
| 39 | 39 | |
| 40 | - @Schema(description = "功能类型", requiredMode = Schema.RequiredMode.REQUIRED) | |
| 40 | + @Schema(description = "功能类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | |
| 41 | 41 | @NotNull(message = "功能类型不能为空") |
| 42 | 42 | @InEnum(IotThingModelTypeEnum.class) |
| 43 | 43 | private Integer type; |
| 44 | 44 | |
| 45 | 45 | @Schema(description = "属性", requiredMode = Schema.RequiredMode.REQUIRED) |
| 46 | + @Valid | |
| 46 | 47 | private ThingModelProperty property; |
| 47 | 48 | |
| 48 | 49 | @Schema(description = "服务", requiredMode = Schema.RequiredMode.REQUIRED) |
| 50 | + @Valid | |
| 49 | 51 | private ThingModelService service; |
| 50 | 52 | |
| 51 | 53 | @Schema(description = "事件", requiredMode = Schema.RequiredMode.REQUIRED) |
| 54 | + @Valid | |
| 52 | 55 | private ThingModelEvent event; |
| 53 | 56 | |
| 54 | 57 | } |
| 55 | 58 | \ No newline at end of file | ... | ... |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thingmodel/IotThingModelServiceImpl.java
| ... | ... | @@ -55,7 +55,7 @@ public class IotThingModelServiceImpl implements IotThingModelService { |
| 55 | 55 | @Transactional(rollbackFor = Exception.class) |
| 56 | 56 | public Long createThingModel(IotThingModelSaveReqVO createReqVO) { |
| 57 | 57 | // 1.1 校验功能标识符在同一产品下是否唯一 |
| 58 | - validateIdentifierUnique(createReqVO.getProductId(), createReqVO.getIdentifier()); | |
| 58 | + validateIdentifierUnique(null, createReqVO.getProductId(), createReqVO.getIdentifier()); | |
| 59 | 59 | // 1.2 功能名称在同一产品下是否唯一 |
| 60 | 60 | validateNameUnique(createReqVO.getProductId(), createReqVO.getName()); |
| 61 | 61 | // 1.3 校验产品状态,发布状态下,不允许新增功能 |
| ... | ... | @@ -81,7 +81,7 @@ public class IotThingModelServiceImpl implements IotThingModelService { |
| 81 | 81 | // 1.1 校验功能是否存在 |
| 82 | 82 | validateProductThingModelMapperExists(updateReqVO.getId()); |
| 83 | 83 | // 1.2 校验功能标识符是否唯一 |
| 84 | - validateIdentifierUniqueForUpdate(updateReqVO.getId(), updateReqVO.getProductId(), updateReqVO.getIdentifier()); | |
| 84 | + validateIdentifierUnique(updateReqVO.getId(), updateReqVO.getProductId(), updateReqVO.getIdentifier()); | |
| 85 | 85 | // 1.3 校验产品状态,发布状态下,不允许操作功能 |
| 86 | 86 | validateProductStatus(updateReqVO.getProductId()); |
| 87 | 87 | |
| ... | ... | @@ -159,8 +159,23 @@ public class IotThingModelServiceImpl implements IotThingModelService { |
| 159 | 159 | } |
| 160 | 160 | } |
| 161 | 161 | |
| 162 | - // TODO @puhui999:这个方法,和 validateIdentifierUnique 可以融合下 | |
| 163 | - private void validateIdentifierUniqueForUpdate(Long id, Long productId, String identifier) { | |
| 162 | + private void validateIdentifierUnique(Long id, Long productId, String identifier) { | |
| 163 | + // 1.0 情况一:创建时校验 | |
| 164 | + if (id == null) { | |
| 165 | + // 1.1 系统保留字段,不能用于标识符定义 | |
| 166 | + if (StrUtil.equalsAny(identifier, "set", "get", "post", "property", "event", "time", "value")) { | |
| 167 | + throw exception(THING_MODEL_IDENTIFIER_INVALID); | |
| 168 | + } | |
| 169 | + | |
| 170 | + // 1.2 校验唯一 | |
| 171 | + IotThingModelDO thingModel = thingModelMapper.selectByProductIdAndIdentifier(productId, identifier); | |
| 172 | + if (thingModel != null) { | |
| 173 | + throw exception(THING_MODEL_IDENTIFIER_EXISTS); | |
| 174 | + } | |
| 175 | + return; | |
| 176 | + } | |
| 177 | + | |
| 178 | + // 2.0 情况二:更新时校验 | |
| 164 | 179 | IotThingModelDO thingModel = thingModelMapper.selectByProductIdAndIdentifier(productId, identifier); |
| 165 | 180 | if (thingModel != null && ObjectUtil.notEqual(thingModel.getId(), id)) { |
| 166 | 181 | throw exception(THING_MODEL_IDENTIFIER_EXISTS); |
| ... | ... | @@ -181,23 +196,10 @@ public class IotThingModelServiceImpl implements IotThingModelService { |
| 181 | 196 | } |
| 182 | 197 | } |
| 183 | 198 | |
| 184 | - private void validateIdentifierUnique(Long productId, String identifier) { | |
| 185 | - // 系统保留字段,不能用于标识符定义 | |
| 186 | - if (StrUtil.equalsAny(identifier, "set", "get", "post", "property", "event", "time", "value")) { | |
| 187 | - throw exception(THING_MODEL_IDENTIFIER_INVALID); | |
| 188 | - } | |
| 189 | - | |
| 190 | - // 校验唯一 | |
| 191 | - IotThingModelDO thingModel = thingModelMapper.selectByProductIdAndIdentifier(productId, identifier); | |
| 192 | - if (thingModel != null) { | |
| 193 | - throw exception(THING_MODEL_IDENTIFIER_EXISTS); | |
| 194 | - } | |
| 195 | - } | |
| 196 | - | |
| 197 | 199 | /** |
| 198 | 200 | * 创建默认的事件和服务 |
| 199 | 201 | * |
| 200 | - * @param productId 产品编号 | |
| 202 | + * @param productId 产品编号 | |
| 201 | 203 | * @param productKey 产品标识 |
| 202 | 204 | */ |
| 203 | 205 | public void createDefaultEventsAndServices(Long productId, String productKey) { |
| ... | ... | @@ -282,6 +284,7 @@ public class IotThingModelServiceImpl implements IotThingModelService { |
| 282 | 284 | } |
| 283 | 285 | |
| 284 | 286 | // TODO @haohao:是不是不用生成这个?目前属性上报,是个批量接口 |
| 287 | + | |
| 285 | 288 | /** |
| 286 | 289 | * 生成属性上报事件 |
| 287 | 290 | */ |
| ... | ... | @@ -298,6 +301,7 @@ public class IotThingModelServiceImpl implements IotThingModelService { |
| 298 | 301 | } |
| 299 | 302 | |
| 300 | 303 | // TODO @haohao:是不是不用生成这个?目前属性上报,是个批量接口 |
| 304 | + | |
| 301 | 305 | /** |
| 302 | 306 | * 生成属性设置服务 |
| 303 | 307 | */ |
| ... | ... | @@ -352,7 +356,8 @@ public class IotThingModelServiceImpl implements IotThingModelService { |
| 352 | 356 | } |
| 353 | 357 | |
| 354 | 358 | @CacheEvict(value = RedisKeyConstants.THING_MODEL_LIST, key = "#productKey") |
| 355 | - public void deleteThingModelListCache0(String productKey) {} | |
| 359 | + public void deleteThingModelListCache0(String productKey) { | |
| 360 | + } | |
| 356 | 361 | |
| 357 | 362 | private IotThingModelServiceImpl getSelf() { |
| 358 | 363 | return SpringUtil.getBean(getClass()); | ... | ... |