Commit 862f356cb8c81def23309b3e0ddb6c022f8a9e3a
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 | 1 | package cn.iocoder.yudao.module.iot.controller.admin.device; |
| 2 | 2 | |
| 3 | -import cn.hutool.core.collection.CollUtil; | |
| 4 | 3 | import cn.hutool.core.date.LocalDateTimeUtil; |
| 5 | 4 | import cn.hutool.core.lang.Assert; |
| 6 | 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 | 10 | import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; |
| 10 | 11 | import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDevicePropertyDO; |
| 11 | 12 | import cn.iocoder.yudao.module.iot.dal.dataobject.thingmodel.IotThingModelDO; |
| 13 | +import cn.iocoder.yudao.module.iot.enums.thingmodel.IotThingModelTypeEnum; | |
| 12 | 14 | import cn.iocoder.yudao.module.iot.service.device.IotDeviceService; |
| 13 | 15 | import cn.iocoder.yudao.module.iot.service.device.property.IotDevicePropertyService; |
| 14 | 16 | import cn.iocoder.yudao.module.iot.service.thingmodel.IotThingModelService; |
| ... | ... | @@ -47,24 +49,32 @@ public class IotDevicePropertyController { |
| 47 | 49 | @Operation(summary = "获取设备属性最新属性") |
| 48 | 50 | @Parameter(name = "deviceId", description = "设备编号", required = true) |
| 49 | 51 | @PreAuthorize("@ss.hasPermission('iot:device:property-query')") |
| 50 | - public CommonResult<List<IotDevicePropertyRespVO>> getLatestDeviceProperties( | |
| 52 | + public CommonResult<List<IotDevicePropertyDetailRespVO>> getLatestDeviceProperties( | |
| 51 | 53 | @RequestParam("deviceId") Long deviceId) { |
| 52 | - Map<String, IotDevicePropertyDO> properties = devicePropertyService.getLatestDeviceProperties(deviceId); | |
| 53 | - | |
| 54 | - // 拼接数据 | |
| 54 | + // 1.1 获取设备信息 | |
| 55 | 55 | IotDeviceDO device = deviceService.getDevice(deviceId); |
| 56 | 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 | 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 | 3 | import io.swagger.v3.oas.annotations.media.Schema; |
| 4 | 4 | import jakarta.validation.constraints.NotEmpty; |
| ... | ... | @@ -28,4 +28,4 @@ public class IotDevicePropertyHistoryListReqVO { |
| 28 | 28 | @Size(min = 2, max = 2, message = "请选择时间范围") |
| 29 | 29 | private LocalDateTime[] times; |
| 30 | 30 | |
| 31 | -} | |
| 32 | 31 | \ No newline at end of file |
| 32 | +} | |
| 33 | 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 | 3 | import io.swagger.v3.oas.annotations.media.Schema; |
| 5 | 4 | import lombok.Data; |
| 6 | 5 | |
| ... | ... | @@ -8,10 +7,10 @@ import lombok.Data; |
| 8 | 7 | @Data |
| 9 | 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 | 14 | private Object value; |
| 16 | 15 | |
| 17 | 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 | 3 | import cn.hutool.core.collection.CollUtil; |
| 4 | 4 | import cn.hutool.core.util.ObjectUtil; |
| 5 | 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 | 8 | import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; |
| 9 | 9 | import cn.iocoder.yudao.module.iot.framework.tdengine.core.TDengineTableField; |
| 10 | 10 | import cn.iocoder.yudao.module.iot.framework.tdengine.core.annotation.TDengineDS; |
| 11 | 11 | import com.baomidou.mybatisplus.annotation.InterceptorIgnore; |
| 12 | -import com.baomidou.mybatisplus.core.metadata.IPage; | |
| 13 | 12 | import org.apache.ibatis.annotations.Mapper; |
| 14 | 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 | 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 | 5 | import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage; |
| 7 | 6 | import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; |
| 8 | 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 | 4 | import cn.hutool.core.date.LocalDateTimeUtil; |
| 5 | 5 | import cn.hutool.core.map.MapUtil; |
| 6 | 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 | 9 | import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.model.dataType.ThingModelDateOrTextDataSpecs; |
| 10 | 10 | import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage; |
| 11 | 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 | 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 | 132 | } |
| 133 | 133 | |
| 134 | 134 | @Override |
| 135 | + public List<IotThingModelDO> getThingModelListByProductIdAndType(Long productId, Integer type) { | |
| 136 | + return thingModelMapper.selectListByProductIdAndType(productId, type); | |
| 137 | + } | |
| 138 | + | |
| 139 | + @Override | |
| 135 | 140 | @Cacheable(value = RedisKeyConstants.THING_MODEL_LIST, key = "#productId") |
| 136 | 141 | @TenantIgnore // 忽略租户信息,跨租户 productKey 是唯一的 |
| 137 | 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 | 67 | </select> |
| 68 | 68 | |
| 69 | 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 | 71 | SELECT ${@cn.hutool.core.util.StrUtil@toUnderlineCase(reqVO.identifier)} AS `value`, ts AS update_time |
| 72 | 72 | FROM device_property_${reqVO.deviceId} |
| 73 | 73 | WHERE ${@cn.hutool.core.util.StrUtil@toUnderlineCase(reqVO.identifier)} IS NOT NULL | ... | ... |