【功能优化】IoT:部分实现 IotDevicePropertyMessageConsumer,支持缓存的记录(差设备属性的日志记录)

This commit is contained in:
YunaiV 2025-01-27 16:50:10 +08:00
parent b319485ca6
commit 8e80a53a8b
15 changed files with 245 additions and 215 deletions

View File

@ -4,7 +4,7 @@ import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData.*; import cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData.*;
import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDataDO; import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDevicePropertyDO;
import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceLogDO; import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceLogDO;
import cn.iocoder.yudao.module.iot.service.device.data.IotDeviceLogService; import cn.iocoder.yudao.module.iot.service.device.data.IotDeviceLogService;
import cn.iocoder.yudao.module.iot.service.device.data.IotDevicePropertyService; import cn.iocoder.yudao.module.iot.service.device.data.IotDevicePropertyService;
@ -28,18 +28,14 @@ public class IotDeviceDataController {
@Resource @Resource
private IotDevicePropertyService deviceDataService; private IotDevicePropertyService deviceDataService;
@Resource @Resource
private IotDeviceLogService iotDeviceLogDataService;
@Resource // TODO @superservice 之间不用空行原因是这样更简洁空行主要是为了间隔提升可读性
private IotDeviceLogService deviceLogDataService; private IotDeviceLogService deviceLogDataService;
// TODO @浩浩这里的 /latest-list包括方法名 // TODO @浩浩这里的 /latest-list包括方法名
@GetMapping("/latest") @GetMapping("/latest")
@Operation(summary = "获取设备属性最新数据") @Operation(summary = "获取设备属性最新数据")
public CommonResult<List<IotDeviceDataRespVO>> getLatestDeviceProperties(@Valid IotDeviceDataPageReqVO deviceDataReqVO) { public CommonResult<List<IotDeviceDataRespVO>> getLatestDeviceProperties(@Valid IotDeviceDataPageReqVO deviceDataReqVO) {
List<IotDeviceDataDO> list = deviceDataService.getLatestDeviceProperties(deviceDataReqVO); List<IotDevicePropertyDO> list = deviceDataService.getLatestDeviceProperties(deviceDataReqVO);
return success(BeanUtils.toBean(list, IotDeviceDataRespVO.class)); return success(BeanUtils.toBean(list, IotDeviceDataRespVO.class));
} }

View File

@ -1,82 +0,0 @@
package cn.iocoder.yudao.module.iot.dal.dataobject.device;
import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO;
import cn.iocoder.yudao.module.iot.dal.dataobject.thingmodel.IotThingModelDO;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDateTime;
/**
* IoT 设备数据 DO
*
* @author haohao
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class IotDeviceDataDO {
/**
* 设备编号
* <p>
* 关联 {@link IotDeviceDO#getId()}
*/
private Long deviceId;
/**
* 物模型编号
* <p>
* 关联 {@link IotThingModelDO#getId()}
*/
private Long thingModelId;
/**
* 产品标识
* <p>
* 关联 {@link IotProductDO#getProductKey()}
*/
private String productKey;
/**
* 设备名称
* <p>
* 冗余 {@link IotDeviceDO#getDeviceName()}
*/
private String deviceName;
/**
* 属性标识符
* <p>
* 关联 {@link IotThingModelDO#getIdentifier()}
*/
private String identifier;
/**
* 属性名称
* <p>
* 关联 {@link IotThingModelDO#getName()}
*/
private String name;
/**
* 数据类型
* <p>
* 关联 {@link IotThingModelDO#getProperty()#getDataType()}
*/
private String dataType;
/**
* 更新时间
*/
private LocalDateTime updateTime;
/**
* 最新值
*/
private String value;
}

View File

@ -0,0 +1,35 @@
package cn.iocoder.yudao.module.iot.dal.dataobject.device;
import cn.iocoder.yudao.module.iot.dal.redis.device.DevicePropertyRedisDAO;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDateTime;
/**
* IoT 设备属性项 Redis DO
*
* @see cn.iocoder.yudao.module.iot.dal.redis.RedisKeyConstants#DEVICE_PROPERTY
* @see DevicePropertyRedisDAO
*
* @author haohao
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class IotDevicePropertyDO {
/**
* 属性值最新
*/
private Object value;
/**
* 更新时间
*/
private LocalDateTime updateTime;
}

View File

@ -1,6 +1,6 @@
package cn.iocoder.yudao.module.iot.dal.redis; package cn.iocoder.yudao.module.iot.dal.redis;
import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDevicePropertyDO;
/** /**
* Iot Redis Key 枚举类 * Iot Redis Key 枚举类
@ -10,11 +10,20 @@ package cn.iocoder.yudao.module.iot.dal.redis;
public interface RedisKeyConstants { public interface RedisKeyConstants {
/** /**
* 设备属性数据缓存 * 设备属性数据缓存采用 HASH 结构
* <p> * <p>
* KEY 格式device_property_data:{deviceId} * KEY 格式device_property:{deviceKey}
* VALUE 数据类型String 设备属性数据 * HASH KEYidentifier 属性标识
* VALUE 数据类型String(JSON) {@link IotDevicePropertyDO}
*/ */
String DEVICE_PROPERTY_DATA = "device_property_data:%s_%s_%s"; String DEVICE_PROPERTY = "device_property:%s";
/**
* 设备的最后上报时间采用 ZSET 结构
*
* KEY 格式{deviceKey}
* SCORE上报时间
*/
String DEVICE_REPORT_TIME = "device_report_time";
} }

View File

@ -0,0 +1,54 @@
package cn.iocoder.yudao.module.iot.dal.redis.device;
import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDevicePropertyDO;
import jakarta.annotation.Resource;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Repository;
import java.util.Collections;
import java.util.Map;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
import static cn.iocoder.yudao.module.iot.dal.redis.RedisKeyConstants.DEVICE_PROPERTY;
/**
* {@link IotDevicePropertyDO} Redis DAO
*/
@Repository
public class DevicePropertyRedisDAO {
@Resource
private StringRedisTemplate stringRedisTemplate;
public Map<String, IotDevicePropertyDO> get(String deviceKey) {
String redisKey = formatKey(deviceKey);
Map<Object, Object> entries = stringRedisTemplate.opsForHash().entries(redisKey);
if (CollUtil.isEmpty(entries)) {
return Collections.emptyMap();
}
return convertMap(entries.values(), key -> (String) key,
value -> JsonUtils.parseObject((String) value, IotDevicePropertyDO.class));
}
public void set(String deviceKey, Map<String, IotDevicePropertyDO> properties) {
if (CollUtil.isEmpty(properties)) {
return;
}
String redisKey = formatKey(deviceKey);
stringRedisTemplate.opsForHash().putAll(redisKey, convertMap(properties.entrySet(),
Map.Entry::getKey,
entry -> JsonUtils.toJsonString(entry.getValue())));
}
public void delete(String deviceKey) {
String redisKey = formatKey(deviceKey);
stringRedisTemplate.delete(redisKey);
}
private static String formatKey(String deviceKey) {
return String.format(DEVICE_PROPERTY, deviceKey);
}
}

View File

@ -0,0 +1,27 @@
package cn.iocoder.yudao.module.iot.dal.redis.device;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.iocoder.yudao.module.iot.dal.redis.RedisKeyConstants;
import jakarta.annotation.Resource;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Repository;
import java.time.LocalDateTime;
/**
* 设备的最后上报时间的 Redis DAO
*
* @author 芋道源码
*/
@Repository
public class DeviceReportTimeRedisDAO {
@Resource
private StringRedisTemplate stringRedisTemplate;
public void update(String deviceKey, LocalDateTime reportTime) {
stringRedisTemplate.opsForZSet().add(RedisKeyConstants.DEVICE_REPORT_TIME, deviceKey,
LocalDateTimeUtil.toEpochMilli(reportTime));
}
}

View File

@ -1,43 +0,0 @@
package cn.iocoder.yudao.module.iot.dal.redis.deviceData;
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDataDO;
import jakarta.annotation.Resource;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Repository;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.TimeUnit;
import static cn.iocoder.yudao.module.iot.dal.redis.RedisKeyConstants.DEVICE_PROPERTY_DATA;
/**
* {@link IotDeviceDataDO} Redis DAO
*/
@Repository
public class DeviceDataRedisDAO {
@Resource
private StringRedisTemplate stringRedisTemplate;
public IotDeviceDataDO get(String productKey, String deviceName, String identifier) {
String redisKey = formatKey(productKey, deviceName, identifier);
return JsonUtils.parseObject(stringRedisTemplate.opsForValue().get(redisKey), IotDeviceDataDO.class);
}
public void set(IotDeviceDataDO deviceData) {
String redisKey = formatKey(deviceData.getProductKey(), deviceData.getDeviceName(), deviceData.getIdentifier());
stringRedisTemplate.opsForValue().set(redisKey, JsonUtils.toJsonString(deviceData));
}
public void delete(String productKey, String deviceName, String identifier) {
String redisKey = formatKey(productKey, deviceName, identifier);
stringRedisTemplate.delete(redisKey);
}
private static String formatKey(String productKey, String deviceName, String identifier) {
return String.format(DEVICE_PROPERTY_DATA, productKey, deviceName, identifier);
}
}

View File

@ -77,6 +77,7 @@ public interface IotDevicePropertyDataMapper {
void alterProductPropertySTableDropField(@Param("productKey") String productKey, void alterProductPropertySTableDropField(@Param("productKey") String productKey,
@Param("field") TDengineTableField field); @Param("field") TDengineTableField field);
// TODO @芋艿待实现
/** /**
* 获取历史数据列表 * 获取历史数据列表
* *

View File

@ -39,7 +39,7 @@ public class EmqxServiceImpl implements EmqxService {
// .deviceName(deviceName) // .deviceName(deviceName)
// .properties(message) // TODO 芋艿临时去掉看看 // .properties(message) // TODO 芋艿临时去掉看看
.build(); .build();
iotDeviceDataService.saveDeviceData(createDTO); // iotDeviceDataService.saveDeviceProperty(createDTO);
} }
} }

View File

@ -1,5 +1,8 @@
package cn.iocoder.yudao.module.iot.mq.consumer.device; package cn.iocoder.yudao.module.iot.mq.consumer.device;
import cn.hutool.core.util.ObjectUtil;
import cn.iocoder.yudao.module.iot.enums.device.IotDeviceMessageIdentifierEnum;
import cn.iocoder.yudao.module.iot.enums.device.IotDeviceMessageTypeEnum;
import cn.iocoder.yudao.module.iot.mq.message.IotDeviceMessage; import cn.iocoder.yudao.module.iot.mq.message.IotDeviceMessage;
import cn.iocoder.yudao.module.iot.service.device.data.IotDevicePropertyService; import cn.iocoder.yudao.module.iot.service.device.data.IotDevicePropertyService;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@ -24,11 +27,14 @@ public class IotDevicePropertyMessageConsumer {
@EventListener @EventListener
@Async @Async
public void onMessage(IotDeviceMessage message) { public void onMessage(IotDeviceMessage message) {
if (ObjectUtil.notEqual(message.getType(), IotDeviceMessageTypeEnum.PROPERTY.getType())
|| ObjectUtil.notEqual(message.getIdentifier(), IotDeviceMessageIdentifierEnum.PROPERTY_REPORT.getIdentifier())) {
return;
}
log.info("[onMessage][消息内容({})]", message); log.info("[onMessage][消息内容({})]", message);
// 设备日志记录 // 保存设备属性
// TODO @芋艿重新写下 deviceDataService.saveDeviceProperty(message);
// deviceLogDataService.createDeviceLog(message);
} }
} }

View File

@ -113,6 +113,7 @@ public interface IotDeviceService {
*/ */
Long getDeviceCountByGroupId(Long groupId); Long getDeviceCountByGroupId(Long groupId);
// TODO @芋艿增加缓存
/** /**
* 根据产品 key 和设备名称获得设备信息 * 根据产品 key 和设备名称获得设备信息
* *

View File

@ -8,7 +8,6 @@ import cn.iocoder.yudao.framework.common.exception.ServiceException;
import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils; import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils;
import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils; import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils;
import cn.iocoder.yudao.module.iot.controller.admin.device.vo.device.*; import cn.iocoder.yudao.module.iot.controller.admin.device.vo.device.*;
import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO;
@ -247,7 +246,6 @@ public class IotDeviceServiceImpl implements IotDeviceService {
} }
@Override @Override
@TenantIgnore
public IotDeviceDO getDeviceByProductKeyAndDeviceName(String productKey, String deviceName) { public IotDeviceDO getDeviceByProductKeyAndDeviceName(String productKey, String deviceName) {
return deviceMapper.selectByProductKeyAndDeviceName(productKey, deviceName); return deviceMapper.selectByProductKeyAndDeviceName(productKey, deviceName);
} }

View File

@ -1,10 +1,10 @@
package cn.iocoder.yudao.module.iot.service.device.data; package cn.iocoder.yudao.module.iot.service.device.data;
import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.iot.api.device.dto.IotDevicePropertyReportReqDTO;
import cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData.IotDeviceDataPageReqVO; import cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData.IotDeviceDataPageReqVO;
import cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData.IotDeviceDataSimulatorSaveReqVO; import cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData.IotDeviceDataSimulatorSaveReqVO;
import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDataDO; import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDevicePropertyDO;
import cn.iocoder.yudao.module.iot.mq.message.IotDeviceMessage;
import jakarta.validation.Valid; import jakarta.validation.Valid;
import java.util.List; import java.util.List;
@ -27,9 +27,9 @@ public interface IotDevicePropertyService {
/** /**
* 保存设备数据 * 保存设备数据
* *
* @param createDTO 设备数据 * @param message 设备消息
*/ */
void saveDeviceData(IotDevicePropertyReportReqDTO createDTO); void saveDeviceProperty(IotDeviceMessage message);
/** /**
* 模拟设备 * 模拟设备
@ -44,7 +44,7 @@ public interface IotDevicePropertyService {
* @param deviceId 设备编号 * @param deviceId 设备编号
* @return 设备属性最新数据 * @return 设备属性最新数据
*/ */
List<IotDeviceDataDO> getLatestDeviceProperties(@Valid IotDeviceDataPageReqVO deviceId); List<IotDevicePropertyDO> getLatestDeviceProperties(@Valid IotDeviceDataPageReqVO deviceId);
/** /**
* 获得设备属性历史数据 * 获得设备属性历史数据

View File

@ -1,27 +1,26 @@
package cn.iocoder.yudao.module.iot.service.device.data; package cn.iocoder.yudao.module.iot.service.device.data;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
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.hutool.json.JSONObject; import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil; import cn.hutool.json.JSONUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.iot.api.device.dto.IotDevicePropertyReportReqDTO; import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils;
import cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData.IotDeviceDataPageReqVO; import cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData.IotDeviceDataPageReqVO;
import cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData.IotDeviceDataSimulatorSaveReqVO; import cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData.IotDeviceDataSimulatorSaveReqVO;
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.dal.dataobject.device.IotDeviceDO; import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO;
import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDataDO; import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDevicePropertyDO;
import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO; import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO;
import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.SelectVisualDO;
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.dal.redis.deviceData.DeviceDataRedisDAO; import cn.iocoder.yudao.module.iot.dal.redis.device.DevicePropertyRedisDAO;
import cn.iocoder.yudao.module.iot.dal.tdengine.IotDevicePropertyDataMapper; import cn.iocoder.yudao.module.iot.dal.tdengine.IotDevicePropertyDataMapper;
import cn.iocoder.yudao.module.iot.enums.IotConstants; import cn.iocoder.yudao.module.iot.enums.IotConstants;
import cn.iocoder.yudao.module.iot.enums.thingmodel.IotDataSpecsDataTypeEnum; import cn.iocoder.yudao.module.iot.enums.thingmodel.IotDataSpecsDataTypeEnum;
import cn.iocoder.yudao.module.iot.enums.thingmodel.IotThingModelTypeEnum; 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.framework.tdengine.core.TDengineTableField;
import cn.iocoder.yudao.module.iot.mq.message.IotDeviceMessage;
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.product.IotProductService; import cn.iocoder.yudao.module.iot.service.product.IotProductService;
import cn.iocoder.yudao.module.iot.service.thingmodel.IotThingModelService; import cn.iocoder.yudao.module.iot.service.thingmodel.IotThingModelService;
@ -31,15 +30,13 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.time.ZoneId;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.filterList;
import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.DEVICE_DATA_CONTENT_JSON_PARSE_ERROR; import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.DEVICE_DATA_CONTENT_JSON_PARSE_ERROR;
/** /**
@ -77,7 +74,7 @@ public class IotDevicePropertyServiceImpl implements IotDevicePropertyService {
private IotProductService productService; private IotProductService productService;
@Resource @Resource
private DeviceDataRedisDAO deviceDataRedisDAO; private DevicePropertyRedisDAO deviceDataRedisDAO;
@Resource @Resource
private IotDevicePropertyDataMapper devicePropertyDataMapper; private IotDevicePropertyDataMapper devicePropertyDataMapper;
@ -126,13 +123,41 @@ public class IotDevicePropertyServiceImpl implements IotDevicePropertyService {
} }
@Override @Override
public void saveDeviceData(IotDevicePropertyReportReqDTO createDTO) { public void saveDeviceProperty(IotDeviceMessage message) {
// TODO 芋艿这块需要实现 if (!(message.getData() instanceof Map)) {
// 1. 根据产品 key 和设备名称获得设备信息 log.error("[saveDeviceProperty][消息内容({}) 的 data 类型不正确]", message);
IotDeviceDO device = deviceService.getDeviceByProductKeyAndDeviceName(createDTO.getProductKey(), createDTO.getDeviceName()); return;
// 2. 解析消息保存数据 }
JSONObject jsonObject = new JSONObject(createDTO.getProperties()); // 1. 获得设备信息
log.info("[saveDeviceData][productKey({}) deviceName({}) data({})]", createDTO.getProductKey(), createDTO.getDeviceName(), jsonObject); IotDeviceDO device = TenantUtils.executeIgnore(() ->
deviceService.getDeviceByProductKeyAndDeviceName(message.getProductKey(), message.getDeviceName()));
if (device == null) {
log.error("[saveDeviceProperty][消息({}) 对应的设备不存在]", message);
return;
}
// 2. 根据物模型拼接合法的属性
List<IotThingModelDO> thingModels = TenantUtils.executeIgnore(() ->
thingModelService.getThingModelListByProductId(device.getProductId()));
Map<String, Object> properties = new HashMap<>();
((Map<?, ?>) message.getData()).forEach((key, value) -> {
if (CollUtil.findOne(thingModels, thingModel -> thingModel.getIdentifier().equals(key)) == null) {
log.error("[saveDeviceProperty][消息({}) 的属性({}) 不存在]", message, key);
return;
}
properties.put((String) key, value);
});
if (CollUtil.isEmpty(properties)) {
log.error("[saveDeviceProperty][消息({}) 没有合法的属性]", message);
return;
}
// 3.1 保存属性数据
// TODO 芋艿未实现
// 3.2 保存属性日志
deviceDataRedisDAO.set(message.getDeviceKey(), convertMap(properties.entrySet(), Map.Entry::getKey,
entry -> IotDevicePropertyDO.builder().value(entry.getValue()).updateTime(message.getReportTime()).build()));
} }
//TODO @芋艿:copy saveDeviceData 的逻辑后续看看这块怎么优化 //TODO @芋艿:copy saveDeviceData 的逻辑后续看看这块怎么优化
@ -163,62 +188,64 @@ public class IotDevicePropertyServiceImpl implements IotDevicePropertyService {
} }
@Override @Override
public List<IotDeviceDataDO> getLatestDeviceProperties(@Valid IotDeviceDataPageReqVO deviceDataReqVO) { public List<IotDevicePropertyDO> getLatestDeviceProperties(@Valid IotDeviceDataPageReqVO deviceDataReqVO) {
List<IotDeviceDataDO> list = new ArrayList<>(); // List<IotDevicePropertyDO> list = new ArrayList<>();
// 1. 获取设备信息 // // 1. 获取设备信息
IotDeviceDO device = deviceService.getDevice(deviceDataReqVO.getDeviceId()); // IotDeviceDO device = deviceService.getDevice(deviceDataReqVO.getDeviceId());
// 2. 获取设备属性最新数据 // // 2. 获取设备属性最新数据
List<IotThingModelDO> thingModelList = thingModelService.getProductThingModelListByProductKey(device.getProductKey()); // List<IotThingModelDO> thingModelList = thingModelService.getProductThingModelListByProductKey(device.getProductKey());
thingModelList = filterList(thingModelList, thingModel -> IotThingModelTypeEnum.PROPERTY.getType() // thingModelList = filterList(thingModelList, thingModel -> IotThingModelTypeEnum.PROPERTY.getType()
.equals(thingModel.getType())); // .equals(thingModel.getType()));
//
// 3. 过滤标识符和属性名称 // // 3. 过滤标识符和属性名称
if (deviceDataReqVO.getIdentifier() != null) { // if (deviceDataReqVO.getIdentifier() != null) {
thingModelList = filterList(thingModelList, thingModel -> thingModel.getIdentifier() // thingModelList = filterList(thingModelList, thingModel -> thingModel.getIdentifier()
.toLowerCase().contains(deviceDataReqVO.getIdentifier().toLowerCase())); // .toLowerCase().contains(deviceDataReqVO.getIdentifier().toLowerCase()));
} // }
if (deviceDataReqVO.getName() != null) { // if (deviceDataReqVO.getName() != null) {
thingModelList = filterList(thingModelList, thingModel -> thingModel.getName() // thingModelList = filterList(thingModelList, thingModel -> thingModel.getName()
.toLowerCase().contains(deviceDataReqVO.getName().toLowerCase())); // .toLowerCase().contains(deviceDataReqVO.getName().toLowerCase()));
} // }
// 4. 获取设备属性最新数据 // // 4. 获取设备属性最新数据
thingModelList.forEach(thingModel -> { // thingModelList.forEach(thingModel -> {
IotDeviceDataDO deviceData = deviceDataRedisDAO.get(device.getProductKey(), device.getDeviceName(), thingModel.getIdentifier()); // IotDevicePropertyDO deviceData = deviceDataRedisDAO.get(device.getProductKey(), device.getDeviceName(), thingModel.getIdentifier());
if (deviceData == null) { // if (deviceData == null) {
deviceData = new IotDeviceDataDO(); // deviceData = new IotDevicePropertyDO();
deviceData.setProductKey(device.getProductKey()); // deviceData.setProductKey(device.getProductKey());
deviceData.setDeviceName(device.getDeviceName()); // deviceData.setDeviceName(device.getDeviceName());
deviceData.setIdentifier(thingModel.getIdentifier()); // deviceData.setIdentifier(thingModel.getIdentifier());
deviceData.setDeviceId(deviceDataReqVO.getDeviceId()); // deviceData.setDeviceId(deviceDataReqVO.getDeviceId());
deviceData.setThingModelId(thingModel.getId()); // deviceData.setThingModelId(thingModel.getId());
deviceData.setName(thingModel.getName()); // deviceData.setName(thingModel.getName());
deviceData.setDataType(thingModel.getProperty().getDataType()); // deviceData.setDataType(thingModel.getProperty().getDataType());
} // }
list.add(deviceData); // list.add(deviceData);
}); // });
return list; // return list;
return null; // TODO 芋艿晚点实现
} }
@Override @Override
public PageResult<Map<String, Object>> getHistoryDeviceProperties(IotDeviceDataPageReqVO deviceDataReqVO) { public PageResult<Map<String, Object>> getHistoryDeviceProperties(IotDeviceDataPageReqVO deviceDataReqVO) {
PageResult<Map<String, Object>> pageResult = new PageResult<>(); // PageResult<Map<String, Object>> pageResult = new PageResult<>();
// 1. 获取设备信息 // // 1. 获取设备信息
IotDeviceDO device = deviceService.getDevice(deviceDataReqVO.getDeviceId()); // IotDeviceDO device = deviceService.getDevice(deviceDataReqVO.getDeviceId());
// 2. 获取设备属性历史数据 // // 2. 获取设备属性历史数据
SelectVisualDO selectVisualDO = new SelectVisualDO(); // SelectVisualDO selectVisualDO = new SelectVisualDO();
selectVisualDO.setDataBaseName(getDatabaseName()); // selectVisualDO.setDataBaseName(getDatabaseName());
selectVisualDO.setTableName(getDeviceTableName(device.getProductKey(), device.getDeviceName())); // selectVisualDO.setTableName(getDeviceTableName(device.getProductKey(), device.getDeviceName()));
selectVisualDO.setDeviceKey(device.getDeviceKey()); // selectVisualDO.setDeviceKey(device.getDeviceKey());
selectVisualDO.setFieldName(deviceDataReqVO.getIdentifier()); // selectVisualDO.setFieldName(deviceDataReqVO.getIdentifier());
selectVisualDO.setStartTime(DateUtil.date(deviceDataReqVO.getTimes()[0].atZone(ZoneId.systemDefault()).toInstant().toEpochMilli()).getTime()); // selectVisualDO.setStartTime(DateUtil.date(deviceDataReqVO.getTimes()[0].atZone(ZoneId.systemDefault()).toInstant().toEpochMilli()).getTime());
selectVisualDO.setEndTime(DateUtil.date(deviceDataReqVO.getTimes()[1].atZone(ZoneId.systemDefault()).toInstant().toEpochMilli()).getTime()); // selectVisualDO.setEndTime(DateUtil.date(deviceDataReqVO.getTimes()[1].atZone(ZoneId.systemDefault()).toInstant().toEpochMilli()).getTime());
Map<String, Object> params = new HashMap<>(); // Map<String, Object> params = new HashMap<>();
params.put("rows", deviceDataReqVO.getPageSize()); // params.put("rows", deviceDataReqVO.getPageSize());
params.put("page", (deviceDataReqVO.getPageNo() - 1) * deviceDataReqVO.getPageSize()); // params.put("page", (deviceDataReqVO.getPageNo() - 1) * deviceDataReqVO.getPageSize());
selectVisualDO.setParams(params); // selectVisualDO.setParams(params);
pageResult.setList(devicePropertyDataMapper.selectHistoryDataList(selectVisualDO)); // pageResult.setList(devicePropertyDataMapper.selectHistoryDataList(selectVisualDO));
pageResult.setTotal(devicePropertyDataMapper.selectHistoryCount(selectVisualDO)); // pageResult.setTotal(devicePropertyDataMapper.selectHistoryCount(selectVisualDO));
return pageResult; // return pageResult;
return null; // TODO 芋艿晚点实现
} }
private String getDatabaseName() { private String getDatabaseName() {

View File

@ -46,6 +46,7 @@ public interface IotThingModelService {
*/ */
IotThingModelDO getThingModel(Long id); IotThingModelDO getThingModel(Long id);
// TODO @芋艿增加缓存
/** /**
* 获得产品物模型列表 * 获得产品物模型列表
* *