Commit 862f356cb8c81def23309b3e0ddb6c022f8a9e3a

Authored by YunaiV
1 parent e476dcb2

feat:【IoT 物联网】获取设备属性时,即使没有值,也进行返回,和 aliyun 保持一致

Showing 10 changed files with 79 additions and 33 deletions
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/IotDevicePropertyController.java
1 package cn.iocoder.yudao.module.iot.controller.admin.device; 1 package cn.iocoder.yudao.module.iot.controller.admin.device;
2 2
3 -import cn.hutool.core.collection.CollUtil;  
4 import cn.hutool.core.date.LocalDateTimeUtil; 3 import cn.hutool.core.date.LocalDateTimeUtil;
5 import cn.hutool.core.lang.Assert; 4 import cn.hutool.core.lang.Assert;
6 import cn.iocoder.yudao.framework.common.pojo.CommonResult; 5 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
7 -import cn.iocoder.yudao.module.iot.controller.admin.device.vo.data.IotDevicePropertyHistoryListReqVO;  
8 -import cn.iocoder.yudao.module.iot.controller.admin.device.vo.data.IotDevicePropertyRespVO; 6 +import cn.iocoder.yudao.module.iot.controller.admin.device.vo.property.IotDevicePropertyDetailRespVO;
  7 +import cn.iocoder.yudao.module.iot.controller.admin.device.vo.property.IotDevicePropertyHistoryListReqVO;
  8 +import cn.iocoder.yudao.module.iot.controller.admin.device.vo.property.IotDevicePropertyRespVO;
  9 +import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.model.ThingModelProperty;
9 import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; 10 import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO;
10 import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDevicePropertyDO; 11 import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDevicePropertyDO;
11 import cn.iocoder.yudao.module.iot.dal.dataobject.thingmodel.IotThingModelDO; 12 import cn.iocoder.yudao.module.iot.dal.dataobject.thingmodel.IotThingModelDO;
  13 +import cn.iocoder.yudao.module.iot.enums.thingmodel.IotThingModelTypeEnum;
12 import cn.iocoder.yudao.module.iot.service.device.IotDeviceService; 14 import cn.iocoder.yudao.module.iot.service.device.IotDeviceService;
13 import cn.iocoder.yudao.module.iot.service.device.property.IotDevicePropertyService; 15 import cn.iocoder.yudao.module.iot.service.device.property.IotDevicePropertyService;
14 import cn.iocoder.yudao.module.iot.service.thingmodel.IotThingModelService; 16 import cn.iocoder.yudao.module.iot.service.thingmodel.IotThingModelService;
@@ -47,24 +49,32 @@ public class IotDevicePropertyController { @@ -47,24 +49,32 @@ public class IotDevicePropertyController {
47 @Operation(summary = "获取设备属性最新属性") 49 @Operation(summary = "获取设备属性最新属性")
48 @Parameter(name = "deviceId", description = "设备编号", required = true) 50 @Parameter(name = "deviceId", description = "设备编号", required = true)
49 @PreAuthorize("@ss.hasPermission('iot:device:property-query')") 51 @PreAuthorize("@ss.hasPermission('iot:device:property-query')")
50 - public CommonResult<List<IotDevicePropertyRespVO>> getLatestDeviceProperties( 52 + public CommonResult<List<IotDevicePropertyDetailRespVO>> getLatestDeviceProperties(
51 @RequestParam("deviceId") Long deviceId) { 53 @RequestParam("deviceId") Long deviceId) {
52 - Map<String, IotDevicePropertyDO> properties = devicePropertyService.getLatestDeviceProperties(deviceId);  
53 -  
54 - // 拼接数据 54 + // 1.1 获取设备信息
55 IotDeviceDO device = deviceService.getDevice(deviceId); 55 IotDeviceDO device = deviceService.getDevice(deviceId);
56 Assert.notNull(device, "设备不存在"); 56 Assert.notNull(device, "设备不存在");
57 - List<IotThingModelDO> thingModels = thingModelService.getThingModelListByProductId(device.getProductId());  
58 - return success(convertList(properties.entrySet(), entry -> {  
59 - IotThingModelDO thingModel = CollUtil.findOne(thingModels,  
60 - item -> item.getIdentifier().equals(entry.getKey()));  
61 - if (thingModel == null || thingModel.getProperty() == null) {  
62 - return null; 57 + // 1.2 获取设备最新属性
  58 + Map<String, IotDevicePropertyDO> properties = devicePropertyService.getLatestDeviceProperties(deviceId);
  59 + // 1.3 根据 productId + type 查询属性类型的物模型
  60 + List<IotThingModelDO> thingModels = thingModelService.getThingModelListByProductIdAndType(
  61 + device.getProductId(), IotThingModelTypeEnum.PROPERTY.getType());
  62 +
  63 + // 2. 基于 thingModels 遍历,拼接 properties
  64 + return success(convertList(thingModels, thingModel -> {
  65 + ThingModelProperty thingModelProperty = thingModel.getProperty();
  66 + Assert.notNull(thingModelProperty, "属性不能为空");
  67 + IotDevicePropertyDetailRespVO result = new IotDevicePropertyDetailRespVO()
  68 + .setName(thingModel.getName()).setDataType(thingModelProperty.getDataType())
  69 + .setDataSpecs(thingModelProperty.getDataSpecs())
  70 + .setDataSpecsList(thingModelProperty.getDataSpecsList());
  71 + result.setIdentifier(thingModel.getIdentifier());
  72 + IotDevicePropertyDO property = properties.get(thingModel.getIdentifier());
  73 + if (property != null) {
  74 + result.setValue(property.getValue())
  75 + .setUpdateTime(LocalDateTimeUtil.toEpochMilli(property.getUpdateTime()));
63 } 76 }
64 - // 构建对象  
65 - IotDevicePropertyDO property = entry.getValue();  
66 - return new IotDevicePropertyRespVO().setProperty(thingModel.getProperty())  
67 - .setValue(property.getValue()).setUpdateTime(LocalDateTimeUtil.toEpochMilli(property.getUpdateTime())); 77 + return result;
68 })); 78 }));
69 } 79 }
70 80
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/property/IotDevicePropertyDetailRespVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.iot.controller.admin.device.vo.property;
  2 +
  3 +import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.model.dataType.ThingModelDataSpecs;
  4 +import io.swagger.v3.oas.annotations.media.Schema;
  5 +import lombok.Data;
  6 +
  7 +import java.util.List;
  8 +
  9 +@Schema(description = "管理后台 - IoT 设备属性详细 Response VO") // 额外增加 来自 ThingModelProperty 的变量 属性
  10 +@Data
  11 +public class IotDevicePropertyDetailRespVO extends IotDevicePropertyRespVO {
  12 +
  13 + @Schema(description = "属性名称", requiredMode = Schema.RequiredMode.REQUIRED)
  14 + private String name;
  15 +
  16 + @Schema(description = "数据类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "int")
  17 + private String dataType;
  18 +
  19 + @Schema(description = "数据定义")
  20 + private ThingModelDataSpecs dataSpecs;
  21 +
  22 + @Schema(description = "数据定义列表")
  23 + private List<ThingModelDataSpecs> dataSpecsList;
  24 +
  25 +}
0 \ No newline at end of file 26 \ No newline at end of file
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/data/IotDevicePropertyHistoryListReqVO.java renamed to yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/property/IotDevicePropertyHistoryListReqVO.java
1 -package cn.iocoder.yudao.module.iot.controller.admin.device.vo.data; 1 +package cn.iocoder.yudao.module.iot.controller.admin.device.vo.property;
2 2
3 import io.swagger.v3.oas.annotations.media.Schema; 3 import io.swagger.v3.oas.annotations.media.Schema;
4 import jakarta.validation.constraints.NotEmpty; 4 import jakarta.validation.constraints.NotEmpty;
@@ -28,4 +28,4 @@ public class IotDevicePropertyHistoryListReqVO { @@ -28,4 +28,4 @@ public class IotDevicePropertyHistoryListReqVO {
28 @Size(min = 2, max = 2, message = "请选择时间范围") 28 @Size(min = 2, max = 2, message = "请选择时间范围")
29 private LocalDateTime[] times; 29 private LocalDateTime[] times;
30 30
31 -}  
32 \ No newline at end of file 31 \ No newline at end of file
  32 +}
33 \ No newline at end of file 33 \ No newline at end of file
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/data/IotDevicePropertyRespVO.java renamed to yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/property/IotDevicePropertyRespVO.java
1 -package cn.iocoder.yudao.module.iot.controller.admin.device.vo.data; 1 +package cn.iocoder.yudao.module.iot.controller.admin.device.vo.property;
2 2
3 -import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.model.ThingModelProperty;  
4 import io.swagger.v3.oas.annotations.media.Schema; 3 import io.swagger.v3.oas.annotations.media.Schema;
5 import lombok.Data; 4 import lombok.Data;
6 5
@@ -8,10 +7,10 @@ import lombok.Data; @@ -8,10 +7,10 @@ import lombok.Data;
8 @Data 7 @Data
9 public class IotDevicePropertyRespVO { 8 public class IotDevicePropertyRespVO {
10 9
11 - @Schema(description = "属性定义", requiredMode = Schema.RequiredMode.REQUIRED)  
12 - private ThingModelProperty property; 10 + @Schema(description = "属性标识符", requiredMode = Schema.RequiredMode.REQUIRED)
  11 + private String identifier;
13 12
14 - @Schema(description = "最新值", requiredMode = Schema.RequiredMode.REQUIRED) 13 + @Schema(description = "属性值", requiredMode = Schema.RequiredMode.REQUIRED)
15 private Object value; 14 private Object value;
16 15
17 @Schema(description = "更新时间", requiredMode = Schema.RequiredMode.REQUIRED) 16 @Schema(description = "更新时间", requiredMode = Schema.RequiredMode.REQUIRED)
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/IotDevicePropertyMapper.java
@@ -3,13 +3,12 @@ package cn.iocoder.yudao.module.iot.dal.tdengine; @@ -3,13 +3,12 @@ package cn.iocoder.yudao.module.iot.dal.tdengine;
3 import cn.hutool.core.collection.CollUtil; 3 import cn.hutool.core.collection.CollUtil;
4 import cn.hutool.core.util.ObjectUtil; 4 import cn.hutool.core.util.ObjectUtil;
5 import cn.hutool.core.util.StrUtil; 5 import cn.hutool.core.util.StrUtil;
6 -import cn.iocoder.yudao.module.iot.controller.admin.device.vo.data.IotDevicePropertyHistoryListReqVO;  
7 -import cn.iocoder.yudao.module.iot.controller.admin.device.vo.data.IotDevicePropertyRespVO; 6 +import cn.iocoder.yudao.module.iot.controller.admin.device.vo.property.IotDevicePropertyHistoryListReqVO;
  7 +import cn.iocoder.yudao.module.iot.controller.admin.device.vo.property.IotDevicePropertyRespVO;
8 import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; 8 import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO;
9 import cn.iocoder.yudao.module.iot.framework.tdengine.core.TDengineTableField; 9 import cn.iocoder.yudao.module.iot.framework.tdengine.core.TDengineTableField;
10 import cn.iocoder.yudao.module.iot.framework.tdengine.core.annotation.TDengineDS; 10 import cn.iocoder.yudao.module.iot.framework.tdengine.core.annotation.TDengineDS;
11 import com.baomidou.mybatisplus.annotation.InterceptorIgnore; 11 import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
12 -import com.baomidou.mybatisplus.core.metadata.IPage;  
13 import org.apache.ibatis.annotations.Mapper; 12 import org.apache.ibatis.annotations.Mapper;
14 import org.apache.ibatis.annotations.Param; 13 import org.apache.ibatis.annotations.Param;
15 14
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/property/IotDevicePropertyService.java
1 package cn.iocoder.yudao.module.iot.service.device.property; 1 package cn.iocoder.yudao.module.iot.service.device.property;
2 2
3 -import cn.iocoder.yudao.framework.common.pojo.PageResult;  
4 -import cn.iocoder.yudao.module.iot.controller.admin.device.vo.data.IotDevicePropertyHistoryListReqVO;  
5 -import cn.iocoder.yudao.module.iot.controller.admin.device.vo.data.IotDevicePropertyRespVO; 3 +import cn.iocoder.yudao.module.iot.controller.admin.device.vo.property.IotDevicePropertyHistoryListReqVO;
  4 +import cn.iocoder.yudao.module.iot.controller.admin.device.vo.property.IotDevicePropertyRespVO;
6 import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage; 5 import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
7 import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; 6 import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO;
8 import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDevicePropertyDO; 7 import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDevicePropertyDO;
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/property/IotDevicePropertyServiceImpl.java
@@ -4,8 +4,8 @@ import cn.hutool.core.collection.CollUtil; @@ -4,8 +4,8 @@ import cn.hutool.core.collection.CollUtil;
4 import cn.hutool.core.date.LocalDateTimeUtil; 4 import cn.hutool.core.date.LocalDateTimeUtil;
5 import cn.hutool.core.map.MapUtil; 5 import cn.hutool.core.map.MapUtil;
6 import cn.hutool.core.util.StrUtil; 6 import cn.hutool.core.util.StrUtil;
7 -import cn.iocoder.yudao.module.iot.controller.admin.device.vo.data.IotDevicePropertyHistoryListReqVO;  
8 -import cn.iocoder.yudao.module.iot.controller.admin.device.vo.data.IotDevicePropertyRespVO; 7 +import cn.iocoder.yudao.module.iot.controller.admin.device.vo.property.IotDevicePropertyHistoryListReqVO;
  8 +import cn.iocoder.yudao.module.iot.controller.admin.device.vo.property.IotDevicePropertyRespVO;
9 import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.model.dataType.ThingModelDateOrTextDataSpecs; 9 import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.model.dataType.ThingModelDateOrTextDataSpecs;
10 import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage; 10 import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
11 import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; 11 import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO;
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thingmodel/IotThingModelService.java
@@ -55,6 +55,15 @@ public interface IotThingModelService { @@ -55,6 +55,15 @@ public interface IotThingModelService {
55 List<IotThingModelDO> getThingModelListByProductId(Long productId); 55 List<IotThingModelDO> getThingModelListByProductId(Long productId);
56 56
57 /** 57 /**
  58 + * 获得产品物模型列表
  59 + *
  60 + * @param productId 产品编号
  61 + * @param type 物模型类型
  62 + * @return 产品物模型列表
  63 + */
  64 + List<IotThingModelDO> getThingModelListByProductIdAndType(Long productId, Integer type);
  65 +
  66 + /**
58 * 【缓存】获得产品物模型列表 67 * 【缓存】获得产品物模型列表
59 * 68 *
60 * 注意:该方法会忽略租户信息,所以调用时,需要确认会不会有跨租户访问的风险!!! 69 * 注意:该方法会忽略租户信息,所以调用时,需要确认会不会有跨租户访问的风险!!!
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thingmodel/IotThingModelServiceImpl.java
@@ -132,6 +132,11 @@ public class IotThingModelServiceImpl implements IotThingModelService { @@ -132,6 +132,11 @@ public class IotThingModelServiceImpl implements IotThingModelService {
132 } 132 }
133 133
134 @Override 134 @Override
  135 + public List<IotThingModelDO> getThingModelListByProductIdAndType(Long productId, Integer type) {
  136 + return thingModelMapper.selectListByProductIdAndType(productId, type);
  137 + }
  138 +
  139 + @Override
135 @Cacheable(value = RedisKeyConstants.THING_MODEL_LIST, key = "#productId") 140 @Cacheable(value = RedisKeyConstants.THING_MODEL_LIST, key = "#productId")
136 @TenantIgnore // 忽略租户信息,跨租户 productKey 是唯一的 141 @TenantIgnore // 忽略租户信息,跨租户 productKey 是唯一的
137 public List<IotThingModelDO> getThingModelListByProductIdFromCache(Long productId) { 142 public List<IotThingModelDO> getThingModelListByProductIdFromCache(Long productId) {
yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/device/IotDevicePropertyMapper.xml
@@ -67,7 +67,7 @@ @@ -67,7 +67,7 @@
67 </select> 67 </select>
68 68
69 <select id="selectListByHistory" 69 <select id="selectListByHistory"
70 - resultType="cn.iocoder.yudao.module.iot.controller.admin.device.vo.data.IotDevicePropertyRespVO"> 70 + resultType="cn.iocoder.yudao.module.iot.controller.admin.device.vo.property.IotDevicePropertyRespVO">
71 SELECT ${@cn.hutool.core.util.StrUtil@toUnderlineCase(reqVO.identifier)} AS `value`, ts AS update_time 71 SELECT ${@cn.hutool.core.util.StrUtil@toUnderlineCase(reqVO.identifier)} AS `value`, ts AS update_time
72 FROM device_property_${reqVO.deviceId} 72 FROM device_property_${reqVO.deviceId}
73 WHERE ${@cn.hutool.core.util.StrUtil@toUnderlineCase(reqVO.identifier)} IS NOT NULL 73 WHERE ${@cn.hutool.core.util.StrUtil@toUnderlineCase(reqVO.identifier)} IS NOT NULL