Commit 8ff09fea018acc63b107430fe4a5c7ca1ffbed5c

Authored by alwayssuper
1 parent b2434b7b

[代码优化]:物模型日志评审优化

yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/ErrorCodeConstants.java
@@ -14,6 +14,7 @@ public interface ErrorCodeConstants { @@ -14,6 +14,7 @@ public interface ErrorCodeConstants {
14 ErrorCode PRODUCT_KEY_EXISTS = new ErrorCode(1_050_001_001, "产品标识已经存在"); 14 ErrorCode PRODUCT_KEY_EXISTS = new ErrorCode(1_050_001_001, "产品标识已经存在");
15 ErrorCode PRODUCT_STATUS_NOT_DELETE = new ErrorCode(1_050_001_002, "产品状是发布状态,不允许删除"); 15 ErrorCode PRODUCT_STATUS_NOT_DELETE = new ErrorCode(1_050_001_002, "产品状是发布状态,不允许删除");
16 ErrorCode PRODUCT_STATUS_NOT_ALLOW_THING_MODEL = new ErrorCode(1_050_001_003, "产品状是发布状态,不允许操作物模型"); 16 ErrorCode PRODUCT_STATUS_NOT_ALLOW_THING_MODEL = new ErrorCode(1_050_001_003, "产品状是发布状态,不允许操作物模型");
  17 + ErrorCode PRODUCT_DEVICE_NOT_EXISTS = new ErrorCode(1_050_001_004, "产品设备类型不存在");
17 18
18 // ========== 产品物模型 1-050-002-000 ============ 19 // ========== 产品物模型 1-050-002-000 ============
19 ErrorCode THING_MODEL_NOT_EXISTS = new ErrorCode(1_050_002_000, "产品物模型不存在"); 20 ErrorCode THING_MODEL_NOT_EXISTS = new ErrorCode(1_050_002_000, "产品物模型不存在");
yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/product/IotProductDeviceTypeEnum.java
@@ -16,7 +16,7 @@ import java.util.Arrays; @@ -16,7 +16,7 @@ import java.util.Arrays;
16 public enum IotProductDeviceTypeEnum implements IntArrayValuable { 16 public enum IotProductDeviceTypeEnum implements IntArrayValuable {
17 17
18 DIRECT(0, "直连设备"), 18 DIRECT(0, "直连设备"),
19 - GATEWAY_CHILD(1, "网关子设备"), 19 + GATEWAY_SUB(1, "网关子设备"),
20 GATEWAY(2, "网关设备"); 20 GATEWAY(2, "网关设备");
21 21
22 /** 22 /**
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdThinkModelMessageMapper.java renamed to yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdThingModelMessageMapper.java
@@ -10,7 +10,7 @@ import org.apache.ibatis.annotations.Mapper; @@ -10,7 +10,7 @@ import org.apache.ibatis.annotations.Mapper;
10 */ 10 */
11 @Mapper 11 @Mapper
12 @DS("tdengine") 12 @DS("tdengine")
13 -public interface TdThinkModelMessageMapper { 13 +public interface TdThingModelMessageMapper {
14 14
15 /** 15 /**
16 * 创建物模型消息日志超级表超级表 16 * 创建物模型消息日志超级表超级表
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/mq/consumer/simulatesend/SimulateSendConsumer.java 0 → 100644
  1 +package cn.iocoder.yudao.module.iot.mq.consumer.simulatesend;
  2 +
  3 +/**
  4 + * @author alwayssuper
  5 + * @date 2024/12/20 8:04
  6 + */
  7 +public class SimulateSendConsumer {
  8 +}
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotThingModelMessageServiceImpl.java
@@ -13,11 +13,9 @@ import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO; @@ -13,11 +13,9 @@ import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO;
13 import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.ThingModelMessage; 13 import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.ThingModelMessage;
14 import cn.iocoder.yudao.module.iot.dal.dataobject.thingmodel.IotProductThingModelDO; 14 import cn.iocoder.yudao.module.iot.dal.dataobject.thingmodel.IotProductThingModelDO;
15 import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO; 15 import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO;
16 -import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.*;  
17 import cn.iocoder.yudao.module.iot.dal.redis.deviceData.DeviceDataRedisDAO; 16 import cn.iocoder.yudao.module.iot.dal.redis.deviceData.DeviceDataRedisDAO;
18 import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineDDLMapper; 17 import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineDDLMapper;
19 import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineDMLMapper; 18 import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineDMLMapper;
20 -import cn.iocoder.yudao.module.iot.dal.tdengine.TdThinkModelMessageMapper;  
21 import cn.iocoder.yudao.module.iot.enums.IotConstants; 19 import cn.iocoder.yudao.module.iot.enums.IotConstants;
22 import cn.iocoder.yudao.module.iot.enums.device.IotDeviceStatusEnum; 20 import cn.iocoder.yudao.module.iot.enums.device.IotDeviceStatusEnum;
23 import cn.iocoder.yudao.module.iot.enums.thingmodel.IotProductThingModelTypeEnum; 21 import cn.iocoder.yudao.module.iot.enums.thingmodel.IotProductThingModelTypeEnum;
@@ -68,11 +66,6 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ @@ -68,11 +66,6 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ
68 @Resource 66 @Resource
69 private DeviceDataRedisDAO deviceDataRedisDAO; 67 private DeviceDataRedisDAO deviceDataRedisDAO;
70 68
71 - @Resource  
72 - private IotTdDatabaseUtils iotTdDatabaseUtils;  
73 -  
74 - @Resource  
75 - private TdThinkModelMessageMapper tdThinkModelMessageMapper;  
76 69
77 // TODO @haohao:这个方法,可以考虑加下 1. 2. 3. 更有层次感 70 // TODO @haohao:这个方法,可以考虑加下 1. 2. 3. 更有层次感
78 @Override 71 @Override
@@ -85,7 +78,7 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ @@ -85,7 +78,7 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ
85 iotDeviceService.updateDeviceStatus(new IotDeviceStatusUpdateReqVO() 78 iotDeviceService.updateDeviceStatus(new IotDeviceStatusUpdateReqVO()
86 .setId(device.getId()).setStatus(IotDeviceStatusEnum.ONLINE.getStatus())); 79 .setId(device.getId()).setStatus(IotDeviceStatusEnum.ONLINE.getStatus()));
87 // 1.2 创建物模型日志设备表 80 // 1.2 创建物模型日志设备表
88 - createThinkModelMessageDeviceTable(device.getProductKey(), device.getDeviceName(), device.getDeviceKey()); 81 + createThingModelMessageDeviceTable(device.getProductKey(), device.getDeviceName(), device.getDeviceKey());
89 } 82 }
90 83
91 // 2. 获取设备属性并进行物模型校验,过滤非物模型属性 84 // 2. 获取设备属性并进行物模型校验,过滤非物模型属性
@@ -122,13 +115,23 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ @@ -122,13 +115,23 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ
122 115
123 // 2. 获取超级表的名称和数据库名称 116 // 2. 获取超级表的名称和数据库名称
124 // TODO @alwayssuper:最好 databaseName、superTableName 的处理,放到 tdThinkModelMessageMapper 里。可以考虑,弄个 default 方法 117 // TODO @alwayssuper:最好 databaseName、superTableName 的处理,放到 tdThinkModelMessageMapper 里。可以考虑,弄个 default 方法
125 - String databaseName = iotTdDatabaseUtils.getDatabaseName(); 118 + String databaseName = IotTdDatabaseUtils.getDatabaseName(url);
126 String superTableName = IotTdDatabaseUtils.getThingModelMessageSuperTableName(product.getProductKey()); 119 String superTableName = IotTdDatabaseUtils.getThingModelMessageSuperTableName(product.getProductKey());
127 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 + );
128 // 3. 创建超级表 133 // 3. 创建超级表
129 - tdThinkModelMessageMapper.createSuperTable(ThingModelMessageDO.builder().build()  
130 - .setDataBaseName(databaseName)  
131 - .setSuperTableName(superTableName)); 134 + tdEngineDDLMapper.createSuperTable(new TdTableDO(databaseName, superTableName, schemaFields, tagsFields));
132 } 135 }
133 136
134 private List<IotProductThingModelDO> getValidFunctionList(String productKey) { 137 private List<IotProductThingModelDO> getValidFunctionList(String productKey) {
@@ -237,20 +240,20 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ @@ -237,20 +240,20 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ
237 * @param deviceKey 设备 Key 240 * @param deviceKey 设备 Key
238 * 241 *
239 */ 242 */
240 - private void createThinkModelMessageDeviceTable(String productKey, String deviceName, String deviceKey){ 243 + private void createThingModelMessageDeviceTable(String productKey, String deviceName, String deviceKey){
241 244
242 // 1. 获取超级表的名称、数据库名称、设备日志表名称 245 // 1. 获取超级表的名称、数据库名称、设备日志表名称
243 - String databaseName = iotTdDatabaseUtils.getDatabaseName(); 246 + String databaseName = IotTdDatabaseUtils.getDatabaseName(url);
244 String superTableName = IotTdDatabaseUtils.getThingModelMessageSuperTableName(productKey); 247 String superTableName = IotTdDatabaseUtils.getThingModelMessageSuperTableName(productKey);
245 // TODO @alwayssuper:最好 databaseName、superTableName、thinkModelMessageDeviceTableName 的处理,放到 tdThinkModelMessageMapper 里。可以考虑,弄个 default 方法 248 // TODO @alwayssuper:最好 databaseName、superTableName、thinkModelMessageDeviceTableName 的处理,放到 tdThinkModelMessageMapper 里。可以考虑,弄个 default 方法
246 - String thinkModelMessageDeviceTableName = IotTdDatabaseUtils.getThinkModelMessageDeviceTableName(productKey, deviceName); 249 + String thinkModelMessageDeviceTableName = IotTdDatabaseUtils.getThingModelMessageDeviceTableName(productKey, deviceName);
247 250
248 // 2. 创建物模型日志设备数据表 251 // 2. 创建物模型日志设备数据表
249 - tdThinkModelMessageMapper.createTableWithTag(ThingModelMessageDO.builder().build()  
250 - .setDataBaseName(databaseName)  
251 - .setSuperTableName(superTableName)  
252 - .setTableName(thinkModelMessageDeviceTableName)  
253 - .setDeviceKey(deviceKey)); 252 +// tdThingModelMessageMapper.createTableWithTag(ThingModelMessageDO.builder().build()
  253 +// .setDataBaseName(databaseName)
  254 +// .setSuperTableName(superTableName)
  255 +// .setTableName(thinkModelMessageDeviceTableName)
  256 +// .setDeviceKey(deviceKey));
254 } 257 }
255 258
256 /** 259 /**
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/util/IotTdDatabaseUtils.java
1 package cn.iocoder.yudao.module.iot.util; 1 package cn.iocoder.yudao.module.iot.util;
2 2
  3 +import cn.hutool.core.util.StrUtil;
3 import cn.iocoder.yudao.module.iot.enums.IotConstants; 4 import cn.iocoder.yudao.module.iot.enums.IotConstants;
  5 +import cn.iocoder.yudao.module.iot.enums.product.IotProductDeviceTypeEnum;
4 import org.springframework.beans.factory.annotation.Value; 6 import org.springframework.beans.factory.annotation.Value;
5 import org.springframework.stereotype.Component; 7 import org.springframework.stereotype.Component;
6 8
  9 +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
  10 +import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.PRODUCT_DEVICE_NOT_EXISTS;
  11 +
7 // TODO @芋艿:可能要思索下,有没更好的处理方式 12 // TODO @芋艿:可能要思索下,有没更好的处理方式
8 // TODO @芋艿:怎么改成无状态 13 // TODO @芋艿:怎么改成无状态
9 /** 14 /**
@@ -11,19 +16,14 @@ import org.springframework.stereotype.Component; @@ -11,19 +16,14 @@ import org.springframework.stereotype.Component;
11 * 16 *
12 * @author AlwaysSuper 17 * @author AlwaysSuper
13 */ 18 */
14 -@Component  
15 public class IotTdDatabaseUtils { 19 public class IotTdDatabaseUtils {
16 20
17 - @Value("${spring.datasource.dynamic.datasource.tdengine.url}")  
18 - private String url;  
19 -  
20 /** 21 /**
21 * 获取数据库名称 22 * 获取数据库名称
22 */ 23 */
23 - public String getDatabaseName() { 24 + public static String getDatabaseName(String url) {
24 // TODO @alwayssuper:StrUtil.subAfter("/") 25 // TODO @alwayssuper:StrUtil.subAfter("/")
25 - int index = url.lastIndexOf("/");  
26 - return index != -1 ? url.substring(index + 1) : url; 26 + return StrUtil.subAfter(url, "/", true);
27 } 27 }
28 28
29 /** 29 /**
@@ -35,11 +35,19 @@ public class IotTdDatabaseUtils { @@ -35,11 +35,19 @@ public class IotTdDatabaseUtils {
35 */ 35 */
36 public static String getProductSuperTableName(Integer deviceType, String productKey) { 36 public static String getProductSuperTableName(Integer deviceType, String productKey) {
37 // TODO @alwayssuper:枚举字段,不要 1、2、3;不符合预期,抛出异常 37 // TODO @alwayssuper:枚举字段,不要 1、2、3;不符合预期,抛出异常
38 - return switch (deviceType) {  
39 - case 1 -> String.format(IotConstants.GATEWAY_SUB_STABLE_NAME_FORMAT, productKey).toLowerCase();  
40 - case 2 -> String.format(IotConstants.GATEWAY_STABLE_NAME_FORMAT, productKey).toLowerCase();  
41 - default -> String.format(IotConstants.DEVICE_STABLE_NAME_FORMAT, productKey).toLowerCase();  
42 - }; 38 + if (deviceType == null) {
  39 + throw exception(PRODUCT_DEVICE_NOT_EXISTS);
  40 + }
  41 + if (IotProductDeviceTypeEnum.GATEWAY_SUB.getType().equals(deviceType)) {
  42 + return String.format(IotConstants.GATEWAY_SUB_STABLE_NAME_FORMAT, productKey).toLowerCase();
  43 + } else if (IotProductDeviceTypeEnum.GATEWAY.getType().equals(deviceType)) {
  44 + return String.format(IotConstants.GATEWAY_STABLE_NAME_FORMAT, productKey).toLowerCase();
  45 + } else if (IotProductDeviceTypeEnum.DIRECT.getType().equals(deviceType)){
  46 + return String.format(IotConstants.DEVICE_STABLE_NAME_FORMAT, productKey).toLowerCase();
  47 + }
  48 + else{
  49 + throw exception(PRODUCT_DEVICE_NOT_EXISTS);
  50 + }
43 } 51 }
44 52
45 /** 53 /**
@@ -51,7 +59,7 @@ public class IotTdDatabaseUtils { @@ -51,7 +59,7 @@ public class IotTdDatabaseUtils {
51 */ 59 */
52 public static String getThingModelMessageSuperTableName(String productKey) { 60 public static String getThingModelMessageSuperTableName(String productKey) {
53 // TODO @alwayssuper:是不是应该 + 拼接就好,不用 format 61 // TODO @alwayssuper:是不是应该 + 拼接就好,不用 format
54 - return String.format("thing_model_message_", productKey).toLowerCase(); 62 + return "thing_model_message_" + productKey.toLowerCase();
55 } 63 }
56 64
57 /** 65 /**
@@ -61,7 +69,7 @@ public class IotTdDatabaseUtils { @@ -61,7 +69,7 @@ public class IotTdDatabaseUtils {
61 * @param deviceName 设备名称 69 * @param deviceName 设备名称
62 * @return 物模型日志设备表名 70 * @return 物模型日志设备表名
63 */ 71 */
64 - public static String getThinkModelMessageDeviceTableName(String productKey, String deviceName) { 72 + public static String getThingModelMessageDeviceTableName(String productKey, String deviceName) {
65 return String.format(IotConstants.THING_MODEL_MESSAGE_TABLE_NAME_FORMAT, productKey.toLowerCase(), deviceName.toLowerCase()); 73 return String.format(IotConstants.THING_MODEL_MESSAGE_TABLE_NAME_FORMAT, productKey.toLowerCase(), deviceName.toLowerCase());
66 } 74 }
67 75
yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdThinkModelMessageMapper.xml
@@ -2,7 +2,7 @@ @@ -2,7 +2,7 @@
2 <!DOCTYPE mapper 2 <!DOCTYPE mapper
3 PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 3 PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
4 "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> 4 "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
5 -<mapper namespace="cn.iocoder.yudao.module.iot.dal.tdengine.TdThinkModelMessageMapper"> 5 +<mapper namespace="cn.iocoder.yudao.module.iot.dal.tdengine.TdThingModelMessageMapper">
6 6
7 <!-- 创建物模型消息日志超级表 --> 7 <!-- 创建物模型消息日志超级表 -->
8 <!-- TODO @芋艿:捉摸下字段,特别是 sys、ts 这种缩写 --> 8 <!-- TODO @芋艿:捉摸下字段,特别是 sys、ts 这种缩写 -->
@@ -14,7 +14,7 @@ @@ -14,7 +14,7 @@
14 method VARCHAR(255), 14 method VARCHAR(255),
15 params VARCHAR(2048) 15 params VARCHAR(2048)
16 )TAGS ( 16 )TAGS (
17 - deviceKey VARCHAR(255) 17 + device_key VARCHAR(255)
18 ) 18 )
19 </update> 19 </update>
20 20
@@ -28,7 +28,7 @@ @@ -28,7 +28,7 @@
28 method , 28 method ,
29 params 29 params
30 )TAGS( 30 )TAGS(
31 - #{deviceKey} 31 + #{device_key}
32 ) 32 )
33 </update> 33 </update>
34 </mapper> 34 </mapper>
35 \ No newline at end of file 35 \ No newline at end of file