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