Sfoglia il codice sorgente

优化设备信息表-新增和设备信息表-修改两个接口,增加地址码字段值的录入;优化设备信息表-分页和设备信息表-分页-白名单两个接口,增加所属网关的刷选条件;优化网关配置信息-导出接口,调整导出文件格式和导出方式;

james 14 ore fa
parent
commit
db5a081802

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

@@ -143,8 +143,8 @@ public class DmpDeviceInfoController {
      * @return
      */
     @PostMapping("/gatewayExport")
-    public void gatewayExport(@RequestBody GatewayDeviceInfoRequestVO gatewayDeviceInfoRequestVO) {
-        dmpDeviceInfoService.gatewayExport(gatewayDeviceInfoRequestVO);
+    public void gatewayExport(@RequestBody GatewayDeviceInfoRequestVO gatewayDeviceInfoRequestVO, HttpServletResponse response) {
+        dmpDeviceInfoService.gatewayExport(gatewayDeviceInfoRequestVO, response);
     }
 
     /**

+ 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:离线
      */

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

@@ -72,7 +72,7 @@ public interface DmpDeviceInfoService extends CrudService<DmpDeviceInfo> {
      * 网关设备信息导出
      * @param gatewayDeviceInfoRequestVO
      */
-    void gatewayExport(GatewayDeviceInfoRequestVO gatewayDeviceInfoRequestVO);
+    void gatewayExport(GatewayDeviceInfoRequestVO gatewayDeviceInfoRequestVO, HttpServletResponse response);
 
     CommonPage<Object> deviceCurrentDataList(String deviceName,String installAddress,String productCode,Integer pageNum,Integer pageSize);
 

+ 118 - 37
service-iot/service-iot-biz/src/main/java/com/usky/iot/service/impl/DmpDeviceInfoServiceImpl.java

@@ -8,9 +8,9 @@ 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.alibaba.fastjson.serializer.SerializerFeature;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
@@ -53,9 +53,8 @@ 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.net.URLEncoder;
 import java.nio.charset.StandardCharsets;
 import java.text.DecimalFormat;
 import java.time.Instant;
@@ -106,6 +105,12 @@ public class DmpDeviceInfoServiceImpl extends AbstractCrudService<DmpDeviceInfoM
     @Autowired
     private DeviceOperate deviceOperate;
 
+    @Autowired
+    private DmpProductInfoService dmpProductInfoService;
+
+    @Autowired
+    private DmpDeviceTypeService dmpDeviceTypeService;
+
     private static final String ALARM_HTTP_URL = "/service-alarm/baseAlarm/alarmInfo";
 
 
@@ -654,6 +659,7 @@ public class DmpDeviceInfoServiceImpl extends AbstractCrudService<DmpDeviceInfoM
             spaceGatewayLambdaQueryWrapper.eq(BaseSpaceGateway::getSpaceId, diRequest.getSpaceId());
             gatewayUuidList = baseSpaceGatewayService.list(spaceGatewayLambdaQueryWrapper).stream().map(BaseSpaceGateway::getGatewayUuid).collect(Collectors.toList());
         }
+        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,7 @@ public class DmpDeviceInfoServiceImpl extends AbstractCrudService<DmpDeviceInfoM
             spaceGatewayLambdaQueryWrapper.eq(BaseSpaceGateway::getSpaceId, diRequest.getSpaceId());
             gatewayUuidList = baseSpaceGatewayService.list(spaceGatewayLambdaQueryWrapper).stream().map(BaseSpaceGateway::getGatewayUuid).collect(Collectors.toList());
         }
+        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,57 +1187,131 @@ public class DmpDeviceInfoServiceImpl extends AbstractCrudService<DmpDeviceInfoM
     }
 
     @Override
-    public void gatewayExport(GatewayDeviceInfoRequestVO gatewayDeviceInfoRequestVO){
+    public void gatewayExport(GatewayDeviceInfoRequestVO gatewayDeviceInfoRequestVO, HttpServletResponse response) {
         try {
-            // 1. 查询数据库中的设备信息
+            if (StringUtils.isBlank(gatewayDeviceInfoRequestVO.getGatewayUuid())) {
+                throw new BusinessException("网关UUID不能为空");
+            }
             LambdaQueryWrapper<DmpDeviceInfo> queryWrapper = Wrappers.lambdaQuery();
-            queryWrapper.eq(DmpDeviceInfo::getCategoryType,3)
+            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::getGatewayUuid, gatewayDeviceInfoRequestVO.getGatewayUuid())
                     .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));
+            if (CollectionUtil.isEmpty(gatewayDeviceList)) {
+                throw new BusinessException("未查询到网关子设备信息");
+            }
+            String content = buildGatewayDeviceCfgContent(gatewayDeviceList);
+            exportCfg(content, response);
+        } catch (BusinessException e) {
+            throw e;
         } catch (Exception e) {
-            throw new RuntimeException("导出网关设备配置信息失败", e);
+            log.error("导出网关设备配置信息失败", e);
+            throw new BusinessException("导出网关设备配置信息失败" + e.getMessage());
         }
     }
 
     /**
-     * 导出设备信息到TXT文件
-     * @param deviceList 设备列表
-     * @param outputStream 输出流(用于下载)
+     * 按设备类型简称 -> 地址码 构建网关子设备配置内容
      */
-    public static void exportDeviceToTxt(List<DmpDeviceInfo> deviceList, OutputStream outputStream) {
-        // 1. 构建TXT内容(自定义格式,按行写入)
-        StringBuilder content = new StringBuilder();
-        // 写入表头
-        content.append("{");
-        // 写入数据行
+    private String buildGatewayDeviceCfgContent(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, JSONObject>> 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() + " 未找到对应设备类型简称");
+            }
+            JSONObject deviceInfo = new JSONObject(true);
+            deviceInfo.put("deviceid", device.getDeviceId());
+            deviceInfo.put("deviceUuid", device.getDeviceUuid());
+            deviceInfo.put("productCode", device.getProductCode());
+            grouped.computeIfAbsent(typeAbbrevia, key -> new LinkedHashMap<>())
+                    .put(device.getAddressCode(), deviceInfo);
+        }
+        if (grouped.isEmpty()) {
+            throw new BusinessException("网关子设备地址码为空,无法导出配置");
+        }
+
+        JSONObject root = new JSONObject(true);
+        grouped.forEach(root::put);
+        return JSON.toJSONString(root, SerializerFeature.PrettyFormat);
+    }
+
+    /**
+     * 根据产品ID批量查询设备类型简称
+     */
+    private Map<Integer, String> getProductTypeAbbreviaMap(List<Integer> productIds) {
+        if (CollectionUtil.isEmpty(productIds)) {
+            return Collections.emptyMap();
+        }
+        LambdaQueryWrapper<DmpProductInfo> productQuery = Wrappers.lambdaQuery();
+        productQuery.select(DmpProductInfo::getId, DmpProductInfo::getDeviceType)
+                .in(DmpProductInfo::getId, productIds)
+                .eq(DmpProductInfo::getDeleteFlag, 0);
+        List<DmpProductInfo> products = dmpProductInfoService.list(productQuery);
+        if (CollectionUtil.isEmpty(products)) {
+            return Collections.emptyMap();
         }
-        content.delete(content.length()-1, content.length());
-        content.append("\n}");
 
-        // 2. 将内容写入输出流(UTF-8编码避免乱码)
+        Map<Integer, Integer> productDeviceTypeMap = products.stream()
+                .collect(Collectors.toMap(DmpProductInfo::getId, DmpProductInfo::getDeviceType, (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;
+    }
+
+    private void exportCfg(String content, HttpServletResponse response) {
+        ServletOutputStream outputStream = null;
         try {
-            outputStream.write(content.toString().getBytes(StandardCharsets.UTF_8));
+            response.setContentType("application/octet-stream");
+            response.setCharacterEncoding("utf-8");
+            String fileName = URLEncoder.encode("gateway.cfg", StandardCharsets.UTF_8.name()).replace("+", "%20");
+            response.setHeader("Content-Disposition", "attachment; filename=" + fileName);
+            outputStream = response.getOutputStream();
+            outputStream.write(content.getBytes(StandardCharsets.UTF_8));
             outputStream.flush();
-        } catch (Exception e) {
-            throw new RuntimeException("导出TXT文件失败", e);
+        } catch (IOException e) {
+            log.error("导出cfg文件失败", e);
+            throw new BusinessException("导出cfg文件失败" + e.getMessage());
+        } finally {
+            if (outputStream != null) {
+                try {
+                    outputStream.close();
+                } catch (IOException e) {
+                    log.error("关闭输出流失败", e);
+                }
+            }
         }
     }
 

+ 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;
+
 }

+ 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;
 }