feat:【IoT 物联网】获取设备属性时,即使没有值,也进行返回,和 aliyun 保持一致
This commit is contained in:
@@ -1,14 +1,16 @@
|
|||||||
package cn.iocoder.yudao.module.iot.controller.admin.device;
|
package cn.iocoder.yudao.module.iot.controller.admin.device;
|
||||||
|
|
||||||
import cn.hutool.core.collection.CollUtil;
|
|
||||||
import cn.hutool.core.date.LocalDateTimeUtil;
|
import cn.hutool.core.date.LocalDateTimeUtil;
|
||||||
import cn.hutool.core.lang.Assert;
|
import cn.hutool.core.lang.Assert;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||||
import cn.iocoder.yudao.module.iot.controller.admin.device.vo.data.IotDevicePropertyHistoryListReqVO;
|
import cn.iocoder.yudao.module.iot.controller.admin.device.vo.property.IotDevicePropertyDetailRespVO;
|
||||||
import cn.iocoder.yudao.module.iot.controller.admin.device.vo.data.IotDevicePropertyRespVO;
|
import cn.iocoder.yudao.module.iot.controller.admin.device.vo.property.IotDevicePropertyHistoryListReqVO;
|
||||||
|
import cn.iocoder.yudao.module.iot.controller.admin.device.vo.property.IotDevicePropertyRespVO;
|
||||||
|
import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.model.ThingModelProperty;
|
||||||
import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO;
|
import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO;
|
||||||
import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDevicePropertyDO;
|
import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDevicePropertyDO;
|
||||||
import cn.iocoder.yudao.module.iot.dal.dataobject.thingmodel.IotThingModelDO;
|
import cn.iocoder.yudao.module.iot.dal.dataobject.thingmodel.IotThingModelDO;
|
||||||
|
import cn.iocoder.yudao.module.iot.enums.thingmodel.IotThingModelTypeEnum;
|
||||||
import cn.iocoder.yudao.module.iot.service.device.IotDeviceService;
|
import cn.iocoder.yudao.module.iot.service.device.IotDeviceService;
|
||||||
import cn.iocoder.yudao.module.iot.service.device.property.IotDevicePropertyService;
|
import cn.iocoder.yudao.module.iot.service.device.property.IotDevicePropertyService;
|
||||||
import cn.iocoder.yudao.module.iot.service.thingmodel.IotThingModelService;
|
import cn.iocoder.yudao.module.iot.service.thingmodel.IotThingModelService;
|
||||||
@@ -47,24 +49,32 @@ public class IotDevicePropertyController {
|
|||||||
@Operation(summary = "获取设备属性最新属性")
|
@Operation(summary = "获取设备属性最新属性")
|
||||||
@Parameter(name = "deviceId", description = "设备编号", required = true)
|
@Parameter(name = "deviceId", description = "设备编号", required = true)
|
||||||
@PreAuthorize("@ss.hasPermission('iot:device:property-query')")
|
@PreAuthorize("@ss.hasPermission('iot:device:property-query')")
|
||||||
public CommonResult<List<IotDevicePropertyRespVO>> getLatestDeviceProperties(
|
public CommonResult<List<IotDevicePropertyDetailRespVO>> getLatestDeviceProperties(
|
||||||
@RequestParam("deviceId") Long deviceId) {
|
@RequestParam("deviceId") Long deviceId) {
|
||||||
Map<String, IotDevicePropertyDO> properties = devicePropertyService.getLatestDeviceProperties(deviceId);
|
// 1.1 获取设备信息
|
||||||
|
|
||||||
// 拼接数据
|
|
||||||
IotDeviceDO device = deviceService.getDevice(deviceId);
|
IotDeviceDO device = deviceService.getDevice(deviceId);
|
||||||
Assert.notNull(device, "设备不存在");
|
Assert.notNull(device, "设备不存在");
|
||||||
List<IotThingModelDO> thingModels = thingModelService.getThingModelListByProductId(device.getProductId());
|
// 1.2 获取设备最新属性
|
||||||
return success(convertList(properties.entrySet(), entry -> {
|
Map<String, IotDevicePropertyDO> properties = devicePropertyService.getLatestDeviceProperties(deviceId);
|
||||||
IotThingModelDO thingModel = CollUtil.findOne(thingModels,
|
// 1.3 根据 productId + type 查询属性类型的物模型
|
||||||
item -> item.getIdentifier().equals(entry.getKey()));
|
List<IotThingModelDO> thingModels = thingModelService.getThingModelListByProductIdAndType(
|
||||||
if (thingModel == null || thingModel.getProperty() == null) {
|
device.getProductId(), IotThingModelTypeEnum.PROPERTY.getType());
|
||||||
return null;
|
|
||||||
|
// 2. 基于 thingModels 遍历,拼接 properties
|
||||||
|
return success(convertList(thingModels, thingModel -> {
|
||||||
|
ThingModelProperty thingModelProperty = thingModel.getProperty();
|
||||||
|
Assert.notNull(thingModelProperty, "属性不能为空");
|
||||||
|
IotDevicePropertyDetailRespVO result = new IotDevicePropertyDetailRespVO()
|
||||||
|
.setName(thingModel.getName()).setDataType(thingModelProperty.getDataType())
|
||||||
|
.setDataSpecs(thingModelProperty.getDataSpecs())
|
||||||
|
.setDataSpecsList(thingModelProperty.getDataSpecsList());
|
||||||
|
result.setIdentifier(thingModel.getIdentifier());
|
||||||
|
IotDevicePropertyDO property = properties.get(thingModel.getIdentifier());
|
||||||
|
if (property != null) {
|
||||||
|
result.setValue(property.getValue())
|
||||||
|
.setUpdateTime(LocalDateTimeUtil.toEpochMilli(property.getUpdateTime()));
|
||||||
}
|
}
|
||||||
// 构建对象
|
return result;
|
||||||
IotDevicePropertyDO property = entry.getValue();
|
|
||||||
return new IotDevicePropertyRespVO().setProperty(thingModel.getProperty())
|
|
||||||
.setValue(property.getValue()).setUpdateTime(LocalDateTimeUtil.toEpochMilli(property.getUpdateTime()));
|
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
package cn.iocoder.yudao.module.iot.controller.admin.device.vo.property;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.model.dataType.ThingModelDataSpecs;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Schema(description = "管理后台 - IoT 设备属性详细 Response VO") // 额外增加 来自 ThingModelProperty 的变量 属性
|
||||||
|
@Data
|
||||||
|
public class IotDevicePropertyDetailRespVO extends IotDevicePropertyRespVO {
|
||||||
|
|
||||||
|
@Schema(description = "属性名称", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@Schema(description = "数据类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "int")
|
||||||
|
private String dataType;
|
||||||
|
|
||||||
|
@Schema(description = "数据定义")
|
||||||
|
private ThingModelDataSpecs dataSpecs;
|
||||||
|
|
||||||
|
@Schema(description = "数据定义列表")
|
||||||
|
private List<ThingModelDataSpecs> dataSpecsList;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package cn.iocoder.yudao.module.iot.controller.admin.device.vo.data;
|
package cn.iocoder.yudao.module.iot.controller.admin.device.vo.property;
|
||||||
|
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import jakarta.validation.constraints.NotEmpty;
|
import jakarta.validation.constraints.NotEmpty;
|
||||||
@@ -28,4 +28,4 @@ public class IotDevicePropertyHistoryListReqVO {
|
|||||||
@Size(min = 2, max = 2, message = "请选择时间范围")
|
@Size(min = 2, max = 2, message = "请选择时间范围")
|
||||||
private LocalDateTime[] times;
|
private LocalDateTime[] times;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
package cn.iocoder.yudao.module.iot.controller.admin.device.vo.data;
|
package cn.iocoder.yudao.module.iot.controller.admin.device.vo.property;
|
||||||
|
|
||||||
import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.model.ThingModelProperty;
|
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
@@ -8,10 +7,10 @@ import lombok.Data;
|
|||||||
@Data
|
@Data
|
||||||
public class IotDevicePropertyRespVO {
|
public class IotDevicePropertyRespVO {
|
||||||
|
|
||||||
@Schema(description = "属性定义", requiredMode = Schema.RequiredMode.REQUIRED)
|
@Schema(description = "属性标识符", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||||
private ThingModelProperty property;
|
private String identifier;
|
||||||
|
|
||||||
@Schema(description = "最新值", requiredMode = Schema.RequiredMode.REQUIRED)
|
@Schema(description = "属性值", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||||
private Object value;
|
private Object value;
|
||||||
|
|
||||||
@Schema(description = "更新时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
@Schema(description = "更新时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||||
@@ -3,13 +3,12 @@ package cn.iocoder.yudao.module.iot.dal.tdengine;
|
|||||||
import cn.hutool.core.collection.CollUtil;
|
import cn.hutool.core.collection.CollUtil;
|
||||||
import cn.hutool.core.util.ObjectUtil;
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import cn.iocoder.yudao.module.iot.controller.admin.device.vo.data.IotDevicePropertyHistoryListReqVO;
|
import cn.iocoder.yudao.module.iot.controller.admin.device.vo.property.IotDevicePropertyHistoryListReqVO;
|
||||||
import cn.iocoder.yudao.module.iot.controller.admin.device.vo.data.IotDevicePropertyRespVO;
|
import cn.iocoder.yudao.module.iot.controller.admin.device.vo.property.IotDevicePropertyRespVO;
|
||||||
import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO;
|
import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO;
|
||||||
import cn.iocoder.yudao.module.iot.framework.tdengine.core.TDengineTableField;
|
import cn.iocoder.yudao.module.iot.framework.tdengine.core.TDengineTableField;
|
||||||
import cn.iocoder.yudao.module.iot.framework.tdengine.core.annotation.TDengineDS;
|
import cn.iocoder.yudao.module.iot.framework.tdengine.core.annotation.TDengineDS;
|
||||||
import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
|
import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
|
||||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
import org.apache.ibatis.annotations.Param;
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
package cn.iocoder.yudao.module.iot.service.device.property;
|
package cn.iocoder.yudao.module.iot.service.device.property;
|
||||||
|
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
import cn.iocoder.yudao.module.iot.controller.admin.device.vo.property.IotDevicePropertyHistoryListReqVO;
|
||||||
import cn.iocoder.yudao.module.iot.controller.admin.device.vo.data.IotDevicePropertyHistoryListReqVO;
|
import cn.iocoder.yudao.module.iot.controller.admin.device.vo.property.IotDevicePropertyRespVO;
|
||||||
import cn.iocoder.yudao.module.iot.controller.admin.device.vo.data.IotDevicePropertyRespVO;
|
|
||||||
import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
|
import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
|
||||||
import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO;
|
import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO;
|
||||||
import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDevicePropertyDO;
|
import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDevicePropertyDO;
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ import cn.hutool.core.collection.CollUtil;
|
|||||||
import cn.hutool.core.date.LocalDateTimeUtil;
|
import cn.hutool.core.date.LocalDateTimeUtil;
|
||||||
import cn.hutool.core.map.MapUtil;
|
import cn.hutool.core.map.MapUtil;
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import cn.iocoder.yudao.module.iot.controller.admin.device.vo.data.IotDevicePropertyHistoryListReqVO;
|
import cn.iocoder.yudao.module.iot.controller.admin.device.vo.property.IotDevicePropertyHistoryListReqVO;
|
||||||
import cn.iocoder.yudao.module.iot.controller.admin.device.vo.data.IotDevicePropertyRespVO;
|
import cn.iocoder.yudao.module.iot.controller.admin.device.vo.property.IotDevicePropertyRespVO;
|
||||||
import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.model.dataType.ThingModelDateOrTextDataSpecs;
|
import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.model.dataType.ThingModelDateOrTextDataSpecs;
|
||||||
import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
|
import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
|
||||||
import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO;
|
import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO;
|
||||||
|
|||||||
@@ -54,6 +54,15 @@ public interface IotThingModelService {
|
|||||||
*/
|
*/
|
||||||
List<IotThingModelDO> getThingModelListByProductId(Long productId);
|
List<IotThingModelDO> getThingModelListByProductId(Long productId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得产品物模型列表
|
||||||
|
*
|
||||||
|
* @param productId 产品编号
|
||||||
|
* @param type 物模型类型
|
||||||
|
* @return 产品物模型列表
|
||||||
|
*/
|
||||||
|
List<IotThingModelDO> getThingModelListByProductIdAndType(Long productId, Integer type);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 【缓存】获得产品物模型列表
|
* 【缓存】获得产品物模型列表
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -131,6 +131,11 @@ public class IotThingModelServiceImpl implements IotThingModelService {
|
|||||||
return thingModelMapper.selectListByProductId(productId);
|
return thingModelMapper.selectListByProductId(productId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<IotThingModelDO> getThingModelListByProductIdAndType(Long productId, Integer type) {
|
||||||
|
return thingModelMapper.selectListByProductIdAndType(productId, type);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Cacheable(value = RedisKeyConstants.THING_MODEL_LIST, key = "#productId")
|
@Cacheable(value = RedisKeyConstants.THING_MODEL_LIST, key = "#productId")
|
||||||
@TenantIgnore // 忽略租户信息,跨租户 productKey 是唯一的
|
@TenantIgnore // 忽略租户信息,跨租户 productKey 是唯一的
|
||||||
|
|||||||
@@ -67,7 +67,7 @@
|
|||||||
</select>
|
</select>
|
||||||
|
|
||||||
<select id="selectListByHistory"
|
<select id="selectListByHistory"
|
||||||
resultType="cn.iocoder.yudao.module.iot.controller.admin.device.vo.data.IotDevicePropertyRespVO">
|
resultType="cn.iocoder.yudao.module.iot.controller.admin.device.vo.property.IotDevicePropertyRespVO">
|
||||||
SELECT ${@cn.hutool.core.util.StrUtil@toUnderlineCase(reqVO.identifier)} AS `value`, ts AS update_time
|
SELECT ${@cn.hutool.core.util.StrUtil@toUnderlineCase(reqVO.identifier)} AS `value`, ts AS update_time
|
||||||
FROM device_property_${reqVO.deviceId}
|
FROM device_property_${reqVO.deviceId}
|
||||||
WHERE ${@cn.hutool.core.util.StrUtil@toUnderlineCase(reqVO.identifier)} IS NOT NULL
|
WHERE ${@cn.hutool.core.util.StrUtil@toUnderlineCase(reqVO.identifier)} IS NOT NULL
|
||||||
|
|||||||
Reference in New Issue
Block a user