Selaa lähdekoodia

Merge branch 'usky-zyj' of uskycloud/usky-modules into master

hanzhengyi 12 tuntia sitten
vanhempi
commit
aeae33b905

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

@@ -138,13 +138,13 @@ public class DmpDeviceInfoController {
     }
 
     /**
-     * 网关配置导出
+     * 网关配置查询
      * @param gatewayDeviceInfoRequestVO
      * @return
      */
     @PostMapping("/gatewayExport")
-    public void gatewayExport(@RequestBody GatewayDeviceInfoRequestVO gatewayDeviceInfoRequestVO) {
-        dmpDeviceInfoService.gatewayExport(gatewayDeviceInfoRequestVO);
+    public ApiResult<Map<String, Map<String, GatewayDeviceExportItemVO>>> gatewayExport(@RequestBody GatewayDeviceInfoRequestVO gatewayDeviceInfoRequestVO) {
+        return ApiResult.success(dmpDeviceInfoService.gatewayExport(gatewayDeviceInfoRequestVO));
     }
 
     /**

+ 5 - 0
service-iot/service-iot-biz/src/main/java/com/usky/iot/domain/DmpDeviceInfo.java

@@ -157,6 +157,11 @@ public class DmpDeviceInfo implements Serializable {
      */
     private Integer buildId;
 
+    /**
+     * 地址码
+     */
+    private String addressCode;
+
     /**
      * 设备状态;1:在线,2:离线
      */

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

@@ -21,4 +21,6 @@ public interface DmpProductInfoMapper extends CrudMapper<DmpProductInfo> {
 
 
     List<Map<String,Object>> selectCollect(@Param("tenantId") Integer tenantId);
+
+    List<Map<String, Object>> selectDeviceTypeByProductIds(@Param("productIds") List<Integer> productIds);
 }

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

@@ -69,10 +69,10 @@ public interface DmpDeviceInfoService extends CrudService<DmpDeviceInfo> {
     void export(DmpDeviceInfoRequest dmpDeviceInfoRequest, HttpServletResponse response);
 
     /**
-     * 网关设备信息导出
+     * 网关设备配置查询
      * @param gatewayDeviceInfoRequestVO
      */
-    void gatewayExport(GatewayDeviceInfoRequestVO gatewayDeviceInfoRequestVO);
+    Map<String, Map<String, GatewayDeviceExportItemVO>> gatewayExport(GatewayDeviceInfoRequestVO gatewayDeviceInfoRequestVO);
 
     CommonPage<Object> deviceCurrentDataList(String deviceName,String installAddress,String productCode,Integer pageNum,Integer pageSize);
 

+ 94 - 47
service-iot/service-iot-biz/src/main/java/com/usky/iot/service/impl/DmpDeviceInfoServiceImpl.java

@@ -8,7 +8,6 @@ import cn.afterturn.easypoi.excel.entity.ImportParams;
 import cn.hutool.core.collection.CollectionUtil;
 import cn.hutool.core.date.DateTime;
 import cn.hutool.core.date.DateUtil;
-import cn.hutool.core.io.FileUtil;
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
@@ -38,6 +37,7 @@ import com.usky.iot.domain.*;
 import com.usky.common.security.utils.SecurityUtils;
 import com.usky.iot.mapper.DmpDeviceInfoMapper;
 import com.usky.iot.mapper.DmpProductAttributeMapper;
+import com.usky.iot.mapper.DmpProductInfoMapper;
 import com.usky.iot.service.*;
 import com.usky.iot.service.config.DeviceOperate;
 import com.usky.iot.service.enums.TopicInfo;
@@ -53,10 +53,7 @@ import org.springframework.web.multipart.MultipartFile;
 
 import javax.servlet.ServletOutputStream;
 import javax.servlet.http.HttpServletResponse;
-import java.io.File;
 import java.io.IOException;
-import java.io.OutputStream;
-import java.nio.charset.StandardCharsets;
 import java.text.DecimalFormat;
 import java.time.Instant;
 import java.time.LocalDateTime;
@@ -106,6 +103,12 @@ public class DmpDeviceInfoServiceImpl extends AbstractCrudService<DmpDeviceInfoM
     @Autowired
     private DeviceOperate deviceOperate;
 
+    @Autowired
+    private DmpProductInfoMapper dmpProductInfoMapper;
+
+    @Autowired
+    private DmpDeviceTypeService dmpDeviceTypeService;
+
     private static final String ALARM_HTTP_URL = "/service-alarm/baseAlarm/alarmInfo";
 
 
@@ -654,6 +657,9 @@ public class DmpDeviceInfoServiceImpl extends AbstractCrudService<DmpDeviceInfoM
             spaceGatewayLambdaQueryWrapper.eq(BaseSpaceGateway::getSpaceId, diRequest.getSpaceId());
             gatewayUuidList = baseSpaceGatewayService.list(spaceGatewayLambdaQueryWrapper).stream().map(BaseSpaceGateway::getGatewayUuid).collect(Collectors.toList());
         }
+        if(StringUtils.isNotBlank(diRequest.getGatewayUuid())){
+            gatewayUuidList.add(diRequest.getGatewayUuid());
+        }
 
         if (diRequest.getDeviceStatus() != null) {
             if (StringUtils.isNotBlank(diRequest.getDeviceId()) || StringUtils.isNotBlank(diRequest.getDeviceUuid()) || StringUtils.isNotBlank(diRequest.getDeviceName()) || diRequest.getProductId() != null || StringUtils.isNotBlank(diRequest.getProductCode()) || diRequest.getServiceStatus() != null || diRequest.getCategoryType() != null) {
@@ -860,6 +866,9 @@ public class DmpDeviceInfoServiceImpl extends AbstractCrudService<DmpDeviceInfoM
             spaceGatewayLambdaQueryWrapper.eq(BaseSpaceGateway::getSpaceId, diRequest.getSpaceId());
             gatewayUuidList = baseSpaceGatewayService.list(spaceGatewayLambdaQueryWrapper).stream().map(BaseSpaceGateway::getGatewayUuid).collect(Collectors.toList());
         }
+        if(StringUtils.isNotBlank(diRequest.getGatewayUuid())){
+            gatewayUuidList.add(diRequest.getGatewayUuid());
+        }
 
         if (diRequest.getDeviceStatus() != null) {
             if (StringUtils.isNotBlank(diRequest.getDeviceId()) || StringUtils.isNotBlank(diRequest.getDeviceName()) || diRequest.getProductId() != null || StringUtils.isNotBlank(diRequest.getProductCode()) || diRequest.getServiceStatus() != null || diRequest.getCategoryType() != null) {
@@ -1180,58 +1189,96 @@ public class DmpDeviceInfoServiceImpl extends AbstractCrudService<DmpDeviceInfoM
     }
 
     @Override
-    public void gatewayExport(GatewayDeviceInfoRequestVO gatewayDeviceInfoRequestVO){
-        try {
-            // 1. 查询数据库中的设备信息
-            LambdaQueryWrapper<DmpDeviceInfo> queryWrapper = Wrappers.lambdaQuery();
-            queryWrapper.eq(DmpDeviceInfo::getCategoryType,3)
-                    .eq(DmpDeviceInfo::getDeleteFlag, 0)
-                    .eq(StringUtils.isNotBlank(gatewayDeviceInfoRequestVO.getGatewayUuid()), DmpDeviceInfo::getGatewayUuid, gatewayDeviceInfoRequestVO.getGatewayUuid())
-                    .eq(StringUtils.isNotBlank(gatewayDeviceInfoRequestVO.getProductCode()), DmpDeviceInfo::getProductCode, gatewayDeviceInfoRequestVO.getProductCode())
-                    .eq(DmpDeviceInfo::getTenantId, SecurityUtils.getTenantId())
-                    .orderByDesc(DmpDeviceInfo::getId);
-            List<DmpDeviceInfo> gatewayDeviceList = this.list(queryWrapper);
-
-            // 2. 定义服务器本地保存路径(建议配置在application.yml中,这里简化写死)
-            // 注意:要确保该目录存在,否则会报错;Windows路径用\\,Linux/Mac用/
-            String localPath = gatewayDeviceInfoRequestVO.getFilePath()+ "/" + gatewayDeviceInfoRequestVO.getProductCode() + ".cfg";
-
-            // 3. 调用exportToLocalFile导出到本地
-            File file = FileUtil.file(localPath);
-            exportDeviceToTxt(gatewayDeviceList, FileUtil.getOutputStream(file));
-        } catch (Exception e) {
-            throw new RuntimeException("导出网关设备配置信息失败", e);
+    public Map<String, Map<String, GatewayDeviceExportItemVO>> gatewayExport(GatewayDeviceInfoRequestVO gatewayDeviceInfoRequestVO) {
+        if (StringUtils.isBlank(gatewayDeviceInfoRequestVO.getGatewayUuid())) {
+            throw new BusinessException("网关UUID不能为空");
         }
+        LambdaQueryWrapper<DmpDeviceInfo> queryWrapper = Wrappers.lambdaQuery();
+        queryWrapper.eq(DmpDeviceInfo::getCategoryType, 3)
+                .eq(DmpDeviceInfo::getDeleteFlag, 0)
+                .eq(DmpDeviceInfo::getGatewayUuid, gatewayDeviceInfoRequestVO.getGatewayUuid())
+                .eq(DmpDeviceInfo::getTenantId, SecurityUtils.getTenantId())
+                .orderByDesc(DmpDeviceInfo::getId);
+        List<DmpDeviceInfo> gatewayDeviceList = this.list(queryWrapper);
+        if (CollectionUtil.isEmpty(gatewayDeviceList)) {
+            throw new BusinessException("未查询到网关子设备信息");
+        }
+        return buildGatewayDeviceExportMap(gatewayDeviceList);
     }
 
     /**
-     * 导出设备信息到TXT文件
-     * @param deviceList 设备列表
-     * @param outputStream 输出流(用于下载)
+     * 按设备类型简称 -> 地址码 构建网关子设备配置
      */
-    public static void exportDeviceToTxt(List<DmpDeviceInfo> deviceList, OutputStream outputStream) {
-        // 1. 构建TXT内容(自定义格式,按行写入)
-        StringBuilder content = new StringBuilder();
-        // 写入表头
-        content.append("{");
-        // 写入数据行
+    private Map<String, Map<String, GatewayDeviceExportItemVO>> buildGatewayDeviceExportMap(List<DmpDeviceInfo> deviceList) {
+        List<Integer> productIds = deviceList.stream()
+                .map(DmpDeviceInfo::getProductId)
+                .filter(Objects::nonNull)
+                .distinct()
+                .collect(Collectors.toList());
+        Map<Integer, String> productTypeAbbreviaMap = getProductTypeAbbreviaMap(productIds);
+
+        Map<String, Map<String, GatewayDeviceExportItemVO>> grouped = new LinkedHashMap<>();
         for (DmpDeviceInfo device : deviceList) {
-            content.append("\n\t\"").append(device.getImsiCode()).append("\":")
-                    .append("{").append("\"").append("deviceid").append("\"").append(":").append("\"").append(device.getDeviceId()).append("\"").append(",")
-                    .append("\"").append("deviceUuid").append("\"").append(":").append("\"").append(device.getDeviceUuid()).append("\"").append(",")
-                    .append("\"").append("productCode").append("\"").append(":").append("\"").append(device.getProductCode()).append("\"")
-                    .append("}").append(",");
+            if (StringUtils.isBlank(device.getAddressCode())) {
+                continue;
+            }
+            String typeAbbrevia = productTypeAbbreviaMap.get(device.getProductId());
+            if (StringUtils.isBlank(typeAbbrevia)) {
+                throw new BusinessException("产品ID " + device.getProductId() + " 未找到对应设备类型简称");
+            }
+            GatewayDeviceExportItemVO deviceInfo = new GatewayDeviceExportItemVO();
+            deviceInfo.setDeviceid(device.getDeviceId());
+            deviceInfo.setDeviceUuid(device.getDeviceUuid());
+            deviceInfo.setProductCode(device.getProductCode());
+            grouped.computeIfAbsent(typeAbbrevia, key -> new LinkedHashMap<>())
+                    .put(device.getAddressCode(), deviceInfo);
         }
-        content.delete(content.length()-1, content.length());
-        content.append("\n}");
+        if (grouped.isEmpty()) {
+            throw new BusinessException("网关子设备地址码为空,无法导出配置");
+        }
+        return grouped;
+    }
 
-        // 2. 将内容写入输出流(UTF-8编码避免乱码)
-        try {
-            outputStream.write(content.toString().getBytes(StandardCharsets.UTF_8));
-            outputStream.flush();
-        } catch (Exception e) {
-            throw new RuntimeException("导出TXT文件失败", e);
+    /**
+     * 根据产品ID批量查询设备类型简称
+     */
+    private Map<Integer, String> getProductTypeAbbreviaMap(List<Integer> productIds) {
+        if (CollectionUtil.isEmpty(productIds)) {
+            return Collections.emptyMap();
         }
+        List<Map<String, Object>> products = dmpProductInfoMapper.selectDeviceTypeByProductIds(productIds);
+        if (CollectionUtil.isEmpty(products)) {
+            return Collections.emptyMap();
+        }
+
+        Map<Integer, Integer> productDeviceTypeMap = products.stream()
+                .collect(Collectors.toMap(
+                        map -> Integer.valueOf(map.get("id").toString()),
+                        map -> Integer.valueOf(map.get("deviceType").toString()),
+                        (a, b) -> a));
+
+        Set<String> typeCodes = productDeviceTypeMap.values().stream()
+                .filter(Objects::nonNull)
+                .map(String::valueOf)
+                .collect(Collectors.toSet());
+        if (CollectionUtil.isEmpty(typeCodes)) {
+            return Collections.emptyMap();
+        }
+
+        LambdaQueryWrapper<DmpDeviceType> typeQuery = Wrappers.lambdaQuery();
+        typeQuery.select(DmpDeviceType::getTypeCode, DmpDeviceType::getTypeAbbrevia)
+                .in(DmpDeviceType::getTypeCode, typeCodes);
+        Map<String, String> typeCodeAbbreviaMap = dmpDeviceTypeService.list(typeQuery).stream()
+                .collect(Collectors.toMap(DmpDeviceType::getTypeCode, DmpDeviceType::getTypeAbbrevia, (a, b) -> a));
+
+        Map<Integer, String> result = new HashMap<>();
+        productDeviceTypeMap.forEach((productId, deviceType) -> {
+            String typeAbbrevia = typeCodeAbbreviaMap.get(String.valueOf(deviceType));
+            if (StringUtils.isNotBlank(typeAbbrevia)) {
+                result.put(productId, typeAbbrevia);
+            }
+        });
+        return result;
     }
 
     public void exportExcel(Workbook workbook, HttpServletResponse response) {

+ 5 - 0
service-iot/service-iot-biz/src/main/java/com/usky/iot/service/vo/DmpDeviceInfoRequest.java

@@ -66,4 +66,9 @@ public class DmpDeviceInfoRequest {
      */
     private Integer spaceId;
 
+    /**
+     * 所属网关
+     */
+    private String gatewayUuid;
+
 }

+ 13 - 0
service-iot/service-iot-biz/src/main/java/com/usky/iot/service/vo/GatewayDeviceExportItemVO.java

@@ -0,0 +1,13 @@
+package com.usky.iot.service.vo;
+
+import lombok.Data;
+
+@Data
+public class GatewayDeviceExportItemVO {
+
+    private String deviceid;
+
+    private String deviceUuid;
+
+    private String productCode;
+}

+ 0 - 10
service-iot/service-iot-biz/src/main/java/com/usky/iot/service/vo/GatewayDeviceInfoRequestVO.java

@@ -5,18 +5,8 @@ import lombok.Data;
 @Data
 public class GatewayDeviceInfoRequestVO {
 
-    /**
-     * 产品编码
-     */
-    private String productCode;
-
     /**
      * 网关设备Uuid
      */
     private String gatewayUuid;
-
-    /**
-     * 文件路径
-     */
-    private String filePath;
 }

+ 10 - 0
service-iot/service-iot-biz/src/main/resources/mapper/iot/DmpProductInfoMapper.xml

@@ -43,4 +43,14 @@
         group by product_name
     </select>
 
+    <select id="selectDeviceTypeByProductIds" resultType="java.util.Map">
+        select id, device_type as deviceType
+        from dmp_product
+        where delete_flag = 0
+        and id in
+        <foreach collection="productIds" item="productId" open="(" separator="," close=")">
+            #{productId}
+        </foreach>
+    </select>
+
 </mapper>

+ 22 - 6
service-tsdb/service-tsdb-biz/src/main/java/com/usky/demo/service/impl/QueryTdengineDataServiceImpl.java

@@ -63,10 +63,10 @@ public class QueryTdengineDataServiceImpl extends AbstractCrudService<QueryTdeng
 
         // 遍历设备表集合,自动忽略表中不存在的字段,用有效字段构建查询,避免错误
         for (int i = 0; i < deviceUUIds.size(); i++) {
-            try (Connection connection = dataSource.getConnection()) {
 
-                String tablename = "_"+deviceUUIds.get(i);
+            String tablename = "_"+deviceUUIds.get(i);
 
+            try (Connection connection = dataSource.getConnection()) {
                 String sql = "describe " + tablename;
 
                 try (PreparedStatement itemStmt = connection.prepareStatement(sql)) {
@@ -123,6 +123,15 @@ public class QueryTdengineDataServiceImpl extends AbstractCrudService<QueryTdeng
                     }
                 }
 
+            } catch (SQLException e) {
+                // 判断TDengine专属错误码 0x2603 = 表不存在
+                if (e.getMessage().contains("0x2603") || e.getMessage().contains("Table does not exist")) {
+                    System.out.println("表" + tablename + "不存在,跳过");
+                    log.error("表" + tablename + "不存在,跳过");
+                } else {
+                    // 其他异常正常打印堆栈
+                    e.printStackTrace();
+                }
             } catch (Exception e) {
                 e.printStackTrace();
             }
@@ -141,10 +150,10 @@ public class QueryTdengineDataServiceImpl extends AbstractCrudService<QueryTdeng
 
         // 遍历设备表集合,自动忽略表中不存在的字段,用有效字段构建查询,避免错误
         for (int i = 0; i < deviceUUIds.size(); i++) {
-            try (Connection connection = dataSource.getConnection()) {
 
-                String tablename = "_"+deviceUUIds.get(i);
+            String tablename = "_"+deviceUUIds.get(i);
 
+            try (Connection connection = dataSource.getConnection()) {
                 String sql = "describe " + tablename;
 
                 try (PreparedStatement itemStmt = connection.prepareStatement(sql)) {
@@ -228,6 +237,15 @@ public class QueryTdengineDataServiceImpl extends AbstractCrudService<QueryTdeng
                     }
                 }
 
+            } catch (SQLException e) {
+                // 判断TDengine专属错误码 0x2603 = 表不存在
+                if (e.getMessage().contains("0x2603") || e.getMessage().contains("Table does not exist")) {
+                    System.out.println("表" + tablename + "不存在,跳过");
+                    log.error("表" + tablename + "不存在,跳过");
+                } else {
+                    // 其他异常正常打印堆栈
+                    e.printStackTrace();
+                }
             } catch (Exception e) {
                 e.printStackTrace();
             }
@@ -352,7 +370,6 @@ public class QueryTdengineDataServiceImpl extends AbstractCrudService<QueryTdeng
             }
         } catch (SQLException e) {
             log.error("能耗分项汇总查询失败, sql=" + sql + ", " + e.getMessage());
-            throw new BusinessException("能耗分项汇总查询失败: " + e.getMessage());
         }
         return result;
     }
@@ -405,7 +422,6 @@ public class QueryTdengineDataServiceImpl extends AbstractCrudService<QueryTdeng
             }
         } catch (SQLException e) {
             log.error("能耗分项趋势查询失败, sql=" + sql + ", " + e.getMessage());
-            throw new BusinessException("能耗分项趋势查询失败: " + e.getMessage());
         }
 
         result.setPoints(points);