Commit 16120820a0094ecc74e5197e7497c10d485c9668

Authored by YunaiV
2 parents aad05817 6aad4545

Merge branch 'feature/iot' of https://gitee.com/alwayssuper/ruoyi-vue-pro into feature/iot

# Conflicts:
#	yudao-server/src/main/resources/application-local.yaml
Showing 24 changed files with 618 additions and 103 deletions
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/IotDeviceDataController.java
@@ -3,19 +3,19 @@ package cn.iocoder.yudao.module.iot.controller.admin.device; @@ -3,19 +3,19 @@ package cn.iocoder.yudao.module.iot.controller.admin.device;
3 import cn.iocoder.yudao.framework.common.pojo.CommonResult; 3 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
4 import cn.iocoder.yudao.framework.common.pojo.PageResult; 4 import cn.iocoder.yudao.framework.common.pojo.PageResult;
5 import cn.iocoder.yudao.framework.common.util.object.BeanUtils; 5 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
6 -import cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData.IotDeviceDataPageReqVO;  
7 -import cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData.IotDeviceDataRespVO; 6 +import cn.iocoder.yudao.module.iot.controller.admin.device.vo.device.IotDeviceSaveReqVO;
  7 +import cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData.*;
8 import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDataDO; 8 import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDataDO;
9 -import cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData.IotTimeDataRespVO; 9 +import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceLogDO;
  10 +import cn.iocoder.yudao.module.iot.service.device.IotDeviceLogDataService;
10 import cn.iocoder.yudao.module.iot.service.device.IotDevicePropertyDataService; 11 import cn.iocoder.yudao.module.iot.service.device.IotDevicePropertyDataService;
11 import io.swagger.v3.oas.annotations.Operation; 12 import io.swagger.v3.oas.annotations.Operation;
12 import io.swagger.v3.oas.annotations.tags.Tag; 13 import io.swagger.v3.oas.annotations.tags.Tag;
13 import jakarta.annotation.Resource; 14 import jakarta.annotation.Resource;
14 import jakarta.validation.Valid; 15 import jakarta.validation.Valid;
  16 +import org.springframework.security.access.prepost.PreAuthorize;
15 import org.springframework.validation.annotation.Validated; 17 import org.springframework.validation.annotation.Validated;
16 -import org.springframework.web.bind.annotation.GetMapping;  
17 -import org.springframework.web.bind.annotation.RequestMapping;  
18 -import org.springframework.web.bind.annotation.RestController; 18 +import org.springframework.web.bind.annotation.*;
19 19
20 import java.util.List; 20 import java.util.List;
21 import java.util.Map; 21 import java.util.Map;
@@ -31,6 +31,12 @@ public class IotDeviceDataController { @@ -31,6 +31,12 @@ public class IotDeviceDataController {
31 @Resource 31 @Resource
32 private IotDevicePropertyDataService deviceDataService; 32 private IotDevicePropertyDataService deviceDataService;
33 33
  34 + @Resource
  35 + private IotDeviceLogDataService iotDeviceLogDataService;
  36 +
  37 + @Resource
  38 + private IotDeviceLogDataService deviceLogDataService;
  39 +
34 // TODO @浩浩:这里的 /latest-list,包括方法名。 40 // TODO @浩浩:这里的 /latest-list,包括方法名。
35 @GetMapping("/latest") 41 @GetMapping("/latest")
36 @Operation(summary = "获取设备属性最新数据") 42 @Operation(summary = "获取设备属性最新数据")
@@ -46,5 +52,20 @@ public class IotDeviceDataController { @@ -46,5 +52,20 @@ public class IotDeviceDataController {
46 PageResult<Map<String, Object>> list = deviceDataService.getHistoryDeviceProperties(deviceDataReqVO); 52 PageResult<Map<String, Object>> list = deviceDataService.getHistoryDeviceProperties(deviceDataReqVO);
47 return success(BeanUtils.toBean(list, IotTimeDataRespVO.class)); 53 return success(BeanUtils.toBean(list, IotTimeDataRespVO.class));
48 } 54 }
  55 + // TODO:数据权限
  56 + @PostMapping("/simulator")
  57 + @Operation(summary = "模拟设备")
  58 + public CommonResult<Boolean> simulatorDevice(@Valid @RequestBody IotDeviceDataSimulatorSaveReqVO simulatorReqVO) {
  59 + //TODO:先生成一下设备日志 后续完善模拟设备代码逻辑
  60 + iotDeviceLogDataService.createDeviceLog(simulatorReqVO);
  61 + return success(true);
  62 + }
  63 + // TODO:数据权限
  64 + @GetMapping("/log/page")
  65 + @Operation(summary = "获得设备日志分页")
  66 + public CommonResult<PageResult<IotDeviceLogRespVO>> getDeviceLogPage(@Valid IotDeviceLogPageReqVO pageReqVO) {
  67 + PageResult<IotDeviceLogDO> pageResult = deviceLogDataService.getDeviceLogPage(pageReqVO);
  68 + return success(BeanUtils.toBean(pageResult, IotDeviceLogRespVO.class));
  69 + }
49 70
50 } 71 }
51 \ No newline at end of file 72 \ No newline at end of file
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/device/IotDeviceSaveReqVO.java
1 package cn.iocoder.yudao.module.iot.controller.admin.device.vo.device; 1 package cn.iocoder.yudao.module.iot.controller.admin.device.vo.device;
2 2
3 import io.swagger.v3.oas.annotations.media.Schema; 3 import io.swagger.v3.oas.annotations.media.Schema;
  4 +import jakarta.validation.constraints.Size;
4 import lombok.Data; 5 import lombok.Data;
5 6
6 import java.util.Set; 7 import java.util.Set;
@@ -13,6 +14,7 @@ public class IotDeviceSaveReqVO { @@ -13,6 +14,7 @@ public class IotDeviceSaveReqVO {
13 private Long id; 14 private Long id;
14 15
15 @Schema(description = "设备编号", requiredMode = Schema.RequiredMode.AUTO, example = "177") 16 @Schema(description = "设备编号", requiredMode = Schema.RequiredMode.AUTO, example = "177")
  17 + @Size(max = 50, message = "设备编号长度不能超过50个字符")
16 private String deviceKey; 18 private String deviceKey;
17 19
18 @Schema(description = "设备名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "王五") 20 @Schema(description = "设备名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "王五")
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/deviceData/IotDeviceDataSimulatorSaveReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData;
  2 +
  3 +import io.swagger.v3.oas.annotations.media.Schema;
  4 +import jakarta.validation.constraints.NotEmpty;
  5 +import lombok.Data;
  6 +import org.springframework.format.annotation.DateTimeFormat;
  7 +
  8 +import java.time.LocalDateTime;
  9 +
  10 +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
  11 +
  12 +@Schema(description = "管理后台 - IoT 模拟设备数据 Request VO")
  13 +@Data
  14 +public class IotDeviceDataSimulatorSaveReqVO {
  15 +
  16 + @Schema(description = "消息ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "msg123")
  17 + private String id;
  18 +
  19 + @Schema(description = "产品ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "product123")
  20 + @NotEmpty(message = "产品ID不能为空")
  21 + private String productKey;
  22 +
  23 + @Schema(description = "设备ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "device123")
  24 + @NotEmpty(message = "设备ID不能为空")
  25 + private String deviceKey;
  26 +
  27 + @Schema(description = "消息/日志类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "property")
  28 + @NotEmpty(message = "消息类型不能为空")
  29 + private String type;
  30 +
  31 + @Schema(description = "标识符", requiredMode = Schema.RequiredMode.REQUIRED, example = "temperature")
  32 + @NotEmpty(message = "标识符不能为空")
  33 + private String subType;
  34 +
  35 + @Schema(description = "数据内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "{\"value\": 25.6}")
  36 + @NotEmpty(message = "数据内容不能为空")
  37 + private String content;
  38 +
  39 + @Schema(description = "上报时间", requiredMode = Schema.RequiredMode.REQUIRED)
  40 + private Long reportTime;
  41 +
  42 +}
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/deviceData/IotDeviceLogPageReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData;
  2 +
  3 +import cn.iocoder.yudao.framework.common.pojo.PageParam;
  4 +import io.swagger.v3.oas.annotations.media.Schema;
  5 +import jakarta.validation.constraints.NotEmpty;
  6 +import lombok.Data;
  7 +import org.springframework.format.annotation.DateTimeFormat;
  8 +
  9 +import java.time.LocalDateTime;
  10 +
  11 +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
  12 +
  13 +@Schema(description = "管理后台 - IoT 设备日志分页查询 Request VO")
  14 +@Data
  15 +public class IotDeviceLogPageReqVO extends PageParam {
  16 +
  17 + @Schema(description = "设备标识", requiredMode = Schema.RequiredMode.REQUIRED, example = "device123")
  18 + @NotEmpty(message = "设备标识不能为空")
  19 + private String deviceKey;
  20 +
  21 + @Schema(description = "消息类型", example = "property")
  22 + private String type;
  23 +
  24 + @Schema(description = "标识符", example = "temperature")
  25 + private String subType;
  26 +
  27 + @Schema(description = "创建时间")
  28 + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
  29 + private LocalDateTime[] createTime;
  30 +}
0 \ No newline at end of file 31 \ No newline at end of file
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/deviceData/IotDeviceLogRespVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData;
  2 +
  3 +import io.swagger.v3.oas.annotations.media.Schema;
  4 +import lombok.Data;
  5 +
  6 +import java.time.LocalDateTime;
  7 +
  8 +@Schema(description = "管理后台 - IoT 设备日志 Response VO")
  9 +@Data
  10 +public class IotDeviceLogRespVO {
  11 +
  12 + @Schema(description = "日志编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
  13 + private String id;
  14 + @Schema(description = "产品标识", requiredMode = Schema.RequiredMode.REQUIRED, example = "product123")
  15 + private String productKey;
  16 + @Schema(description = "设备标识", requiredMode = Schema.RequiredMode.REQUIRED, example = "device123")
  17 + private String deviceKey;
  18 +
  19 + @Schema(description = "消息类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "property")
  20 + private String type;
  21 +
  22 + @Schema(description = "标识符", requiredMode = Schema.RequiredMode.REQUIRED, example = "temperature")
  23 + private String subType;
  24 +
  25 + @Schema(description = "日志内容", requiredMode = Schema.RequiredMode.REQUIRED)
  26 + private String content;
  27 +
  28 + @Schema(description = "上报时间", requiredMode = Schema.RequiredMode.REQUIRED)
  29 + private LocalDateTime reportTime;
  30 +
  31 + @Schema(description = "记录时间戳", requiredMode = Schema.RequiredMode.REQUIRED)
  32 + private LocalDateTime ts;
  33 +}
0 \ No newline at end of file 34 \ No newline at end of file
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thingmodel/IotThingModelController.java
@@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.iot.controller.admin.thingmodel; @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.iot.controller.admin.thingmodel;
3 import cn.iocoder.yudao.framework.common.pojo.CommonResult; 3 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
4 import cn.iocoder.yudao.framework.common.pojo.PageResult; 4 import cn.iocoder.yudao.framework.common.pojo.PageResult;
5 import cn.iocoder.yudao.framework.common.util.object.BeanUtils; 5 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
  6 +import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.vo.IotThingModelListReqVO;
6 import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.vo.IotThingModelPageReqVO; 7 import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.vo.IotThingModelPageReqVO;
7 import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.vo.IotThingModelRespVO; 8 import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.vo.IotThingModelRespVO;
8 import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.vo.IotThingModelSaveReqVO; 9 import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.vo.IotThingModelSaveReqVO;
@@ -73,6 +74,14 @@ public class IotThingModelController { @@ -73,6 +74,14 @@ public class IotThingModelController {
73 return success(IotThingModelConvert.INSTANCE.convertList(list)); 74 return success(IotThingModelConvert.INSTANCE.convertList(list));
74 } 75 }
75 76
  77 + @GetMapping("/list")
  78 + @Operation(summary = "获得产品物模型列表")
  79 + @PreAuthorize("@ss.hasPermission('iot:thing-model:query')")
  80 + public CommonResult<List<IotThingModelRespVO>> getThingModelListByProductId(@Valid IotThingModelListReqVO reqVO) {
  81 + List<IotThingModelDO> list = thingModelService.getThingModelList(reqVO);
  82 + return success(IotThingModelConvert.INSTANCE.convertList(list));
  83 + }
  84 +
76 @GetMapping("/page") 85 @GetMapping("/page")
77 @Operation(summary = "获得产品物模型分页") 86 @Operation(summary = "获得产品物模型分页")
78 @PreAuthorize("@ss.hasPermission('iot:thing-model:query')") 87 @PreAuthorize("@ss.hasPermission('iot:thing-model:query')")
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thingmodel/vo/IotThingModelListReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.iot.controller.admin.thingmodel.vo;
  2 +
  3 +import cn.iocoder.yudao.framework.common.validation.InEnum;
  4 +import cn.iocoder.yudao.module.iot.enums.thingmodel.IotThingModelTypeEnum;
  5 +import io.swagger.v3.oas.annotations.media.Schema;
  6 +import jakarta.validation.constraints.NotNull;
  7 +import lombok.Data;
  8 +
  9 +
  10 +
  11 +@Schema(description = "管理后台 - IoT 产品物模型List Request VO")
  12 +@Data
  13 +public class IotThingModelListReqVO {
  14 + @Schema(description = "功能标识")
  15 + private String identifier;
  16 +
  17 + @Schema(description = "功能名称", example = "张三")
  18 + private String name;
  19 +
  20 + @Schema(description = "功能类型", example = "1")
  21 + @InEnum(IotThingModelTypeEnum.class)
  22 + private Integer type;
  23 +
  24 + @Schema(description = "产品ID", requiredMode = Schema.RequiredMode.REQUIRED)
  25 + @NotNull(message = "产品ID不能为空")
  26 + private Long productId;
  27 +}
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/device/IotDeviceLogDO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.iot.dal.dataobject.device;
  2 +
  3 +import cn.hutool.core.date.DateTime;
  4 +import lombok.AllArgsConstructor;
  5 +import lombok.Builder;
  6 +import lombok.Data;
  7 +import lombok.NoArgsConstructor;
  8 +
  9 +import java.time.LocalDateTime;
  10 +
  11 +/**
  12 + * IoT 设备日志数据 DO
  13 + *
  14 + * @author alwayssuper
  15 + */
  16 +@Data
  17 +@Builder
  18 +@NoArgsConstructor
  19 +@AllArgsConstructor
  20 +public class IotDeviceLogDO {
  21 + /**
  22 + * 消息ID
  23 + */
  24 + private String id;
  25 +
  26 + /**
  27 + * 产品ID
  28 + */
  29 + private String productKey;
  30 +
  31 + /**
  32 + * 设备ID
  33 + */
  34 + private String deviceKey;
  35 +
  36 + /**
  37 + * 消息/日志类型
  38 + */
  39 + private String type;
  40 +
  41 + /**
  42 + * 标识符:用于标识具体的属性、事件或服务
  43 + */
  44 + private String subType;
  45 +
  46 + /**
  47 + * 数据内容:存储具体的消息数据内容,通常是JSON格式
  48 + */
  49 + private String content;
  50 +
  51 + /**
  52 + * 上报时间戳
  53 + */
  54 + private Long reportTime;
  55 +
  56 + /**
  57 + * 时序时间
  58 + */
  59 + private Long ts;
  60 +
  61 +
  62 +}
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/ThingModelMessageDO.java
@@ -6,6 +6,7 @@ import lombok.Data; @@ -6,6 +6,7 @@ import lombok.Data;
6 import lombok.NoArgsConstructor; 6 import lombok.NoArgsConstructor;
7 7
8 // TODO @芋艿:纠结下字段 8 // TODO @芋艿:纠结下字段
  9 +@Deprecated
9 /** 10 /**
10 * TD 物模型消息日志的数据库 11 * TD 物模型消息日志的数据库
11 */ 12 */
@@ -15,21 +16,7 @@ import lombok.NoArgsConstructor; @@ -15,21 +16,7 @@ import lombok.NoArgsConstructor;
15 @AllArgsConstructor 16 @AllArgsConstructor
16 public class ThingModelMessageDO { 17 public class ThingModelMessageDO {
17 18
18 - /**  
19 - * 数据库名称  
20 - */  
21 - private String dataBaseName;  
22 19
23 - // TODO @haohao:superTableName 和 tableName 是不是合并。因为每个 mapper 操作的时候,有且只会使用到其中一个。  
24 - /**  
25 - * 超级表名称  
26 - */  
27 - private String superTableName;  
28 -  
29 - /**  
30 - * 表名称  
31 - */  
32 - private String tableName;  
33 20
34 /** 21 /**
35 * 消息 ID 22 * 消息 ID
@@ -37,9 +24,11 @@ public class ThingModelMessageDO { @@ -37,9 +24,11 @@ public class ThingModelMessageDO {
37 private String id; 24 private String id;
38 25
39 /** 26 /**
40 - * 扩展功能的参数 27 + * 系统扩展参数
  28 + *
  29 + * 例如:设备状态、系统时间、固件版本等系统级信息
41 */ 30 */
42 - private Object sys; 31 + private Object system;
43 32
44 /** 33 /**
45 * 请求方法 34 * 请求方法
@@ -59,6 +48,12 @@ public class ThingModelMessageDO { @@ -59,6 +48,12 @@ public class ThingModelMessageDO {
59 private Long time; 48 private Long time;
60 49
61 /** 50 /**
  51 + * 设备信息
  52 + */
  53 + private String productKey;
  54 +
  55 +
  56 + /**
62 * 设备 key 57 * 设备 key
63 */ 58 */
64 private String deviceKey; 59 private String deviceKey;
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/thingmodel/IotThingModelMapper.java
@@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.iot.dal.mysql.thingmodel; @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.iot.dal.mysql.thingmodel;
3 import cn.iocoder.yudao.framework.common.pojo.PageResult; 3 import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; 4 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
5 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; 5 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
  6 +import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.vo.IotThingModelListReqVO;
6 import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.vo.IotThingModelPageReqVO; 7 import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.vo.IotThingModelPageReqVO;
7 import cn.iocoder.yudao.module.iot.dal.dataobject.thingmodel.IotThingModelDO; 8 import cn.iocoder.yudao.module.iot.dal.dataobject.thingmodel.IotThingModelDO;
8 import org.apache.ibatis.annotations.Mapper; 9 import org.apache.ibatis.annotations.Mapper;
@@ -28,6 +29,17 @@ public interface IotThingModelMapper extends BaseMapperX&lt;IotThingModelDO&gt; { @@ -28,6 +29,17 @@ public interface IotThingModelMapper extends BaseMapperX&lt;IotThingModelDO&gt; {
28 .orderByDesc(IotThingModelDO::getId)); 29 .orderByDesc(IotThingModelDO::getId));
29 } 30 }
30 31
  32 + default List<IotThingModelDO> selectList(IotThingModelListReqVO reqVO) {
  33 + return selectList(new LambdaQueryWrapperX<IotThingModelDO>()
  34 + .eqIfPresent(IotThingModelDO::getIdentifier, reqVO.getIdentifier())
  35 + .likeIfPresent(IotThingModelDO::getName, reqVO.getName())
  36 + .eqIfPresent(IotThingModelDO::getType, reqVO.getType())
  37 + .eqIfPresent(IotThingModelDO::getProductId, reqVO.getProductId())
  38 + // TODO @芋艿:看看要不要加枚举
  39 + .notIn(IotThingModelDO::getIdentifier, "get", "set", "post")
  40 + .orderByDesc(IotThingModelDO::getId));
  41 + }
  42 +
31 default IotThingModelDO selectByProductIdAndIdentifier(Long productId, String identifier) { 43 default IotThingModelDO selectByProductIdAndIdentifier(Long productId, String identifier) {
32 return selectOne(IotThingModelDO::getProductId, productId, 44 return selectOne(IotThingModelDO::getProductId, productId,
33 IotThingModelDO::getIdentifier, identifier); 45 IotThingModelDO::getIdentifier, identifier);
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/IotDeviceLogDataMapper.java 0 → 100644
  1 +package cn.iocoder.yudao.module.iot.dal.tdengine;
  2 +
  3 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  4 +import cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData.IotDeviceLogPageReqVO;
  5 +import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceLogDO;
  6 +import cn.iocoder.yudao.module.iot.framework.tdengine.core.annotation.TDengineDS;
  7 +import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
  8 +import org.apache.ibatis.annotations.Mapper;
  9 +import org.apache.ibatis.annotations.Param;
  10 +
  11 +import java.util.List;
  12 +
  13 +/**
  14 + * IOT 设备日志数据 Mapper 接口
  15 + *
  16 + * 基于 TDengine 实现设备日志的存储
  17 + */
  18 +@Mapper
  19 +@TDengineDS
  20 +@InterceptorIgnore(tenantLine = "true") // 避免 SQL 解析,因为 JSqlParser 对 TDengine 的 SQL 解析会报错
  21 +public interface IotDeviceLogDataMapper {
  22 +
  23 + /**
  24 + * 创建设备日志超级表
  25 + *
  26 + * 注意:初始化时只需创建一次
  27 + */
  28 + void createDeviceLogSTable();
  29 +
  30 + /**
  31 + * 创建设备日志子表
  32 + *
  33 + * @param deviceKey 设备标识
  34 + */
  35 + void createDeviceLogTable(@Param("deviceKey") String deviceKey);
  36 +
  37 + /**
  38 + * 插入设备日志数据
  39 + *
  40 + * 如果子表不存在,会自动创建子表
  41 + *
  42 + * @param log 设备日志数据
  43 + */
  44 + void insert(@Param("log") IotDeviceLogDO log);
  45 +
  46 + /**
  47 + * 获得设备日志分页
  48 + *
  49 + * @param reqVO 分页查询条件
  50 + * @return 设备日志列表
  51 + */
  52 + List<IotDeviceLogDO> selectPage(@Param("reqVO") IotDeviceLogPageReqVO reqVO);
  53 +
  54 + /**
  55 + * 获得设备日志总数
  56 + *
  57 + * @param reqVO 查询条件
  58 + * @return 日志总数
  59 + */
  60 + Long selectCount(@Param("reqVO") IotDeviceLogPageReqVO reqVO);
  61 +}
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdThingModelMessageMapper.java
1 package cn.iocoder.yudao.module.iot.dal.tdengine; 1 package cn.iocoder.yudao.module.iot.dal.tdengine;
2 2
3 import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore; 3 import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
  4 +import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.ThingModelMessage;
4 import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.ThingModelMessageDO; 5 import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.ThingModelMessageDO;
  6 +import cn.iocoder.yudao.module.iot.framework.tdengine.core.annotation.TDengineDS;
5 import com.baomidou.dynamic.datasource.annotation.DS; 7 import com.baomidou.dynamic.datasource.annotation.DS;
  8 +import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
6 import org.apache.ibatis.annotations.Mapper; 9 import org.apache.ibatis.annotations.Mapper;
  10 +import org.apache.ibatis.annotations.Param;
7 11
8 /** 12 /**
9 * 处理 TD 中物模型消息日志的操作 13 * 处理 TD 中物模型消息日志的操作
10 */ 14 */
11 @Mapper 15 @Mapper
12 -@DS("tdengine") 16 +@Deprecated
  17 +@TDengineDS
  18 +@InterceptorIgnore(tenantLine = "true") // 避免 SQL 解析,因为 JSqlParser 对 TDengine 的 SQL 解析会报错
13 public interface TdThingModelMessageMapper { 19 public interface TdThingModelMessageMapper {
14 20
15 /** 21 /**
16 * 创建物模型消息日志超级表超级表 22 * 创建物模型消息日志超级表超级表
17 * 23 *
18 */ 24 */
19 - @TenantIgnore  
20 - void createSuperTable(ThingModelMessageDO superTable); 25 +
  26 + void createSuperTable(@Param("productKey") String productKey);
21 27
22 /** 28 /**
23 * 创建子表 29 * 创建子表
24 * 30 *
25 */ 31 */
26 - @TenantIgnore  
27 - void createTableWithTag(ThingModelMessageDO table); 32 +
  33 + void createTableWithTag(@Param("productKey") String productKey,@Param("deviceKey") String deviceKey);
28 34
29 } 35 }
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/tdengine/config/TDengineTableInitConfiguration.java 0 → 100644
  1 +package cn.iocoder.yudao.module.iot.framework.tdengine.config;
  2 +
  3 +import cn.iocoder.yudao.module.iot.service.device.IotDeviceLogDataService;
  4 +import lombok.RequiredArgsConstructor;
  5 +import lombok.extern.slf4j.Slf4j;
  6 +import org.springframework.boot.ApplicationArguments;
  7 +import org.springframework.boot.ApplicationRunner;
  8 +import org.springframework.context.annotation.Configuration;
  9 +import org.springframework.core.annotation.Order;
  10 +
  11 +/**
  12 + * TDengine 表初始化的 Configuration
  13 + *
  14 + * @author alwayssuper
  15 + */
  16 +@Slf4j
  17 +@RequiredArgsConstructor
  18 +@Configuration
  19 +@Order(Integer.MAX_VALUE) // 保证在最后执行
  20 +public class TDengineTableInitConfiguration implements ApplicationRunner {
  21 +
  22 + private final IotDeviceLogDataService deviceLogService;
  23 +
  24 + @Override
  25 + public void run(ApplicationArguments args) {
  26 + try {
  27 + // 初始化设备日志表
  28 + deviceLogService.initTDengineSTable();
  29 + log.info("初始化 设备日志表 TDengine 表结构成功");
  30 + } catch (Exception ex) {
  31 + if (ex.getMessage().contains("Table already exists")) {
  32 + log.info("TDengine 设备日志超级表已存在,跳过创建");
  33 + return;
  34 + }else{
  35 + log.error("初始化 设备日志表 TDengine 表结构失败", ex);
  36 + }
  37 + throw ex;
  38 + }
  39 + }
  40 +}
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceLogDataService.java 0 → 100644
  1 +package cn.iocoder.yudao.module.iot.service.device;
  2 +
  3 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  4 +import cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData.IotDeviceDataSimulatorSaveReqVO;
  5 +import cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData.IotDeviceLogPageReqVO;
  6 +import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceLogDO;
  7 +
  8 +
  9 +/**
  10 + * IoT 设备日志数据 Service 接口
  11 + *
  12 + * @author alwayssuper
  13 + */
  14 +public interface IotDeviceLogDataService {
  15 +
  16 + /**
  17 + * 初始化 TDengine 超级表
  18 + *
  19 + *系统启动时,会自动初始化一次
  20 + */
  21 + void initTDengineSTable();
  22 +
  23 + /**
  24 + * 插入设备日志
  25 + *
  26 + * 当该设备第一次插入日志时,自动创建该设备的设备日志子表
  27 + *
  28 + * @param simulatorReqVO 设备日志模拟数据
  29 + */
  30 + void createDeviceLog(IotDeviceDataSimulatorSaveReqVO simulatorReqVO);
  31 +
  32 + /**
  33 + * 获得设备日志分页
  34 + *
  35 + * @param pageReqVO 分页查询
  36 + * @return 设备日志分页
  37 + */
  38 + PageResult<IotDeviceLogDO> getDeviceLogPage(IotDeviceLogPageReqVO pageReqVO);
  39 +
  40 +}
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceLogDataServiceImpl.java 0 → 100644
  1 +package cn.iocoder.yudao.module.iot.service.device;
  2 +
  3 +import cn.hutool.core.date.DateTime;
  4 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  5 +import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
  6 +import cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData.IotDeviceDataSimulatorSaveReqVO;
  7 +import cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData.IotDeviceLogPageReqVO;
  8 +import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceLogDO;
  9 +import cn.iocoder.yudao.module.iot.dal.tdengine.IotDeviceLogDataMapper;
  10 +import jakarta.annotation.Resource;
  11 +import lombok.extern.slf4j.Slf4j;
  12 +import org.springframework.stereotype.Service;
  13 +import org.springframework.validation.annotation.Validated;
  14 +
  15 +import java.time.LocalDateTime;
  16 +import java.time.ZoneId;
  17 +import java.util.List;
  18 +
  19 +/**
  20 + * IoT 设备日志数据 Service 实现了
  21 + *
  22 + * @author alwayssuper
  23 + */
  24 +@Service
  25 +@Slf4j
  26 +@Validated
  27 +public class IotDeviceLogDataServiceImpl implements IotDeviceLogDataService{
  28 +
  29 + @Resource
  30 + private IotDeviceLogDataMapper iotDeviceLogDataMapper;
  31 +
  32 +
  33 + @Override
  34 + public void initTDengineSTable() {
  35 + try {
  36 + // 创建设备日志超级表
  37 + iotDeviceLogDataMapper.createDeviceLogSTable();
  38 + log.info("创建设备日志超级表成功");
  39 + } catch (Exception ex) {
  40 + throw ex;
  41 + }
  42 + }
  43 +
  44 + @Override
  45 + public void createDeviceLog(IotDeviceDataSimulatorSaveReqVO simulatorReqVO) {
  46 + //TODO:讨论一下,iotkit这块TS和上报时间都是外部传入的 但是看TDengine文档 他是建议对TS在SQL中直接NOW 咱们的TS数据获取是走哪一种
  47 +
  48 + // 1. 转换请求对象为 DO
  49 + IotDeviceLogDO iotDeviceLogDO = BeanUtils.toBean(simulatorReqVO, IotDeviceLogDO.class);
  50 +
  51 + // 2. 处理时间字段
  52 + long currentTime = System.currentTimeMillis();
  53 + // 2.1 设置时序时间为当前时间
  54 + iotDeviceLogDO.setTs(currentTime);
  55 +
  56 + // 3. 插入数据
  57 + iotDeviceLogDataMapper.insert(iotDeviceLogDO);
  58 + }
  59 +
  60 + @Override
  61 + public PageResult<IotDeviceLogDO> getDeviceLogPage(IotDeviceLogPageReqVO pageReqVO) {
  62 + // 查询数据
  63 + List<IotDeviceLogDO> list = iotDeviceLogDataMapper.selectPage(pageReqVO);
  64 + Long total = iotDeviceLogDataMapper.selectCount(pageReqVO);
  65 + // 构造分页结果
  66 + return new PageResult<>(list, total);
  67 + }
  68 +}
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDevicePropertyDataServiceImpl.java
@@ -18,6 +18,7 @@ import cn.iocoder.yudao.module.iot.dal.dataobject.thingmodel.IotThingModelDO; @@ -18,6 +18,7 @@ import cn.iocoder.yudao.module.iot.dal.dataobject.thingmodel.IotThingModelDO;
18 import cn.iocoder.yudao.module.iot.dal.redis.deviceData.DeviceDataRedisDAO; 18 import cn.iocoder.yudao.module.iot.dal.redis.deviceData.DeviceDataRedisDAO;
19 import cn.iocoder.yudao.module.iot.dal.tdengine.IotDevicePropertyDataMapper; 19 import cn.iocoder.yudao.module.iot.dal.tdengine.IotDevicePropertyDataMapper;
20 import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineDMLMapper; 20 import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineDMLMapper;
  21 +import cn.iocoder.yudao.module.iot.dal.tdengine.TdThingModelMessageMapper;
21 import cn.iocoder.yudao.module.iot.enums.IotConstants; 22 import cn.iocoder.yudao.module.iot.enums.IotConstants;
22 import cn.iocoder.yudao.module.iot.enums.thingmodel.IotDataSpecsDataTypeEnum; 23 import cn.iocoder.yudao.module.iot.enums.thingmodel.IotDataSpecsDataTypeEnum;
23 import cn.iocoder.yudao.module.iot.enums.thingmodel.IotThingModelTypeEnum; 24 import cn.iocoder.yudao.module.iot.enums.thingmodel.IotThingModelTypeEnum;
@@ -85,6 +86,7 @@ public class IotDevicePropertyDataServiceImpl implements IotDevicePropertyDataSe @@ -85,6 +86,7 @@ public class IotDevicePropertyDataServiceImpl implements IotDevicePropertyDataSe
85 @Resource 86 @Resource
86 private IotDevicePropertyDataMapper devicePropertyDataMapper; 87 private IotDevicePropertyDataMapper devicePropertyDataMapper;
87 88
  89 +
88 @Override 90 @Override
89 public void defineDevicePropertyData(Long productId) { 91 public void defineDevicePropertyData(Long productId) {
90 // 1.1 查询产品和物模型 92 // 1.1 查询产品和物模型
@@ -109,6 +111,7 @@ public class IotDevicePropertyDataServiceImpl implements IotDevicePropertyDataSe @@ -109,6 +111,7 @@ public class IotDevicePropertyDataServiceImpl implements IotDevicePropertyDataSe
109 return; 111 return;
110 } 112 }
111 newFields.add(0, new TDengineTableField(TDengineTableField.FIELD_TS, TDengineTableField.TYPE_TIMESTAMP)); 113 newFields.add(0, new TDengineTableField(TDengineTableField.FIELD_TS, TDengineTableField.TYPE_TIMESTAMP));
  114 + // 2.1.1 创建产品超级表
112 devicePropertyDataMapper.createProductPropertySTable(product.getProductKey(), newFields); 115 devicePropertyDataMapper.createProductPropertySTable(product.getProductKey(), newFields);
113 return; 116 return;
114 } 117 }
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/product/IotProductServiceImpl.java
@@ -36,9 +36,6 @@ public class IotProductServiceImpl implements IotProductService { @@ -36,9 +36,6 @@ public class IotProductServiceImpl implements IotProductService {
36 36
37 @Resource 37 @Resource
38 @Lazy // 延迟加载,解决循环依赖 38 @Lazy // 延迟加载,解决循环依赖
39 - private IotThingModelMessageService thingModelMessageService;  
40 - @Resource  
41 - @Lazy // 延迟加载,解决循环依赖  
42 private IotDevicePropertyDataService devicePropertyDataService; 39 private IotDevicePropertyDataService devicePropertyDataService;
43 40
44 @Override 41 @Override
@@ -125,8 +122,7 @@ public class IotProductServiceImpl implements IotProductService { @@ -125,8 +122,7 @@ public class IotProductServiceImpl implements IotProductService {
125 if (Objects.equals(status, IotProductStatusEnum.PUBLISHED.getStatus())) { 122 if (Objects.equals(status, IotProductStatusEnum.PUBLISHED.getStatus())) {
126 // 3.1 创建产品超级表数据模型 123 // 3.1 创建产品超级表数据模型
127 devicePropertyDataService.defineDevicePropertyData(id); 124 devicePropertyDataService.defineDevicePropertyData(id);
128 - // 3.2 创建物模型日志超级表数据模型 TODO 待定:message 要不要分;  
129 - thingModelMessageService.createSuperTable(id); 125 +
130 } 126 }
131 productMapper.updateById(updateObj); 127 productMapper.updateById(updateObj);
132 } 128 }
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotThingModelMessageService.java
@@ -16,11 +16,6 @@ public interface IotThingModelMessageService { @@ -16,11 +16,6 @@ public interface IotThingModelMessageService {
16 */ 16 */
17 void saveThingModelMessage(IotDeviceDO device, ThingModelMessage thingModelMessage); 17 void saveThingModelMessage(IotDeviceDO device, ThingModelMessage thingModelMessage);
18 18
19 - /**  
20 - * 创建物模型消息日志超级表  
21 - *  
22 - * @param productId 产品编号  
23 - */  
24 - void createSuperTable(Long productId); 19 +
25 20
26 } 21 }
27 \ No newline at end of file 22 \ No newline at end of file
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotThingModelMessageServiceImpl.java
@@ -7,15 +7,13 @@ import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore; @@ -7,15 +7,13 @@ import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
7 import cn.iocoder.yudao.module.iot.controller.admin.device.vo.device.IotDeviceStatusUpdateReqVO; 7 import cn.iocoder.yudao.module.iot.controller.admin.device.vo.device.IotDeviceStatusUpdateReqVO;
8 import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; 8 import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO;
9 import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDataDO; 9 import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDataDO;
10 -import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.FieldParser;  
11 -import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdFieldDO;  
12 -import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO;  
13 -import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.ThingModelMessage; 10 +import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.*;
14 import cn.iocoder.yudao.module.iot.dal.dataobject.thingmodel.IotThingModelDO; 11 import cn.iocoder.yudao.module.iot.dal.dataobject.thingmodel.IotThingModelDO;
15 import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO; 12 import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO;
16 import cn.iocoder.yudao.module.iot.dal.redis.deviceData.DeviceDataRedisDAO; 13 import cn.iocoder.yudao.module.iot.dal.redis.deviceData.DeviceDataRedisDAO;
17 import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineDDLMapper; 14 import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineDDLMapper;
18 import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineDMLMapper; 15 import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineDMLMapper;
  16 +import cn.iocoder.yudao.module.iot.dal.tdengine.TdThingModelMessageMapper;
19 import cn.iocoder.yudao.module.iot.enums.IotConstants; 17 import cn.iocoder.yudao.module.iot.enums.IotConstants;
20 import cn.iocoder.yudao.module.iot.enums.device.IotDeviceStatusEnum; 18 import cn.iocoder.yudao.module.iot.enums.device.IotDeviceStatusEnum;
21 import cn.iocoder.yudao.module.iot.enums.thingmodel.IotThingModelTypeEnum; 19 import cn.iocoder.yudao.module.iot.enums.thingmodel.IotThingModelTypeEnum;
@@ -64,6 +62,9 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ @@ -64,6 +62,9 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ
64 private TdEngineDMLMapper tdEngineDMLMapper; 62 private TdEngineDMLMapper tdEngineDMLMapper;
65 63
66 @Resource 64 @Resource
  65 + private TdThingModelMessageMapper tdThingModelMessageMapper;
  66 +
  67 + @Resource
67 private DeviceDataRedisDAO deviceDataRedisDAO; 68 private DeviceDataRedisDAO deviceDataRedisDAO;
68 69
69 70
@@ -77,8 +78,6 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ @@ -77,8 +78,6 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ
77 createDeviceTable(device.getDeviceType(), device.getProductKey(), device.getDeviceName(), device.getDeviceKey()); 78 createDeviceTable(device.getDeviceType(), device.getProductKey(), device.getDeviceName(), device.getDeviceKey());
78 iotDeviceService.updateDeviceStatus(new IotDeviceStatusUpdateReqVO() 79 iotDeviceService.updateDeviceStatus(new IotDeviceStatusUpdateReqVO()
79 .setId(device.getId()).setStatus(IotDeviceStatusEnum.ONLINE.getStatus())); 80 .setId(device.getId()).setStatus(IotDeviceStatusEnum.ONLINE.getStatus()));
80 - // 1.2 创建物模型日志设备表  
81 - createThingModelMessageDeviceTable(device.getProductKey(), device.getDeviceName(), device.getDeviceKey());  
82 } 81 }
83 82
84 // 2. 获取设备属性并进行物模型校验,过滤非物模型属性 83 // 2. 获取设备属性并进行物模型校验,过滤非物模型属性
@@ -107,32 +106,34 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ @@ -107,32 +106,34 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ
107 thingModel -> IotThingModelTypeEnum.PROPERTY.getType().equals(thingModel.getType())); 106 thingModel -> IotThingModelTypeEnum.PROPERTY.getType().equals(thingModel.getType()));
108 } 107 }
109 108
110 - @Override  
111 - @TenantIgnore  
112 - public void createSuperTable(Long productId) {  
113 - // 1. 查询产品  
114 - IotProductDO product = productService.getProduct(productId);  
115 -  
116 - // 2. 获取超级表的名称和数据库名称  
117 - // TODO @alwayssuper:最好 databaseName、superTableName 的处理,放到 tdThinkModelMessageMapper 里。可以考虑,弄个 default 方法  
118 - String databaseName = IotTdDatabaseUtils.getDatabaseName(url);  
119 - String superTableName = IotTdDatabaseUtils.getThingModelMessageSuperTableName(product.getProductKey());  
120 -  
121 - // 解析物模型,获取字段列表  
122 - List<TdFieldDO> schemaFields = List.of(  
123 - TdFieldDO.builder().fieldName("time").dataType("TIMESTAMP").build(),  
124 - TdFieldDO.builder().fieldName("id").dataType("NCHAR").dataLength(64).build(),  
125 - TdFieldDO.builder().fieldName("sys").dataType("NCHAR").dataLength(2048).build(),  
126 - TdFieldDO.builder().fieldName("method").dataType("NCHAR").dataLength(256).build(),  
127 - TdFieldDO.builder().fieldName("params").dataType("NCHAR").dataLength(2048).build()  
128 - );  
129 - // 设置超级表的标签  
130 - List<TdFieldDO> tagsFields = List.of(  
131 - TdFieldDO.builder().fieldName("device_key").dataType("NCHAR").dataLength(64).build()  
132 - );  
133 - // 3. 创建超级表  
134 - tdEngineDDLMapper.createSuperTable(new TdTableDO(databaseName, superTableName, schemaFields, tagsFields));  
135 - } 109 +// @Override
  110 +// @TenantIgnore
  111 +// public void createSuperTable(Long productId) {
  112 +// // 1. 查询产品
  113 +// IotProductDO product = productService.getProduct(productId);
  114 +// // 2. 创建日志超级表
  115 +// tdThingModelMessageMapper.createSuperTable(product.getProductKey());
  116 +//
  117 +// // 2. 获取超级表的名称和数据库名称
  118 +// // TODO @alwayssuper:最好 databaseName、superTableName 的处理,放到 tdThinkModelMessageMapper 里。可以考虑,弄个 default 方法
  119 +//// String databaseName = IotTdDatabaseUtils.getDatabaseName(url);
  120 +//// String superTableName = IotTdDatabaseUtils.getThingModelMessageSuperTableName(product.getProductKey());
  121 +////
  122 +//// // 解析物模型,获取字段列表
  123 +//// List<TdFieldDO> schemaFields = List.of(
  124 +//// TdFieldDO.builder().fieldName("time").dataType("TIMESTAMP").build(),
  125 +//// TdFieldDO.builder().fieldName("id").dataType("NCHAR").dataLength(64).build(),
  126 +//// TdFieldDO.builder().fieldName("sys").dataType("NCHAR").dataLength(2048).build(),
  127 +//// TdFieldDO.builder().fieldName("method").dataType("NCHAR").dataLength(256).build(),
  128 +//// TdFieldDO.builder().fieldName("params").dataType("NCHAR").dataLength(2048).build()
  129 +//// );
  130 +//// // 设置超级表的标签
  131 +//// List<TdFieldDO> tagsFields = List.of(
  132 +//// TdFieldDO.builder().fieldName("device_key").dataType("NCHAR").dataLength(64).build()
  133 +//// );
  134 +//// // 3. 创建超级表
  135 +//// tdEngineDDLMapper.createSuperTable(new TdTableDO(databaseName, superTableName, schemaFields, tagsFields));
  136 +// }
136 137
137 private List<IotThingModelDO> getValidFunctionList(String productKey) { 138 private List<IotThingModelDO> getValidFunctionList(String productKey) {
138 return filterList(iotThingModelService.getProductThingModelListByProductKey(productKey), 139 return filterList(iotThingModelService.getProductThingModelListByProductKey(productKey),
@@ -228,29 +229,7 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ @@ -228,29 +229,7 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ
228 .setTags(tagsFieldValues)); 229 .setTags(tagsFieldValues));
229 } 230 }
230 231
231 - /**  
232 - * 创建物模型日志设备数据表  
233 - *  
234 - * @param productKey 产品 Key  
235 - * @param deviceName 设备名称  
236 - * @param deviceKey 设备 Key  
237 - *  
238 - */  
239 - private void createThingModelMessageDeviceTable(String productKey, String deviceName, String deviceKey){  
240 -  
241 - // 1. 获取超级表的名称、数据库名称、设备日志表名称  
242 - String databaseName = IotTdDatabaseUtils.getDatabaseName(url);  
243 - String superTableName = IotTdDatabaseUtils.getThingModelMessageSuperTableName(productKey);  
244 - // TODO @alwayssuper:最好 databaseName、superTableName、thinkModelMessageDeviceTableName 的处理,放到 tdThinkModelMessageMapper 里。可以考虑,弄个 default 方法  
245 - String thinkModelMessageDeviceTableName = IotTdDatabaseUtils.getThingModelMessageDeviceTableName(productKey, deviceName);  
246 -  
247 - // 2. 创建物模型日志设备数据表  
248 -// tdThingModelMessageMapper.createTableWithTag(ThingModelMessageDO.builder().build()  
249 -// .setDataBaseName(databaseName)  
250 -// .setSuperTableName(superTableName)  
251 -// .setTableName(thinkModelMessageDeviceTableName)  
252 -// .setDeviceKey(deviceKey));  
253 - } 232 +
254 233
255 /** 234 /**
256 * 获取数据库名称 235 * 获取数据库名称
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thingmodel/IotThingModelService.java
1 package cn.iocoder.yudao.module.iot.service.thingmodel; 1 package cn.iocoder.yudao.module.iot.service.thingmodel;
2 2
3 import cn.iocoder.yudao.framework.common.pojo.PageResult; 3 import cn.iocoder.yudao.framework.common.pojo.PageResult;
  4 +import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.vo.IotThingModelListReqVO;
4 import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.vo.IotThingModelPageReqVO; 5 import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.vo.IotThingModelPageReqVO;
5 import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.vo.IotThingModelSaveReqVO; 6 import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.vo.IotThingModelSaveReqVO;
6 import cn.iocoder.yudao.module.iot.dal.dataobject.thingmodel.IotThingModelDO; 7 import cn.iocoder.yudao.module.iot.dal.dataobject.thingmodel.IotThingModelDO;
@@ -69,4 +70,11 @@ public interface IotThingModelService { @@ -69,4 +70,11 @@ public interface IotThingModelService {
69 */ 70 */
70 List<IotThingModelDO> getProductThingModelListByProductKey(String productKey); 71 List<IotThingModelDO> getProductThingModelListByProductKey(String productKey);
71 72
  73 + /**
  74 + * 获得产品物模型列表
  75 + *
  76 + * @param reqVO 列表查询
  77 + * @return 产品物模型列表
  78 + */
  79 + List<IotThingModelDO> getThingModelList(IotThingModelListReqVO reqVO);
72 } 80 }
73 \ No newline at end of file 81 \ 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
@@ -7,6 +7,7 @@ import cn.iocoder.yudao.framework.common.util.object.BeanUtils; @@ -7,6 +7,7 @@ import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
7 import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.model.ThingModelEvent; 7 import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.model.ThingModelEvent;
8 import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.model.ThingModelParam; 8 import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.model.ThingModelParam;
9 import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.model.ThingModelService; 9 import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.model.ThingModelService;
  10 +import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.vo.IotThingModelListReqVO;
10 import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.vo.IotThingModelPageReqVO; 11 import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.vo.IotThingModelPageReqVO;
11 import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.vo.IotThingModelSaveReqVO; 12 import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.vo.IotThingModelSaveReqVO;
12 import cn.iocoder.yudao.module.iot.convert.thingmodel.IotThingModelConvert; 13 import cn.iocoder.yudao.module.iot.convert.thingmodel.IotThingModelConvert;
@@ -134,6 +135,11 @@ public class IotThingModelServiceImpl implements IotThingModelService { @@ -134,6 +135,11 @@ public class IotThingModelServiceImpl implements IotThingModelService {
134 return thingModelMapper.selectListByProductKey(productKey); 135 return thingModelMapper.selectListByProductKey(productKey);
135 } 136 }
136 137
  138 + @Override
  139 + public List<IotThingModelDO> getThingModelList(IotThingModelListReqVO reqVO) {
  140 + return thingModelMapper.selectList(reqVO);
  141 + }
  142 +
137 /** 143 /**
138 * 校验功能是否存在 144 * 校验功能是否存在
139 * 145 *
yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/device/IotDeviceLogDataMapper.xml 0 → 100644
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<!DOCTYPE mapper
  3 + PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  4 + "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  5 +<mapper namespace="cn.iocoder.yudao.module.iot.dal.tdengine.IotDeviceLogDataMapper">
  6 +
  7 + <!-- 创建设备日志超级表 初始化只创建一次-->
  8 + <update id="createDeviceLogSTable">
  9 + CREATE STABLE device_log (
  10 + ts TIMESTAMP,
  11 + id NCHAR(50),
  12 + product_key NCHAR(50),
  13 + type NCHAR(50),
  14 + subType NCHAR(50),
  15 + content NCHAR(1024),
  16 + report_time TIMESTAMP
  17 + )TAGS (
  18 + device_key NCHAR(50)
  19 + )
  20 + </update>
  21 +
  22 +
  23 + <!-- 创建设备日志子表 讨论:TDengine 在子表不存在的情况下 可在数据插入时 自动建表 要不要去掉创建子表的逻辑 由第一次插入数据时自动创建-->
  24 + <update id="createDeviceLogTable">
  25 + CREATE TABLE device_log_${deviceKey} USING device_log TAGS('${deviceKey}')
  26 + </update>
  27 +
  28 + <!-- 插入设备日志数据 在子表不存在的情况下 可在数据插入时 自动建表 -->
  29 + <insert id="insert">
  30 + INSERT INTO device_log_${log.deviceKey} (ts, id, product_key, type, subType, content, report_time)
  31 + USING device_log
  32 + TAGS ('${log.deviceKey}')
  33 + VALUES (
  34 + #{log.ts},
  35 + #{log.id},
  36 + #{log.productKey},
  37 + #{log.type},
  38 + #{log.subType},
  39 + #{log.content},
  40 + #{log.reportTime}
  41 + )
  42 + </insert>
  43 +
  44 + <select id="selectPage" resultType="cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceLogDO">
  45 + SELECT ts, id, device_key, product_key, type, subType, content, report_time
  46 + FROM device_log_${reqVO.deviceKey}
  47 + <where>
  48 + <if test="reqVO.type != null and reqVO.type != ''">
  49 + AND type = #{reqVO.type}
  50 + </if>
  51 + <if test="reqVO.subType != null and reqVO.subType != ''">
  52 + AND subType = #{reqVO.subType}
  53 + </if>
  54 + <if test="reqVO.createTime != null">
  55 + AND ts BETWEEN #{reqVO.createTime[0]} AND #{reqVO.createTime[1]}
  56 + </if>
  57 + </where>
  58 + ORDER BY ts DESC
  59 + LIMIT #{reqVO.pageSize} OFFSET #{reqVO.pageNo}
  60 + </select>
  61 +
  62 + <select id="selectCount" resultType="Long">
  63 + SELECT COUNT(*)
  64 + FROM device_log_${reqVO.deviceKey}
  65 + <where>
  66 + <if test="reqVO.type != null and reqVO.type != ''">
  67 + AND type = #{reqVO.type}
  68 + </if>
  69 + <if test="reqVO.subType != null and reqVO.subType != ''">
  70 + AND subType = #{reqVO.subType}
  71 + </if>
  72 + <if test="reqVO.createTime != null">
  73 + AND ts BETWEEN #{reqVO.createTime[0]} AND #{reqVO.createTime[1]}
  74 + </if>
  75 + </where>
  76 + </select>
  77 +
  78 +</mapper>
0 \ No newline at end of file 79 \ No newline at end of file
yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineDMLMapper.xml
@@ -42,7 +42,7 @@ @@ -42,7 +42,7 @@
42 42
43 <!-- 根据标签获取最新数据 --> 43 <!-- 根据标签获取最新数据 -->
44 <select id="selectLastDataListByTags" parameterType="cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TagsSelectDO" 44 <select id="selectLastDataListByTags" parameterType="cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TagsSelectDO"
45 - resultType="Map"> 45 + resultType="java.util.Map">
46 SELECT LAST(*) 46 SELECT LAST(*)
47 FROM ${dataBaseName}.${stableName} 47 FROM ${dataBaseName}.${stableName}
48 GROUP BY ${tagsName} 48 GROUP BY ${tagsName}
yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdThinkModelMessageMapper.xml
@@ -6,26 +6,28 @@ @@ -6,26 +6,28 @@
6 6
7 <!-- 创建物模型消息日志超级表 --> 7 <!-- 创建物模型消息日志超级表 -->
8 <update id="createSuperTable"> 8 <update id="createSuperTable">
9 - CREATE STABLE ${dataBaseName}.${superTableName}( 9 + CREATE STABLE thing_model_message_${productKey}(
10 ts TIMESTAMP, 10 ts TIMESTAMP,
11 - id VARCHAR(255),  
12 - sys VARCHAR(2048),  
13 - method VARCHAR(255),  
14 - params VARCHAR(2048) 11 + id NCHAR(64),
  12 + sys NCHAR(2048),
  13 + method NCHAR(255),
  14 + params NCHAR(2048),
  15 + device_name NCHAR(64)
15 )TAGS ( 16 )TAGS (
16 - device_key VARCHAR(255) 17 + device_key NCHAR(50)
17 ) 18 )
18 </update> 19 </update>
19 20
20 <!-- 创建物模型消息日志子表,带有deviceKey的TAG --> 21 <!-- 创建物模型消息日志子表,带有deviceKey的TAG -->
21 <update id="createTableWithTag"> 22 <update id="createTableWithTag">
22 - CREATE TABLE IF NOT EXISTS ${dataBaseName}.${tableName}  
23 - USING ${dataBaseName}.${superTableName}( 23 + CREATE STABLE ${deviceKey}
  24 + USING thing_model_message_${productKey}(
24 ts, 25 ts,
25 id , 26 id ,
26 sys , 27 sys ,
27 method , 28 method ,
28 - params 29 + params ,
  30 + device_name
29 )TAGS( 31 )TAGS(
30 #{device_key} 32 #{device_key}
31 ) 33 )