diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/IotDeviceDataController.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/IotDeviceDataController.java index a626951edb..801cbcb214 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/IotDeviceDataController.java +++ b/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; 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.deviceData.IotDeviceDataPageReqVO; -import cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData.IotDeviceDataRespVO; +import cn.iocoder.yudao.module.iot.controller.admin.device.vo.device.IotDeviceSaveReqVO; +import cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData.*; import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDataDO; -import cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData.IotTimeDataRespVO; +import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceLogDO; +import cn.iocoder.yudao.module.iot.service.device.IotDeviceLogDataService; import cn.iocoder.yudao.module.iot.service.device.IotDevicePropertyDataService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.annotation.Resource; import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; import java.util.List; import java.util.Map; @@ -31,6 +31,12 @@ public class IotDeviceDataController { @Resource private IotDevicePropertyDataService deviceDataService; + @Resource + private IotDeviceLogDataService iotDeviceLogDataService; + + @Resource + private IotDeviceLogDataService deviceLogDataService; + // TODO @浩浩:这里的 /latest-list,包括方法名。 @GetMapping("/latest") @Operation(summary = "获取设备属性最新数据") @@ -46,5 +52,20 @@ public class IotDeviceDataController { PageResult> list = deviceDataService.getHistoryDeviceProperties(deviceDataReqVO); return success(BeanUtils.toBean(list, IotTimeDataRespVO.class)); } + // TODO:数据权限 + @PostMapping("/simulator") + @Operation(summary = "模拟设备") + public CommonResult simulatorDevice(@Valid @RequestBody IotDeviceDataSimulatorSaveReqVO simulatorReqVO) { + //TODO:先生成一下设备日志 后续完善模拟设备代码逻辑 + iotDeviceLogDataService.createDeviceLog(simulatorReqVO); + return success(true); + } + // TODO:数据权限 + @GetMapping("/log/page") + @Operation(summary = "获得设备日志分页") + public CommonResult> getDeviceLogPage(@Valid IotDeviceLogPageReqVO pageReqVO) { + PageResult pageResult = deviceLogDataService.getDeviceLogPage(pageReqVO); + return success(BeanUtils.toBean(pageResult, IotDeviceLogRespVO.class)); + } } \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/device/IotDeviceSaveReqVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/device/IotDeviceSaveReqVO.java index 97220d57a2..e1268b0035 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/device/IotDeviceSaveReqVO.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/device/IotDeviceSaveReqVO.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.iot.controller.admin.device.vo.device; import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.Size; import lombok.Data; import java.util.Set; @@ -13,6 +14,7 @@ public class IotDeviceSaveReqVO { private Long id; @Schema(description = "设备编号", requiredMode = Schema.RequiredMode.AUTO, example = "177") + @Size(max = 50, message = "设备编号长度不能超过50个字符") private String deviceKey; @Schema(description = "设备名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "王五") diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/deviceData/IotDeviceDataSimulatorSaveReqVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/deviceData/IotDeviceDataSimulatorSaveReqVO.java new file mode 100644 index 0000000000..3a4bffacee --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/deviceData/IotDeviceDataSimulatorSaveReqVO.java @@ -0,0 +1,42 @@ +package cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotEmpty; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +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 +public class IotDeviceDataSimulatorSaveReqVO { + + @Schema(description = "消息ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "msg123") + private String id; + + @Schema(description = "产品ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "product123") + @NotEmpty(message = "产品ID不能为空") + private String productKey; + + @Schema(description = "设备ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "device123") + @NotEmpty(message = "设备ID不能为空") + private String deviceKey; + + @Schema(description = "消息/日志类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "property") + @NotEmpty(message = "消息类型不能为空") + private String type; + + @Schema(description = "标识符", requiredMode = Schema.RequiredMode.REQUIRED, example = "temperature") + @NotEmpty(message = "标识符不能为空") + private String subType; + + @Schema(description = "数据内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "{\"value\": 25.6}") + @NotEmpty(message = "数据内容不能为空") + private String content; + + @Schema(description = "上报时间", requiredMode = Schema.RequiredMode.REQUIRED) + private Long reportTime; + +} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/deviceData/IotDeviceLogPageReqVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/deviceData/IotDeviceLogPageReqVO.java new file mode 100644 index 0000000000..67099f3318 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/deviceData/IotDeviceLogPageReqVO.java @@ -0,0 +1,30 @@ +package cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotEmpty; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +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 +public class IotDeviceLogPageReqVO extends PageParam { + + @Schema(description = "设备标识", requiredMode = Schema.RequiredMode.REQUIRED, example = "device123") + @NotEmpty(message = "设备标识不能为空") + private String deviceKey; + + @Schema(description = "消息类型", example = "property") + private String type; + + @Schema(description = "标识符", example = "temperature") + private String subType; + + @Schema(description = "创建时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] createTime; +} \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/deviceData/IotDeviceLogRespVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/deviceData/IotDeviceLogRespVO.java new file mode 100644 index 0000000000..1201f7b742 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/deviceData/IotDeviceLogRespVO.java @@ -0,0 +1,33 @@ +package cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - IoT 设备日志 Response VO") +@Data +public class IotDeviceLogRespVO { + + @Schema(description = "日志编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private String id; + @Schema(description = "产品标识", requiredMode = Schema.RequiredMode.REQUIRED, example = "product123") + private String productKey; + @Schema(description = "设备标识", requiredMode = Schema.RequiredMode.REQUIRED, example = "device123") + private String deviceKey; + + @Schema(description = "消息类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "property") + private String type; + + @Schema(description = "标识符", requiredMode = Schema.RequiredMode.REQUIRED, example = "temperature") + private String subType; + + @Schema(description = "日志内容", requiredMode = Schema.RequiredMode.REQUIRED) + private String content; + + @Schema(description = "上报时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime reportTime; + + @Schema(description = "记录时间戳", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime ts; +} \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thingmodel/IotThingModelController.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thingmodel/IotThingModelController.java index 4397a742f4..d213329e29 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thingmodel/IotThingModelController.java +++ b/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; 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.thingmodel.vo.IotThingModelListReqVO; import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.vo.IotThingModelPageReqVO; import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.vo.IotThingModelRespVO; import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.vo.IotThingModelSaveReqVO; @@ -73,6 +74,14 @@ public class IotThingModelController { return success(IotThingModelConvert.INSTANCE.convertList(list)); } + @GetMapping("/list") + @Operation(summary = "获得产品物模型列表") + @PreAuthorize("@ss.hasPermission('iot:thing-model:query')") + public CommonResult> getThingModelListByProductId(@Valid IotThingModelListReqVO reqVO) { + List list = thingModelService.getThingModelList(reqVO); + return success(IotThingModelConvert.INSTANCE.convertList(list)); + } + @GetMapping("/page") @Operation(summary = "获得产品物模型分页") @PreAuthorize("@ss.hasPermission('iot:thing-model:query')") diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thingmodel/vo/IotThingModelListReqVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thingmodel/vo/IotThingModelListReqVO.java new file mode 100644 index 0000000000..3652b36b94 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thingmodel/vo/IotThingModelListReqVO.java @@ -0,0 +1,27 @@ +package cn.iocoder.yudao.module.iot.controller.admin.thingmodel.vo; + +import cn.iocoder.yudao.framework.common.validation.InEnum; +import cn.iocoder.yudao.module.iot.enums.thingmodel.IotThingModelTypeEnum; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + + + +@Schema(description = "管理后台 - IoT 产品物模型List Request VO") +@Data +public class IotThingModelListReqVO { + @Schema(description = "功能标识") + private String identifier; + + @Schema(description = "功能名称", example = "张三") + private String name; + + @Schema(description = "功能类型", example = "1") + @InEnum(IotThingModelTypeEnum.class) + private Integer type; + + @Schema(description = "产品ID", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "产品ID不能为空") + private Long productId; +} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/device/IotDeviceLogDO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/device/IotDeviceLogDO.java new file mode 100644 index 0000000000..c82b231c5c --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/device/IotDeviceLogDO.java @@ -0,0 +1,62 @@ +package cn.iocoder.yudao.module.iot.dal.dataobject.device; + +import cn.hutool.core.date.DateTime; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.time.LocalDateTime; + +/** + * IoT 设备日志数据 DO + * + * @author alwayssuper + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class IotDeviceLogDO { + /** + * 消息ID + */ + private String id; + + /** + * 产品ID + */ + private String productKey; + + /** + * 设备ID + */ + private String deviceKey; + + /** + * 消息/日志类型 + */ + private String type; + + /** + * 标识符:用于标识具体的属性、事件或服务 + */ + private String subType; + + /** + * 数据内容:存储具体的消息数据内容,通常是JSON格式 + */ + private String content; + + /** + * 上报时间戳 + */ + private Long reportTime; + + /** + * 时序时间 + */ + private Long ts; + + +} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/ThingModelMessageDO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/ThingModelMessageDO.java index c57ec1c7be..b647c68730 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/ThingModelMessageDO.java +++ b/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; import lombok.NoArgsConstructor; // TODO @芋艿:纠结下字段 +@Deprecated /** * TD 物模型消息日志的数据库 */ @@ -15,21 +16,7 @@ import lombok.NoArgsConstructor; @AllArgsConstructor public class ThingModelMessageDO { - /** - * 数据库名称 - */ - private String dataBaseName; - // TODO @haohao:superTableName 和 tableName 是不是合并。因为每个 mapper 操作的时候,有且只会使用到其中一个。 - /** - * 超级表名称 - */ - private String superTableName; - - /** - * 表名称 - */ - private String tableName; /** * 消息 ID @@ -37,9 +24,11 @@ public class ThingModelMessageDO { private String id; /** - * 扩展功能的参数 + * 系统扩展参数 + * + * 例如:设备状态、系统时间、固件版本等系统级信息 */ - private Object sys; + private Object system; /** * 请求方法 @@ -58,6 +47,12 @@ public class ThingModelMessageDO { */ private Long time; + /** + * 设备信息 + */ + private String productKey; + + /** * 设备 key */ diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/thingmodel/IotThingModelMapper.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/thingmodel/IotThingModelMapper.java index b687326340..1258893c57 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/thingmodel/IotThingModelMapper.java +++ b/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; 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.thingmodel.vo.IotThingModelListReqVO; import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.vo.IotThingModelPageReqVO; import cn.iocoder.yudao.module.iot.dal.dataobject.thingmodel.IotThingModelDO; import org.apache.ibatis.annotations.Mapper; @@ -28,6 +29,17 @@ public interface IotThingModelMapper extends BaseMapperX { .orderByDesc(IotThingModelDO::getId)); } + default List selectList(IotThingModelListReqVO reqVO) { + return selectList(new LambdaQueryWrapperX() + .eqIfPresent(IotThingModelDO::getIdentifier, reqVO.getIdentifier()) + .likeIfPresent(IotThingModelDO::getName, reqVO.getName()) + .eqIfPresent(IotThingModelDO::getType, reqVO.getType()) + .eqIfPresent(IotThingModelDO::getProductId, reqVO.getProductId()) + // TODO @芋艿:看看要不要加枚举 + .notIn(IotThingModelDO::getIdentifier, "get", "set", "post") + .orderByDesc(IotThingModelDO::getId)); + } + default IotThingModelDO selectByProductIdAndIdentifier(Long productId, String identifier) { return selectOne(IotThingModelDO::getProductId, productId, IotThingModelDO::getIdentifier, identifier); diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/IotDeviceLogDataMapper.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/IotDeviceLogDataMapper.java new file mode 100644 index 0000000000..51fd625ad1 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/IotDeviceLogDataMapper.java @@ -0,0 +1,61 @@ +package cn.iocoder.yudao.module.iot.dal.tdengine; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData.IotDeviceLogPageReqVO; +import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceLogDO; +import cn.iocoder.yudao.module.iot.framework.tdengine.core.annotation.TDengineDS; +import com.baomidou.mybatisplus.annotation.InterceptorIgnore; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * IOT 设备日志数据 Mapper 接口 + * + * 基于 TDengine 实现设备日志的存储 + */ +@Mapper +@TDengineDS +@InterceptorIgnore(tenantLine = "true") // 避免 SQL 解析,因为 JSqlParser 对 TDengine 的 SQL 解析会报错 +public interface IotDeviceLogDataMapper { + + /** + * 创建设备日志超级表 + * + * 注意:初始化时只需创建一次 + */ + void createDeviceLogSTable(); + + /** + * 创建设备日志子表 + * + * @param deviceKey 设备标识 + */ + void createDeviceLogTable(@Param("deviceKey") String deviceKey); + + /** + * 插入设备日志数据 + * + * 如果子表不存在,会自动创建子表 + * + * @param log 设备日志数据 + */ + void insert(@Param("log") IotDeviceLogDO log); + + /** + * 获得设备日志分页 + * + * @param reqVO 分页查询条件 + * @return 设备日志列表 + */ + List selectPage(@Param("reqVO") IotDeviceLogPageReqVO reqVO); + + /** + * 获得设备日志总数 + * + * @param reqVO 查询条件 + * @return 日志总数 + */ + Long selectCount(@Param("reqVO") IotDeviceLogPageReqVO reqVO); +} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdThingModelMessageMapper.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdThingModelMessageMapper.java index 0a735be03a..b04be11991 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdThingModelMessageMapper.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdThingModelMessageMapper.java @@ -1,29 +1,35 @@ package cn.iocoder.yudao.module.iot.dal.tdengine; import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore; +import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.ThingModelMessage; import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.ThingModelMessageDO; +import cn.iocoder.yudao.module.iot.framework.tdengine.core.annotation.TDengineDS; import com.baomidou.dynamic.datasource.annotation.DS; +import com.baomidou.mybatisplus.annotation.InterceptorIgnore; import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; /** * 处理 TD 中物模型消息日志的操作 */ @Mapper -@DS("tdengine") +@Deprecated +@TDengineDS +@InterceptorIgnore(tenantLine = "true") // 避免 SQL 解析,因为 JSqlParser 对 TDengine 的 SQL 解析会报错 public interface TdThingModelMessageMapper { /** * 创建物模型消息日志超级表超级表 * */ - @TenantIgnore - void createSuperTable(ThingModelMessageDO superTable); + + void createSuperTable(@Param("productKey") String productKey); /** * 创建子表 * */ - @TenantIgnore - void createTableWithTag(ThingModelMessageDO table); + + void createTableWithTag(@Param("productKey") String productKey,@Param("deviceKey") String deviceKey); } diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/tdengine/config/TDengineTableInitConfiguration.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/tdengine/config/TDengineTableInitConfiguration.java new file mode 100644 index 0000000000..e14fa2948c --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/tdengine/config/TDengineTableInitConfiguration.java @@ -0,0 +1,40 @@ +package cn.iocoder.yudao.module.iot.framework.tdengine.config; + +import cn.iocoder.yudao.module.iot.service.device.IotDeviceLogDataService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.ApplicationArguments; +import org.springframework.boot.ApplicationRunner; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.annotation.Order; + +/** + * TDengine 表初始化的 Configuration + * + * @author alwayssuper + */ +@Slf4j +@RequiredArgsConstructor +@Configuration +@Order(Integer.MAX_VALUE) // 保证在最后执行 +public class TDengineTableInitConfiguration implements ApplicationRunner { + + private final IotDeviceLogDataService deviceLogService; + + @Override + public void run(ApplicationArguments args) { + try { + // 初始化设备日志表 + deviceLogService.initTDengineSTable(); + log.info("初始化 设备日志表 TDengine 表结构成功"); + } catch (Exception ex) { + if (ex.getMessage().contains("Table already exists")) { + log.info("TDengine 设备日志超级表已存在,跳过创建"); + return; + }else{ + log.error("初始化 设备日志表 TDengine 表结构失败", ex); + } + throw ex; + } + } +} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceLogDataService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceLogDataService.java new file mode 100644 index 0000000000..72cbf63e9c --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceLogDataService.java @@ -0,0 +1,40 @@ +package cn.iocoder.yudao.module.iot.service.device; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData.IotDeviceDataSimulatorSaveReqVO; +import cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData.IotDeviceLogPageReqVO; +import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceLogDO; + + +/** + * IoT 设备日志数据 Service 接口 + * + * @author alwayssuper + */ +public interface IotDeviceLogDataService { + + /** + * 初始化 TDengine 超级表 + * + *系统启动时,会自动初始化一次 + */ + void initTDengineSTable(); + + /** + * 插入设备日志 + * + * 当该设备第一次插入日志时,自动创建该设备的设备日志子表 + * + * @param simulatorReqVO 设备日志模拟数据 + */ + void createDeviceLog(IotDeviceDataSimulatorSaveReqVO simulatorReqVO); + + /** + * 获得设备日志分页 + * + * @param pageReqVO 分页查询 + * @return 设备日志分页 + */ + PageResult getDeviceLogPage(IotDeviceLogPageReqVO pageReqVO); + +} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceLogDataServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceLogDataServiceImpl.java new file mode 100644 index 0000000000..bf883526d7 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceLogDataServiceImpl.java @@ -0,0 +1,68 @@ +package cn.iocoder.yudao.module.iot.service.device; + +import cn.hutool.core.date.DateTime; +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.deviceData.IotDeviceDataSimulatorSaveReqVO; +import cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData.IotDeviceLogPageReqVO; +import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceLogDO; +import cn.iocoder.yudao.module.iot.dal.tdengine.IotDeviceLogDataMapper; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.util.List; + +/** + * IoT 设备日志数据 Service 实现了 + * + * @author alwayssuper + */ +@Service +@Slf4j +@Validated +public class IotDeviceLogDataServiceImpl implements IotDeviceLogDataService{ + + @Resource + private IotDeviceLogDataMapper iotDeviceLogDataMapper; + + + @Override + public void initTDengineSTable() { + try { + // 创建设备日志超级表 + iotDeviceLogDataMapper.createDeviceLogSTable(); + log.info("创建设备日志超级表成功"); + } catch (Exception ex) { + throw ex; + } + } + + @Override + public void createDeviceLog(IotDeviceDataSimulatorSaveReqVO simulatorReqVO) { + //TODO:讨论一下,iotkit这块TS和上报时间都是外部传入的 但是看TDengine文档 他是建议对TS在SQL中直接NOW 咱们的TS数据获取是走哪一种 + + // 1. 转换请求对象为 DO + IotDeviceLogDO iotDeviceLogDO = BeanUtils.toBean(simulatorReqVO, IotDeviceLogDO.class); + + // 2. 处理时间字段 + long currentTime = System.currentTimeMillis(); + // 2.1 设置时序时间为当前时间 + iotDeviceLogDO.setTs(currentTime); + + // 3. 插入数据 + iotDeviceLogDataMapper.insert(iotDeviceLogDO); + } + + @Override + public PageResult getDeviceLogPage(IotDeviceLogPageReqVO pageReqVO) { + // 查询数据 + List list = iotDeviceLogDataMapper.selectPage(pageReqVO); + Long total = iotDeviceLogDataMapper.selectCount(pageReqVO); + // 构造分页结果 + return new PageResult<>(list, total); + } +} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDevicePropertyDataServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDevicePropertyDataServiceImpl.java index b39df35901..5ca4cffe70 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDevicePropertyDataServiceImpl.java +++ b/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; import cn.iocoder.yudao.module.iot.dal.redis.deviceData.DeviceDataRedisDAO; import cn.iocoder.yudao.module.iot.dal.tdengine.IotDevicePropertyDataMapper; import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineDMLMapper; +import cn.iocoder.yudao.module.iot.dal.tdengine.TdThingModelMessageMapper; import cn.iocoder.yudao.module.iot.enums.IotConstants; import cn.iocoder.yudao.module.iot.enums.thingmodel.IotDataSpecsDataTypeEnum; import cn.iocoder.yudao.module.iot.enums.thingmodel.IotThingModelTypeEnum; @@ -85,6 +86,7 @@ public class IotDevicePropertyDataServiceImpl implements IotDevicePropertyDataSe @Resource private IotDevicePropertyDataMapper devicePropertyDataMapper; + @Override public void defineDevicePropertyData(Long productId) { // 1.1 查询产品和物模型 @@ -109,6 +111,7 @@ public class IotDevicePropertyDataServiceImpl implements IotDevicePropertyDataSe return; } newFields.add(0, new TDengineTableField(TDengineTableField.FIELD_TS, TDengineTableField.TYPE_TIMESTAMP)); + // 2.1.1 创建产品超级表 devicePropertyDataMapper.createProductPropertySTable(product.getProductKey(), newFields); return; } diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/product/IotProductServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/product/IotProductServiceImpl.java index d384e44c04..41537664b0 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/product/IotProductServiceImpl.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/product/IotProductServiceImpl.java @@ -34,9 +34,6 @@ public class IotProductServiceImpl implements IotProductService { @Resource private IotProductMapper productMapper; - @Resource - @Lazy // 延迟加载,解决循环依赖 - private IotThingModelMessageService thingModelMessageService; @Resource @Lazy // 延迟加载,解决循环依赖 private IotDevicePropertyDataService devicePropertyDataService; @@ -125,8 +122,7 @@ public class IotProductServiceImpl implements IotProductService { if (Objects.equals(status, IotProductStatusEnum.PUBLISHED.getStatus())) { // 3.1 创建产品超级表数据模型 devicePropertyDataService.defineDevicePropertyData(id); - // 3.2 创建物模型日志超级表数据模型 TODO 待定:message 要不要分; - thingModelMessageService.createSuperTable(id); + } productMapper.updateById(updateObj); } diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotThingModelMessageService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotThingModelMessageService.java index ab77eb91ac..7f52411d89 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotThingModelMessageService.java +++ b/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 { */ void saveThingModelMessage(IotDeviceDO device, ThingModelMessage thingModelMessage); - /** - * 创建物模型消息日志超级表 - * - * @param productId 产品编号 - */ - void createSuperTable(Long productId); + } \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotThingModelMessageServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotThingModelMessageServiceImpl.java index d910419956..52e90f30f7 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotThingModelMessageServiceImpl.java +++ b/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; import cn.iocoder.yudao.module.iot.controller.admin.device.vo.device.IotDeviceStatusUpdateReqVO; import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDataDO; -import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.FieldParser; -import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdFieldDO; -import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO; -import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.ThingModelMessage; +import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.*; import cn.iocoder.yudao.module.iot.dal.dataobject.thingmodel.IotThingModelDO; import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO; import cn.iocoder.yudao.module.iot.dal.redis.deviceData.DeviceDataRedisDAO; import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineDDLMapper; import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineDMLMapper; +import cn.iocoder.yudao.module.iot.dal.tdengine.TdThingModelMessageMapper; import cn.iocoder.yudao.module.iot.enums.IotConstants; import cn.iocoder.yudao.module.iot.enums.device.IotDeviceStatusEnum; import cn.iocoder.yudao.module.iot.enums.thingmodel.IotThingModelTypeEnum; @@ -63,6 +61,9 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ @Resource private TdEngineDMLMapper tdEngineDMLMapper; + @Resource + private TdThingModelMessageMapper tdThingModelMessageMapper; + @Resource private DeviceDataRedisDAO deviceDataRedisDAO; @@ -77,8 +78,6 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ createDeviceTable(device.getDeviceType(), device.getProductKey(), device.getDeviceName(), device.getDeviceKey()); iotDeviceService.updateDeviceStatus(new IotDeviceStatusUpdateReqVO() .setId(device.getId()).setStatus(IotDeviceStatusEnum.ONLINE.getStatus())); - // 1.2 创建物模型日志设备表 - createThingModelMessageDeviceTable(device.getProductKey(), device.getDeviceName(), device.getDeviceKey()); } // 2. 获取设备属性并进行物模型校验,过滤非物模型属性 @@ -107,32 +106,34 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ thingModel -> IotThingModelTypeEnum.PROPERTY.getType().equals(thingModel.getType())); } - @Override - @TenantIgnore - public void createSuperTable(Long productId) { - // 1. 查询产品 - IotProductDO product = productService.getProduct(productId); - - // 2. 获取超级表的名称和数据库名称 - // TODO @alwayssuper:最好 databaseName、superTableName 的处理,放到 tdThinkModelMessageMapper 里。可以考虑,弄个 default 方法 - String databaseName = IotTdDatabaseUtils.getDatabaseName(url); - String superTableName = IotTdDatabaseUtils.getThingModelMessageSuperTableName(product.getProductKey()); - - // 解析物模型,获取字段列表 - List schemaFields = List.of( - TdFieldDO.builder().fieldName("time").dataType("TIMESTAMP").build(), - TdFieldDO.builder().fieldName("id").dataType("NCHAR").dataLength(64).build(), - TdFieldDO.builder().fieldName("sys").dataType("NCHAR").dataLength(2048).build(), - TdFieldDO.builder().fieldName("method").dataType("NCHAR").dataLength(256).build(), - TdFieldDO.builder().fieldName("params").dataType("NCHAR").dataLength(2048).build() - ); - // 设置超级表的标签 - List tagsFields = List.of( - TdFieldDO.builder().fieldName("device_key").dataType("NCHAR").dataLength(64).build() - ); - // 3. 创建超级表 - tdEngineDDLMapper.createSuperTable(new TdTableDO(databaseName, superTableName, schemaFields, tagsFields)); - } +// @Override +// @TenantIgnore +// public void createSuperTable(Long productId) { +// // 1. 查询产品 +// IotProductDO product = productService.getProduct(productId); +// // 2. 创建日志超级表 +// tdThingModelMessageMapper.createSuperTable(product.getProductKey()); +// +// // 2. 获取超级表的名称和数据库名称 +// // TODO @alwayssuper:最好 databaseName、superTableName 的处理,放到 tdThinkModelMessageMapper 里。可以考虑,弄个 default 方法 +//// String databaseName = IotTdDatabaseUtils.getDatabaseName(url); +//// String superTableName = IotTdDatabaseUtils.getThingModelMessageSuperTableName(product.getProductKey()); +//// +//// // 解析物模型,获取字段列表 +//// List schemaFields = List.of( +//// TdFieldDO.builder().fieldName("time").dataType("TIMESTAMP").build(), +//// TdFieldDO.builder().fieldName("id").dataType("NCHAR").dataLength(64).build(), +//// TdFieldDO.builder().fieldName("sys").dataType("NCHAR").dataLength(2048).build(), +//// TdFieldDO.builder().fieldName("method").dataType("NCHAR").dataLength(256).build(), +//// TdFieldDO.builder().fieldName("params").dataType("NCHAR").dataLength(2048).build() +//// ); +//// // 设置超级表的标签 +//// List tagsFields = List.of( +//// TdFieldDO.builder().fieldName("device_key").dataType("NCHAR").dataLength(64).build() +//// ); +//// // 3. 创建超级表 +//// tdEngineDDLMapper.createSuperTable(new TdTableDO(databaseName, superTableName, schemaFields, tagsFields)); +// } private List getValidFunctionList(String productKey) { return filterList(iotThingModelService.getProductThingModelListByProductKey(productKey), @@ -228,29 +229,7 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ .setTags(tagsFieldValues)); } - /** - * 创建物模型日志设备数据表 - * - * @param productKey 产品 Key - * @param deviceName 设备名称 - * @param deviceKey 设备 Key - * - */ - private void createThingModelMessageDeviceTable(String productKey, String deviceName, String deviceKey){ - // 1. 获取超级表的名称、数据库名称、设备日志表名称 - String databaseName = IotTdDatabaseUtils.getDatabaseName(url); - String superTableName = IotTdDatabaseUtils.getThingModelMessageSuperTableName(productKey); - // TODO @alwayssuper:最好 databaseName、superTableName、thinkModelMessageDeviceTableName 的处理,放到 tdThinkModelMessageMapper 里。可以考虑,弄个 default 方法 - String thinkModelMessageDeviceTableName = IotTdDatabaseUtils.getThingModelMessageDeviceTableName(productKey, deviceName); - - // 2. 创建物模型日志设备数据表 -// tdThingModelMessageMapper.createTableWithTag(ThingModelMessageDO.builder().build() -// .setDataBaseName(databaseName) -// .setSuperTableName(superTableName) -// .setTableName(thinkModelMessageDeviceTableName) -// .setDeviceKey(deviceKey)); - } /** * 获取数据库名称 diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thingmodel/IotThingModelService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thingmodel/IotThingModelService.java index f2ec53ecfc..d68b3429e4 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thingmodel/IotThingModelService.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thingmodel/IotThingModelService.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.iot.service.thingmodel; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.vo.IotThingModelListReqVO; import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.vo.IotThingModelPageReqVO; import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.vo.IotThingModelSaveReqVO; import cn.iocoder.yudao.module.iot.dal.dataobject.thingmodel.IotThingModelDO; @@ -69,4 +70,11 @@ public interface IotThingModelService { */ List getProductThingModelListByProductKey(String productKey); + /** + * 获得产品物模型列表 + * + * @param reqVO 列表查询 + * @return 产品物模型列表 + */ + List getThingModelList(IotThingModelListReqVO reqVO); } \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thingmodel/IotThingModelServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thingmodel/IotThingModelServiceImpl.java index 025c9bca90..f0ce947d52 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thingmodel/IotThingModelServiceImpl.java +++ b/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; import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.model.ThingModelEvent; import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.model.ThingModelParam; import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.model.ThingModelService; +import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.vo.IotThingModelListReqVO; import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.vo.IotThingModelPageReqVO; import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.vo.IotThingModelSaveReqVO; import cn.iocoder.yudao.module.iot.convert.thingmodel.IotThingModelConvert; @@ -134,6 +135,11 @@ public class IotThingModelServiceImpl implements IotThingModelService { return thingModelMapper.selectListByProductKey(productKey); } + @Override + public List getThingModelList(IotThingModelListReqVO reqVO) { + return thingModelMapper.selectList(reqVO); + } + /** * 校验功能是否存在 * diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/device/IotDeviceLogDataMapper.xml b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/device/IotDeviceLogDataMapper.xml new file mode 100644 index 0000000000..dd0f80a949 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/device/IotDeviceLogDataMapper.xml @@ -0,0 +1,78 @@ + + + + + + + CREATE STABLE device_log ( + ts TIMESTAMP, + id NCHAR(50), + product_key NCHAR(50), + type NCHAR(50), + subType NCHAR(50), + content NCHAR(1024), + report_time TIMESTAMP + )TAGS ( + device_key NCHAR(50) + ) + + + + + + CREATE TABLE device_log_${deviceKey} USING device_log TAGS('${deviceKey}') + + + + + INSERT INTO device_log_${log.deviceKey} (ts, id, product_key, type, subType, content, report_time) + USING device_log + TAGS ('${log.deviceKey}') + VALUES ( + #{log.ts}, + #{log.id}, + #{log.productKey}, + #{log.type}, + #{log.subType}, + #{log.content}, + #{log.reportTime} + ) + + + + + + + \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineDMLMapper.xml b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineDMLMapper.xml index 0443a826b2..b4084374cf 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineDMLMapper.xml +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineDMLMapper.xml @@ -42,7 +42,7 @@