Commit 067130ecde7211d2063ba0e2a83e03daf7ab9e5e
1 parent
de78cc92
新增:物模型日志建表
Showing
10 changed files
with
292 additions
and
8 deletions
yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/IotConstants.java
| ... | ... | @@ -35,4 +35,11 @@ public interface IotConstants { |
| 35 | 35 | */ |
| 36 | 36 | String DEVICE_STABLE_NAME_FORMAT = "device_%s"; |
| 37 | 37 | |
| 38 | + /** | |
| 39 | + * 获取物模型消息记录设备名 | |
| 40 | + * <p> | |
| 41 | + * 格式为 thing_model_message_{productKey}_{deviceName} | |
| 42 | + */ | |
| 43 | + String THINK_MODEL_MESSAGE_TABLE_NAME_FORMAT = "thing_model_message_%s_%s"; | |
| 44 | + | |
| 38 | 45 | } |
| 39 | 46 | \ No newline at end of file | ... | ... |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodel/model/dataType/ThinkModelArgument.java
| 1 | 1 | package cn.iocoder.yudao.module.iot.controller.admin.thinkmodel.model.dataType; |
| 2 | 2 | |
| 3 | 3 | import cn.iocoder.yudao.module.iot.controller.admin.thinkmodel.model.ThinkModelProperty; |
| 4 | +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; | |
| 4 | 5 | import lombok.Data; |
| 5 | 6 | |
| 6 | 7 | @Data |
| 8 | +@JsonIgnoreProperties(ignoreUnknown = true) | |
| 7 | 9 | public class ThinkModelArgument { |
| 8 | 10 | |
| 9 | 11 | public static final String DIRECTION_INPUT = "input"; | ... | ... |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/ThinkModelMessageDO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.iot.dal.dataobject.tdengine; | |
| 2 | + | |
| 3 | +import lombok.AllArgsConstructor; | |
| 4 | +import lombok.Builder; | |
| 5 | +import lombok.Data; | |
| 6 | +import lombok.NoArgsConstructor; | |
| 7 | +import org.apache.xmlbeans.impl.xb.xsdschema.Public; | |
| 8 | + | |
| 9 | + | |
| 10 | +/** | |
| 11 | + * TD 物模型消息日志的数据库 | |
| 12 | + */ | |
| 13 | +@Data | |
| 14 | +@Builder | |
| 15 | +@NoArgsConstructor | |
| 16 | +@AllArgsConstructor | |
| 17 | +public class ThinkModelMessageDO { | |
| 18 | + /** | |
| 19 | + * 数据库名称 | |
| 20 | + */ | |
| 21 | + private String dataBaseName; | |
| 22 | + | |
| 23 | + // TODO @haohao:superTableName 和 tableName 是不是合并。因为每个 mapper 操作的时候,有且只会使用到其中一个。 | |
| 24 | + /** | |
| 25 | + * 超级表名称 | |
| 26 | + */ | |
| 27 | + private String superTableName; | |
| 28 | + | |
| 29 | + /** | |
| 30 | + * 表名称 | |
| 31 | + */ | |
| 32 | + private String tableName; | |
| 33 | + | |
| 34 | + /** | |
| 35 | + * 消息ID | |
| 36 | + */ | |
| 37 | + private String id; | |
| 38 | + | |
| 39 | + /** | |
| 40 | + * 扩展功能的参数 | |
| 41 | + */ | |
| 42 | + private Object sys; | |
| 43 | + | |
| 44 | + /** | |
| 45 | + * 请求方法 例如:thing.event.property.post | |
| 46 | + */ | |
| 47 | + private String method; | |
| 48 | + | |
| 49 | + /** | |
| 50 | + * 请求参数 | |
| 51 | + */ | |
| 52 | + private Object params; | |
| 53 | + | |
| 54 | + /** | |
| 55 | + * 属性上报时间戳 | |
| 56 | + */ | |
| 57 | + private Long time; | |
| 58 | + | |
| 59 | + | |
| 60 | + /** | |
| 61 | + * 设备 key | |
| 62 | + */ | |
| 63 | + private String deviceKey; | |
| 64 | + | |
| 65 | + | |
| 66 | +} | ... | ... |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdThinkModelMessageMapper.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.iot.dal.tdengine; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore; | |
| 4 | +import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO; | |
| 5 | +import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.ThinkModelMessageDO; | |
| 6 | +import com.baomidou.dynamic.datasource.annotation.DS; | |
| 7 | +import org.apache.ibatis.annotations.Mapper; | |
| 8 | + | |
| 9 | +/** | |
| 10 | + * 处理 TD 中物模型消息日志的操作 | |
| 11 | + */ | |
| 12 | +@Mapper | |
| 13 | +@DS("tdengine") | |
| 14 | +public interface TdThinkModelMessageMapper { | |
| 15 | + | |
| 16 | + /** | |
| 17 | + * 创建物模型消息日志超级表超级表 | |
| 18 | + * | |
| 19 | + */ | |
| 20 | + @TenantIgnore | |
| 21 | + void createSuperTable(ThinkModelMessageDO superTable); | |
| 22 | + | |
| 23 | + /** | |
| 24 | + * 创建子表 | |
| 25 | + * | |
| 26 | + */ | |
| 27 | + @TenantIgnore | |
| 28 | + void createTableWithTag(ThinkModelMessageDO table); | |
| 29 | +} | ... | ... |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/mq/producer/simulatesend/SimulateSendProducer.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.iot.mq.producer.simulatesend; | |
| 2 | + | |
| 3 | +import jakarta.annotation.Resource; | |
| 4 | +import lombok.extern.slf4j.Slf4j; | |
| 5 | +import org.springframework.context.ApplicationContext; | |
| 6 | +import org.springframework.stereotype.Component; | |
| 7 | + | |
| 8 | +/** | |
| 9 | + * SimulateSend 模拟设备上报的 Producer | |
| 10 | + * | |
| 11 | + * @author alwayssuper | |
| 12 | + * @since 2024/12/17 16:35 | |
| 13 | + */ | |
| 14 | +@Slf4j | |
| 15 | +@Component | |
| 16 | +public class SimulateSendProducer { | |
| 17 | + @Resource | |
| 18 | + private ApplicationContext applicationContext; | |
| 19 | + | |
| 20 | +} | ... | ... |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/product/IotProductServiceImpl.java
| ... | ... | @@ -7,6 +7,7 @@ import cn.iocoder.yudao.module.iot.controller.admin.product.vo.product.IotProduc |
| 7 | 7 | import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO; |
| 8 | 8 | import cn.iocoder.yudao.module.iot.dal.mysql.product.IotProductMapper; |
| 9 | 9 | import cn.iocoder.yudao.module.iot.enums.product.IotProductStatusEnum; |
| 10 | +import cn.iocoder.yudao.module.iot.service.tdengine.IotThinkModelMessageService; | |
| 10 | 11 | import cn.iocoder.yudao.module.iot.service.thinkmodel.IotProductThinkModelService; |
| 11 | 12 | import com.baomidou.dynamic.datasource.annotation.DSTransactional; |
| 12 | 13 | import jakarta.annotation.Resource; |
| ... | ... | @@ -31,11 +32,12 @@ public class IotProductServiceImpl implements IotProductService { |
| 31 | 32 | |
| 32 | 33 | @Resource |
| 33 | 34 | private IotProductMapper productMapper; |
| 34 | - | |
| 35 | 35 | @Resource |
| 36 | 36 | @Lazy |
| 37 | 37 | private IotProductThinkModelService thinkModelFunctionService; |
| 38 | - | |
| 38 | + @Resource | |
| 39 | + @Lazy | |
| 40 | + private IotThinkModelMessageService thinkModelMessageService; | |
| 39 | 41 | @Override |
| 40 | 42 | public Long createProduct(IotProductSaveReqVO createReqVO) { |
| 41 | 43 | // 1. 生成 ProductKey |
| ... | ... | @@ -114,8 +116,10 @@ public class IotProductServiceImpl implements IotProductService { |
| 114 | 116 | IotProductDO updateObj = IotProductDO.builder().id(id).status(status).build(); |
| 115 | 117 | // 3. 产品是发布状态 |
| 116 | 118 | if (Objects.equals(status, IotProductStatusEnum.PUBLISHED.getStatus())) { |
| 117 | - // 3.1 创建超级表数据模型 | |
| 119 | + // 3.1 创建产品超级表数据模型 | |
| 118 | 120 | thinkModelFunctionService.createSuperTableDataModel(id); |
| 121 | + // 3.2 创建物模型日志超级表数据模型 | |
| 122 | + thinkModelMessageService.createSuperTable(id); | |
| 119 | 123 | } |
| 120 | 124 | productMapper.updateById(updateObj); |
| 121 | 125 | } | ... | ... |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotThinkModelMessageService.java
| ... | ... | @@ -15,4 +15,12 @@ public interface IotThinkModelMessageService { |
| 15 | 15 | * @param thingModelMessage 物模型消息 |
| 16 | 16 | */ |
| 17 | 17 | void saveThinkModelMessage(IotDeviceDO device, ThinkModelMessage thingModelMessage); |
| 18 | + | |
| 19 | + /** | |
| 20 | + * 创建物模型消息日志超级表 | |
| 21 | + * | |
| 22 | + * @param productId 产品编号 | |
| 23 | + */ | |
| 24 | + void createSuperTable(Long productId); | |
| 25 | + | |
| 18 | 26 | } |
| 19 | 27 | \ No newline at end of file | ... | ... |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotThinkModelMessageServiceImpl.java
| ... | ... | @@ -7,19 +7,20 @@ import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore; |
| 7 | 7 | import cn.iocoder.yudao.module.iot.controller.admin.device.vo.device.IotDeviceStatusUpdateReqVO; |
| 8 | 8 | import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; |
| 9 | 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.ThinkModelMessage; | |
| 10 | +import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO; | |
| 11 | +import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.*; | |
| 14 | 12 | import cn.iocoder.yudao.module.iot.dal.dataobject.thinkmodel.IotProductThinkModelDO; |
| 15 | 13 | import cn.iocoder.yudao.module.iot.dal.redis.deviceData.DeviceDataRedisDAO; |
| 16 | 14 | import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineDDLMapper; |
| 17 | 15 | import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineDMLMapper; |
| 16 | +import cn.iocoder.yudao.module.iot.dal.tdengine.TdThinkModelMessageMapper; | |
| 18 | 17 | import cn.iocoder.yudao.module.iot.enums.IotConstants; |
| 19 | 18 | import cn.iocoder.yudao.module.iot.enums.device.IotDeviceStatusEnum; |
| 20 | 19 | import cn.iocoder.yudao.module.iot.enums.thinkmodel.IotProductThinkModelTypeEnum; |
| 21 | 20 | import cn.iocoder.yudao.module.iot.service.device.IotDeviceService; |
| 21 | +import cn.iocoder.yudao.module.iot.service.product.IotProductService; | |
| 22 | 22 | import cn.iocoder.yudao.module.iot.service.thinkmodel.IotProductThinkModelService; |
| 23 | +import cn.iocoder.yudao.module.iot.util.IotTdDatabaseUtils; | |
| 23 | 24 | import jakarta.annotation.Resource; |
| 24 | 25 | import lombok.extern.slf4j.Slf4j; |
| 25 | 26 | import org.springframework.beans.factory.annotation.Value; |
| ... | ... | @@ -54,19 +55,29 @@ public class IotThinkModelMessageServiceImpl implements IotThinkModelMessageServ |
| 54 | 55 | private TdEngineDDLMapper tdEngineDDLMapper; |
| 55 | 56 | @Resource |
| 56 | 57 | private TdEngineDMLMapper tdEngineDMLMapper; |
| 57 | - | |
| 58 | + @Resource | |
| 59 | + private IotProductService productService; | |
| 58 | 60 | @Resource |
| 59 | 61 | private DeviceDataRedisDAO deviceDataRedisDAO; |
| 60 | 62 | |
| 63 | + @Resource | |
| 64 | + private IotTdDatabaseUtils iotTdDatabaseUtils; | |
| 65 | + | |
| 66 | + @Resource | |
| 67 | + private TdThinkModelMessageMapper tdThinkModelMessageMapper; | |
| 68 | + | |
| 61 | 69 | // TODO @haohao:这个方法,可以考虑加下 1. 2. 3. 更有层次感 |
| 62 | 70 | @Override |
| 63 | 71 | @TenantIgnore |
| 64 | 72 | public void saveThinkModelMessage(IotDeviceDO device, ThinkModelMessage thingModelMessage) { |
| 65 | 73 | // 1. 判断设备状态,如果为未激活状态,创建数据表并更新设备状态 |
| 66 | 74 | if (IotDeviceStatusEnum.INACTIVE.getStatus().equals(device.getStatus())) { |
| 75 | + // 1.1 创建设备表 | |
| 67 | 76 | createDeviceTable(device.getDeviceType(), device.getProductKey(), device.getDeviceName(), device.getDeviceKey()); |
| 68 | 77 | iotDeviceService.updateDeviceStatus(new IotDeviceStatusUpdateReqVO() |
| 69 | 78 | .setId(device.getId()).setStatus(IotDeviceStatusEnum.ONLINE.getStatus())); |
| 79 | + // 1.2 创建物模型日志设备表 | |
| 80 | + createThinkModelMessageDeviceTable(device.getProductKey(), device.getDeviceName(), device.getDeviceKey()); | |
| 70 | 81 | } |
| 71 | 82 | |
| 72 | 83 | // 2. 获取设备属性并进行物模型校验,过滤非物模型属性 |
| ... | ... | @@ -90,6 +101,22 @@ public class IotThinkModelMessageServiceImpl implements IotThinkModelMessageServ |
| 90 | 101 | .build()); |
| 91 | 102 | } |
| 92 | 103 | |
| 104 | + @Override | |
| 105 | + @TenantIgnore | |
| 106 | + public void createSuperTable(Long productId) { | |
| 107 | + // 1. 查询产品 | |
| 108 | + IotProductDO product = productService.getProduct(productId); | |
| 109 | + | |
| 110 | + // 2. 获取超级表的名称和数据库名称 | |
| 111 | + String databaseName = iotTdDatabaseUtils.getDatabaseName(); | |
| 112 | + String superTableName = IotTdDatabaseUtils.getThinkModelMessageSuperTableName(product.getProductKey()); | |
| 113 | + | |
| 114 | + // 3. 创建超级表 | |
| 115 | + tdThinkModelMessageMapper.createSuperTable(ThinkModelMessageDO.builder().build() | |
| 116 | + .setDataBaseName(databaseName) | |
| 117 | + .setSuperTableName(superTableName)); | |
| 118 | + } | |
| 119 | + | |
| 93 | 120 | private List<IotProductThinkModelDO> getValidFunctionList(String productKey) { |
| 94 | 121 | return iotProductThinkModelService |
| 95 | 122 | .getProductThinkModelListByProductKey(productKey) |
| ... | ... | @@ -189,6 +216,30 @@ public class IotThinkModelMessageServiceImpl implements IotThinkModelMessageServ |
| 189 | 216 | } |
| 190 | 217 | |
| 191 | 218 | /** |
| 219 | + * 创建物模型日志设备数据表 | |
| 220 | + * | |
| 221 | + * @param productKey 产品 Key | |
| 222 | + * @param deviceName 设备名称 | |
| 223 | + * @param deviceKey 设备 Key | |
| 224 | + * | |
| 225 | + */ | |
| 226 | + private void createThinkModelMessageDeviceTable(String productKey, String deviceName, String deviceKey){ | |
| 227 | + | |
| 228 | + // 1. 获取超级表的名称、数据库名称、设备日志表名称 | |
| 229 | + String databaseName = iotTdDatabaseUtils.getDatabaseName(); | |
| 230 | + String superTableName = IotTdDatabaseUtils.getThinkModelMessageSuperTableName(productKey); | |
| 231 | + String thinkModelMessageDeviceTableName = IotTdDatabaseUtils.getThinkModelMessageDeviceTableName(productKey, deviceName); | |
| 232 | + | |
| 233 | + // 2. 创建物模型日志设备数据表 | |
| 234 | + tdThinkModelMessageMapper.createTableWithTag(ThinkModelMessageDO.builder().build() | |
| 235 | + .setDataBaseName(databaseName) | |
| 236 | + .setSuperTableName(superTableName) | |
| 237 | + .setTableName(thinkModelMessageDeviceTableName) | |
| 238 | + .setDeviceKey(deviceKey)); | |
| 239 | + | |
| 240 | + } | |
| 241 | + | |
| 242 | + /** | |
| 192 | 243 | * 获取数据库名称 |
| 193 | 244 | * |
| 194 | 245 | * @return 数据库名称 | ... | ... |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/util/IotTdDatabaseUtils.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.iot.util; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.module.iot.enums.IotConstants; | |
| 4 | +import org.springframework.beans.factory.annotation.Value; | |
| 5 | +import org.springframework.stereotype.Component; | |
| 6 | + | |
| 7 | +/** | |
| 8 | + * TD数据库工具类 | |
| 9 | + * | |
| 10 | + * @author AlwaysSuper | |
| 11 | + */ | |
| 12 | +@Component | |
| 13 | +public class IotTdDatabaseUtils { | |
| 14 | + | |
| 15 | + @Value("${spring.datasource.dynamic.datasource.tdengine.url}") | |
| 16 | + private String url; | |
| 17 | + | |
| 18 | + /** | |
| 19 | + * 获取数据库名称 | |
| 20 | + */ | |
| 21 | + public String getDatabaseName() { | |
| 22 | + int index = url.lastIndexOf("/"); | |
| 23 | + return index != -1 ? url.substring(index + 1) : url; | |
| 24 | + } | |
| 25 | + | |
| 26 | + /** | |
| 27 | + * 获取产品超级表表名 | |
| 28 | + * | |
| 29 | + * @param deviceType 设备类型 | |
| 30 | + * @param productKey 产品 Key | |
| 31 | + * @return 产品超级表表名 | |
| 32 | + */ | |
| 33 | + public static String getProductSuperTableName(Integer deviceType, String productKey) { | |
| 34 | + return switch (deviceType) { | |
| 35 | + case 1 -> String.format(IotConstants.GATEWAY_SUB_STABLE_NAME_FORMAT, productKey).toLowerCase(); | |
| 36 | + case 2 -> String.format(IotConstants.GATEWAY_STABLE_NAME_FORMAT, productKey).toLowerCase(); | |
| 37 | + default -> String.format(IotConstants.DEVICE_STABLE_NAME_FORMAT, productKey).toLowerCase(); | |
| 38 | + }; | |
| 39 | + } | |
| 40 | + | |
| 41 | + /** | |
| 42 | + * 获取物模型日志超级表表名 | |
| 43 | + * | |
| 44 | + * @param productKey 产品 Key | |
| 45 | + * @return 物模型日志超级表表名 | |
| 46 | + * | |
| 47 | + */ | |
| 48 | + public static String getThinkModelMessageSuperTableName(String productKey) { | |
| 49 | + return String.format("thing_model_message_", productKey).toLowerCase(); | |
| 50 | + } | |
| 51 | + | |
| 52 | + /** | |
| 53 | + * 获取物模型日志设备表名 | |
| 54 | + * | |
| 55 | + * @param productKey 产品 Key | |
| 56 | + * @param deviceName 设备名称 | |
| 57 | + * @return 物模型日志设备表名 | |
| 58 | + */ | |
| 59 | + public static String getThinkModelMessageDeviceTableName(String productKey, String deviceName) { | |
| 60 | + return String.format(IotConstants.THINK_MODEL_MESSAGE_TABLE_NAME_FORMAT, productKey.toLowerCase(), deviceName.toLowerCase()); | |
| 61 | + } | |
| 62 | + | |
| 63 | +} | ... | ... |
yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdThinkModelMessageMapper.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.TdThinkModelMessageMapper"> | |
| 6 | + | |
| 7 | + | |
| 8 | + <!-- 创建物模型消息日志超级表 --> | |
| 9 | + <update id="createSuperTable"> | |
| 10 | + CREATE STABLE ${dataBaseName}.${superTableName}( | |
| 11 | + ts TIMESTAMP, | |
| 12 | + id VARCHAR(255), | |
| 13 | + sys VARCHAR(2048), | |
| 14 | + method VARCHAR(255), | |
| 15 | + params VARCHAR(2048) | |
| 16 | + )TAGS ( | |
| 17 | + deviceKey VARCHAR(255) | |
| 18 | + ) | |
| 19 | + </update> | |
| 20 | + | |
| 21 | + <!-- 创建物模型消息日志子表,带有deviceKey的TAG --> | |
| 22 | + <update id="createTableWithTag"> | |
| 23 | + CREATE TABLE IF NOT EXISTS ${dataBaseName}.${tableName} | |
| 24 | + USING ${dataBaseName}.${superTableName}( | |
| 25 | + ts, | |
| 26 | + id , | |
| 27 | + sys , | |
| 28 | + method , | |
| 29 | + params | |
| 30 | + )TAGS( | |
| 31 | + #{deviceKey} | |
| 32 | + ) | |
| 33 | + </update> | |
| 34 | +</mapper> | |
| 0 | 35 | \ No newline at end of file | ... | ... |