xucaiqin 2 роки тому
батько
коміт
8323c8f9b1
26 змінених файлів з 577 додано та 119 видалено
  1. 7 1
      iot-framework/iot-starter-redis/src/main/java/com/middle/platform/redis/constant/CacheConstant.java
  2. 10 0
      iot-framework/iot-starter-redis/src/main/java/com/middle/platform/redis/service/CacheService.java
  3. 13 0
      iot-module/iot-module-data/iot-module-data-api/src/main/java/com/middle/platform/data/api/feign/DataApi.java
  4. 19 0
      iot-module/iot-module-data/iot-module-data-api/src/main/java/com/middle/platform/data/api/pojo/ModPara.java
  5. 21 0
      iot-module/iot-module-data/iot-module-data-biz/src/main/java/com/middle/platform/data/biz/api/DataApiImpl.java
  6. 2 1
      iot-module/iot-module-data/iot-module-data-biz/src/main/java/com/middle/platform/data/biz/config/FeignConfig.java
  7. 4 19
      iot-module/iot-module-data/iot-module-data-biz/src/main/java/com/middle/platform/data/biz/controller/IndexController.java
  8. 44 0
      iot-module/iot-module-data/iot-module-data-biz/src/main/java/com/middle/platform/data/biz/controller/PropertyController.java
  9. 9 0
      iot-module/iot-module-data/iot-module-data-biz/src/main/java/com/middle/platform/data/biz/mapper/TaosMapper.java
  10. 23 0
      iot-module/iot-module-data/iot-module-data-biz/src/main/java/com/middle/platform/data/biz/pojo/HistoryPara.java
  11. 39 0
      iot-module/iot-module-data/iot-module-data-biz/src/main/java/com/middle/platform/data/biz/pojo/PropertyDto.java
  12. 25 0
      iot-module/iot-module-data/iot-module-data-biz/src/main/java/com/middle/platform/data/biz/pojo/PropertyVo.java
  13. 101 0
      iot-module/iot-module-data/iot-module-data-biz/src/main/java/com/middle/platform/data/biz/service/DataAnalyseService.java
  14. 46 59
      iot-module/iot-module-data/iot-module-data-biz/src/main/java/com/middle/platform/data/biz/service/DataService.java
  15. 43 16
      iot-module/iot-module-data/iot-module-data-biz/src/main/java/com/middle/platform/data/biz/service/ProductAnalyse.java
  16. 6 11
      iot-module/iot-module-data/iot-module-data-biz/src/main/java/com/middle/platform/data/biz/service/http/HttpService.java
  17. 5 9
      iot-module/iot-module-data/iot-module-data-biz/src/main/java/com/middle/platform/data/biz/service/mqtt/strategy/AttrReportStrategy.java
  18. 23 0
      iot-module/iot-module-data/iot-module-data-biz/src/main/resources/mapper/TaosMapper.xml
  19. 27 0
      iot-module/iot-module-manage/iot-module-manage-api/src/main/java/com/middle/platform/manage/api/feign/DeviceApi.java
  20. 1 1
      iot-module/iot-module-manage/iot-module-manage-api/src/main/java/com/middle/platform/manage/api/feign/ProductApi.java
  21. 36 0
      iot-module/iot-module-manage/iot-module-manage-api/src/main/java/com/middle/platform/manage/api/pojo/DeviceVo.java
  22. 22 0
      iot-module/iot-module-manage/iot-module-manage-biz/src/main/java/com/middle/platform/manage/biz/api/DeviceApiImpl.java
  23. 8 0
      iot-module/iot-module-manage/iot-module-manage-biz/src/main/java/com/middle/platform/manage/biz/mapper/IotDeviceMapper.java
  24. 16 0
      iot-module/iot-module-manage/iot-module-manage-biz/src/main/java/com/middle/platform/manage/biz/service/IotDeviceService.java
  25. 12 2
      iot-module/iot-module-manage/iot-module-manage-biz/src/main/java/com/middle/platform/manage/biz/service/IotProductService.java
  26. 15 0
      iot-module/iot-module-manage/iot-module-manage-biz/src/main/resources/mapper/IotDeviceMapper.xml

+ 7 - 1
iot-framework/iot-starter-redis/src/main/java/com/middle/platform/redis/constant/CacheConstant.java

@@ -8,13 +8,19 @@ public interface CacheConstant {
     String USER_CACHE = "user:%s";
     String DICT_CACHE = "dict:%s";
     String DICT_ITEM_CACHE = "dictItem:%s:%s";
+
     String TOPIC_CACHE = "topic:%s";
     String PRODUCT_CACHE = "product:%s:%s";
+    String DEVICE_CACHE = "device:%s";
     String MOD_CACHE = "mod:%s";
     String CLOUD_CACHE = "cloud:%s";
+
     //td源数据,是否建子表缓存
-    String TD_ORG_CACHE = "td:org:%s:%s";
+    String TD_ORG_CACHE = "org:%s:%s";
     //td转换后的数据,是否建子表缓存
     String TD_CACHE = "td:%s:%s";
 
+    //设备属性实时数据
+    String D_DATA_CACHE = "data:%s";
+
 }

+ 10 - 0
iot-framework/iot-starter-redis/src/main/java/com/middle/platform/redis/service/CacheService.java

@@ -4,7 +4,9 @@ import jakarta.annotation.Resource;
 import org.springframework.data.redis.core.RedisTemplate;
 import org.springframework.stereotype.Component;
 
+import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 /**
  * 产品相关缓存
@@ -55,4 +57,12 @@ public class CacheService {
         return redisTemplate.opsForValue().get(key);
     }
 
+    public void setHashKey(String key, String hk, Object val) {
+        redisTemplate.opsForHash().put(key, hk, val);
+    }
+
+    public <T> List<T> getHash(String key) {
+        Set<Object> keys = redisTemplate.opsForHash().keys(key);
+        return (List<T>) redisTemplate.opsForHash().multiGet(key, keys);
+    }
 }

+ 13 - 0
iot-module/iot-module-data/iot-module-data-api/src/main/java/com/middle/platform/data/api/feign/DataApi.java

@@ -1,8 +1,21 @@
 package com.middle.platform.data.api.feign;
 
+import com.middle.platform.common.constant.RpcConstants;
+import com.middle.platform.data.api.enums.ApiConstants;
+import com.middle.platform.data.api.pojo.ModPara;
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+
 /**
  * @author xucaiqin
  * @date 2023-12-17 16:05:08
  */
+@FeignClient(name = ApiConstants.NAME, contextId = "dataApi")
 public interface DataApi {
+    String PREFIX = RpcConstants.RPC_API_PREFIX + "/data";
+
+    @PostMapping(PREFIX + "/property")
+    Boolean property(@RequestBody ModPara modPara);
+
 }

+ 19 - 0
iot-module/iot-module-data/iot-module-data-api/src/main/java/com/middle/platform/data/api/pojo/ModPara.java

@@ -0,0 +1,19 @@
+package com.middle.platform.data.api.pojo;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+/**
+ * @author xucaiqin
+ * @date 2023-12-17 16:05:28
+ */
+@Getter
+@Setter
+@AllArgsConstructor
+@NoArgsConstructor
+public class ModPara {
+    private String topic;
+    private Integer qos;
+}

+ 21 - 0
iot-module/iot-module-data/iot-module-data-biz/src/main/java/com/middle/platform/data/biz/api/DataApiImpl.java

@@ -0,0 +1,21 @@
+package com.middle.platform.data.biz.api;
+
+import com.middle.platform.data.api.feign.DataApi;
+import com.middle.platform.data.api.pojo.ModPara;
+import lombok.RequiredArgsConstructor;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * @author xucaiqin
+ * @date 2023-12-26 10:10:55
+ */
+@RestController
+@Validated
+@RequiredArgsConstructor
+public class DataApiImpl implements DataApi {
+    @Override
+    public Boolean property(ModPara modPara) {
+        return null;
+    }
+}

+ 2 - 1
iot-module/iot-module-data/iot-module-data-biz/src/main/java/com/middle/platform/data/biz/config/FeignConfig.java

@@ -1,6 +1,7 @@
 package com.middle.platform.data.biz.config;
 
 import com.middle.platform.manage.api.feign.CloudApi;
+import com.middle.platform.manage.api.feign.DeviceApi;
 import com.middle.platform.manage.api.feign.ModApi;
 import com.middle.platform.manage.api.feign.ProductApi;
 import org.springframework.cloud.openfeign.EnableFeignClients;
@@ -13,6 +14,6 @@ import org.springframework.context.annotation.Configuration;
  * @date 2023-12-19 11:00:25
  */
 @Configuration
-@EnableFeignClients(clients = {CloudApi.class, ModApi.class, ProductApi.class})
+@EnableFeignClients(clients = {CloudApi.class, ModApi.class, ProductApi.class, DeviceApi.class})
 public class FeignConfig {
 }

+ 4 - 19
iot-module/iot-module-data/iot-module-data-biz/src/main/java/com/middle/platform/data/biz/controller/IndexController.java

@@ -2,14 +2,10 @@ package com.middle.platform.data.biz.controller;
 
 import com.middle.platform.common.utils.DateTimeUtil;
 import com.middle.platform.common.utils.Result;
-import com.middle.platform.data.biz.mapper.TaosMapper;
-import com.middle.platform.data.biz.pojo.ProductPara;
-import jakarta.annotation.Resource;
 import org.springframework.beans.factory.annotation.Value;
-import org.springframework.integration.mqtt.inbound.MqttPahoMessageDrivenChannelAdapter;
-import org.springframework.web.bind.annotation.*;
-
-import java.util.Arrays;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
 
 /**
  * @author xucaiqin
@@ -20,21 +16,10 @@ import java.util.Arrays;
 public class IndexController {
     @Value("${spring.application.name}")
     private String name;
-    @Resource
-    private TaosMapper productMapper;
-    @Resource
-    private MqttPahoMessageDrivenChannelAdapter mqttPahoMessageDrivenChannelAdapter;
+
 
     @GetMapping("")
     public Result<Object> server() {
-        mqttPahoMessageDrivenChannelAdapter.addTopic("/iot/car", 0);
-        System.out.println(Arrays.toString(mqttPahoMessageDrivenChannelAdapter.getTopic()));
         return Result.ok(name + ":" + DateTimeUtil.nowStr());
     }
-
-    @PostMapping("test")
-    public void test(@RequestBody ProductPara productPara) {
-        productMapper.insert(productPara);
-    }
-
 }

+ 44 - 0
iot-module/iot-module-data/iot-module-data-biz/src/main/java/com/middle/platform/data/biz/controller/PropertyController.java

@@ -0,0 +1,44 @@
+package com.middle.platform.data.biz.controller;
+
+import com.middle.platform.common.utils.Result;
+import com.middle.platform.data.biz.pojo.HistoryPara;
+import com.middle.platform.data.biz.service.DataService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * @author xucaiqin
+ * @date 2023-12-15 08:46:49
+ */
+@RestController
+@RequestMapping("/property")
+@RequiredArgsConstructor
+public class PropertyController {
+    private final DataService dataService;
+
+    /**
+     * 最新属性数据
+     *
+     * @param guid 设备guid
+     * @param name 属性名称
+     */
+    @GetMapping("/real")
+    public Result<Object> test(@RequestParam("guid") String guid, @RequestParam("name") String name) {
+        return Result.ok(dataService.queryData(guid, name));
+    }
+
+    /**
+     * 历史数据
+     *
+     * @param historyPara
+     * @return
+     */
+    @GetMapping("/history")
+    public Result<Object> history(HistoryPara historyPara) {
+        return Result.ok(dataService.historyData(historyPara));
+    }
+
+}

+ 9 - 0
iot-module/iot-module-data/iot-module-data-biz/src/main/java/com/middle/platform/data/biz/mapper/TaosMapper.java

@@ -3,9 +3,11 @@ package com.middle.platform.data.biz.mapper;
 import com.baomidou.dynamic.datasource.annotation.DS;
 import com.middle.platform.data.biz.pojo.OriginalPara;
 import com.middle.platform.data.biz.pojo.ProductPara;
+import com.middle.platform.data.biz.pojo.PropertyVo;
 import org.apache.ibatis.annotations.Mapper;
 import org.apache.ibatis.annotations.Param;
 
+import java.util.Date;
 import java.util.List;
 
 /**
@@ -81,4 +83,11 @@ public interface TaosMapper {
      * @return
      */
     int batchInsertOriginal(@Param("list") List<OriginalPara> collect, @Param("guid") String guid, @Param("code") String code);
+
+
+    /*查询设备数据*/
+    List<PropertyVo> queryRaw(@Param("code") String code, @Param("guid") String guid,  @Param("startTime") Date time, @Param("endTime") Date endTime);
+
+    List<PropertyVo> query(@Param("code") String code, @Param("guid") String guid, @Param("line") String line, @Param("startTime") Date time, @Param("endTime") Date endTime);
+
 }

+ 23 - 0
iot-module/iot-module-data/iot-module-data-biz/src/main/java/com/middle/platform/data/biz/pojo/HistoryPara.java

@@ -0,0 +1,23 @@
+package com.middle.platform.data.biz.pojo;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.Date;
+
+/**
+ * @author xucaiqin
+ * @date 2023-12-26 14:38:32
+ */
+@Getter
+@Setter
+public class HistoryPara {
+    private Integer type;
+    private String guid;
+    private String line;
+    @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private Date startTime;
+    @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private Date endTime;
+}

+ 39 - 0
iot-module/iot-module-data/iot-module-data-biz/src/main/java/com/middle/platform/data/biz/pojo/PropertyDto.java

@@ -0,0 +1,39 @@
+package com.middle.platform.data.biz.pojo;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+import java.io.Serial;
+import java.io.Serializable;
+
+/**
+ * @author xucaiqin
+ * @date 2023-12-26 11:11:12
+ */
+@Getter
+@Setter
+@AllArgsConstructor
+@NoArgsConstructor
+public class PropertyDto implements Serializable {
+    @Serial
+    private static final long serialVersionUID = -8922451428532981638L;
+    /**
+     * 属性
+     */
+    private String line;
+
+    /**
+     * 属性名
+     */
+    private String name;
+    /**
+     * 属性值
+     */
+    private String val;
+    /**
+     * 时间
+     */
+    private String time;
+}

+ 25 - 0
iot-module/iot-module-data/iot-module-data-biz/src/main/java/com/middle/platform/data/biz/pojo/PropertyVo.java

@@ -0,0 +1,25 @@
+package com.middle.platform.data.biz.pojo;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * @author xucaiqin
+ * @date 2023-12-26 10:31:15
+ */
+@Getter
+@Setter
+public class PropertyVo implements Serializable {
+    @Serial
+    private static final long serialVersionUID = 6725380842122890968L;
+    private String line;
+    private String lineLabel;
+    private Object val;
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private Date date;
+}

+ 101 - 0
iot-module/iot-module-data/iot-module-data-biz/src/main/java/com/middle/platform/data/biz/service/DataAnalyseService.java

@@ -0,0 +1,101 @@
+package com.middle.platform.data.biz.service;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.date.LocalDateTimeUtil;
+import com.middle.platform.data.biz.mapper.TaosMapper;
+import com.middle.platform.data.biz.pojo.OriginalPara;
+import com.middle.platform.data.biz.pojo.ProductPara;
+import com.middle.platform.data.biz.pojo.PropertyDto;
+import com.middle.platform.data.biz.utils.TsUtil;
+import com.middle.platform.manage.api.pojo.ProductVo;
+import com.middle.platform.redis.constant.CacheConstant;
+import com.middle.platform.redis.service.CacheService;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+
+import java.time.LocalDateTime;
+import java.util.*;
+
+/**
+ * @author xucaiqin
+ * @date 2023-12-24 15:33:31
+ */
+@Component
+@Slf4j
+@RequiredArgsConstructor
+public class DataAnalyseService {
+    private final TaosMapper taosMapper;
+    private final CacheService cacheService;
+    private final ProductAnalyse productAnalyse;
+
+    /**
+     * 源数据处理
+     *
+     * @param productVo
+     * @param payload
+     */
+    public void rawData(String msgId, ProductVo productVo, Object payload) {
+        Object o = cacheService.getKey(String.format(CacheConstant.TD_ORG_CACHE, productVo.getCode(), productVo.getGuid()));
+        if (Objects.isNull(o)) {
+            taosMapper.createOriginalTable(productVo.getGuid(), productVo.getCode());
+            cacheService.setKey(String.format(CacheConstant.TD_ORG_CACHE, productVo.getCode(), productVo.getGuid()), true);
+        }
+        OriginalPara originalPara = new OriginalPara();
+        originalPara.setCode(productVo.getCode());
+        originalPara.setGuid(productVo.getGuid());
+        originalPara.setRawStr(payload.toString());
+        originalPara.setTs(new Date());
+        originalPara.setMsgId(msgId);
+
+        taosMapper.insertOriginal(originalPara);
+    }
+
+    /**
+     * 解析数据
+     *
+     * @param msgId
+     * @param productVo
+     */
+    public void analyzeData(String msgId, ProductVo productVo, Object data) {
+        log.info("源数据:{}", data);
+        //1.云函数解析
+        Object cloudData = productAnalyse.dataConvert(productVo, data);
+        log.info("云函数解析:{}", cloudData);
+        //2.物模型解析
+        Map<String, PropertyDto> modData = productAnalyse.modConvert(productVo, cloudData);
+        log.info("物模型解析:{}", modData);
+        //判断是否创建子表
+        tableCheck(productVo);
+        //数据写入
+        ProductPara productPara;
+        List<ProductPara> list = new ArrayList<>();
+        for (Map.Entry<String, PropertyDto> map : modData.entrySet()) {
+            map.getValue().setTime(LocalDateTimeUtil.formatNormal(LocalDateTime.now()));
+            productPara = new ProductPara();
+            productPara.setCode(productVo.getCode());
+            productPara.setGuid(productVo.getGuid());
+            productPara.setLine(map.getKey());
+            productPara.setReserve("");
+            productPara.setVal(map.getValue().getVal());
+            productPara.setMsgId(msgId);
+            productPara.setTs(TsUtil.getAndIncrement());
+            productPara.setOriginTime(new Date());//todo 有则获取
+            list.add(productPara);
+            cacheService.setHashKey(String.format(CacheConstant.D_DATA_CACHE, productVo.getGuid()), map.getKey(), map.getValue());
+            if (CollUtil.isNotEmpty(list)) {
+                taosMapper.batchInsert(list, productVo.getGuid(), productVo.getCode());
+            }
+        }
+
+    }
+
+    private void tableCheck(ProductVo productVo) {
+        Object o = cacheService.getKey(String.format(CacheConstant.TD_CACHE, productVo.getCode(), productVo.getGuid()));
+        if (Objects.isNull(o)) {
+            taosMapper.createDeviceTable(productVo.getGuid(), productVo.getCode());
+            cacheService.setKey(String.format(CacheConstant.TD_CACHE, productVo.getCode(), productVo.getGuid()), true);
+        }
+    }
+
+}

+ 46 - 59
iot-module/iot-module-data/iot-module-data-biz/src/main/java/com/middle/platform/data/biz/service/DataService.java

@@ -3,86 +3,73 @@ package com.middle.platform.data.biz.service;
 import cn.hutool.core.collection.CollUtil;
 import com.alibaba.fastjson.JSONObject;
 import com.middle.platform.data.biz.mapper.TaosMapper;
-import com.middle.platform.data.biz.pojo.OriginalPara;
-import com.middle.platform.data.biz.pojo.ProductPara;
-import com.middle.platform.data.biz.utils.TsUtil;
-import com.middle.platform.manage.api.pojo.ProductVo;
+import com.middle.platform.data.biz.pojo.HistoryPara;
+import com.middle.platform.data.biz.pojo.PropertyDto;
+import com.middle.platform.data.biz.pojo.PropertyVo;
+import com.middle.platform.data.biz.pojo.mod.ModDto;
+import com.middle.platform.data.biz.pojo.mod.Property;
+import com.middle.platform.manage.api.feign.DeviceApi;
+import com.middle.platform.manage.api.feign.ModApi;
+import com.middle.platform.manage.api.pojo.DeviceVo;
 import com.middle.platform.redis.constant.CacheConstant;
 import com.middle.platform.redis.service.CacheService;
-import jakarta.annotation.Resource;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.stereotype.Component;
+import lombok.RequiredArgsConstructor;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.stereotype.Service;
 
 import java.util.*;
+import java.util.stream.Collectors;
 
 /**
  * @author xucaiqin
- * @date 2023-12-24 15:33:31
+ * @date 2023-12-26 10:14:27
  */
-@Component
-@Slf4j
+@Service
+@RequiredArgsConstructor
 public class DataService {
-    @Resource
-    private TaosMapper taosMapper;
-    @Resource
-    private CacheService cacheService;
+    private final TaosMapper taosMapper;
+    private final CacheService cacheService;
+    private final DeviceApi deviceApi;
+    private final ModApi modApi;
 
     /**
-     * 源数据处理
+     * 查询设备的属性数据
      *
-     * @param productVo
-     * @param payload
+     * @param guid 设备guid
+     * @return
      */
-    public void rawData(String msgId, ProductVo productVo, Object payload) {
-        Object o = cacheService.getKey(String.format(CacheConstant.TD_ORG_CACHE, productVo.getCode(), productVo.getGuid()));
-        if (Objects.isNull(o)) {
-            taosMapper.createOriginalTable(productVo.getGuid(), productVo.getCode());
-            cacheService.setKey(String.format(CacheConstant.TD_ORG_CACHE, productVo.getCode(), productVo.getGuid()), true);
+    public Object queryData(String guid, String name) {
+        List<PropertyDto> hash = cacheService.getHash(String.format(CacheConstant.D_DATA_CACHE, guid));
+        if (StringUtils.isNotBlank(name) && CollUtil.isNotEmpty(hash)) {
+            return hash.stream().filter(a -> StringUtils.equals(a.getName(), name)).collect(Collectors.toList());
         }
-        OriginalPara originalPara = new OriginalPara();
-        originalPara.setCode(productVo.getCode());
-        originalPara.setGuid(productVo.getGuid());
-        originalPara.setRawStr(payload.toString());
-        originalPara.setTs(new Date());
-        originalPara.setMsgId(msgId);
-
-        taosMapper.insertOriginal(originalPara);
+        return hash;
     }
 
     /**
-     * 解析后的数据
+     * 历史记录查询
      *
-     * @param msgId
-     * @param productVo
-     * @param modData
+     * @param historyPara
+     * @return
      */
-    public void analyzeData(String msgId, ProductVo productVo, Object modData) {
-        log.info("解析后的数据:{}", modData);
-        Object o = cacheService.getKey(String.format(CacheConstant.TD_CACHE, productVo.getCode(), productVo.getGuid()));
-        if (Objects.isNull(o)) {
-            taosMapper.createDeviceTable(productVo.getGuid(), productVo.getCode());
-            cacheService.setKey(String.format(CacheConstant.TD_CACHE, productVo.getCode(), productVo.getGuid()), true);
+    public List<PropertyVo> historyData(HistoryPara historyPara) {
+        DeviceVo deviceVo = deviceApi.deviceCache(historyPara.getGuid());
+        if (Objects.isNull(deviceVo)) {
+            return new ArrayList<>();
         }
-        if (modData instanceof JSONObject jsonObject) {
-            List<ProductPara> list = new ArrayList<>();
-            ProductPara productPara;
-            for (Map.Entry<String, Object> map : jsonObject.entrySet()) {
-                productPara = new ProductPara();
-                productPara.setCode(productVo.getCode());
-                productPara.setGuid(productVo.getGuid());
-                productPara.setLine(map.getKey());
-                productPara.setReserve("");
-                productPara.setVal(String.valueOf(map.getValue()));
-                productPara.setMsgId(msgId);
-                productPara.setTs(TsUtil.getAndIncrement());
-                productPara.setOriginTime(new Date());//todo 有则获取
-                list.add(productPara);
-            }
-            if (CollUtil.isNotEmpty(list)) {
-                taosMapper.batchInsert(list, productVo.getGuid(), productVo.getCode());
+        if (Objects.equals(historyPara.getType(), 1)) {
+            List<PropertyVo> query = taosMapper.query(deviceVo.getCode(), historyPara.getGuid(), historyPara.getLine(), historyPara.getStartTime(), historyPara.getEndTime());
+            if (CollUtil.isNotEmpty(query)) {
+                Map<String, String> map = Optional.ofNullable(modApi.queryMod(deviceVo.getProductId())).map(mod -> {
+                    ModDto modDto = JSONObject.parseObject(mod, ModDto.class);
+                    return Optional.ofNullable(modDto).map(ModDto::getProperties).orElse(new ArrayList<>());
+                }).map(properties -> properties.stream().collect(Collectors.toMap(Property::getIdentifier, Property::getName, (a, b) -> a))).orElse(new HashMap<>());
+                for (PropertyVo propertyVo : query) {
+                    propertyVo.setLineLabel(map.get(propertyVo.getLine()));
+                }
             }
+            return query;
         }
-
+        return taosMapper.queryRaw(deviceVo.getCode(), historyPara.getGuid(), historyPara.getStartTime(), historyPara.getEndTime());
     }
-
 }

+ 43 - 16
iot-module/iot-module-data/iot-module-data-biz/src/main/java/com/middle/platform/data/biz/service/ProductAnalyse.java

@@ -2,6 +2,7 @@ package com.middle.platform.data.biz.service;
 
 import cn.hutool.core.collection.CollUtil;
 import com.alibaba.fastjson.JSONObject;
+import com.middle.platform.data.biz.pojo.PropertyDto;
 import com.middle.platform.data.biz.pojo.mod.ModDto;
 import com.middle.platform.data.biz.pojo.mod.Property;
 import com.middle.platform.manage.api.enums.DataFormatConstant;
@@ -16,6 +17,7 @@ import org.apache.commons.lang3.StringUtils;
 import org.springframework.stereotype.Component;
 
 import java.util.*;
+import java.util.stream.Collectors;
 
 /**
  * 产品解析
@@ -60,7 +62,6 @@ public class ProductAnalyse {
      * @return 云函数转换后的数据
      */
     public Object dataConvert(ProductVo productVo, Object payload) {
-        log.info("源数据:{}", payload);
         IotCloudVo iotCloudVo = cloudApi.queryCloud(productVo.getId());
         if (Objects.isNull(iotCloudVo)) {
             log.warn("未找到云函数");
@@ -79,7 +80,7 @@ public class ProductAnalyse {
      * @param payload 云函数解析后的数据
      * @return 解析为物模型对应属性数据
      */
-    public Object modConvert(ProductVo productVo, Object payload) {
+    public Map<String, PropertyDto> modConvert(ProductVo productVo, Object payload) {
         log.info("物模型数据转换:{}", payload);
         String mod = modApi.queryMod(productVo.getId());
         if (StringUtils.isNotBlank(mod)) {
@@ -94,8 +95,8 @@ public class ProductAnalyse {
                         if (payload instanceof JSONObject jsonObject) {
                             return change(properties, jsonObject);
                         }
-                        return new JSONObject();
-                    }).orElse(new JSONObject());
+                        return new HashMap<String, PropertyDto>();
+                    }).orElse(new HashMap<>());
         }
         return null;
     }
@@ -107,22 +108,48 @@ public class ProductAnalyse {
      * @param jsonObject 上报的json数据
      * @return
      */
-    private JSONObject change(List<Property> properties, JSONObject jsonObject) {
+//    private JSONObject change(List<Property> properties, JSONObject jsonObject) {
+//        if (CollUtil.isEmpty(properties)) {
+//            return jsonObject;
+//        }
+//        //物模型中需要保留的属性字段
+//        List<String> key = properties.stream().map(Property::getIdentifier).toList();
+//        //上报数据中,所有的字段
+//        Set<String> keyAll = jsonObject.keySet();
+//
+//        // 仅保留需要的属性字段
+//        List<String> collect = keyAll.stream().filter(one -> !key.contains(one)).toList();
+//
+//        // 使用 removeAll 方法一次性移除所有需要删除的字段
+//        collect.forEach(jsonObject.keySet()::remove);
+//        return jsonObject;
+//    }
+    /**
+     * 过滤物模型中的属性,仅保留物模型中的属性字段
+     *
+     * @param properties 物模型属性
+     * @param jsonObject 上报的json数据
+     * @return
+     */
+    private Map<String, PropertyDto> change(List<Property> properties, JSONObject jsonObject) {
         if (CollUtil.isEmpty(properties)) {
-            return jsonObject;
+            return new HashMap<>();
         }
-        //物模型中需要保留的属性字段
-        List<String> key = properties.stream().map(Property::getIdentifier).toList();
-        //上报数据中,所有的字段
-        Set<String> keyAll = jsonObject.keySet();
+        Set<String> keySet = jsonObject.keySet();
+        // 属性字段,属性名称 tmp:温度
+        Map<String, String> map = properties.stream().collect(Collectors.toMap(Property::getIdentifier, Property::getName, (a, b) -> a));
 
-        // 仅保留需要的属性字段
-        List<String> collect = keyAll.stream().filter(one -> !key.contains(one)).toList();
+        Map<String, PropertyDto> res = new HashMap<>();
 
-        // 使用 removeAll 方法一次性移除所有需要删除的字段
-        collect.forEach(jsonObject.keySet()::remove);
-        return jsonObject;
-    }
+        for (String key : keySet) {
+            Optional.ofNullable(map.get(key)).ifPresent(label -> {
+                //属性值
+                String val = jsonObject.getString(key);
+                res.put(key, new PropertyDto(key, label, val, ""));
+            });
+        }
 
+        return res;
+    }
 
 }

+ 6 - 11
iot-module/iot-module-data/iot-module-data-biz/src/main/java/com/middle/platform/data/biz/service/http/HttpService.java

@@ -1,8 +1,7 @@
 package com.middle.platform.data.biz.service.http;
 
 import cn.hutool.core.util.IdUtil;
-import com.alibaba.fastjson.JSONObject;
-import com.middle.platform.data.biz.service.DataService;
+import com.middle.platform.data.biz.service.DataAnalyseService;
 import com.middle.platform.data.biz.service.ProductAnalyse;
 import com.middle.platform.manage.api.pojo.ProductVo;
 import lombok.RequiredArgsConstructor;
@@ -20,7 +19,7 @@ import java.util.Objects;
 @Slf4j
 public class HttpService {
     private final ProductAnalyse productAnalyse;
-    private final DataService dataService;
+    private final DataAnalyseService dataAnalyseService;
 
     /**
      * 数据上报
@@ -29,7 +28,7 @@ public class HttpService {
      * @param deviceSn
      * @param data
      */
-    public void dataReport(String code, String deviceSn, JSONObject data) {
+    public void dataReport(String code, String deviceSn, Object data) {
         ProductVo productVo = productAnalyse.getProduct(code, deviceSn);
         if (Objects.isNull(productVo)) {
             log.warn("产品:{} 设备:{} 不存在", code, deviceSn);
@@ -37,12 +36,8 @@ public class HttpService {
         }
         String msgId = IdUtil.fastSimpleUUID();
         //1.源数据处理
-        dataService.rawData(msgId, productVo, data);
-        //2.云函数解析
-        Object cloudData = productAnalyse.dataConvert(productVo, data);
-        //3.物模型解析
-        Object modData = productAnalyse.modConvert(productVo, cloudData);
-        //4.存储解析后的数据
-        dataService.analyzeData(msgId, productVo, modData);
+        dataAnalyseService.rawData(msgId, productVo, data);
+        //2.存储解析后的数据
+        dataAnalyseService.analyzeData(msgId, productVo, data);
     }
 }

+ 5 - 9
iot-module/iot-module-data/iot-module-data-biz/src/main/java/com/middle/platform/data/biz/service/mqtt/strategy/AttrReportStrategy.java

@@ -1,7 +1,7 @@
 package com.middle.platform.data.biz.service.mqtt.strategy;
 
 import cn.hutool.core.util.IdUtil;
-import com.middle.platform.data.biz.service.DataService;
+import com.middle.platform.data.biz.service.DataAnalyseService;
 import com.middle.platform.data.biz.service.ProductAnalyse;
 import com.middle.platform.data.biz.service.mqtt.MqttTopicStrategy;
 import com.middle.platform.data.biz.utils.MqttTopicUtil;
@@ -20,7 +20,7 @@ import java.util.Objects;
 @RequiredArgsConstructor
 public class AttrReportStrategy implements MqttTopicStrategy {
     private final ProductAnalyse productAnalyse;
-    private final DataService dataService;
+    private final DataAnalyseService dataAnalyseService;
 
     @Override
     public void dealMsg(String topic, Object msg) {
@@ -35,12 +35,8 @@ public class AttrReportStrategy implements MqttTopicStrategy {
         }
         String msgId = IdUtil.fastSimpleUUID();
         //1.源数据处理
-        dataService.rawData(msgId, productVo, msg);
-        //2.云函数解析
-        Object cloudData = productAnalyse.dataConvert(productVo, msg);
-        //3.物模型解析
-        Object modData = productAnalyse.modConvert(productVo, cloudData);
-        //4.存储解析后的数据
-        dataService.analyzeData(msgId, productVo, modData);
+        dataAnalyseService.rawData(msgId, productVo, msg);
+        //2.存储解析后的数据
+        dataAnalyseService.analyzeData(msgId, productVo, msg);
     }
 }

+ 23 - 0
iot-module/iot-module-data/iot-module-data-biz/src/main/resources/mapper/TaosMapper.xml

@@ -40,4 +40,27 @@
             (#{item.ts}, #{item.rawStr}, #{item.msgId})
         </foreach>
     </select>
+
+    <select id="query" resultType="com.middle.platform.data.biz.pojo.PropertyVo">
+        select line, val, ts as date
+        from device_${code}_${guid}
+        <where>
+            <if test="line != null and line != ''">
+                and line = #{line,jdbcType=VARCHAR}
+            </if>
+            <if test="startTime != null and endTime != null">
+                and ts between #{startTime} and #{endTime}
+            </if>
+        </where>
+    </select>
+
+    <select id="queryRaw" resultType="com.middle.platform.data.biz.pojo.PropertyVo">
+        select ts as date, raw_str as val
+        from original_${code}_${guid}
+        <where>
+            <if test="startTime != null and endTime != null">
+                and ts between #{startTime} and #{endTime}
+            </if>
+        </where>
+    </select>
 </mapper>

+ 27 - 0
iot-module/iot-module-manage/iot-module-manage-api/src/main/java/com/middle/platform/manage/api/feign/DeviceApi.java

@@ -0,0 +1,27 @@
+package com.middle.platform.manage.api.feign;
+
+import com.middle.platform.common.constant.RpcConstants;
+import com.middle.platform.manage.api.enums.ApiConstants;
+import com.middle.platform.manage.api.pojo.DeviceVo;
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+
+/**
+ * @author xucaiqin
+ * @date 2023-12-17 11:09:05
+ */
+@FeignClient(name = ApiConstants.NAME, contextId = "deviceApi")
+public interface DeviceApi {
+    String prefix = RpcConstants.RPC_API_PREFIX + "/device";
+
+    /**
+     * 查询设备
+     *
+     * @param guid
+     * @return
+     */
+    @GetMapping(prefix + "/cache")
+    DeviceVo deviceCache(@RequestParam("guid") String guid);
+
+}

+ 1 - 1
iot-module/iot-module-manage/iot-module-manage-api/src/main/java/com/middle/platform/manage/api/feign/ProductApi.java

@@ -25,7 +25,7 @@ public interface ProductApi {
      * @return
      */
     @GetMapping(prefix + "/get")
-    ProductVo queryProduct(@RequestParam("productKey") String productKey,@RequestParam("deviceSn")String deviceSn);
+    ProductVo queryProduct(@RequestParam("productKey") String productKey, @RequestParam("deviceSn") String deviceSn);
 
     /**
      * 获取所有产品的mqtt,需要订阅的topic

+ 36 - 0
iot-module/iot-module-manage/iot-module-manage-api/src/main/java/com/middle/platform/manage/api/pojo/DeviceVo.java

@@ -0,0 +1,36 @@
+package com.middle.platform.manage.api.pojo;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import java.io.Serial;
+import java.io.Serializable;
+
+/**
+ * 产品关联设备
+ *
+ * @author xucaiqin
+ * @date 2023-12-23 14:04:27
+ */
+@Getter
+@Setter
+public class DeviceVo implements Serializable {
+    @Serial
+    private static final long serialVersionUID = -9119654517133030431L;
+    /**
+     * 设备id
+     */
+    private Long id;
+    /**
+     * 产品id
+     */
+    private Long productId;
+    /**
+     * 产品编码
+     */
+    private String code;
+    /**
+     * 设备guid
+     */
+    private String guid;
+}

+ 22 - 0
iot-module/iot-module-manage/iot-module-manage-biz/src/main/java/com/middle/platform/manage/biz/api/DeviceApiImpl.java

@@ -0,0 +1,22 @@
+package com.middle.platform.manage.biz.api;
+
+import com.middle.platform.manage.api.feign.DeviceApi;
+import com.middle.platform.manage.api.pojo.DeviceVo;
+import com.middle.platform.manage.biz.service.IotDeviceService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * @author xucaiqin
+ * @date 2023-12-23 14:12:44
+ */
+@RequiredArgsConstructor
+@RestController
+public class DeviceApiImpl implements DeviceApi {
+    private final IotDeviceService iotDeviceService;
+
+    @Override
+    public DeviceVo deviceCache(String guid) {
+        return iotDeviceService.deviceCache(guid);
+    }
+}

+ 8 - 0
iot-module/iot-module-manage/iot-module-manage-biz/src/main/java/com/middle/platform/manage/biz/mapper/IotDeviceMapper.java

@@ -1,6 +1,7 @@
 package com.middle.platform.manage.biz.mapper;
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.middle.platform.manage.api.pojo.DeviceVo;
 import com.middle.platform.manage.biz.domain.req.DevicePage;
 import com.middle.platform.manage.biz.domain.req.TypeStatisticsReq;
 import com.middle.platform.manage.biz.domain.vo.*;
@@ -51,4 +52,11 @@ public interface IotDeviceMapper extends BaseMapper<IotDevice> {
 
     ProductDeviceDto query(@Param("id") Long id);
 
+    /**
+     * 查询设备缓存信息
+     *
+     * @param guid
+     * @return
+     */
+    DeviceVo deviceCache(@Param("guid") String guid);
 }

+ 16 - 0
iot-module/iot-module-manage/iot-module-manage-biz/src/main/java/com/middle/platform/manage/biz/service/IotDeviceService.java

@@ -8,6 +8,7 @@ import com.github.pagehelper.PageInfo;
 import com.middle.platform.common.constant.Global;
 import com.middle.platform.common.exception.BusinessException;
 import com.middle.platform.excel.core.util.ExcelUtils;
+import com.middle.platform.manage.api.pojo.DeviceVo;
 import com.middle.platform.manage.biz.domain.req.DevicePage;
 import com.middle.platform.manage.biz.domain.req.IotDeviceFlag;
 import com.middle.platform.manage.biz.domain.req.IotDevicePara;
@@ -203,4 +204,19 @@ public class IotDeviceService {
         }
         return "导入成功";
     }
+
+    /**
+     * 查询设备信息
+     * @param guid
+     * @return
+     */
+    public DeviceVo deviceCache(String guid) {
+        DeviceVo deviceVo = (DeviceVo) cacheService.getKey(String.format(CacheConstant.DEVICE_CACHE, guid));
+        if (Objects.nonNull(deviceVo)) {
+            return deviceVo;
+        }
+        DeviceVo deviceVoC = iotDeviceMapper.deviceCache(guid);
+        Optional.ofNullable(deviceVoC).ifPresent(product -> cacheService.setKey(String.format(CacheConstant.DEVICE_CACHE, guid), product));
+        return deviceVoC;
+    }
 }

+ 12 - 2
iot-module/iot-module-manage/iot-module-manage-biz/src/main/java/com/middle/platform/manage/biz/service/IotProductService.java

@@ -4,8 +4,8 @@ import cn.hutool.core.util.IdUtil;
 import com.github.pagehelper.PageHelper;
 import com.github.pagehelper.PageInfo;
 import com.middle.platform.common.exception.BusinessException;
-import com.middle.platform.pagehelper.core.PageRes;
 import com.middle.platform.data.api.feign.TdApi;
+import com.middle.platform.manage.api.pojo.DeviceVo;
 import com.middle.platform.manage.api.pojo.ProductVo;
 import com.middle.platform.manage.api.pojo.TopicVo;
 import com.middle.platform.manage.biz.constant.UrlType;
@@ -16,6 +16,7 @@ import com.middle.platform.manage.biz.domain.vo.IotProductVo;
 import com.middle.platform.manage.biz.entity.IotProduct;
 import com.middle.platform.manage.biz.mapper.IotDeviceMapper;
 import com.middle.platform.manage.biz.mapper.IotProductMapper;
+import com.middle.platform.pagehelper.core.PageRes;
 import com.middle.platform.redis.constant.CacheConstant;
 import com.middle.platform.redis.service.CacheService;
 import com.middle.platform.system.api.enums.DictType;
@@ -24,7 +25,6 @@ import com.middle.platform.system.api.feign.UserApi;
 import jakarta.annotation.Resource;
 import lombok.RequiredArgsConstructor;
 import org.springframework.beans.BeanUtils;
-import org.springframework.data.redis.core.RedisTemplate;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
@@ -190,4 +190,14 @@ public class IotProductService {
     public List<TopicVo> queryList() {
         return iotProductMapper.queryProductTopic(UrlType.MQTT);
     }
+
+    /**
+     * 查询设备/产品详情
+     * @param id 设备id
+     * @return
+     */
+    public DeviceVo productDevice(Long id) {
+
+        return null;
+    }
 }

+ 15 - 0
iot-module/iot-module-manage/iot-module-manage-biz/src/main/resources/mapper/IotDeviceMapper.xml

@@ -174,4 +174,19 @@
         </where>
     </select>
 
+    <select id="deviceCache" resultType="com.middle.platform.manage.api.pojo.DeviceVo">
+        select id.id,
+               ip.id productId,
+               id.sn,
+               ip.code
+        from iot_device id
+                 inner join iot_product ip on id.product_id = ip.id and ip.del_flag = 0
+        <where>
+            <if test="guid != null and guid != ''">
+                and id.guid = #{guid,jdbcType=VARCHAR}
+            </if>
+            and id.enable_flag = 1
+            and id.del_flag = 0
+        </where>
+    </select>
 </mapper>