【代码评审】IoT:设备日志 TDengine 表与模拟设备

This commit is contained in:
YunaiV 2025-01-09 12:36:30 +08:00
parent 16120820a0
commit deab8c1cc6
18 changed files with 90 additions and 87 deletions

View File

@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.iot.controller.admin.device;
import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
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.controller.admin.device.vo.deviceData.*;
import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDataDO; import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDataDO;
import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceLogDO; import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceLogDO;
@ -13,7 +12,6 @@ import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import jakarta.validation.Valid; import jakarta.validation.Valid;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
@ -34,7 +32,7 @@ public class IotDeviceDataController {
@Resource @Resource
private IotDeviceLogDataService iotDeviceLogDataService; private IotDeviceLogDataService iotDeviceLogDataService;
@Resource @Resource // TODO @superservice 之间不用空行原因是这样更简洁空行主要是为了间隔提升可读性
private IotDeviceLogDataService deviceLogDataService; private IotDeviceLogDataService deviceLogDataService;
// TODO @浩浩这里的 /latest-list包括方法名 // TODO @浩浩这里的 /latest-list包括方法名
@ -52,14 +50,17 @@ public class IotDeviceDataController {
PageResult<Map<String, Object>> list = deviceDataService.getHistoryDeviceProperties(deviceDataReqVO); PageResult<Map<String, Object>> list = deviceDataService.getHistoryDeviceProperties(deviceDataReqVO);
return success(BeanUtils.toBean(list, IotTimeDataRespVO.class)); return success(BeanUtils.toBean(list, IotTimeDataRespVO.class));
} }
// TODO:数据权限 // TODO:数据权限
@PostMapping("/simulator") @PostMapping("/simulator")
@Operation(summary = "模拟设备") @Operation(summary = "模拟设备")
public CommonResult<Boolean> simulatorDevice(@Valid @RequestBody IotDeviceDataSimulatorSaveReqVO simulatorReqVO) { public CommonResult<Boolean> simulatorDevice(@Valid @RequestBody IotDeviceDataSimulatorSaveReqVO simulatorReqVO) {
//TODO:先生成一下设备日志 后续完善模拟设备代码逻辑 //TODO:先生成一下设备日志 后续完善模拟设备代码逻辑
// TODO @super应该 deviceDataService 里面有个 simulatorDevice然后里面去 insert 日志
iotDeviceLogDataService.createDeviceLog(simulatorReqVO); iotDeviceLogDataService.createDeviceLog(simulatorReqVO);
return success(true); return success(true);
} }
// TODO:数据权限 // TODO:数据权限
@GetMapping("/log/page") @GetMapping("/log/page")
@Operation(summary = "获得设备日志分页") @Operation(summary = "获得设备日志分页")

View File

@ -14,7 +14,7 @@ public class IotDeviceSaveReqVO {
private Long id; private Long id;
@Schema(description = "设备编号", requiredMode = Schema.RequiredMode.AUTO, example = "177") @Schema(description = "设备编号", requiredMode = Schema.RequiredMode.AUTO, example = "177")
@Size(max = 50, message = "设备编号长度不能超过50个字符") @Size(max = 50, message = "设备编号长度不能超过 50 个字符")
private String deviceKey; private String deviceKey;
@Schema(description = "设备名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "王五") @Schema(description = "设备名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "王五")

View File

@ -3,27 +3,27 @@ package cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotEmpty; import jakarta.validation.constraints.NotEmpty;
import lombok.Data; 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;
// TODO super SaveReqVO => ReqVO
@Schema(description = "管理后台 - IoT 模拟设备数据 Request VO") @Schema(description = "管理后台 - IoT 模拟设备数据 Request VO")
@Data @Data
public class IotDeviceDataSimulatorSaveReqVO { public class IotDeviceDataSimulatorSaveReqVO {
@Schema(description = "消息ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "msg123") // TODO @super感觉后端随机更合适
@Schema(description = "消息 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "msg123")
private String id; private String id;
// TODO @super不用传递 productKey因为 deviceKey 可以推导出来
@Schema(description = "产品ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "product123") @Schema(description = "产品ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "product123")
@NotEmpty(message = "产品ID不能为空") @NotEmpty(message = "产品ID不能为空")
private String productKey; private String productKey;
// TODO @super中文写作规范中英文之间要有空格例如说设备 IDps这里应该是设备标识
@Schema(description = "设备ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "device123") @Schema(description = "设备ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "device123")
@NotEmpty(message = "设备ID不能为空") @NotEmpty(message = "设备ID不能为空")
private String deviceKey; private String deviceKey;
// TODO @supertypesubType是不是不用传递因为模拟只有属性
@Schema(description = "消息/日志类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "property") @Schema(description = "消息/日志类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "property")
@NotEmpty(message = "消息类型不能为空") @NotEmpty(message = "消息类型不能为空")
private String type; private String type;
@ -36,6 +36,7 @@ public class IotDeviceDataSimulatorSaveReqVO {
@NotEmpty(message = "数据内容不能为空") @NotEmpty(message = "数据内容不能为空")
private String content; private String content;
// TODO @芋艿需要讨论下reportTime 到底以那个为准
@Schema(description = "上报时间", requiredMode = Schema.RequiredMode.REQUIRED) @Schema(description = "上报时间", requiredMode = Schema.RequiredMode.REQUIRED)
private Long reportTime; private Long reportTime;

View File

@ -18,13 +18,16 @@ public class IotDeviceLogPageReqVO extends PageParam {
@NotEmpty(message = "设备标识不能为空") @NotEmpty(message = "设备标识不能为空")
private String deviceKey; private String deviceKey;
// TODO @super对应的枚举类
@Schema(description = "消息类型", example = "property") @Schema(description = "消息类型", example = "property")
private String type; private String type;
@Schema(description = "标识符", example = "temperature") @Schema(description = "标识符", example = "temperature")
// TODO @super对应的枚举类
private String subType; private String subType;
@Schema(description = "创建时间") @Schema(description = "创建时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] createTime; private LocalDateTime[] createTime;
} }

View File

@ -11,8 +11,10 @@ public class IotDeviceLogRespVO {
@Schema(description = "日志编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") @Schema(description = "日志编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private String id; private String id;
@Schema(description = "产品标识", requiredMode = Schema.RequiredMode.REQUIRED, example = "product123") @Schema(description = "产品标识", requiredMode = Schema.RequiredMode.REQUIRED, example = "product123")
private String productKey; private String productKey;
@Schema(description = "设备标识", requiredMode = Schema.RequiredMode.REQUIRED, example = "device123") @Schema(description = "设备标识", requiredMode = Schema.RequiredMode.REQUIRED, example = "device123")
private String deviceKey; private String deviceKey;
@ -30,4 +32,5 @@ public class IotDeviceLogRespVO {
@Schema(description = "记录时间戳", requiredMode = Schema.RequiredMode.REQUIRED) @Schema(description = "记录时间戳", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime ts; private LocalDateTime ts;
} }

View File

@ -74,6 +74,7 @@ public class IotThingModelController {
return success(IotThingModelConvert.INSTANCE.convertList(list)); return success(IotThingModelConvert.INSTANCE.convertList(list));
} }
// TODO @puhui @supergetThingModelListByProductId getThingModelListByProductId 可以融合么
@GetMapping("/list") @GetMapping("/list")
@Operation(summary = "获得产品物模型列表") @Operation(summary = "获得产品物模型列表")
@PreAuthorize("@ss.hasPermission('iot:thing-model:query')") @PreAuthorize("@ss.hasPermission('iot:thing-model:query')")

View File

@ -6,11 +6,10 @@ import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.NotNull;
import lombok.Data; import lombok.Data;
@Schema(description = "管理后台 - IoT 产品物模型List Request VO") @Schema(description = "管理后台 - IoT 产品物模型List Request VO")
@Data @Data
public class IotThingModelListReqVO { public class IotThingModelListReqVO {
@Schema(description = "功能标识") @Schema(description = "功能标识")
private String identifier; private String identifier;
@ -21,7 +20,8 @@ public class IotThingModelListReqVO {
@InEnum(IotThingModelTypeEnum.class) @InEnum(IotThingModelTypeEnum.class)
private Integer type; private Integer type;
@Schema(description = "产品ID", requiredMode = Schema.RequiredMode.REQUIRED) @Schema(description = "产品 ID", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "产品ID不能为空") @NotNull(message = "产品 ID 不能为空")
private Long productId; private Long productId;
} }

View File

@ -1,16 +1,15 @@
package cn.iocoder.yudao.module.iot.dal.dataobject.device; package cn.iocoder.yudao.module.iot.dal.dataobject.device;
import cn.hutool.core.date.DateTime;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Builder; import lombok.Builder;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import java.time.LocalDateTime;
/** /**
* IoT 设备日志数据 DO * IoT 设备日志数据 DO
* *
* 目前使用 TDengine 存储
*
* @author alwayssuper * @author alwayssuper
*/ */
@Data @Data
@ -18,33 +17,41 @@ import java.time.LocalDateTime;
@NoArgsConstructor @NoArgsConstructor
@AllArgsConstructor @AllArgsConstructor
public class IotDeviceLogDO { public class IotDeviceLogDO {
// TODO @芋艿消息 ID 的生成逻辑
/** /**
* 消息ID * 消息 ID
*/ */
private String id; private String id;
// TODO @super关联要 @下
/** /**
* 产品ID * 产品标识
*/ */
private String productKey; private String productKey;
// TODO @super关联要 @下
/** /**
* 设备ID * 设备标识
*/ */
private String deviceKey; private String deviceKey;
// TODO @super枚举类
/** /**
* 消息/日志类型 * 日志类型
*/ */
private String type; private String type;
// TODO @super枚举类
/** /**
* 标识符用于标识具体的属性事件或服务 * 标识符用于标识具体的属性事件或服务
*/ */
private String subType; private String subType;
/** /**
* 数据内容存储具体的消息数据内容通常是JSON格式 * 数据内容
*
* 存储具体的消息数据内容通常是 JSON 格式
*/ */
private String content; private String content;
@ -58,5 +65,4 @@ public class IotDeviceLogDO {
*/ */
private Long ts; private Long ts;
} }

View File

@ -6,7 +6,7 @@ import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
// TODO @芋艿纠结下字段 // TODO @芋艿纠结下字段
@Deprecated @Deprecated // TODO @super看看啥时候删除下哈
/** /**
* TD 物模型消息日志的数据库 * TD 物模型消息日志的数据库
*/ */

View File

@ -1,6 +1,5 @@
package cn.iocoder.yudao.module.iot.dal.tdengine; 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.controller.admin.device.vo.deviceData.IotDeviceLogPageReqVO;
import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceLogDO; import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceLogDO;
import cn.iocoder.yudao.module.iot.framework.tdengine.core.annotation.TDengineDS; import cn.iocoder.yudao.module.iot.framework.tdengine.core.annotation.TDengineDS;
@ -27,6 +26,7 @@ public interface IotDeviceLogDataMapper {
*/ */
void createDeviceLogSTable(); void createDeviceLogSTable();
// TODO @super是不是删除哈
/** /**
* 创建设备日志子表 * 创建设备日志子表
* *
@ -34,6 +34,7 @@ public interface IotDeviceLogDataMapper {
*/ */
void createDeviceLogTable(@Param("deviceKey") String deviceKey); void createDeviceLogTable(@Param("deviceKey") String deviceKey);
// TODO @super单个参数不用加 @Param
/** /**
* 插入设备日志数据 * 插入设备日志数据
* *
@ -58,4 +59,5 @@ public interface IotDeviceLogDataMapper {
* @return 日志总数 * @return 日志总数
*/ */
Long selectCount(@Param("reqVO") IotDeviceLogPageReqVO reqVO); Long selectCount(@Param("reqVO") IotDeviceLogPageReqVO reqVO);
} }

View File

@ -1,10 +1,6 @@
package cn.iocoder.yudao.module.iot.dal.tdengine; 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 cn.iocoder.yudao.module.iot.framework.tdengine.core.annotation.TDengineDS;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.annotation.InterceptorIgnore; import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Param;
@ -13,7 +9,7 @@ import org.apache.ibatis.annotations.Param;
* 处理 TD 中物模型消息日志的操作 * 处理 TD 中物模型消息日志的操作
*/ */
@Mapper @Mapper
@Deprecated @Deprecated // TODO super什么时候删除下哈
@TDengineDS @TDengineDS
@InterceptorIgnore(tenantLine = "true") // 避免 SQL 解析因为 JSqlParser TDengine SQL 解析会报错 @InterceptorIgnore(tenantLine = "true") // 避免 SQL 解析因为 JSqlParser TDengine SQL 解析会报错
public interface TdThingModelMessageMapper { public interface TdThingModelMessageMapper {

View File

@ -16,7 +16,7 @@ import org.springframework.core.annotation.Order;
@Slf4j @Slf4j
@RequiredArgsConstructor @RequiredArgsConstructor
@Configuration @Configuration
@Order(Integer.MAX_VALUE) // 保证在最后执行 @Order
public class TDengineTableInitConfiguration implements ApplicationRunner { public class TDengineTableInitConfiguration implements ApplicationRunner {
private final IotDeviceLogDataService deviceLogService; private final IotDeviceLogDataService deviceLogService;
@ -26,15 +26,18 @@ public class TDengineTableInitConfiguration implements ApplicationRunner {
try { try {
// 初始化设备日志表 // 初始化设备日志表
deviceLogService.initTDengineSTable(); deviceLogService.initTDengineSTable();
log.info("初始化 设备日志表 TDengine 表结构成功"); // TODO @super这个日志是不是不用打不然重复啦
log.info("[run]初始化 设备日志表 TDengine 表结构成功");
} catch (Exception ex) { } catch (Exception ex) {
// TODO @super初始化失败打印 error 日志退出系统不然跑起来就初始啦
if (ex.getMessage().contains("Table already exists")) { if (ex.getMessage().contains("Table already exists")) {
log.info("TDengine 设备日志超级表已存在,跳过创建"); log.info("TDengine 设备日志超级表已存在,跳过创建");
return; return;
}else{ } else{
log.error("初始化 设备日志表 TDengine 表结构失败", ex); log.error("初始化 设备日志表 TDengine 表结构失败", ex);
} }
throw ex; throw ex;
} }
} }
} }

View File

@ -5,7 +5,6 @@ import cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData.IotDevi
import cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData.IotDeviceLogPageReqVO; 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.dataobject.device.IotDeviceLogDO;
/** /**
* IoT 设备日志数据 Service 接口 * IoT 设备日志数据 Service 接口
* *

View File

@ -1,6 +1,5 @@
package cn.iocoder.yudao.module.iot.service.device; 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.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils; 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.IotDeviceDataSimulatorSaveReqVO;
@ -12,8 +11,6 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.List; import java.util.List;
/** /**
@ -29,34 +26,30 @@ public class IotDeviceLogDataServiceImpl implements IotDeviceLogDataService{
@Resource @Resource
private IotDeviceLogDataMapper iotDeviceLogDataMapper; private IotDeviceLogDataMapper iotDeviceLogDataMapper;
// TODO @super方法名defineDeviceLog未来有可能别人使用别的记录日志例如说 es 之类的
@Override @Override
public void initTDengineSTable() { public void initTDengineSTable() {
try { // TODO @super改成不存在才创建
// 创建设备日志超级表 iotDeviceLogDataMapper.createDeviceLogSTable();
iotDeviceLogDataMapper.createDeviceLogSTable();
log.info("创建设备日志超级表成功");
} catch (Exception ex) {
throw ex;
}
} }
@Override @Override
public void createDeviceLog(IotDeviceDataSimulatorSaveReqVO simulatorReqVO) { public void createDeviceLog(IotDeviceDataSimulatorSaveReqVO simulatorReqVO) {
//TODO:讨论一下iotkit这块TS和上报时间都是外部传入的 但是看TDengine文档 他是建议对TS在SQL中直接NOW 咱们的TS数据获取是走哪一种
// 1. 转换请求对象为 DO // 1. 转换请求对象为 DO
IotDeviceLogDO iotDeviceLogDO = BeanUtils.toBean(simulatorReqVO, IotDeviceLogDO.class); IotDeviceLogDO iotDeviceLogDO = BeanUtils.toBean(simulatorReqVO, IotDeviceLogDO.class);
// 2. 处理时间字段 // 2. 处理时间字段
// TODO @super一次性的字段不用单独给个变量
long currentTime = System.currentTimeMillis(); long currentTime = System.currentTimeMillis();
// 2.1 设置时序时间为当前时间 // 2.1 设置时序时间为当前时间
iotDeviceLogDO.setTs(currentTime); iotDeviceLogDO.setTs(currentTime); // TODO @superTS在SQL中直接NOW 咱们的TS数据获取是走哪一种 now()
// 3. 插入数据 // 3. 插入数据
// TODO @super不要直接调用对方的 IotDeviceLogDataMapper通过 service
iotDeviceLogDataMapper.insert(iotDeviceLogDO); iotDeviceLogDataMapper.insert(iotDeviceLogDO);
} }
// TODO @super iotDeviceLogDataService
@Override @Override
public PageResult<IotDeviceLogDO> getDeviceLogPage(IotDeviceLogPageReqVO pageReqVO) { public PageResult<IotDeviceLogDO> getDeviceLogPage(IotDeviceLogPageReqVO pageReqVO) {
// 查询数据 // 查询数据
@ -65,4 +58,5 @@ public class IotDeviceLogDataServiceImpl implements IotDeviceLogDataService{
// 构造分页结果 // 构造分页结果
return new PageResult<>(list, total); return new PageResult<>(list, total);
} }
} }

View File

@ -18,7 +18,6 @@ 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.redis.deviceData.DeviceDataRedisDAO;
import cn.iocoder.yudao.module.iot.dal.tdengine.IotDevicePropertyDataMapper; 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.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.IotConstants;
import cn.iocoder.yudao.module.iot.enums.thingmodel.IotDataSpecsDataTypeEnum; import cn.iocoder.yudao.module.iot.enums.thingmodel.IotDataSpecsDataTypeEnum;
import cn.iocoder.yudao.module.iot.enums.thingmodel.IotThingModelTypeEnum; import cn.iocoder.yudao.module.iot.enums.thingmodel.IotThingModelTypeEnum;
@ -111,7 +110,6 @@ public class IotDevicePropertyDataServiceImpl implements IotDevicePropertyDataSe
return; return;
} }
newFields.add(0, new TDengineTableField(TDengineTableField.FIELD_TS, TDengineTableField.TYPE_TIMESTAMP)); newFields.add(0, new TDengineTableField(TDengineTableField.FIELD_TS, TDengineTableField.TYPE_TIMESTAMP));
// 2.1.1 创建产品超级表
devicePropertyDataMapper.createProductPropertySTable(product.getProductKey(), newFields); devicePropertyDataMapper.createProductPropertySTable(product.getProductKey(), newFields);
return; return;
} }

View File

@ -9,7 +9,6 @@ import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO;
import cn.iocoder.yudao.module.iot.dal.mysql.product.IotProductMapper; import cn.iocoder.yudao.module.iot.dal.mysql.product.IotProductMapper;
import cn.iocoder.yudao.module.iot.enums.product.IotProductStatusEnum; import cn.iocoder.yudao.module.iot.enums.product.IotProductStatusEnum;
import cn.iocoder.yudao.module.iot.service.device.IotDevicePropertyDataService; import cn.iocoder.yudao.module.iot.service.device.IotDevicePropertyDataService;
import cn.iocoder.yudao.module.iot.service.tdengine.IotThingModelMessageService;
import com.baomidou.dynamic.datasource.annotation.DSTransactional; import com.baomidou.dynamic.datasource.annotation.DSTransactional;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import org.springframework.context.annotation.Lazy; import org.springframework.context.annotation.Lazy;
@ -116,14 +115,15 @@ public class IotProductServiceImpl implements IotProductService {
public void updateProductStatus(Long id, Integer status) { public void updateProductStatus(Long id, Integer status) {
// 1. 校验存在 // 1. 校验存在
validateProductExists(id); validateProductExists(id);
// 2. 更新
IotProductDO updateObj = IotProductDO.builder().id(id).status(status).build();
// 3. 产品是发布状态
if (Objects.equals(status, IotProductStatusEnum.PUBLISHED.getStatus())) {
// 3.1 创建产品超级表数据模型
devicePropertyDataService.defineDevicePropertyData(id);
// 2. 产品是发布状态
if (Objects.equals(status, IotProductStatusEnum.PUBLISHED.getStatus())) {
// 创建产品超级表数据模型
devicePropertyDataService.defineDevicePropertyData(id);
} }
// 3. 更新
IotProductDO updateObj = IotProductDO.builder().id(id).status(status).build();
productMapper.updateById(updateObj); productMapper.updateById(updateObj);
} }

View File

@ -7,20 +7,20 @@ 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.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.IotDeviceDO;
import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDataDO; import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDataDO;
import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.*; 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.thingmodel.IotThingModelDO; 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.redis.deviceData.DeviceDataRedisDAO;
import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineDDLMapper; 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.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.IotConstants;
import cn.iocoder.yudao.module.iot.enums.device.IotDeviceStatusEnum; import cn.iocoder.yudao.module.iot.enums.device.IotDeviceStatusEnum;
import cn.iocoder.yudao.module.iot.enums.thingmodel.IotThingModelTypeEnum; import cn.iocoder.yudao.module.iot.enums.thingmodel.IotThingModelTypeEnum;
import cn.iocoder.yudao.module.iot.service.device.IotDeviceService; import cn.iocoder.yudao.module.iot.service.device.IotDeviceService;
import cn.iocoder.yudao.module.iot.service.thingmodel.IotThingModelService;
import cn.iocoder.yudao.module.iot.service.product.IotProductService; import cn.iocoder.yudao.module.iot.service.product.IotProductService;
import cn.iocoder.yudao.module.iot.util.IotTdDatabaseUtils; import cn.iocoder.yudao.module.iot.service.thingmodel.IotThingModelService;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
@ -61,13 +61,9 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ
@Resource @Resource
private TdEngineDMLMapper tdEngineDMLMapper; private TdEngineDMLMapper tdEngineDMLMapper;
@Resource
private TdThingModelMessageMapper tdThingModelMessageMapper;
@Resource @Resource
private DeviceDataRedisDAO deviceDataRedisDAO; private DeviceDataRedisDAO deviceDataRedisDAO;
// TODO @haohao这个方法可以考虑加下 1. 2. 3. 更有层次感 // TODO @haohao这个方法可以考虑加下 1. 2. 3. 更有层次感
@Override @Override
@TenantIgnore @TenantIgnore

View File

@ -7,19 +7,19 @@
<!-- 创建设备日志超级表 初始化只创建一次--> <!-- 创建设备日志超级表 初始化只创建一次-->
<update id="createDeviceLogSTable"> <update id="createDeviceLogSTable">
CREATE STABLE device_log ( CREATE STABLE device_log (
ts TIMESTAMP, ts TIMESTAMP,
id NCHAR(50), id NCHAR(50),
product_key NCHAR(50), product_key NCHAR(50),
type NCHAR(50), type NCHAR(50),
subType NCHAR(50), <!-- TODO @super下划线 sub_type -->
content NCHAR(1024), subType NCHAR(50),
report_time TIMESTAMP content NCHAR(1024),
)TAGS ( report_time TIMESTAMP
device_key NCHAR(50) ) TAGS (
) device_key NCHAR(50)
)
</update> </update>
<!-- 创建设备日志子表 讨论TDengine 在子表不存在的情况下 可在数据插入时 自动建表 要不要去掉创建子表的逻辑 由第一次插入数据时自动创建--> <!-- 创建设备日志子表 讨论TDengine 在子表不存在的情况下 可在数据插入时 自动建表 要不要去掉创建子表的逻辑 由第一次插入数据时自动创建-->
<update id="createDeviceLogTable"> <update id="createDeviceLogTable">
CREATE TABLE device_log_${deviceKey} USING device_log TAGS('${deviceKey}') CREATE TABLE device_log_${deviceKey} USING device_log TAGS('${deviceKey}')