Commit 8e80a53a8bb37fe40f9a1d1ee5f243ce0f7b1ed5

Authored by YunaiV
1 parent b319485c

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

Showing 15 changed files with 245 additions and 215 deletions
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/IotDeviceDataController.java
... ... @@ -4,7 +4,7 @@ import cn.iocoder.yudao.framework.common.pojo.CommonResult;
4 4 import cn.iocoder.yudao.framework.common.pojo.PageResult;
5 5 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
6 6 import cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData.*;
7   -import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDataDO;
  7 +import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDevicePropertyDO;
8 8 import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceLogDO;
9 9 import cn.iocoder.yudao.module.iot.service.device.data.IotDeviceLogService;
10 10 import cn.iocoder.yudao.module.iot.service.device.data.IotDevicePropertyService;
... ... @@ -28,18 +28,14 @@ public class IotDeviceDataController {
28 28  
29 29 @Resource
30 30 private IotDevicePropertyService deviceDataService;
31   -
32 31 @Resource
33   - private IotDeviceLogService iotDeviceLogDataService;
34   -
35   - @Resource // TODO @super:service 之间,不用空行;原因是,这样更简洁;空行,主要是为了“间隔”,提升可读性
36 32 private IotDeviceLogService deviceLogDataService;
37 33  
38 34 // TODO @浩浩:这里的 /latest-list,包括方法名。
39 35 @GetMapping("/latest")
40 36 @Operation(summary = "获取设备属性最新数据")
41 37 public CommonResult<List<IotDeviceDataRespVO>> getLatestDeviceProperties(@Valid IotDeviceDataPageReqVO deviceDataReqVO) {
42   - List<IotDeviceDataDO> list = deviceDataService.getLatestDeviceProperties(deviceDataReqVO);
  38 + List<IotDevicePropertyDO> list = deviceDataService.getLatestDeviceProperties(deviceDataReqVO);
43 39 return success(BeanUtils.toBean(list, IotDeviceDataRespVO.class));
44 40 }
45 41  
... ...
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/device/IotDeviceDataDO.java deleted
1   -package cn.iocoder.yudao.module.iot.dal.dataobject.device;
2   -
3   -import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO;
4   -import cn.iocoder.yudao.module.iot.dal.dataobject.thingmodel.IotThingModelDO;
5   -import lombok.AllArgsConstructor;
6   -import lombok.Builder;
7   -import lombok.Data;
8   -import lombok.NoArgsConstructor;
9   -
10   -import java.time.LocalDateTime;
11   -
12   -/**
13   - * IoT 设备数据 DO
14   - *
15   - * @author haohao
16   - */
17   -@Data
18   -@Builder
19   -@NoArgsConstructor
20   -@AllArgsConstructor
21   -public class IotDeviceDataDO {
22   -
23   - /**
24   - * 设备编号
25   - * <p>
26   - * 关联 {@link IotDeviceDO#getId()}
27   - */
28   - private Long deviceId;
29   -
30   - /**
31   - * 物模型编号
32   - * <p>
33   - * 关联 {@link IotThingModelDO#getId()}
34   - */
35   - private Long thingModelId;
36   -
37   - /**
38   - * 产品标识
39   - * <p>
40   - * 关联 {@link IotProductDO#getProductKey()}
41   - */
42   - private String productKey;
43   -
44   - /**
45   - * 设备名称
46   - * <p>
47   - * 冗余 {@link IotDeviceDO#getDeviceName()}
48   - */
49   - private String deviceName;
50   -
51   - /**
52   - * 属性标识符
53   - * <p>
54   - * 关联 {@link IotThingModelDO#getIdentifier()}
55   - */
56   - private String identifier;
57   -
58   - /**
59   - * 属性名称
60   - * <p>
61   - * 关联 {@link IotThingModelDO#getName()}
62   - */
63   - private String name;
64   -
65   - /**
66   - * 数据类型
67   - * <p>
68   - * 关联 {@link IotThingModelDO#getProperty()#getDataType()}
69   - */
70   - private String dataType;
71   -
72   - /**
73   - * 更新时间
74   - */
75   - private LocalDateTime updateTime;
76   -
77   - /**
78   - * 最新值
79   - */
80   - private String value;
81   -
82   -}
83 0 \ No newline at end of file
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/device/IotDevicePropertyDO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.iot.dal.dataobject.device;
  2 +
  3 +import cn.iocoder.yudao.module.iot.dal.redis.device.DevicePropertyRedisDAO;
  4 +import lombok.AllArgsConstructor;
  5 +import lombok.Builder;
  6 +import lombok.Data;
  7 +import lombok.NoArgsConstructor;
  8 +
  9 +import java.time.LocalDateTime;
  10 +
  11 +/**
  12 + * IoT 设备属性项 Redis DO
  13 + *
  14 + * @see cn.iocoder.yudao.module.iot.dal.redis.RedisKeyConstants#DEVICE_PROPERTY
  15 + * @see DevicePropertyRedisDAO
  16 + *
  17 + * @author haohao
  18 + */
  19 +@Data
  20 +@Builder
  21 +@NoArgsConstructor
  22 +@AllArgsConstructor
  23 +public class IotDevicePropertyDO {
  24 +
  25 + /**
  26 + * 属性值(最新)
  27 + */
  28 + private Object value;
  29 +
  30 + /**
  31 + * 更新时间
  32 + */
  33 + private LocalDateTime updateTime;
  34 +
  35 +}
0 36 \ No newline at end of file
... ...
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/redis/RedisKeyConstants.java
1 1 package cn.iocoder.yudao.module.iot.dal.redis;
2 2  
3   -
  3 +import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDevicePropertyDO;
4 4  
5 5 /**
6 6 * Iot Redis Key 枚举类
... ... @@ -10,11 +10,20 @@ package cn.iocoder.yudao.module.iot.dal.redis;
10 10 public interface RedisKeyConstants {
11 11  
12 12 /**
13   - * 设备属性数据缓存
  13 + * 设备属性数据缓存,采用 HASH 结构
14 14 * <p>
15   - * KEY 格式:device_property_data:{deviceId}
16   - * VALUE 数据类型:String 设备属性数据
  15 + * KEY 格式:device_property:{deviceKey}
  16 + * HASH KEY:identifier 属性标识
  17 + * VALUE 数据类型:String(JSON) {@link IotDevicePropertyDO}
  18 + */
  19 + String DEVICE_PROPERTY = "device_property:%s";
  20 +
  21 + /**
  22 + * 设备的最后上报时间,采用 ZSET 结构
  23 + *
  24 + * KEY 格式:{deviceKey}
  25 + * SCORE:上报时间
17 26 */
18   - String DEVICE_PROPERTY_DATA = "device_property_data:%s_%s_%s";
  27 + String DEVICE_REPORT_TIME = "device_report_time";
19 28  
20 29 }
... ...
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/redis/device/DevicePropertyRedisDAO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.iot.dal.redis.device;
  2 +
  3 +import cn.hutool.core.collection.CollUtil;
  4 +import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
  5 +import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDevicePropertyDO;
  6 +import jakarta.annotation.Resource;
  7 +import org.springframework.data.redis.core.StringRedisTemplate;
  8 +import org.springframework.stereotype.Repository;
  9 +
  10 +import java.util.Collections;
  11 +import java.util.Map;
  12 +
  13 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
  14 +import static cn.iocoder.yudao.module.iot.dal.redis.RedisKeyConstants.DEVICE_PROPERTY;
  15 +
  16 +/**
  17 + * {@link IotDevicePropertyDO} 的 Redis DAO
  18 + */
  19 +@Repository
  20 +public class DevicePropertyRedisDAO {
  21 +
  22 + @Resource
  23 + private StringRedisTemplate stringRedisTemplate;
  24 +
  25 + public Map<String, IotDevicePropertyDO> get(String deviceKey) {
  26 + String redisKey = formatKey(deviceKey);
  27 + Map<Object, Object> entries = stringRedisTemplate.opsForHash().entries(redisKey);
  28 + if (CollUtil.isEmpty(entries)) {
  29 + return Collections.emptyMap();
  30 + }
  31 + return convertMap(entries.values(), key -> (String) key,
  32 + value -> JsonUtils.parseObject((String) value, IotDevicePropertyDO.class));
  33 + }
  34 +
  35 + public void set(String deviceKey, Map<String, IotDevicePropertyDO> properties) {
  36 + if (CollUtil.isEmpty(properties)) {
  37 + return;
  38 + }
  39 + String redisKey = formatKey(deviceKey);
  40 + stringRedisTemplate.opsForHash().putAll(redisKey, convertMap(properties.entrySet(),
  41 + Map.Entry::getKey,
  42 + entry -> JsonUtils.toJsonString(entry.getValue())));
  43 + }
  44 +
  45 + public void delete(String deviceKey) {
  46 + String redisKey = formatKey(deviceKey);
  47 + stringRedisTemplate.delete(redisKey);
  48 + }
  49 +
  50 + private static String formatKey(String deviceKey) {
  51 + return String.format(DEVICE_PROPERTY, deviceKey);
  52 + }
  53 +
  54 +}
... ...
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/redis/device/DeviceReportTimeRedisDAO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.iot.dal.redis.device;
  2 +
  3 +import cn.hutool.core.date.LocalDateTimeUtil;
  4 +import cn.iocoder.yudao.module.iot.dal.redis.RedisKeyConstants;
  5 +import jakarta.annotation.Resource;
  6 +import org.springframework.data.redis.core.StringRedisTemplate;
  7 +import org.springframework.stereotype.Repository;
  8 +
  9 +import java.time.LocalDateTime;
  10 +
  11 +/**
  12 + * 设备的最后上报时间的 Redis DAO
  13 + *
  14 + * @author 芋道源码
  15 + */
  16 +@Repository
  17 +public class DeviceReportTimeRedisDAO {
  18 +
  19 + @Resource
  20 + private StringRedisTemplate stringRedisTemplate;
  21 +
  22 + public void update(String deviceKey, LocalDateTime reportTime) {
  23 + stringRedisTemplate.opsForZSet().add(RedisKeyConstants.DEVICE_REPORT_TIME, deviceKey,
  24 + LocalDateTimeUtil.toEpochMilli(reportTime));
  25 + }
  26 +
  27 +}
... ...
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/redis/deviceData/DeviceDataRedisDAO.java deleted
1   -package cn.iocoder.yudao.module.iot.dal.redis.deviceData;
2   -
3   -import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
4   -import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
5   -import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDataDO;
6   -import jakarta.annotation.Resource;
7   -import org.springframework.data.redis.core.StringRedisTemplate;
8   -import org.springframework.stereotype.Repository;
9   -
10   -import java.util.Collection;
11   -import java.util.List;
12   -import java.util.concurrent.TimeUnit;
13   -
14   -import static cn.iocoder.yudao.module.iot.dal.redis.RedisKeyConstants.DEVICE_PROPERTY_DATA;
15   -
16   -/**
17   - * {@link IotDeviceDataDO} 的 Redis DAO
18   - */
19   -@Repository
20   -public class DeviceDataRedisDAO {
21   -
22   - @Resource
23   - private StringRedisTemplate stringRedisTemplate;
24   -
25   - public IotDeviceDataDO get(String productKey, String deviceName, String identifier) {
26   - String redisKey = formatKey(productKey, deviceName, identifier);
27   - return JsonUtils.parseObject(stringRedisTemplate.opsForValue().get(redisKey), IotDeviceDataDO.class);
28   - }
29   -
30   - public void set(IotDeviceDataDO deviceData) {
31   - String redisKey = formatKey(deviceData.getProductKey(), deviceData.getDeviceName(), deviceData.getIdentifier());
32   - stringRedisTemplate.opsForValue().set(redisKey, JsonUtils.toJsonString(deviceData));
33   - }
34   -
35   - public void delete(String productKey, String deviceName, String identifier) {
36   - String redisKey = formatKey(productKey, deviceName, identifier);
37   - stringRedisTemplate.delete(redisKey);
38   - }
39   -
40   - private static String formatKey(String productKey, String deviceName, String identifier) {
41   - return String.format(DEVICE_PROPERTY_DATA, productKey, deviceName, identifier);
42   - }
43   -}
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/IotDevicePropertyDataMapper.java
... ... @@ -77,6 +77,7 @@ public interface IotDevicePropertyDataMapper {
77 77 void alterProductPropertySTableDropField(@Param("productKey") String productKey,
78 78 @Param("field") TDengineTableField field);
79 79  
  80 + // TODO @芋艿:待实现
80 81 /**
81 82 * 获取历史数据列表
82 83 *
... ...
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/emq/service/EmqxServiceImpl.java
... ... @@ -39,7 +39,7 @@ public class EmqxServiceImpl implements EmqxService {
39 39 // .deviceName(deviceName)
40 40 // .properties(message) // TODO 芋艿:临时去掉,看看
41 41 .build();
42   - iotDeviceDataService.saveDeviceData(createDTO);
  42 +// iotDeviceDataService.saveDeviceProperty(createDTO);
43 43 }
44 44 }
45 45  
... ...
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/mq/consumer/device/IotDevicePropertyMessageConsumer.java
1 1 package cn.iocoder.yudao.module.iot.mq.consumer.device;
2 2  
  3 +import cn.hutool.core.util.ObjectUtil;
  4 +import cn.iocoder.yudao.module.iot.enums.device.IotDeviceMessageIdentifierEnum;
  5 +import cn.iocoder.yudao.module.iot.enums.device.IotDeviceMessageTypeEnum;
3 6 import cn.iocoder.yudao.module.iot.mq.message.IotDeviceMessage;
4 7 import cn.iocoder.yudao.module.iot.service.device.data.IotDevicePropertyService;
5 8 import lombok.extern.slf4j.Slf4j;
... ... @@ -24,11 +27,14 @@ public class IotDevicePropertyMessageConsumer {
24 27 @EventListener
25 28 @Async
26 29 public void onMessage(IotDeviceMessage message) {
  30 + if (ObjectUtil.notEqual(message.getType(), IotDeviceMessageTypeEnum.PROPERTY.getType())
  31 + || ObjectUtil.notEqual(message.getIdentifier(), IotDeviceMessageIdentifierEnum.PROPERTY_REPORT.getIdentifier())) {
  32 + return;
  33 + }
27 34 log.info("[onMessage][消息内容({})]", message);
28 35  
29   - // 设备日志记录
30   - // TODO @芋艿:重新写下
31   -// deviceLogDataService.createDeviceLog(message);
  36 + // 保存设备属性
  37 + deviceDataService.saveDeviceProperty(message);
32 38 }
33 39  
34 40 }
... ...
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceService.java
... ... @@ -113,6 +113,7 @@ public interface IotDeviceService {
113 113 */
114 114 Long getDeviceCountByGroupId(Long groupId);
115 115  
  116 + // TODO @芋艿:增加缓存
116 117 /**
117 118 * 根据产品 key 和设备名称,获得设备信息
118 119 *
... ...
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceServiceImpl.java
... ... @@ -8,7 +8,6 @@ import cn.iocoder.yudao.framework.common.exception.ServiceException;
8 8 import cn.iocoder.yudao.framework.common.pojo.PageResult;
9 9 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
10 10 import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils;
11   -import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
12 11 import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils;
13 12 import cn.iocoder.yudao.module.iot.controller.admin.device.vo.device.*;
14 13 import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO;
... ... @@ -247,7 +246,6 @@ public class IotDeviceServiceImpl implements IotDeviceService {
247 246 }
248 247  
249 248 @Override
250   - @TenantIgnore
251 249 public IotDeviceDO getDeviceByProductKeyAndDeviceName(String productKey, String deviceName) {
252 250 return deviceMapper.selectByProductKeyAndDeviceName(productKey, deviceName);
253 251 }
... ...
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/data/IotDevicePropertyService.java
1 1 package cn.iocoder.yudao.module.iot.service.device.data;
2 2  
3 3 import cn.iocoder.yudao.framework.common.pojo.PageResult;
4   -import cn.iocoder.yudao.module.iot.api.device.dto.IotDevicePropertyReportReqDTO;
5 4 import cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData.IotDeviceDataPageReqVO;
6 5 import cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData.IotDeviceDataSimulatorSaveReqVO;
7   -import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDataDO;
  6 +import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDevicePropertyDO;
  7 +import cn.iocoder.yudao.module.iot.mq.message.IotDeviceMessage;
8 8 import jakarta.validation.Valid;
9 9  
10 10 import java.util.List;
... ... @@ -27,9 +27,9 @@ public interface IotDevicePropertyService {
27 27 /**
28 28 * 保存设备数据
29 29 *
30   - * @param createDTO 设备数据
  30 + * @param message 设备消息
31 31 */
32   - void saveDeviceData(IotDevicePropertyReportReqDTO createDTO);
  32 + void saveDeviceProperty(IotDeviceMessage message);
33 33  
34 34 /**
35 35 * 模拟设备
... ... @@ -44,7 +44,7 @@ public interface IotDevicePropertyService {
44 44 * @param deviceId 设备编号
45 45 * @return 设备属性最新数据
46 46 */
47   - List<IotDeviceDataDO> getLatestDeviceProperties(@Valid IotDeviceDataPageReqVO deviceId);
  47 + List<IotDevicePropertyDO> getLatestDeviceProperties(@Valid IotDeviceDataPageReqVO deviceId);
48 48  
49 49 /**
50 50 * 获得设备属性历史数据
... ...
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/data/IotDevicePropertyServiceImpl.java
1 1 package cn.iocoder.yudao.module.iot.service.device.data;
2 2  
3 3 import cn.hutool.core.collection.CollUtil;
4   -import cn.hutool.core.date.DateUtil;
5 4 import cn.hutool.core.map.MapUtil;
6 5 import cn.hutool.core.util.StrUtil;
7 6 import cn.hutool.json.JSONObject;
8 7 import cn.hutool.json.JSONUtil;
9 8 import cn.iocoder.yudao.framework.common.pojo.PageResult;
10   -import cn.iocoder.yudao.module.iot.api.device.dto.IotDevicePropertyReportReqDTO;
  9 +import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils;
11 10 import cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData.IotDeviceDataPageReqVO;
12 11 import cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData.IotDeviceDataSimulatorSaveReqVO;
13 12 import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.model.dataType.ThingModelDateOrTextDataSpecs;
14 13 import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO;
15   -import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDataDO;
  14 +import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDevicePropertyDO;
16 15 import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO;
17   -import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.SelectVisualDO;
18 16 import cn.iocoder.yudao.module.iot.dal.dataobject.thingmodel.IotThingModelDO;
19   -import cn.iocoder.yudao.module.iot.dal.redis.deviceData.DeviceDataRedisDAO;
  17 +import cn.iocoder.yudao.module.iot.dal.redis.device.DevicePropertyRedisDAO;
20 18 import cn.iocoder.yudao.module.iot.dal.tdengine.IotDevicePropertyDataMapper;
21 19 import cn.iocoder.yudao.module.iot.enums.IotConstants;
22 20 import cn.iocoder.yudao.module.iot.enums.thingmodel.IotDataSpecsDataTypeEnum;
23 21 import cn.iocoder.yudao.module.iot.enums.thingmodel.IotThingModelTypeEnum;
24 22 import cn.iocoder.yudao.module.iot.framework.tdengine.core.TDengineTableField;
  23 +import cn.iocoder.yudao.module.iot.mq.message.IotDeviceMessage;
25 24 import cn.iocoder.yudao.module.iot.service.device.IotDeviceService;
26 25 import cn.iocoder.yudao.module.iot.service.product.IotProductService;
27 26 import cn.iocoder.yudao.module.iot.service.thingmodel.IotThingModelService;
... ... @@ -31,15 +30,13 @@ import lombok.extern.slf4j.Slf4j;
31 30 import org.springframework.beans.factory.annotation.Value;
32 31 import org.springframework.stereotype.Service;
33 32  
34   -import java.time.ZoneId;
35 33 import java.util.ArrayList;
36 34 import java.util.HashMap;
37 35 import java.util.List;
38 36 import java.util.Map;
39 37  
40 38 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
41   -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
42   -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.filterList;
  39 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;
43 40 import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.DEVICE_DATA_CONTENT_JSON_PARSE_ERROR;
44 41  
45 42 /**
... ... @@ -77,7 +74,7 @@ public class IotDevicePropertyServiceImpl implements IotDevicePropertyService {
77 74 private IotProductService productService;
78 75  
79 76 @Resource
80   - private DeviceDataRedisDAO deviceDataRedisDAO;
  77 + private DevicePropertyRedisDAO deviceDataRedisDAO;
81 78  
82 79 @Resource
83 80 private IotDevicePropertyDataMapper devicePropertyDataMapper;
... ... @@ -126,13 +123,41 @@ public class IotDevicePropertyServiceImpl implements IotDevicePropertyService {
126 123 }
127 124  
128 125 @Override
129   - public void saveDeviceData(IotDevicePropertyReportReqDTO createDTO) {
130   - // TODO 芋艿:这块需要实现
131   - // 1. 根据产品 key 和设备名称,获得设备信息
132   - IotDeviceDO device = deviceService.getDeviceByProductKeyAndDeviceName(createDTO.getProductKey(), createDTO.getDeviceName());
133   - // 2. 解析消息,保存数据
134   - JSONObject jsonObject = new JSONObject(createDTO.getProperties());
135   - log.info("[saveDeviceData][productKey({}) deviceName({}) data({})]", createDTO.getProductKey(), createDTO.getDeviceName(), jsonObject);
  126 + public void saveDeviceProperty(IotDeviceMessage message) {
  127 + if (!(message.getData() instanceof Map)) {
  128 + log.error("[saveDeviceProperty][消息内容({}) 的 data 类型不正确]", message);
  129 + return;
  130 + }
  131 + // 1. 获得设备信息
  132 + IotDeviceDO device = TenantUtils.executeIgnore(() ->
  133 + deviceService.getDeviceByProductKeyAndDeviceName(message.getProductKey(), message.getDeviceName()));
  134 + if (device == null) {
  135 + log.error("[saveDeviceProperty][消息({}) 对应的设备不存在]", message);
  136 + return;
  137 + }
  138 +
  139 + // 2. 根据物模型,拼接合法的属性
  140 + List<IotThingModelDO> thingModels = TenantUtils.executeIgnore(() ->
  141 + thingModelService.getThingModelListByProductId(device.getProductId()));
  142 + Map<String, Object> properties = new HashMap<>();
  143 + ((Map<?, ?>) message.getData()).forEach((key, value) -> {
  144 + if (CollUtil.findOne(thingModels, thingModel -> thingModel.getIdentifier().equals(key)) == null) {
  145 + log.error("[saveDeviceProperty][消息({}) 的属性({}) 不存在]", message, key);
  146 + return;
  147 + }
  148 + properties.put((String) key, value);
  149 + });
  150 + if (CollUtil.isEmpty(properties)) {
  151 + log.error("[saveDeviceProperty][消息({}) 没有合法的属性]", message);
  152 + return;
  153 + }
  154 +
  155 + // 3.1 保存属性【数据】
  156 + // TODO 芋艿,未实现
  157 +
  158 + // 3.2 保存属性【日志】
  159 + deviceDataRedisDAO.set(message.getDeviceKey(), convertMap(properties.entrySet(), Map.Entry::getKey,
  160 + entry -> IotDevicePropertyDO.builder().value(entry.getValue()).updateTime(message.getReportTime()).build()));
136 161 }
137 162  
138 163 //TODO @芋艿:copy 了 saveDeviceData 的逻辑,后续看看这块怎么优化
... ... @@ -163,62 +188,64 @@ public class IotDevicePropertyServiceImpl implements IotDevicePropertyService {
163 188 }
164 189  
165 190 @Override
166   - public List<IotDeviceDataDO> getLatestDeviceProperties(@Valid IotDeviceDataPageReqVO deviceDataReqVO) {
167   - List<IotDeviceDataDO> list = new ArrayList<>();
168   - // 1. 获取设备信息
169   - IotDeviceDO device = deviceService.getDevice(deviceDataReqVO.getDeviceId());
170   - // 2. 获取设备属性最新数据
171   - List<IotThingModelDO> thingModelList = thingModelService.getProductThingModelListByProductKey(device.getProductKey());
172   - thingModelList = filterList(thingModelList, thingModel -> IotThingModelTypeEnum.PROPERTY.getType()
173   - .equals(thingModel.getType()));
174   -
175   - // 3. 过滤标识符和属性名称
176   - if (deviceDataReqVO.getIdentifier() != null) {
177   - thingModelList = filterList(thingModelList, thingModel -> thingModel.getIdentifier()
178   - .toLowerCase().contains(deviceDataReqVO.getIdentifier().toLowerCase()));
179   - }
180   - if (deviceDataReqVO.getName() != null) {
181   - thingModelList = filterList(thingModelList, thingModel -> thingModel.getName()
182   - .toLowerCase().contains(deviceDataReqVO.getName().toLowerCase()));
183   - }
184   - // 4. 获取设备属性最新数据
185   - thingModelList.forEach(thingModel -> {
186   - IotDeviceDataDO deviceData = deviceDataRedisDAO.get(device.getProductKey(), device.getDeviceName(), thingModel.getIdentifier());
187   - if (deviceData == null) {
188   - deviceData = new IotDeviceDataDO();
189   - deviceData.setProductKey(device.getProductKey());
190   - deviceData.setDeviceName(device.getDeviceName());
191   - deviceData.setIdentifier(thingModel.getIdentifier());
192   - deviceData.setDeviceId(deviceDataReqVO.getDeviceId());
193   - deviceData.setThingModelId(thingModel.getId());
194   - deviceData.setName(thingModel.getName());
195   - deviceData.setDataType(thingModel.getProperty().getDataType());
196   - }
197   - list.add(deviceData);
198   - });
199   - return list;
  191 + public List<IotDevicePropertyDO> getLatestDeviceProperties(@Valid IotDeviceDataPageReqVO deviceDataReqVO) {
  192 +// List<IotDevicePropertyDO> list = new ArrayList<>();
  193 +// // 1. 获取设备信息
  194 +// IotDeviceDO device = deviceService.getDevice(deviceDataReqVO.getDeviceId());
  195 +// // 2. 获取设备属性最新数据
  196 +// List<IotThingModelDO> thingModelList = thingModelService.getProductThingModelListByProductKey(device.getProductKey());
  197 +// thingModelList = filterList(thingModelList, thingModel -> IotThingModelTypeEnum.PROPERTY.getType()
  198 +// .equals(thingModel.getType()));
  199 +//
  200 +// // 3. 过滤标识符和属性名称
  201 +// if (deviceDataReqVO.getIdentifier() != null) {
  202 +// thingModelList = filterList(thingModelList, thingModel -> thingModel.getIdentifier()
  203 +// .toLowerCase().contains(deviceDataReqVO.getIdentifier().toLowerCase()));
  204 +// }
  205 +// if (deviceDataReqVO.getName() != null) {
  206 +// thingModelList = filterList(thingModelList, thingModel -> thingModel.getName()
  207 +// .toLowerCase().contains(deviceDataReqVO.getName().toLowerCase()));
  208 +// }
  209 +// // 4. 获取设备属性最新数据
  210 +// thingModelList.forEach(thingModel -> {
  211 +// IotDevicePropertyDO deviceData = deviceDataRedisDAO.get(device.getProductKey(), device.getDeviceName(), thingModel.getIdentifier());
  212 +// if (deviceData == null) {
  213 +// deviceData = new IotDevicePropertyDO();
  214 +// deviceData.setProductKey(device.getProductKey());
  215 +// deviceData.setDeviceName(device.getDeviceName());
  216 +// deviceData.setIdentifier(thingModel.getIdentifier());
  217 +// deviceData.setDeviceId(deviceDataReqVO.getDeviceId());
  218 +// deviceData.setThingModelId(thingModel.getId());
  219 +// deviceData.setName(thingModel.getName());
  220 +// deviceData.setDataType(thingModel.getProperty().getDataType());
  221 +// }
  222 +// list.add(deviceData);
  223 +// });
  224 +// return list;
  225 + return null; // TODO 芋艿:晚点实现
200 226 }
201 227  
202 228 @Override
203 229 public PageResult<Map<String, Object>> getHistoryDeviceProperties(IotDeviceDataPageReqVO deviceDataReqVO) {
204   - PageResult<Map<String, Object>> pageResult = new PageResult<>();
205   - // 1. 获取设备信息
206   - IotDeviceDO device = deviceService.getDevice(deviceDataReqVO.getDeviceId());
207   - // 2. 获取设备属性历史数据
208   - SelectVisualDO selectVisualDO = new SelectVisualDO();
209   - selectVisualDO.setDataBaseName(getDatabaseName());
210   - selectVisualDO.setTableName(getDeviceTableName(device.getProductKey(), device.getDeviceName()));
211   - selectVisualDO.setDeviceKey(device.getDeviceKey());
212   - selectVisualDO.setFieldName(deviceDataReqVO.getIdentifier());
213   - selectVisualDO.setStartTime(DateUtil.date(deviceDataReqVO.getTimes()[0].atZone(ZoneId.systemDefault()).toInstant().toEpochMilli()).getTime());
214   - selectVisualDO.setEndTime(DateUtil.date(deviceDataReqVO.getTimes()[1].atZone(ZoneId.systemDefault()).toInstant().toEpochMilli()).getTime());
215   - Map<String, Object> params = new HashMap<>();
216   - params.put("rows", deviceDataReqVO.getPageSize());
217   - params.put("page", (deviceDataReqVO.getPageNo() - 1) * deviceDataReqVO.getPageSize());
218   - selectVisualDO.setParams(params);
219   - pageResult.setList(devicePropertyDataMapper.selectHistoryDataList(selectVisualDO));
220   - pageResult.setTotal(devicePropertyDataMapper.selectHistoryCount(selectVisualDO));
221   - return pageResult;
  230 +// PageResult<Map<String, Object>> pageResult = new PageResult<>();
  231 +// // 1. 获取设备信息
  232 +// IotDeviceDO device = deviceService.getDevice(deviceDataReqVO.getDeviceId());
  233 +// // 2. 获取设备属性历史数据
  234 +// SelectVisualDO selectVisualDO = new SelectVisualDO();
  235 +// selectVisualDO.setDataBaseName(getDatabaseName());
  236 +// selectVisualDO.setTableName(getDeviceTableName(device.getProductKey(), device.getDeviceName()));
  237 +// selectVisualDO.setDeviceKey(device.getDeviceKey());
  238 +// selectVisualDO.setFieldName(deviceDataReqVO.getIdentifier());
  239 +// selectVisualDO.setStartTime(DateUtil.date(deviceDataReqVO.getTimes()[0].atZone(ZoneId.systemDefault()).toInstant().toEpochMilli()).getTime());
  240 +// selectVisualDO.setEndTime(DateUtil.date(deviceDataReqVO.getTimes()[1].atZone(ZoneId.systemDefault()).toInstant().toEpochMilli()).getTime());
  241 +// Map<String, Object> params = new HashMap<>();
  242 +// params.put("rows", deviceDataReqVO.getPageSize());
  243 +// params.put("page", (deviceDataReqVO.getPageNo() - 1) * deviceDataReqVO.getPageSize());
  244 +// selectVisualDO.setParams(params);
  245 +// pageResult.setList(devicePropertyDataMapper.selectHistoryDataList(selectVisualDO));
  246 +// pageResult.setTotal(devicePropertyDataMapper.selectHistoryCount(selectVisualDO));
  247 +// return pageResult;
  248 + return null; // TODO 芋艿:晚点实现
222 249 }
223 250  
224 251 private String getDatabaseName() {
... ...
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thingmodel/IotThingModelService.java
... ... @@ -46,6 +46,7 @@ public interface IotThingModelService {
46 46 */
47 47 IotThingModelDO getThingModel(Long id);
48 48  
  49 + // TODO @芋艿:增加缓存
49 50 /**
50 51 * 获得产品物模型列表
51 52 *
... ...