Ver Fonte

【代码评审】IoT:tdengine 封装的 review

YunaiV há 9 meses atrás
pai
commit
9b30d5d355
21 ficheiros alterados com 43 adições e 19 exclusões
  1. 2 0
      yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/IotDeviceDataController.java
  2. 1 0
      yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/deviceData/IotDeviceDataReqVO.java
  3. 1 0
      yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/device/IotDeviceDataDO.java
  4. 4 0
      yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/SelectDO.java
  5. 1 0
      yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/SelectVisualDO.java
  6. 1 0
      yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TableManager.java
  7. 1 0
      yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TdRestApi.java
  8. 1 0
      yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TdTableDO.java
  9. 1 0
      yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/device/IotDeviceMapper.java
  10. 3 2
      yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/thinkmodelfunction/IotThinkModelFunctionMapper.java
  11. 1 0
      yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineDatabaseMapper.java
  12. 1 0
      yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineQueryMapper.java
  13. 2 0
      yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/emq/service/EmqxServiceImpl.java
  14. 1 0
      yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataServiceImpl.java
  15. 10 11
      yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceServiceImpl.java
  16. 12 1
      yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotThingModelMessageServiceImpl.java
  17. 0 1
      yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineDataWriterMapper.xml
  18. 0 1
      yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineDatabaseMapper.xml
  19. 0 1
      yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineQueryMapper.xml
  20. 0 1
      yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineSuperTableMapper.xml
  21. 0 1
      yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineTableMapper.xml

+ 2 - 0
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/IotDeviceDataController.java

@@ -31,6 +31,7 @@ public class IotDeviceDataController {
     @Resource
     private IotDeviceDataService deviceDataService;
 
+    // TODO @haohao:是不是叫 get-latest 就好了。因为 data 已经在 url 里了哈
     @GetMapping("/latest-data")
     @Operation(summary = "获取设备属性最新数据")
     public CommonResult<List<IotDeviceDataRespVO>> getDevicePropertiesLatestData(@Valid IotDeviceDataReqVO deviceDataReqVO) {
@@ -38,6 +39,7 @@ public class IotDeviceDataController {
         return success(BeanUtils.toBean(list, IotDeviceDataRespVO.class));
     }
 
+    // TODO @haohao:是不是叫 /history-data => page
     @GetMapping("/history-data")
     @Operation(summary = "获取设备属性历史数据")
     public CommonResult<PageResult<IotTimeDataRespVO>> getDevicePropertiesHistoryData(@Valid IotDeviceDataReqVO deviceDataReqVO) {

+ 1 - 0
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/deviceData/IotDeviceDataReqVO.java

@@ -10,6 +10,7 @@ import java.time.LocalDateTime;
 
 import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
 
+// TODO @haohao:IotDeviceDataPageReqVO
 @Schema(description = "管理后台 - IoT 设备数据 Request VO")
 @Data
 public class IotDeviceDataReqVO extends PageParam {

+ 1 - 0
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/device/IotDeviceDataDO.java

@@ -23,6 +23,7 @@ import java.time.LocalDateTime;
 @AllArgsConstructor
 public class IotDeviceDataDO {
 
+    // TODO @haohao:每个字段的关联关系,可以 @ 下哈。
     /**
      * 设备编号
      */

+ 4 - 0
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/SelectDO.java

@@ -3,12 +3,15 @@ package cn.iocoder.yudao.module.iot.dal.dataobject.tdengine;
 import lombok.Data;
 
 import java.util.Set;
+
+// TODO @haohao:类似这个,其实可以参考 mybatis plus,querywrapper,搞个 TdEngineQueryWrapper。这样看起来会更好懂。
 /**
  * 查询DO
  */
 @Data
 public class SelectDO {
 
+    // TODO @haoha:database 是个单词
     /**
      * 数据库名称
      */
@@ -39,6 +42,7 @@ public class SelectDO {
      */
     private String type;
 
+    // TODO @haohao:这个字段,是啥哈?
     /**
      * 查询条件
      */

+ 1 - 0
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/SelectVisualDO.java

@@ -4,6 +4,7 @@ import lombok.Data;
 
 import java.util.Map;
 
+// TODO @haohao:类似 SelectDO 的想法,只是它是返回。ps:貌似可以在 tdengine 里面,创建一个 query 包,放这种比较特殊的查询和结果对象。dataobject 更多还是实际存储的结构化的 do
 @Data
 public class SelectVisualDO {
 

+ 1 - 0
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TableManager.java

@@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.iot.dal.dataobject.tdengine;
 
 import java.util.List;
 
+// TODO @haohao:这个还有用哇?
 /**
  * TableManager 类用于管理 TDengine 表的创建、删除和结构信息获取
  */

+ 1 - 0
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TdRestApi.java

@@ -7,6 +7,7 @@ import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
 
+// TODO @haohao:有部分非实体的部分,是不是可以搞到 iot 的 framework 包下,搞个 tdengine 包,作为框架级的封装,放在 dataobject,感觉不是很合理哈。【可以微信讨论下】
 /**
  * TdRestApi 类用于处理 TDengine 的 REST API 请求
  */

+ 1 - 0
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TdTableDO.java

@@ -21,6 +21,7 @@ public class TdTableDO {
      */
     private String dataBaseName;
 
+    // TODO @haohao:superTableName 和 tableName 是不是合并。因为每个 mapper 操作的时候,有且只会使用到其中一个。
     /**
      * 超级表名称
      */

+ 1 - 0
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/device/IotDeviceMapper.java

@@ -15,6 +15,7 @@ import org.apache.ibatis.annotations.Mapper;
 @Mapper
 public interface IotDeviceMapper extends BaseMapperX<IotDeviceDO> {
 
+    // TODO @haohao:可能多余的查询条件,要去掉哈
     default PageResult<IotDeviceDO> selectPage(IotDevicePageReqVO reqVO) {
         return selectPage(reqVO, new LambdaQueryWrapperX<IotDeviceDO>()
                 .eqIfPresent(IotDeviceDO::getDeviceKey, reqVO.getDeviceKey())

+ 3 - 2
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/thinkmodelfunction/IotThinkModelFunctionMapper.java

@@ -43,7 +43,7 @@ public interface IotThinkModelFunctionMapper extends BaseMapperX<IotThinkModelFu
 
     default List<IotThinkModelFunctionDO> selectListByProductIdAndIdentifiersAndTypes(Long productId,
                                                                                       List<String> identifiers,
-                                                                                      List<Integer> types){
+                                                                                      List<Integer> types) {
         return selectList(new LambdaQueryWrapperX<IotThinkModelFunctionDO>()
                 .eq(IotThinkModelFunctionDO::getProductId, productId)
                 .in(IotThinkModelFunctionDO::getIdentifier, identifiers)
@@ -55,7 +55,8 @@ public interface IotThinkModelFunctionMapper extends BaseMapperX<IotThinkModelFu
                 IotThinkModelFunctionDO::getName, name);
     }
 
-    default List<IotThinkModelFunctionDO> selectListByProductKey(String productKey){
+    default List<IotThinkModelFunctionDO> selectListByProductKey(String productKey) {
         return selectList(IotThinkModelFunctionDO::getProductKey, productKey);
     }
+
 }

+ 1 - 0
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineDatabaseMapper.java

@@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
 import org.apache.ibatis.annotations.Mapper;
 import org.apache.ibatis.annotations.Param;
 
+// TODO @haohao:InterceptorIgnore 忽略租户,可以在每个方法上,添加 @TenantIgnore 哈。
 /**
  * TD 引擎的数据库 Mapper
  */

+ 1 - 0
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineQueryMapper.java

@@ -25,6 +25,7 @@ public interface TdEngineQueryMapper {
      */
     List<Map<String, Object>> selectByTimestamp(SelectDO selectDO);
 
+    // TODO @haohao:最好方法的命名,和数据库操作的保持一直。get => select。然后 selectList or selectOne
     /**
      * 根据时间戳获取数据条数
      *

+ 2 - 0
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/emq/service/EmqxServiceImpl.java

@@ -31,6 +31,7 @@ public class EmqxServiceImpl implements EmqxService {
         // 根据不同的主题,处理不同的业务逻辑
         if (topic.contains("/property/post")) {
             // 设备上报数据 topic /sys/f13f57c63e9/dianbiao1/thing/event/property/post
+            // TODO @hao:这块未来可能,搞个 IotTopicUrls 之类?把拼接和解析的逻辑,收敛
             String productKey = topic.split("/")[2];
             String deviceName = topic.split("/")[3];
             String message = new String(mqttMessage.getPayload());
@@ -48,4 +49,5 @@ public class EmqxServiceImpl implements EmqxService {
             log.error("订阅默认主题失败", e);
         }
     }
+
 }

+ 1 - 0
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataServiceImpl.java

@@ -133,4 +133,5 @@ public class IotDeviceDataServiceImpl implements IotDeviceDataService {
     private static String getDeviceTableName(String productKey, String deviceName) {
         return String.format("device_%s_%s", productKey.toLowerCase(), deviceName.toLowerCase());
     }
+
 }

+ 10 - 11
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceServiceImpl.java

@@ -213,31 +213,30 @@ public class IotDeviceServiceImpl implements IotDeviceService {
 
     @Override
     public void updateDeviceStatus(IotDeviceStatusUpdateReqVO updateReqVO) {
-        // 校验存在
+        // 1. 校验存在
+        // TODO @haohao:这里的 iotDeviceDO =>  device。一个是去掉 iot,一个是去掉 DO 后缀。这样,简洁一点。
         IotDeviceDO iotDeviceDO = validateDeviceExists(updateReqVO.getId());
 
-        // 更新状态和更新时间
+        // 2.1 更新状态和更新时间
         IotDeviceDO updateObj = BeanUtils.toBean(updateReqVO, IotDeviceDO.class);
-
-        // 以前是未激活,现在是上线,设置设备激活时间
+        // TODO @haohao:下面几个状态的处理,可以考虑 if else if。这样,看起来会有层次感哈
+        // 2.2.1 以前是未激活,现在是上线,设置设备激活时间
+        // TODO @haohao:这里可以使用 ObjectUtils.equalsAny 类似这种哈。
         if (Objects.equals(iotDeviceDO.getStatus(), IotDeviceStatusEnum.INACTIVE.getStatus())
                 && Objects.equals(updateObj.getStatus(), IotDeviceStatusEnum.ONLINE.getStatus())) {
             updateObj.setActiveTime(LocalDateTime.now());
         }
-
-        // 如果是上线,设置上线时间
+        // 2.2.2 如果是上线,设置上线时间
         if (Objects.equals(updateObj.getStatus(), IotDeviceStatusEnum.ONLINE.getStatus())) {
             updateObj.setLastOnlineTime(LocalDateTime.now());
         }
-
-        // 如果是离线,设置离线时间
+        // 2.2.3 如果是离线,设置离线时间
         if (Objects.equals(updateObj.getStatus(), IotDeviceStatusEnum.OFFLINE.getStatus())) {
             updateObj.setLastOfflineTime(LocalDateTime.now());
         }
-
-        // 设置状态更新时间
+        // 2.3 设置状态更新时间
         updateObj.setStatusLastUpdateTime(LocalDateTime.now());
-
+        // 2.4 更新到数据库
         deviceMapper.updateById(updateObj);
     }
 

+ 12 - 1
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotThingModelMessageServiceImpl.java

@@ -47,6 +47,7 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ
     @Resource
     private DeviceDataRedisDAO deviceDataRedisDAO;
 
+    // TODO @haohao:这个方法,可以考虑加下 1. 2. 3. 更有层次感
     @Override
     @TenantIgnore
     public void saveThingModelMessage(IotDeviceDO device, ThingModelMessage thingModelMessage) {
@@ -55,12 +56,14 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ
             // 创建设备数据表
             createDeviceTable(device.getDeviceType(), device.getProductKey(), device.getDeviceName(), device.getDeviceKey());
             // 更新设备状态
+            // TODO @haohao:下面可以考虑,链式调用。iotDeviceService.updateDeviceStatus(new IotDeviceStatusUpdateReqVO().setid().setstatus())
             IotDeviceStatusUpdateReqVO updateReqVO = new IotDeviceStatusUpdateReqVO();
             updateReqVO.setId(device.getId());
             updateReqVO.setStatus(IotDeviceStatusEnum.ONLINE.getStatus());
             iotDeviceService.updateDeviceStatus(updateReqVO);
         }
 
+        // TODO @haohao:这个变量,可以和 “过滤并收集有效的属性字段” 那块,因为关联度高一点。
         // 获取设备属性
         Map<String, Object> params = thingModelMessage.dataToMap();
 
@@ -70,12 +73,12 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ
                 .stream()
                 .filter(function -> IotProductFunctionTypeEnum.PROPERTY.getType().equals(function.getType()))
                 .toList();
-
         if (functionList.isEmpty()) {
             return;
         }
 
         // 获取属性标识符集合
+        // TODO @haohao:这个变量,可以和 “过滤并收集有效的属性字段” 那块,因为关联度高一点。另外,可以使用 CollectionUtils。convertSet
         Set<String> propertyIdentifiers = functionList.stream()
                 .map(IotThinkModelFunctionDO::getIdentifier)
                 .collect(Collectors.toSet());
@@ -90,9 +93,11 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ
             if (propertyIdentifiers.contains(key)) {
                 schemaFieldValues.add(new TdFieldDO(key.toLowerCase(), val));
                 // 缓存设备属性
+                // TODO @haohao:这个缓存的写入,可以使用的时候 cache 么?被动读
                 setDeviceDataCache(device, functionMap.get(key), val, thingModelMessage.getTime());
             }
         });
+        // TODO @haohao:疑问,为什么 1 不继续哈?
         if (schemaFieldValues.size() == 1) {
             return;
         }
@@ -127,6 +132,7 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ
         deviceDataRedisDAO.set(deviceData);
     }
 
+    // TODO @haohao:实现没问题哈。这个方法的空行有点多,逻辑分块上没这么明显。看看能不能改下。
     /**
      * 创建设备数据表
      *
@@ -143,6 +149,8 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ
         List<TdFieldDO> tagsFieldValues = new ArrayList<>();
 
         if (maps != null) {
+            // TODO @haohao:一些字符串,是不是可以枚举起来哈。
+            // TODO @haohao:这种过滤的,常用的,可以考虑用 CollectionUtils.filterList。一些常用的 stream 操作,适合封装哈
             List<Map<String, Object>> taggedNotesList = maps.stream()
                     .filter(map -> "TAG".equals(map.get("note")))
                     .toList();
@@ -176,6 +184,7 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ
      * @return 数据库名称
      */
     private String getDatabaseName() {
+        // TODO @haohao:可以使用 StrUtil.subAftetLast 这种方法
         return url.substring(url.lastIndexOf("/") + 1);
     }
 
@@ -187,6 +196,7 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ
      * @return 产品属性表名
      */
     private static String getProductPropertySTableName(Integer deviceType, String productKey) {
+        // TODO @haohao:枚举下,会好点哈。
         return switch (deviceType) {
             case 1 -> String.format("gateway_sub_%s", productKey).toLowerCase();
             case 2 -> String.format("gateway_%s", productKey).toLowerCase();
@@ -204,4 +214,5 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ
     private static String getDeviceTableName(String productKey, String deviceName) {
         return String.format("device_%s_%s", productKey.toLowerCase(), deviceName.toLowerCase());
     }
+
 }

+ 0 - 1
yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineDataWriterMapper.xml

@@ -2,7 +2,6 @@
 <!DOCTYPE mapper
         PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
-
 <mapper namespace="cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineDataWriterMapper">
 
     <!-- 插入数据 -->

+ 0 - 1
yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineDatabaseMapper.xml

@@ -2,7 +2,6 @@
 <!DOCTYPE mapper
         PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
-
 <mapper namespace="cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineDatabaseMapper">
 
     <!-- 创建数据库 -->

+ 0 - 1
yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineQueryMapper.xml

@@ -2,7 +2,6 @@
 <!DOCTYPE mapper
         PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
-
 <mapper namespace="cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineQueryMapper">
 
     <!-- 根据时间戳查询数据 -->

+ 0 - 1
yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineSuperTableMapper.xml

@@ -2,7 +2,6 @@
 <!DOCTYPE mapper
         PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
-
 <mapper namespace="cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineSuperTableMapper">
 
     <!-- 创建超级表 -->

+ 0 - 1
yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineTableMapper.xml

@@ -2,7 +2,6 @@
 <!DOCTYPE mapper
         PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
-
 <mapper namespace="cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineTableMapper">
 
     <!-- 创建子表 -->