فهرست منبع

reactor:【IoT 物联网】调整物模型相关的时序表,通过 productId 和 deviceId 区分

YunaiV 5 ماه پیش
والد
کامیت
b37814ec9c

+ 0 - 6
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/data/IotDevicePropertyHistoryPageReqVO.java

@@ -20,12 +20,6 @@ public class IotDevicePropertyHistoryPageReqVO extends PageParam {
     @NotNull(message = "设备编号不能为空")
     private Long deviceId;
 
-    @Schema(description = "产品 Key", hidden = true)
-    private String productKey; // 非前端传递,后端自己查询设置
-
-    @Schema(description = "设备名称", hidden = true)
-    private String deviceName; // 非前端传递,后端自己查询设置
-
     @Schema(description = "属性标识符", requiredMode = Schema.RequiredMode.REQUIRED)
     @NotEmpty(message = "属性标识符不能为空")
     private String identifier;

+ 0 - 4
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/thingmodel/IotThingModelMapper.java

@@ -50,10 +50,6 @@ public interface IotThingModelMapper extends BaseMapperX<IotThingModelDO> {
         return selectList(IotThingModelDO::getProductId, productId);
     }
 
-    default List<IotThingModelDO> selectListByProductKey(String productKey) {
-        return selectList(IotThingModelDO::getProductKey, productKey);
-    }
-
     default List<IotThingModelDO> selectListByProductIdAndType(Long productId, Integer type) {
         return selectList(IotThingModelDO::getProductId, productId,
                 IotThingModelDO::getType, type);

+ 4 - 5
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/redis/RedisKeyConstants.java

@@ -9,15 +9,14 @@ import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDevicePropertyDO;
  */
 public interface RedisKeyConstants {
 
-    // TODO @芋艿:弱化 deviceKey;使用 product_key + device_name 替代
     /**
      * 设备属性的数据缓存,采用 HASH 结构
      * <p>
-     * KEY 格式:device_property:{deviceKey}
+     * KEY 格式:device_property:{deviceId}
      * HASH KEY:identifier 属性标识
      * VALUE 数据类型:String(JSON) {@link IotDevicePropertyDO}
      */
-    String DEVICE_PROPERTY = "iot:device_property:%s";
+    String DEVICE_PROPERTY = "iot:device_property:%d";
 
     /**
      * 设备的最后上报时间,采用 ZSET 结构
@@ -31,7 +30,7 @@ public interface RedisKeyConstants {
      * 设备关联的网关 serverId 缓存,采用 HASH 结构
      *
      * KEY 格式:device_server_id
-     * HASH KEY:{productKey},{deviceName}
+     * HASH KEY:{deviceId}
      * VALUE 数据类型:String serverId
      */
     String DEVICE_SERVER_ID = "iot:device_server_id";
@@ -56,7 +55,7 @@ public interface RedisKeyConstants {
     /**
      * 物模型的数据缓存,使用 Spring Cache 操作(忽略租户)
      *
-     * KEY 格式:thing_model_${productKey}
+     * KEY 格式:thing_model_${productId}
      * VALUE 数据类型:String 数组(JSON),即 {@link cn.iocoder.yudao.module.iot.dal.dataobject.thingmodel.IotThingModelDO} 列表
      */
     String THING_MODEL_LIST = "iot:thing_model_list";

+ 6 - 6
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/redis/device/DevicePropertyRedisDAO.java

@@ -22,8 +22,8 @@ public class DevicePropertyRedisDAO {
     @Resource
     private StringRedisTemplate stringRedisTemplate;
 
-    public Map<String, IotDevicePropertyDO> get(String productKey, String deviceName) {
-        String redisKey = formatKey(productKey, deviceName);
+    public Map<String, IotDevicePropertyDO> get(Long id) {
+        String redisKey = formatKey(id);
         Map<Object, Object> entries = stringRedisTemplate.opsForHash().entries(redisKey);
         if (CollUtil.isEmpty(entries)) {
             return Collections.emptyMap();
@@ -33,18 +33,18 @@ public class DevicePropertyRedisDAO {
                 entry -> JsonUtils.parseObject((String) entry.getValue(), IotDevicePropertyDO.class));
     }
 
-    public void putAll(String productKey, String deviceName, Map<String, IotDevicePropertyDO> properties) {
+    public void putAll(Long id, Map<String, IotDevicePropertyDO> properties) {
         if (CollUtil.isEmpty(properties)) {
             return;
         }
-        String redisKey = formatKey(productKey, deviceName);
+        String redisKey = formatKey(id);
         stringRedisTemplate.opsForHash().putAll(redisKey, convertMap(properties.entrySet(),
                 Map.Entry::getKey,
                 entry -> JsonUtils.toJsonString(entry.getValue())));
     }
 
-    private static String formatKey(String productKey, String deviceName) {
-        return String.format(DEVICE_PROPERTY, productKey, deviceName);
+    private static String formatKey(Long id) {
+        return String.format(DEVICE_PROPERTY, id);
     }
 
 }

+ 12 - 12
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/IotDevicePropertyMapper.java

@@ -23,17 +23,17 @@ import java.util.stream.Collectors;
 @InterceptorIgnore(tenantLine = "true") // 避免 SQL 解析,因为 JSqlParser 对 TDengine 的 SQL 解析会报错
 public interface IotDevicePropertyMapper {
 
-    List<TDengineTableField> getProductPropertySTableFieldList(@Param("productKey") String productKey);
+    List<TDengineTableField> getProductPropertySTableFieldList(@Param("productId") Long productId);
 
-    void createProductPropertySTable(@Param("productKey") String productKey,
+    void createProductPropertySTable(@Param("productId") Long productId,
                                      @Param("fields") List<TDengineTableField> fields);
 
     @SuppressWarnings("SimplifyStreamApiCallChains") // 保持 JDK8 兼容性
-    default void alterProductPropertySTable(String productKey,
+    default void alterProductPropertySTable(Long productId,
                                             List<TDengineTableField> oldFields,
                                             List<TDengineTableField> newFields) {
         oldFields.removeIf(field -> StrUtil.equalsAny(field.getField(),
-                TDengineTableField.FIELD_TS, "report_time", "device_name"));
+                TDengineTableField.FIELD_TS, "report_time"));
         List<TDengineTableField> addFields = newFields.stream().filter( // 新增的字段
                         newField -> oldFields.stream().noneMatch(oldField -> oldField.getField().equals(newField.getField())))
                 .collect(Collectors.toList());
@@ -62,22 +62,22 @@ public interface IotDevicePropertyMapper {
         });
 
         // 执行
-        addFields.forEach(field -> alterProductPropertySTableAddField(productKey, field));
-        dropFields.forEach(field -> alterProductPropertySTableDropField(productKey, field));
-        modifyLengthFields.forEach(field -> alterProductPropertySTableModifyField(productKey, field));
+        addFields.forEach(field -> alterProductPropertySTableAddField(productId, field));
+        dropFields.forEach(field -> alterProductPropertySTableDropField(productId, field));
+        modifyLengthFields.forEach(field -> alterProductPropertySTableModifyField(productId, field));
         modifyTypeFields.forEach(field -> {
-            alterProductPropertySTableDropField(productKey, field);
-            alterProductPropertySTableAddField(productKey, field);
+            alterProductPropertySTableDropField(productId, field);
+            alterProductPropertySTableAddField(productId, field);
         });
     }
 
-    void alterProductPropertySTableAddField(@Param("productKey") String productKey,
+    void alterProductPropertySTableAddField(@Param("productId") Long productId,
                                             @Param("field") TDengineTableField field);
 
-    void alterProductPropertySTableModifyField(@Param("productKey") String productKey,
+    void alterProductPropertySTableModifyField(@Param("productId") Long productId,
                                                @Param("field") TDengineTableField field);
 
-    void alterProductPropertySTableDropField(@Param("productKey") String productKey,
+    void alterProductPropertySTableDropField(@Param("productId") Long productId,
                                              @Param("field") TDengineTableField field);
 
     void insert(@Param("device") IotDeviceDO device,

+ 9 - 20
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/property/IotDevicePropertyServiceImpl.java

@@ -20,7 +20,6 @@ import cn.iocoder.yudao.module.iot.dal.tdengine.IotDevicePropertyMapper;
 import cn.iocoder.yudao.module.iot.enums.thingmodel.IotDataSpecsDataTypeEnum;
 import cn.iocoder.yudao.module.iot.enums.thingmodel.IotThingModelTypeEnum;
 import cn.iocoder.yudao.module.iot.framework.tdengine.core.TDengineTableField;
-import cn.iocoder.yudao.module.iot.service.device.IotDeviceService;
 import cn.iocoder.yudao.module.iot.service.product.IotProductService;
 import cn.iocoder.yudao.module.iot.service.thingmodel.IotThingModelService;
 import com.baomidou.mybatisplus.core.metadata.IPage;
@@ -59,8 +58,6 @@ public class IotDevicePropertyServiceImpl implements IotDevicePropertyService {
             .put(IotDataSpecsDataTypeEnum.ARRAY.getDataType(), TDengineTableField.TYPE_NCHAR) // TODO 芋艿:怎么映射!!!!
             .build();
 
-    @Resource
-    private IotDeviceService deviceService;
     @Resource
     private IotThingModelService thingModelService;
     @Resource
@@ -87,7 +84,7 @@ public class IotDevicePropertyServiceImpl implements IotDevicePropertyService {
         // 1.2 解析 DB 里的字段
         List<TDengineTableField> oldFields = new ArrayList<>();
         try {
-            oldFields.addAll(devicePropertyMapper.getProductPropertySTableFieldList(product.getProductKey()));
+            oldFields.addAll(devicePropertyMapper.getProductPropertySTableFieldList(product.getId()));
         } catch (Exception e) {
             if (!e.getMessage().contains("Table does not exist")) {
                 throw e;
@@ -101,11 +98,11 @@ public class IotDevicePropertyServiceImpl implements IotDevicePropertyService {
                 log.info("[defineDevicePropertyData][productId({}) 没有需要定义的属性]", productId);
                 return;
             }
-            devicePropertyMapper.createProductPropertySTable(product.getProductKey(), newFields);
+            devicePropertyMapper.createProductPropertySTable(product.getId(), newFields);
             return;
         }
         // 2.2 情况二:如果是修改的时候,需要更新表
-        devicePropertyMapper.alterProductPropertySTable(product.getProductKey(), oldFields, newFields);
+        devicePropertyMapper.alterProductPropertySTable(product.getId(), oldFields, newFields);
     }
 
     private List<TDengineTableField> buildTableFieldList(List<IotThingModelDO> thingModels) {
@@ -122,16 +119,17 @@ public class IotDevicePropertyServiceImpl implements IotDevicePropertyService {
 
     @Override
     public void saveDeviceProperty(IotDeviceDO device, IotDeviceMessage message) {
-        if (!(message.getData() instanceof Map)) {
+        // TODO @芋艿:这里要改下协议!
+        if (!(message.getParams() instanceof Map)) {
             log.error("[saveDeviceProperty][消息内容({}) 的 data 类型不正确]", message);
             return;
         }
 
         // 1. 根据物模型,拼接合法的属性
         // TODO @芋艿:【待定 004】赋能后,属性到底以 thingModel 为准(ik),还是 db 的表结构为准(tl)?
-        List<IotThingModelDO> thingModels = thingModelService.getThingModelListByProductKeyFromCache(device.getProductKey());
+        List<IotThingModelDO> thingModels = thingModelService.getThingModelListByProductIdFromCache(device.getProductId());
         Map<String, Object> properties = new HashMap<>();
-        ((Map<?, ?>) message.getData()).forEach((key, value) -> {
+        ((Map<?, ?>) message.getParams()).forEach((key, value) -> {
             if (CollUtil.findOne(thingModels, thingModel -> thingModel.getIdentifier().equals(key)) == null) {
                 log.error("[saveDeviceProperty][消息({}) 的属性({}) 不存在]", message, key);
                 return;
@@ -150,25 +148,16 @@ public class IotDevicePropertyServiceImpl implements IotDevicePropertyService {
         // 2.2 保存设备属性【日志】
         Map<String, IotDevicePropertyDO> properties2 = convertMap(properties.entrySet(), Map.Entry::getKey, entry ->
                 IotDevicePropertyDO.builder().value(entry.getValue()).updateTime(message.getReportTime()).build());
-        deviceDataRedisDAO.putAll(device.getProductKey(), device.getDeviceName(), properties2);
+        deviceDataRedisDAO.putAll(device.getId(), properties2);
     }
 
     @Override
     public Map<String, IotDevicePropertyDO> getLatestDeviceProperties(Long deviceId) {
-        // 获取设备信息
-        IotDeviceDO device = deviceService.validateDeviceExists(deviceId);
-
-        // 获得设备属性
-        return deviceDataRedisDAO.get(device.getProductKey(), device.getDeviceName());
+        return deviceDataRedisDAO.get(deviceId);
     }
 
     @Override
     public PageResult<IotDevicePropertyRespVO> getHistoryDevicePropertyPage(IotDevicePropertyHistoryPageReqVO pageReqVO) {
-        // 获取设备信息
-        IotDeviceDO device = deviceService.validateDeviceExists(pageReqVO.getDeviceId());
-        pageReqVO.setProductKey(device.getProductKey()).setDeviceName(device.getDeviceName());
-
-        // 分页查询
         try {
             IPage<IotDevicePropertyRespVO> page = devicePropertyMapper.selectPageByHistory(
                     new Page<>(pageReqVO.getPageNo(), pageReqVO.getPageSize()), pageReqVO);

+ 2 - 12
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thingmodel/IotThingModelService.java

@@ -7,7 +7,6 @@ import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.vo.IotThingModelS
 import cn.iocoder.yudao.module.iot.dal.dataobject.thingmodel.IotThingModelDO;
 import jakarta.validation.Valid;
 
-import java.time.LocalDateTime;
 import java.util.List;
 
 /**
@@ -60,10 +59,10 @@ public interface IotThingModelService {
      *
      * 注意:该方法会忽略租户信息,所以调用时,需要确认会不会有跨租户访问的风险!!!
      *
-     * @param productKey 产品标识
+     * @param productId 产品编号
      * @return 产品物模型列表
      */
-    List<IotThingModelDO> getThingModelListByProductKeyFromCache(String productKey);
+    List<IotThingModelDO> getThingModelListByProductIdFromCache(Long productId);
 
     /**
      * 获得产品物模型分页
@@ -81,13 +80,4 @@ public interface IotThingModelService {
      */
     List<IotThingModelDO> getThingModelList(IotThingModelListReqVO reqVO);
 
-    // TODO @super:用不到,删除下哈。
-    /**
-     * 获得物模型数量
-     *
-     * @param createTime 创建时间,如果为空,则统计所有物模型数量
-     * @return 物模型数量
-     */
-    Long getThingModelCount(LocalDateTime createTime);
-
 }

+ 3 - 10
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thingmodel/IotThingModelServiceImpl.java

@@ -29,7 +29,6 @@ import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.validation.annotation.Validated;
 
-import java.time.LocalDateTime;
 import java.util.*;
 
 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
@@ -133,10 +132,10 @@ public class IotThingModelServiceImpl implements IotThingModelService {
     }
 
     @Override
-    @Cacheable(value = RedisKeyConstants.THING_MODEL_LIST, key = "#productKey")
+    @Cacheable(value = RedisKeyConstants.THING_MODEL_LIST, key = "#productId")
     @TenantIgnore // 忽略租户信息,跨租户 productKey 是唯一的
-    public List<IotThingModelDO> getThingModelListByProductKeyFromCache(String productKey) {
-        return thingModelMapper.selectListByProductKey(productKey);
+    public List<IotThingModelDO> getThingModelListByProductIdFromCache(Long productId) {
+        return thingModelMapper.selectListByProductId(productId);
     }
 
     @Override
@@ -364,10 +363,4 @@ public class IotThingModelServiceImpl implements IotThingModelService {
         return SpringUtil.getBean(getClass());
     }
 
-    // TODO @super:用不到,删除下;
-    @Override
-    public Long getThingModelCount(LocalDateTime createTime) {
-        return thingModelMapper.selectCountByCreateTime(createTime);
-    }
-
 }

+ 12 - 11
yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/device/IotDevicePropertyMapper.xml

@@ -5,11 +5,11 @@
 <mapper namespace="cn.iocoder.yudao.module.iot.dal.tdengine.IotDevicePropertyMapper">
 
     <select id="getProductPropertySTableFieldList" resultType="cn.iocoder.yudao.module.iot.framework.tdengine.core.TDengineTableField">
-        DESCRIBE product_property_${productKey}
+        DESCRIBE product_property_${productId}
     </select>
 
     <update id="createProductPropertySTable">
-        CREATE STABLE product_property_${productKey} (
+        CREATE STABLE product_property_${productId} (
             ts TIMESTAMP,
             report_time TIMESTAMP,
         <foreach item="field" collection="fields" separator=",">
@@ -20,12 +20,12 @@
         </foreach>
         )
         TAGS (
-            device_name NCHAR(50)
+            device_id BIGINT
         )
     </update>
 
     <update id="alterProductPropertySTableAddField">
-        ALTER STABLE product_property_${productKey}
+        ALTER STABLE product_property_${productId}
         ADD COLUMN ${field.field} ${field.type}
         <if test="field.length != null and field.length > 0">
             (${field.length})
@@ -33,7 +33,7 @@
     </update>
 
     <update id="alterProductPropertySTableModifyField">
-        ALTER STABLE product_property_${productKey}
+        ALTER STABLE product_property_${productId}
         MODIFY COLUMN ${field.field} ${field.type}
         <if test="field.length != null and field.length > 0">
             (${field.length})
@@ -41,14 +41,14 @@
     </update>
 
     <update id="alterProductPropertySTableDropField">
-        ALTER STABLE product_property_${productKey}
+        ALTER STABLE product_property_${productId}
         DROP COLUMN ${field.field}
     </update>
 
     <insert id="insert">
-        INSERT INTO device_property_${device.productKey}_${device.deviceName}
-        USING product_property_${device.productKey}
-        TAGS ('${device.deviceName}')
+        INSERT INTO device_property_${device.id}
+        USING product_property_${device.productId}
+        TAGS ('${device.id}')
         (ts, report_time,
         <foreach item="key" collection="properties.keys" separator=",">
             ${@cn.hutool.core.util.StrUtil@toUnderlineCase(key)}
@@ -63,13 +63,14 @@
     </insert>
 
     <select id="describeSuperTable" resultType="java.util.Map">
-        DESCRIBE product_property_${productKey}
+        DESCRIBE product_property_${productId}
     </select>
 
+    <!-- TODO @芋艿:这里查询有点问题 -->
     <select id="selectPageByHistory"
             resultType="cn.iocoder.yudao.module.iot.controller.admin.device.vo.data.IotDevicePropertyRespVO">
         SELECT ${@cn.hutool.core.util.StrUtil@toUnderlineCase(reqVO.identifier)} AS `value`, ts AS update_time
-        FROM device_property_${reqVO.productKey}_${reqVO.deviceName}
+        FROM device_property_${reqVO.deviceId}
         WHERE ${@cn.hutool.core.util.StrUtil@toUnderlineCase(reqVO.identifier)} IS NOT NULL
           AND ts BETWEEN ${@cn.hutool.core.date.LocalDateTimeUtil@toEpochMilli(reqVO.times[0])}
               AND ${@cn.hutool.core.date.LocalDateTimeUtil@toEpochMilli(reqVO.times[1])}