From 4e0e50a4f8f1c0adb85443fd1256fc8fd955f8ca Mon Sep 17 00:00:00 2001 From: hongawen <83944980@qq.com> Date: Wed, 18 Jun 2025 17:53:09 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BA=8C=E7=BB=B4=E7=A0=81=E5=8A=9F=E8=83=BD?= =?UTF-8?q?=E5=BC=80=E5=8F=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- detection/pom.xml | 14 +- .../DetectionCommunicateConstant.java | 3 + .../pojo/enums/SourceOperateCodeEnum.java | 5 + .../service/impl/PreDetectionServiceImpl.java | 6 +- .../business/DetectionCommunicateUtil.java | 11 +- .../report/service/IPqReportService.java | 5 + .../service/impl/PqReportServiceImpl.java | 136 +++++++++++++++++- entrance/src/main/resources/application.yml | 4 +- .../src/test/java/com/njcn/BaseJunitTest.java | 21 ++- 9 files changed, 183 insertions(+), 22 deletions(-) diff --git a/detection/pom.xml b/detection/pom.xml index 536458db..b431b7e1 100644 --- a/detection/pom.xml +++ b/detection/pom.xml @@ -94,7 +94,7 @@ org.docx4j docx4j - 3.3.4 + 6.1.0 com.fasterxml.jackson.core @@ -112,6 +112,18 @@ 2.12.0 + + com.njcn + RestTemplate-plugin + 1.0.0 + + + + commons-net + commons-net + 3.10.0 + + diff --git a/detection/src/main/java/com/njcn/gather/detection/pojo/constant/DetectionCommunicateConstant.java b/detection/src/main/java/com/njcn/gather/detection/pojo/constant/DetectionCommunicateConstant.java index 0420724d..3a6ca24f 100644 --- a/detection/src/main/java/com/njcn/gather/detection/pojo/constant/DetectionCommunicateConstant.java +++ b/detection/src/main/java/com/njcn/gather/detection/pojo/constant/DetectionCommunicateConstant.java @@ -13,6 +13,9 @@ public interface DetectionCommunicateConstant { String DEVICE_CHANNEL_NAME = "AUTO_DETECTION_DEV"; + String DEV = "_Dev"; + + String SOURCE = "_Source"; diff --git a/detection/src/main/java/com/njcn/gather/detection/pojo/enums/SourceOperateCodeEnum.java b/detection/src/main/java/com/njcn/gather/detection/pojo/enums/SourceOperateCodeEnum.java index 10e560e4..5bdc8dfc 100644 --- a/detection/src/main/java/com/njcn/gather/detection/pojo/enums/SourceOperateCodeEnum.java +++ b/detection/src/main/java/com/njcn/gather/detection/pojo/enums/SourceOperateCodeEnum.java @@ -94,6 +94,11 @@ public enum SourceOperateCodeEnum { small_comp_end("small_comp_end","小电压校准结束"), + /** + * ftp文件传送指令 + */ + FTP_SEND_01("FTP_SEND$01", "发送文件") + ; diff --git a/detection/src/main/java/com/njcn/gather/detection/service/impl/PreDetectionServiceImpl.java b/detection/src/main/java/com/njcn/gather/detection/service/impl/PreDetectionServiceImpl.java index e8af2e53..5292ca90 100644 --- a/detection/src/main/java/com/njcn/gather/detection/service/impl/PreDetectionServiceImpl.java +++ b/detection/src/main/java/com/njcn/gather/detection/service/impl/PreDetectionServiceImpl.java @@ -191,7 +191,7 @@ public class PreDetectionServiceImpl implements PreDetectionService { xuMsg.setOperateCode(SourceOperateCodeEnum.OPER_GATHER.getValue()); xuMsg.setData(JSON.toJSONString(sourceIssues)); xuMsg.setRequestId(SourceOperateCodeEnum.FORMAL_REAL.getValue() + "&&" + sourceIssues.getType()); - SocketManager.sendMsg(DetectionCommunicateConstant.SOURCE_CHANNEL_NAME, JSON.toJSONString(xuMsg)); + SocketManager.sendMsg(param.getUserPageId() + DetectionCommunicateConstant.SOURCE, JSON.toJSONString(xuMsg)); } else { //TODO 是否最终检测完成需要推送给用户 PqScriptCheckDataParam checkDataParam = new PqScriptCheckDataParam(); @@ -219,7 +219,7 @@ public class PreDetectionServiceImpl implements PreDetectionService { @Override public void sendScript(SimulateDetectionParam param) { - Channel channel = SocketManager.getChannelByUserId(DetectionCommunicateConstant.SOURCE_CHANNEL_NAME); + Channel channel = SocketManager.getChannelByUserId(param.getUserPageId() + DetectionCommunicateConstant.SOURCE); if (Objects.isNull(channel) || !channel.isActive()) { // 进行源通信连接 PreDetectionParam preDetectionParam = new PreDetectionParam(); @@ -253,7 +253,7 @@ public class PreDetectionServiceImpl implements PreDetectionService { @Override public void closeTestSimulate(SimulateDetectionParam param) { - Channel channel = SocketManager.getChannelByUserId(DetectionCommunicateConstant.SOURCE_CHANNEL_NAME); + Channel channel = SocketManager.getChannelByUserId(param.getUserPageId() + DetectionCommunicateConstant.SOURCE); if (Objects.isNull(channel) || !channel.isActive()) { throw new BusinessException(DetectionResponseEnum.SOURCE_NOT_CONNECT); } diff --git a/detection/src/main/java/com/njcn/gather/detection/util/business/DetectionCommunicateUtil.java b/detection/src/main/java/com/njcn/gather/detection/util/business/DetectionCommunicateUtil.java index 82057c7b..afa13166 100644 --- a/detection/src/main/java/com/njcn/gather/detection/util/business/DetectionCommunicateUtil.java +++ b/detection/src/main/java/com/njcn/gather/detection/util/business/DetectionCommunicateUtil.java @@ -10,7 +10,6 @@ import lombok.extern.slf4j.Slf4j; import java.util.Objects; /** - * * 检测通讯工具类 * * @author hongawen @@ -26,8 +25,9 @@ public class DetectionCommunicateUtil { * 有则强行关闭 */ public static void checkCommunicateChannel(PreDetectionParam param) { - Channel channelSource = SocketManager.getChannelByUserId(DetectionCommunicateConstant.SOURCE_CHANNEL_NAME); - Channel channelDev = SocketManager.getChannelByUserId(DetectionCommunicateConstant.DEVICE_CHANNEL_NAME); + Channel channelSource = SocketManager.getChannelByUserId(param.getUserPageId() + DetectionCommunicateConstant.SOURCE); + Channel channelDev = SocketManager.getChannelByUserId(param.getUserPageId() + DetectionCommunicateConstant.DEV); + if (Objects.nonNull(channelSource) && channelSource.isActive()) { System.out.println("发送关闭源指令。。。。。。。。"); CnSocketUtil.quitSendSource(param); @@ -43,8 +43,8 @@ public class DetectionCommunicateUtil { log.error(e.getMessage()); } - SocketManager.removeUser(DetectionCommunicateConstant.SOURCE_CHANNEL_NAME); - SocketManager.removeUser(DetectionCommunicateConstant.DEVICE_CHANNEL_NAME); + SocketManager.removeUser(param.getUserPageId() + DetectionCommunicateConstant.SOURCE); + SocketManager.removeUser(param.getUserPageId() + DetectionCommunicateConstant.DEV); try { Thread.sleep(2000); @@ -54,5 +54,4 @@ public class DetectionCommunicateUtil { } - } diff --git a/detection/src/main/java/com/njcn/gather/report/service/IPqReportService.java b/detection/src/main/java/com/njcn/gather/report/service/IPqReportService.java index 582a9b64..1e21eaf8 100644 --- a/detection/src/main/java/com/njcn/gather/report/service/IPqReportService.java +++ b/detection/src/main/java/com/njcn/gather/report/service/IPqReportService.java @@ -64,8 +64,10 @@ public interface IPqReportService extends IService { void generateReport(DevReportParam devReportParam); + void downloadReport(DevReportParam devReportParam, HttpServletResponse response); + /** * 设备归档操作 * @@ -73,4 +75,7 @@ public interface IPqReportService extends IService { * @return 归档成功返回true,否则返回false */ boolean documented(List id); + + + } diff --git a/detection/src/main/java/com/njcn/gather/report/service/impl/PqReportServiceImpl.java b/detection/src/main/java/com/njcn/gather/report/service/impl/PqReportServiceImpl.java index 774cab9a..72265e7a 100644 --- a/detection/src/main/java/com/njcn/gather/report/service/impl/PqReportServiceImpl.java +++ b/detection/src/main/java/com/njcn/gather/report/service/impl/PqReportServiceImpl.java @@ -8,7 +8,12 @@ import cn.hutool.core.text.StrPool; import cn.hutool.core.util.ArrayUtil; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; +import cn.hutool.extra.ftp.Ftp; +import cn.hutool.extra.qrcode.QrCodeUtil; +import cn.hutool.extra.qrcode.QrConfig; +import cn.hutool.json.JSONObject; import cn.hutool.json.JSONUtil; +import com.alibaba.fastjson.JSON; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; @@ -17,8 +22,18 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.njcn.common.pojo.constant.PatternRegex; import com.njcn.common.pojo.enums.common.DataStateEnum; import com.njcn.common.pojo.exception.BusinessException; +import com.njcn.common.utils.BinaryDataConverter; +import com.njcn.common.utils.images.ImageConverter; +import com.njcn.gather.detection.handler.SocketDevResponseService; +import com.njcn.gather.detection.pojo.constant.DetectionCommunicateConstant; import com.njcn.gather.detection.pojo.enums.DetectionCodeEnum; +import com.njcn.gather.detection.pojo.enums.SourceOperateCodeEnum; +import com.njcn.gather.detection.pojo.param.PreDetectionParam; import com.njcn.gather.detection.pojo.vo.DetectionData; +import com.njcn.gather.detection.pojo.vo.SocketMsg; +import com.njcn.gather.detection.util.socket.SocketManager; +import com.njcn.gather.detection.util.socket.cilent.NettyClient; +import com.njcn.gather.detection.util.socket.cilent.NettyDevClientHandler; import com.njcn.gather.device.mapper.PqDevMapper; import com.njcn.gather.device.pojo.enums.CheckStateEnum; import com.njcn.gather.device.pojo.enums.DevReportStateEnum; @@ -35,7 +50,6 @@ import com.njcn.gather.report.pojo.constant.PowerConstant; import com.njcn.gather.report.pojo.constant.ReportConstant; import com.njcn.gather.report.pojo.enums.*; import com.njcn.gather.report.pojo.param.ReportParam; -import com.njcn.gather.report.pojo.po.CellEntity; import com.njcn.gather.report.pojo.po.PqReport; import com.njcn.gather.report.pojo.result.SingleTestResult; import com.njcn.gather.report.pojo.vo.PqReportVO; @@ -57,7 +71,10 @@ import com.njcn.gather.system.dictionary.pojo.po.DictData; import com.njcn.gather.system.dictionary.service.IDictDataService; import com.njcn.gather.type.pojo.po.DevType; import com.njcn.gather.type.service.IDevTypeService; +import com.njcn.http.util.RestTemplateUtil; import com.njcn.web.factory.PageFactory; +import com.njcn.web.utils.HttpServletUtil; +import io.netty.channel.Channel; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.poi.xwpf.usermodel.*; @@ -65,24 +82,34 @@ import org.docx4j.jaxb.Context; import org.docx4j.openpackaging.packages.WordprocessingMLPackage; import org.docx4j.openpackaging.parts.WordprocessingML.MainDocumentPart; import org.docx4j.wml.*; -import org.openxmlformats.schemas.wordprocessingml.x2006.main.*; import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.core.io.ClassPathResource; +import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.multipart.MultipartFile; +import javax.imageio.ImageIO; import javax.servlet.http.HttpServletResponse; import javax.xml.bind.JAXBElement; +import java.awt.*; +import java.awt.Color; +import java.awt.image.BufferedImage; +import java.awt.image.DataBufferUShort; import java.io.*; import java.math.BigDecimal; import java.math.BigInteger; import java.math.RoundingMode; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.*; +import java.util.List; +import java.util.concurrent.*; import java.util.regex.Pattern; import java.util.stream.Collectors; @@ -120,6 +147,16 @@ public class PqReportServiceImpl extends ServiceImpl i private final ISysTestConfigService sysTestConfigService; + @Autowired + private RestTemplateUtil restTemplateUtil; + + private final ThreadPoolExecutor executor = new ThreadPoolExecutor( + 4, 8, 30, TimeUnit.SECONDS, + new LinkedBlockingQueue<>(100), + // 队列满时由主线程执行 + new ThreadPoolExecutor.CallerRunsPolicy() + ); + private final long FILE_SIZE_LIMIT = 5 * 1024 * 1024; @Override @@ -496,6 +533,7 @@ public class PqReportServiceImpl extends ServiceImpl i } } + /** * 根据设备类型生成报告 * 注:该方法目前仅支持楼下出厂检测场景,属于模板占位符替换方式,后期可能会有调整 @@ -537,7 +575,8 @@ public class PqReportServiceImpl extends ServiceImpl i String dirPath = reportPath; // 确保目录存在 ensureDirectoryExists(dirPath); - FileOutputStream out = new FileOutputStream(dirPath.concat(File.separator).concat(pqDevVO.getCreateId()).concat(".docx")); + String reportFullPath = dirPath.concat(File.separator).concat(pqDevVO.getCreateId()).concat(".docx"); + FileOutputStream out = new FileOutputStream(reportFullPath); // 4. 保存新的Word文档 try { baseModelDocument.write(out); @@ -546,7 +585,16 @@ public class PqReportServiceImpl extends ServiceImpl i } out.close(); - this.updateDevAndPlanState(devReportParam.getDevId(), devReportParam.getPlanId()); + Future future = executor.submit(() -> { + this.updateDevAndPlanState(devReportParam.getDevId(), pqDevVO.getCreateId() + ".docx"); + }); + + try { + future.get(); + } catch (Exception e) { + log.error("检测报告上云异常,异常为:"+e.getMessage()); + } + sendReportToCloud(pqDevVO.getIp(), reportFullPath, pqDevVO.getCreateId() + ".docx"); } catch (IOException e) { log.error(ReportResponseEnum.GENERATE_REPORT_ERROR.getMessage(), e); throw new BusinessException(ReportResponseEnum.GENERATE_REPORT_ERROR); @@ -554,6 +602,86 @@ public class PqReportServiceImpl extends ServiceImpl i }); } + @Value("${socket.device.ip}") + private String ip; + + @Value("${socket.device.port}") + private Integer port; + + private final SocketDevResponseService socketDevResponseService; + + /** + * 处理检测报告上传云服务器并生成二维码下装到装置 + * 做成异步执行 + * + * @param devIp 设备IP + * @param reportFullPath 检测报告本地全路径 + * @param reportName 检测报告名称 + */ + public void sendReportToCloud(String devIp, String reportFullPath, String reportName) { +// String url = "http://pqmcc.com:8060/api/file"; + String url = "http://127.0.0.1:18082/api/file"; + devIp = "192.168.1.239"; + // 将文件上传至目标服务器 + File file = new File(reportFullPath); + try { + ResponseEntity responseEntity = restTemplateUtil.uploadFile(url + "/upload", file); + if (responseEntity.getStatusCode().is2xxSuccessful()) { + // 上传没问题后,拼接url生成二维码,并将二维码转为bin格式文件传递给设备通讯模块 + String qrUrl = url + "/download/" + reportName; + BufferedImage bufferedImage = QrCodeUtil.generate(qrUrl, 148, 148); + // 将 BufferedImage 转换为单色图像 + BufferedImage monoImage = new BufferedImage(148, 148, BufferedImage.TYPE_BYTE_BINARY); + Graphics2D g2d = monoImage.createGraphics(); + g2d.drawImage(bufferedImage, 0, 0, null); + g2d.dispose(); + // 3. 【关键修正】创建一个新的1-bit单色图像,并将原始图像绘制上去,以强制转换为单色位图 + BufferedImage monochromeImage = new BufferedImage(bufferedImage.getWidth(), bufferedImage.getHeight(), BufferedImage.TYPE_BYTE_BINARY); + monochromeImage.getGraphics().drawImage(bufferedImage, 0, 0, null); + // 4. 将单色图像在内存中编码为完整的BMP文件流 + byte[] finalBinData = ImageConverter.convertToBinFormat(bufferedImage); + + String base64String = Base64.getEncoder().encodeToString(finalBinData); + System.out.println("二维码base64数据为:" + base64String); + + // 组装设备通讯模块的参数 + SocketMsg sendFileMsg = new SocketMsg<>(); + sendFileMsg.setOperateCode(SourceOperateCodeEnum.FTP_SEND_01.getValue()); + sendFileMsg.setRequestId(SourceOperateCodeEnum.FTP_SEND_01.getValue()); + // 组装业务数据 + JSONObject data = new JSONObject(); + data.set("name", "njcn"); + data.set("password", "Pqs@12345678"); + data.set("port", "21"); + data.set("path", "ftp://" + devIp + "/etc/temp.bin"); + data.set("binData", base64String); + + + + sendFileMsg.setData(data.toString()); + String msg = JSON.toJSONString(sendFileMsg); + Channel channel = SocketManager.getChannelByUserId("cdf" + DetectionCommunicateConstant.DEV); + if (Objects.isNull(channel) || !channel.isActive()) { + // 进行源通信连接 + PreDetectionParam preDetectionParam = new PreDetectionParam(); + preDetectionParam.setUserPageId("cdf"); + preDetectionParam.setSendWebMsg(false); + + NettyClient.socketClient(ip, port, preDetectionParam, msg, new NettyDevClientHandler(preDetectionParam, socketDevResponseService)); + } else { + channel.writeAndFlush(msg + "\n"); + } + + } + } catch (Exception e) { + // 进行日志记录入口 + System.out.println("异常为:" + e.getMessage()); + } + + + } + + /** * 根据计划绑定的报告模板生成报告 * 注:该方法目前属于同用信息占位符替换,数据页为面向对象动态填充拼凑方式 diff --git a/entrance/src/main/resources/application.yml b/entrance/src/main/resources/application.yml index 150d16db..55fae0bc 100644 --- a/entrance/src/main/resources/application.yml +++ b/entrance/src/main/resources/application.yml @@ -77,8 +77,8 @@ Dip: Flicker: - waveFluType: SQU - waveType: CPM + waveFluType: CPM + waveType: SQU fDutyCycle: 50f log: diff --git a/entrance/src/test/java/com/njcn/BaseJunitTest.java b/entrance/src/test/java/com/njcn/BaseJunitTest.java index 71c41933..5d60280a 100644 --- a/entrance/src/test/java/com/njcn/BaseJunitTest.java +++ b/entrance/src/test/java/com/njcn/BaseJunitTest.java @@ -3,13 +3,18 @@ package com.njcn; import com.njcn.gather.EntranceApplication; import com.njcn.gather.report.pojo.DevReportParam; import com.njcn.gather.report.service.IPqReportService; +import com.njcn.http.util.RestTemplateUtil; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.ResponseEntity; import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.context.web.WebAppConfiguration; +import java.io.File; +import java.util.HashMap; + /** * @author hongawen @@ -24,14 +29,18 @@ public class BaseJunitTest { @Autowired private IPqReportService pqReportService; + @Autowired + private RestTemplateUtil restTemplateUtil; + @Test public void test() { - DevReportParam devReportParam = new DevReportParam(); - devReportParam.setPlanId("ad3df9e4a90b4c3c8ce7d21a84ce6f59"); - devReportParam.setPlanCode("31"); - devReportParam.setScriptId("810e4050e1d445e3542c998a077a263a"); - devReportParam.setDevId("a46349a3b3cf4789a6b82690a6076afd"); - pqReportService.generateReport(devReportParam); + File file = new File("D:\\report\\PQS_882B4\\5555.docx"); + + try{ + ResponseEntity stringResponseEntity = restTemplateUtil.uploadFile("http://localhost:18082/api/file/upload",file); + }catch (Exception runtimeException){ + System.out.println(runtimeException.getMessage()); + } } }