Переглянути джерело

'设备信息表-批量导入-对接客户、设备实时历史数据-对接客户'

james 1 рік тому
батько
коміт
6f3ca7563c
15 змінених файлів з 366 додано та 12 видалено
  1. 16 0
      service-backend/service-backend-api/src/main/java/com/usky/backend/client/DeviceDataClient.java
  2. 45 0
      service-backend/service-backend-api/src/main/java/com/usky/backend/domain/request/DeviceDataInfoVO.java
  3. 43 0
      service-backend/service-backend-api/src/main/java/com/usky/backend/domain/request/DmpDeviceDataRequestVO.java
  4. 2 2
      service-backend/service-backend-biz/src/main/java/com/usky/backend/controller/DataRealTimeController.java
  5. 30 0
      service-backend/service-backend-biz/src/main/java/com/usky/backend/controller/api/DeviceDataApi.java
  6. 6 0
      service-backend/service-backend-biz/src/main/java/com/usky/backend/mapper/DataRealTimeMapper.java
  7. 4 0
      service-backend/service-backend-biz/src/main/java/com/usky/backend/service/DataRealTimeService.java
  8. 53 0
      service-backend/service-backend-biz/src/main/java/com/usky/backend/service/impl/DataRealTimeServiceImpl.java
  9. 5 0
      service-backend/service-backend-biz/src/main/resources/mapper.backend/DataRealTimeMapper.xml
  10. 16 8
      service-iot/service-iot-biz/src/main/java/com/usky/iot/controller/web/DeviceHttpController.java
  11. 13 0
      service-iot/service-iot-biz/src/main/java/com/usky/iot/controller/web/DmpDeviceInfoController.java
  12. 3 0
      service-iot/service-iot-biz/src/main/java/com/usky/iot/service/DmpDataInfoService.java
  13. 2 0
      service-iot/service-iot-biz/src/main/java/com/usky/iot/service/DmpDeviceInfoService.java
  14. 93 2
      service-iot/service-iot-biz/src/main/java/com/usky/iot/service/impl/DmpDataInfoServiceImpl.java
  15. 35 0
      service-iot/service-iot-biz/src/main/java/com/usky/iot/service/impl/DmpDeviceInfoServiceImpl.java

+ 16 - 0
service-backend/service-backend-api/src/main/java/com/usky/backend/client/DeviceDataClient.java

@@ -0,0 +1,16 @@
+package com.usky.backend.client;
+
+import com.usky.backend.domain.StatusVO;
+import com.usky.backend.domain.request.DeviceDataInfoVO;
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+
+import java.util.List;
+
+@FeignClient(contextId = "deviceDataClient", value = "usky-backend")
+public interface DeviceDataClient {
+
+    @RequestMapping(value = "data")
+    void data(List<DeviceDataInfoVO> list);
+}

+ 45 - 0
service-backend/service-backend-api/src/main/java/com/usky/backend/domain/request/DeviceDataInfoVO.java

@@ -0,0 +1,45 @@
+package com.usky.backend.domain.request;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+import java.util.Map;
+
+@Data
+@EqualsAndHashCode(callSuper = false)
+public class DeviceDataInfoVO implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 设备编号
+     */
+    private String deviceId;
+
+    /**
+     * 设备类型
+     */
+    private Integer deviceType;
+
+    /**
+     * 设备简称
+     */
+    private String typeAbbrevia;
+
+    /**
+     * 属性名称
+     */
+    private String name;
+
+    /**
+     * 属性值
+     */
+    private float value;
+
+    /**
+     * 数据上报时间
+     */
+    private LocalDateTime timestamp;
+}

+ 43 - 0
service-backend/service-backend-api/src/main/java/com/usky/backend/domain/request/DmpDeviceDataRequestVO.java

@@ -0,0 +1,43 @@
+package com.usky.backend.domain.request;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.io.Serializable;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * <p>
+ *
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+public class DmpDeviceDataRequestVO implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 产品编码
+     */
+    private String productCode;
+
+    /**
+     * 设备编号
+     */
+    private String deviceId;
+
+    /**
+     * 数据上报时间
+     */
+    private long timestamp;
+
+    /**
+     * 属性值集合
+     */
+    private Map<String,Float> metrics;
+
+
+
+}
+

+ 2 - 2
service-backend/service-backend-biz/src/main/java/com/usky/backend/controller/DataRealTimeController.java

@@ -1,9 +1,8 @@
 package com.usky.backend.controller;
 
-
+import io.swagger.annotations.Api;
 import org.springframework.web.bind.annotation.RequestMapping;
 
-import org.springframework.stereotype.Controller;
 import org.springframework.web.bind.annotation.RestController;
 
 /**
@@ -15,6 +14,7 @@ import org.springframework.web.bind.annotation.RestController;
  * @since 2023-06-07
  */
 @RestController
+@Api(tags = "数据统一存储")
 @RequestMapping("/dataRealTime")
 public class DataRealTimeController {
 

+ 30 - 0
service-backend/service-backend-biz/src/main/java/com/usky/backend/controller/api/DeviceDataApi.java

@@ -0,0 +1,30 @@
+package com.usky.backend.controller.api;
+
+import com.usky.backend.client.DeviceDataClient;
+import com.usky.backend.domain.request.DeviceDataInfoVO;
+import com.usky.backend.service.DataRealTimeService;
+import io.swagger.annotations.Api;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.List;
+
+/**
+ * <p>
+ *  数据统一存储 前端控制器
+ * </p>
+ *
+ */
+@RestController
+@Api(tags = "数据统一存储RPC")
+public class DeviceDataApi implements DeviceDataClient {
+
+    @Autowired
+    private DataRealTimeService dataRealTimeService;
+
+    @Override
+    public void data(List<DeviceDataInfoVO> list){
+        dataRealTimeService.data(list);
+    }
+
+}

+ 6 - 0
service-backend/service-backend-biz/src/main/java/com/usky/backend/mapper/DataRealTimeMapper.java

@@ -1,9 +1,13 @@
 package com.usky.backend.mapper;
 
 import com.usky.backend.domain.DataRealTime;
+import com.usky.backend.domain.request.DeviceDataInfoVO;
 import com.usky.common.mybatis.core.CrudMapper;
+import org.apache.ibatis.annotations.Param;
 import org.springframework.stereotype.Repository;
 
+import java.time.LocalDateTime;
+
 /**
  * <p>
  * 实时数据表 Mapper 接口
@@ -15,4 +19,6 @@ import org.springframework.stereotype.Repository;
 @Repository
 public interface DataRealTimeMapper extends CrudMapper<DataRealTime> {
 
+    int insertHistoryTable(@Param("dataInfo") DeviceDataInfoVO dataInfo, @Param("tableName") String tableName, @Param("curTime") LocalDateTime curTime);
+
 }

+ 4 - 0
service-backend/service-backend-biz/src/main/java/com/usky/backend/service/DataRealTimeService.java

@@ -1,8 +1,11 @@
 package com.usky.backend.service;
 
 import com.usky.backend.domain.DataRealTime;
+import com.usky.backend.domain.request.DeviceDataInfoVO;
 import com.usky.common.mybatis.core.CrudService;
 
+import java.util.List;
+
 /**
  * <p>
  * 实时数据表 服务类
@@ -13,4 +16,5 @@ import com.usky.common.mybatis.core.CrudService;
  */
 public interface DataRealTimeService extends CrudService<DataRealTime> {
 
+    void data(List<DeviceDataInfoVO> list);
 }

+ 53 - 0
service-backend/service-backend-biz/src/main/java/com/usky/backend/service/impl/DataRealTimeServiceImpl.java

@@ -1,11 +1,29 @@
 package com.usky.backend.service.impl;
 
+import cn.hutool.json.JSONObject;
+import cn.hutool.json.JSONUtil;
+import com.alibaba.nacos.shaded.com.google.gson.JsonObject;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
+import com.baomidou.mybatisplus.core.toolkit.StringUtils;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.usky.backend.domain.DataRealTime;
+import com.usky.backend.domain.request.DeviceDataInfoVO;
 import com.usky.backend.mapper.DataRealTimeMapper;
 import com.usky.backend.service.DataRealTimeService;
+import com.usky.common.core.util.JsonUtils;
 import com.usky.common.mybatis.core.AbstractCrudService;
+import nonapi.io.github.classgraph.json.JSONUtils;
 import org.springframework.stereotype.Service;
 
+import java.text.SimpleDateFormat;
+import java.time.Instant;
+import java.time.LocalDateTime;
+import java.time.ZoneId;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
 /**
  * <p>
  * 实时数据表 服务实现类
@@ -17,4 +35,39 @@ import org.springframework.stereotype.Service;
 @Service
 public class DataRealTimeServiceImpl extends AbstractCrudService<DataRealTimeMapper, DataRealTime> implements DataRealTimeService {
 
+    @Override
+    public void data(List<DeviceDataInfoVO> list){
+
+        if(CollectionUtils.isNotEmpty(list)){
+            for(int i=0;i<list.size();i++){
+
+                //操作实时数据表,当表中有这个设备的数据时,更新这条属性记录,否则插入
+                LambdaQueryWrapper<DataRealTime> queryWrapper = Wrappers.lambdaQuery();
+                queryWrapper.eq(DataRealTime::getDeviceId,list.get(i).getDeviceId())
+                        .eq(DataRealTime::getAttributeName,list.get(i).getName());
+                DataRealTime one = this.getOne(queryWrapper);
+                if(one != null){
+                    one.setAttributeData(String.valueOf(list.get(i).getValue()));
+                    one.setDataTime(list.get(i).getTimestamp());
+                    one.setInsertTime(LocalDateTime.now());
+                    this.updateById(one);
+                }else{
+                    one.setDeviceId(list.get(i).getDeviceId());
+                    one.setDeviceType(list.get(i).getDeviceType());
+                    one.setAttributeName(list.get(i).getName());
+                    one.setAttributeData(String.valueOf(list.get(i).getValue()));
+                    one.setDataTime(list.get(i).getTimestamp());
+                    one.setInsertTime(LocalDateTime.now());
+                    this.save(one);
+                }
+
+                String tableName = "data_"+list.get(i).getTypeAbbrevia()+"_history";
+                //操作各个设备历史数据表(通用方法)
+                int res = baseMapper.insertHistoryTable(list.get(i),tableName,LocalDateTime.now());
+            }
+        }
+
+    }
+
+
 }

+ 5 - 0
service-backend/service-backend-biz/src/main/resources/mapper.backend/DataRealTimeMapper.xml

@@ -13,5 +13,10 @@
         <result column="data_time" property="dataTime" />
         <result column="insert_time" property="insertTime" />
     </resultMap>
+    <insert id="insertHistoryTable" >
+        insert into ${tableName}   ( device_id, device_type,  attribute_name, attribute_data, data_time, insert_time)
+        values (#{dataInfo.deviceId}, #{dataInfo.deviceType},  #{dataInfo.name},  #{dataInfo.value},  #{dataInfo.timestamp},  #{curTime})
+    </insert>
+
 
 </mapper>

+ 16 - 8
service-iot/service-iot-biz/src/main/java/com/usky/iot/controller/web/DeviceHttpController.java

@@ -1,18 +1,12 @@
 package com.usky.iot.controller.web;
 
-import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
-import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
-import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.usky.common.core.bean.ApiResult;
-import com.usky.iot.domain.DmpDeviceStatus;
+import com.usky.iot.service.DmpDataInfoService;
 import com.usky.iot.service.DmpDeviceStatusService;
+import com.usky.backend.domain.request.DmpDeviceDataRequestVO;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 
-import java.time.LocalDateTime;
-import java.time.format.DateTimeFormatter;
-import java.util.List;
-
 /**
  * @author zyj
  * @date 2023/6/8 13:52:05
@@ -24,11 +18,25 @@ public class DeviceHttpController {
     @Autowired
     private DmpDeviceStatusService dmpDeviceStatusService;
 
+    @Autowired
+    private DmpDataInfoService dmpDataInfoService;
+
     @PutMapping("/status")
     public ApiResult<Void> status(){
         dmpDeviceStatusService.status();
         return ApiResult.success();
     }
 
+    /**
+     * 设备实时历史数据-对接客户
+     * @param dmpDeviceDataRequestVO
+     * @return
+     */
+    @PostMapping("/data")
+    public ApiResult<Void> data(@RequestBody DmpDeviceDataRequestVO dmpDeviceDataRequestVO){
+        dmpDataInfoService.data(dmpDeviceDataRequestVO);
+        return ApiResult.success();
+    }
+
 
 }

+ 13 - 0
service-iot/service-iot-biz/src/main/java/com/usky/iot/controller/web/DmpDeviceInfoController.java

@@ -16,6 +16,7 @@ import org.springframework.web.bind.annotation.*;
 import org.springframework.web.multipart.MultipartFile;
 
 import javax.servlet.http.HttpServletResponse;
+import javax.validation.constraints.NotNull;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -89,6 +90,18 @@ public class DmpDeviceInfoController {
         return ApiResult.success();
     }
 
+    /**
+     * 批量导入-对接客户
+     *
+     * @param list
+     * @return
+     */
+    @PostMapping("/importDeviceInfo")
+    public ApiResult<Void> importDeviceInfo(@RequestBody List<DmpDeviceInfo> list){
+        dmpDeviceInfoService.importDeviceInfo(list);
+        return ApiResult.success();
+    }
+
     /**
      * 导出
      * @param dmpDeviceInfoRequest

+ 3 - 0
service-iot/service-iot-biz/src/main/java/com/usky/iot/service/DmpDataInfoService.java

@@ -2,6 +2,7 @@ package com.usky.iot.service;
 
 import com.usky.common.mybatis.core.CrudService;
 import com.usky.iot.domain.DmpDataInfo;
+import com.usky.backend.domain.request.DmpDeviceDataRequestVO;
 
 
 /**
@@ -14,4 +15,6 @@ import com.usky.iot.domain.DmpDataInfo;
  */
 public interface DmpDataInfoService extends CrudService<DmpDataInfo> {
 
+    void data(DmpDeviceDataRequestVO dmpDeviceDataRequestVO);
+
 }

+ 2 - 0
service-iot/service-iot-biz/src/main/java/com/usky/iot/service/DmpDeviceInfoService.java

@@ -47,6 +47,8 @@ public interface DmpDeviceInfoService extends CrudService<DmpDeviceInfo> {
 
     void addByFile(Integer productId, MultipartFile multipartFiles);
 
+    void importDeviceInfo(List<DmpDeviceInfo> list);
+
     /**
      * 导出
      * @param dmpDeviceInfoRequest

+ 93 - 2
service-iot/service-iot-biz/src/main/java/com/usky/iot/service/impl/DmpDataInfoServiceImpl.java

@@ -1,11 +1,26 @@
 package com.usky.iot.service.impl;
 
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.usky.backend.client.DeviceDataClient;
+import com.usky.backend.domain.request.DeviceDataInfoVO;
+import com.usky.common.core.exception.BusinessException;
 import com.usky.common.mybatis.core.AbstractCrudService;
-import com.usky.iot.domain.DmpDataInfo;
+import com.usky.iot.domain.*;
 import com.usky.iot.mapper.DmpDataInfoMapper;
-import com.usky.iot.service.DmpDataInfoService;
+import com.usky.iot.service.*;
+import com.usky.backend.domain.request.DmpDeviceDataRequestVO;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
+import java.time.Instant;
+import java.time.LocalDateTime;
+import java.time.ZoneId;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
 /**
  * <p>
  * 数据信息 服务实现类
@@ -16,5 +31,81 @@ import org.springframework.stereotype.Service;
  */
 @Service
 public class DmpDataInfoServiceImpl extends AbstractCrudService<DmpDataInfoMapper, DmpDataInfo> implements DmpDataInfoService {
+    @Autowired
+    private DmpProductInfoService dmpProductInfoService;
+
+    @Autowired
+    private DmpProductAttributeService dmpProductAttributeService;
+
+    @Autowired
+    private DmpDeviceInfoService dmpDeviceInfoService;
+
+    @Autowired
+    private DeviceDataClient deviceDataClient;
+
+    @Autowired
+    private DmpDeviceTypeService dmpDeviceTypeService;
+
+    @Override
+    public void data(DmpDeviceDataRequestVO dmpDeviceDataRequestVO){
+        List<DeviceDataInfoVO> dataInfo = new ArrayList<>();
+
+        LambdaQueryWrapper<DmpDeviceInfo> dmpDeviceQuery = Wrappers.lambdaQuery();
+        dmpDeviceQuery.eq(DmpDeviceInfo::getDeleteFlag,0)
+                .eq(DmpDeviceInfo::getDeviceId,dmpDeviceDataRequestVO.getDeviceId());
+        List<DmpDeviceInfo> deviceDataInfo = dmpDeviceInfoService.list(dmpDeviceQuery);
+        if(CollectionUtils.isEmpty(deviceDataInfo)){
+            throw new BusinessException("录入数据失败,"+dmpDeviceDataRequestVO.getDeviceId()+" 这个设备没有注册");
+        }
+
+
+        LambdaQueryWrapper<DmpProductInfo> queryWrapper = Wrappers.lambdaQuery();
+        queryWrapper.select(DmpProductInfo::getId,DmpProductInfo::getDeviceType)
+                .eq(DmpProductInfo::getDeleteFlag,0)
+                .eq(DmpProductInfo::getProductCode,dmpDeviceDataRequestVO.getProductCode());
+        List<DmpProductInfo> list = dmpProductInfoService.list(queryWrapper);
+        if(CollectionUtils.isNotEmpty(list)){
+
+            LambdaQueryWrapper<DmpDeviceType> deviceTypeList = Wrappers.lambdaQuery();
+            deviceTypeList.eq(DmpDeviceType::getTypeCode,list.get(0).getDeviceType());
+            List<DmpDeviceType> lt = dmpDeviceTypeService.list(deviceTypeList);
+            if(CollectionUtils.isEmpty(lt)){
+                throw new BusinessException("查找设备类型简称失败,"+list.get(0).getDeviceType()+" 在设备类型表中不存在");
+            }
+            String shortName = lt.get(0).getTypeAbbrevia();
+
+            LambdaQueryWrapper<DmpProductAttribute> queryWrapper1 = Wrappers.lambdaQuery();
+            queryWrapper1.select(DmpProductAttribute::getAttributeCode)
+                    .eq(DmpProductAttribute::getDeleteFlag,0)
+                    .eq(DmpProductAttribute::getProductId,list.get(0).getId());
+            List<DmpProductAttribute> list1 = dmpProductAttributeService.list(queryWrapper1);
+            if(CollectionUtils.isNotEmpty(list1)){
+                for(int i=0;i<list1.size();i++){
+                    Map<String,Float> metrics = dmpDeviceDataRequestVO.getMetrics();
+                    if(metrics.size()>0){
+                        for(Map.Entry<String,Float> map:metrics.entrySet()){
+                            String key = map.getKey();
+                            float value = map.getValue();
+                            if(key.equals(list1.get(i).getAttributeCode())){   //属性名需和产品注册信息一致
+                                DeviceDataInfoVO deviceDataInfoVO = new DeviceDataInfoVO();
+                                deviceDataInfoVO.setDeviceId(dmpDeviceDataRequestVO.getDeviceId());
+                                deviceDataInfoVO.setDeviceType(list.get(0).getDeviceType());
+                                deviceDataInfoVO.setTypeAbbrevia(shortName);
+                                deviceDataInfoVO.setName(key);
+                                deviceDataInfoVO.setValue(value);
+                                deviceDataInfoVO.setTimestamp(LocalDateTime.ofInstant(Instant.ofEpochSecond(dmpDeviceDataRequestVO.getTimestamp()), ZoneId.systemDefault()));
+                                dataInfo.add(deviceDataInfoVO);
+                            }
+                        }
+                    }
+                }
+            }
+        }else{
+            throw new BusinessException("查找产品信息失败,"+dmpDeviceDataRequestVO.getProductCode()+" 在产品信息表中不存在");
+        }
+        if(CollectionUtils.isNotEmpty(dataInfo)){
+            deviceDataClient.data(dataInfo);
+        }
+    }
 
 }

+ 35 - 0
service-iot/service-iot-biz/src/main/java/com/usky/iot/service/impl/DmpDeviceInfoServiceImpl.java

@@ -75,6 +75,8 @@ public class DmpDeviceInfoServiceImpl extends AbstractCrudService<DmpDeviceInfoM
             dmpDeviceStatus.setDeviceStatus(2);
             dmpDeviceStatus.setLastOfflineTime(LocalDateTime.now());
             dmpDeviceStatusService.save(dmpDeviceStatus);
+        }else{
+            throw new BusinessException("新增设备信息'" + dmpDeviceInfo.getDeviceId() + "'失败,无对应产品信息");
         }
     }
 
@@ -140,6 +142,39 @@ public class DmpDeviceInfoServiceImpl extends AbstractCrudService<DmpDeviceInfoM
         this.saveBatch(deviceByFile);
     }
 
+    @Override
+    public void importDeviceInfo(List<DmpDeviceInfo> devList){
+        List<DmpDeviceStatus> dmpDeviceStatusList = new ArrayList<>();
+        if(CollectionUtils.isEmpty(devList)){
+            throw new BusinessException("数据不能为空");
+        }
+        for(int i=0;i<devList.size();i++){
+            if (checkNameUnique(devList.get(i))){
+                throw new BusinessException("新增设备信息'" + devList.get(i).getDeviceId() + "'失败,设备信息已存在");
+            }
+            List<DmpProductInfo> list = baseMapper.getProductInfo(devList.get(i).getProductCode());
+            if(CollectionUtils.isNotEmpty(list)){
+                devList.get(i).setDeviceType(list.get(0).getDeviceType());
+                devList.get(i).setProductId(list.get(0).getId());
+                devList.get(i).setCreatedBy(SecurityUtils.getUsername());
+                devList.get(i).setCreatedTime(LocalDateTime.now());
+                devList.get(i).setTenantId(SecurityUtils.getTenantId());
+                devList.get(i).setServiceStatus(1);
+
+                DmpDeviceStatus dmpDeviceStatus = new DmpDeviceStatus();
+                dmpDeviceStatus.setDeviceId(devList.get(i).getDeviceId());
+                dmpDeviceStatus.setProductId(devList.get(i).getProductId());
+                dmpDeviceStatus.setDeviceStatus(2);
+                dmpDeviceStatus.setLastOfflineTime(LocalDateTime.now());
+                dmpDeviceStatusList.add(dmpDeviceStatus);
+            }else{
+                throw new BusinessException("新增设备信息'" + devList.get(i).getDeviceId() + "'失败,无对应产品信息");
+            }
+        }
+        this.saveBatch(devList);
+        dmpDeviceStatusService.saveBatch(dmpDeviceStatusList);
+    }
+
     @Override
     public void export(DmpDeviceInfoRequest dmpDeviceInfoRequest, HttpServletResponse response) {
         Workbook workbook = null;