diff --git a/build.gradle b/build.gradle index 5878a8a..6a6db4c 100644 --- a/build.gradle +++ b/build.gradle @@ -40,6 +40,7 @@ dependencies { implementation group: 'com.alibaba', name: 'fastjson', version: '2.0.54' implementation group: 'org.springframework.boot', name: 'spring-boot-starter-websocket', version: '3.4.2' implementation group: 'io.netty', name: 'netty-all', version: '4.1.118.Final' + testImplementation 'org.junit.jupiter:junit-jupiter:5.9.3' //++++++++项目级别的放到下面++++++++ //++++++++项目级别的放到上面++++++++ @@ -52,6 +53,16 @@ dependencies { testRuntimeOnly 'org.junit.platform:junit-platform-launcher' } -tasks.named('test') { +// 使用JUnit平台运行器 +tasks.withType(Test).configureEach { useJUnitPlatform() + + // 生成详细测试报告 + reports { + junitXml.required = true // 生成XML格式报告(兼容工具解析) + html.required = true // 生成HTML报告 + } + + // 解决控制台日志中文乱码问题(Windows下常见) + systemProperty 'file.encoding', 'UTF-8' } \ No newline at end of file diff --git a/matrix-spray.db b/matrix-spray.db index 04f1459..1b3b325 100644 Binary files a/matrix-spray.db and b/matrix-spray.db differ diff --git a/src/main/java/com/qyft/ms/app/common/generator/PathGenerator.java b/src/main/java/com/qyft/ms/app/common/generator/PathGenerator.java index 4d6072a..d4014c6 100644 --- a/src/main/java/com/qyft/ms/app/common/generator/PathGenerator.java +++ b/src/main/java/com/qyft/ms/app/common/generator/PathGenerator.java @@ -7,6 +7,7 @@ import java.util.List; /** * 路径生成器:可选择水平之字形(从上往下) 或 垂直之字形(从左往右), * 并考虑画笔spacing,向内收缩以避免越出外部边界。 + * 坐标系:向右和向下为正。 */ public class PathGenerator { @@ -28,13 +29,13 @@ public class PathGenerator { } /** - * 在 [left, right] x [bottom, top] 范围内生成“之字形”路径, + * 在 [left, right] x [top, bottom] 范围内生成“之字形”路径, * 并考虑画笔 spacing(内缩以防越界)。 * - * @param left 矩形左边界 (数学坐标: 左下角为原点) + * @param left 矩形左边界 * @param right 矩形右边界 - * @param bottom 矩形下边界 * @param top 矩形上边界 + * @param bottom 矩形下边界 * @param spacing 画笔粗细/间距 (>0) * @param mode HORIZONTAL_ZIGZAG_TOP_DOWN 或 VERTICAL_ZIGZAG_LEFT_RIGHT * @return 之字形路径拐点列表 (每个拐点是 (x,y) 的int坐标) @@ -42,15 +43,14 @@ public class PathGenerator { public static List generatePathPoints( int left, int right, - int bottom, int top, + int bottom, int spacing, MoveMode mode ) { // 基本校验 - if (left >= right || bottom >= top) { - - throw new IllegalArgumentException("无效矩形边界: left>=right 或 bottom>=top" + left + ", " + right + " ," + bottom + ", " + top); + if (left >= right || top >= bottom) { + throw new IllegalArgumentException("无效矩形边界: left>=right 或 top>=bottom:" + "top: " +top + ",right: " + right + ",bottom: " + bottom + ",left: "+ left); } if (spacing <= 0) { throw new IllegalArgumentException("spacing必须>0"); @@ -60,11 +60,11 @@ public class PathGenerator { // 留出 spacing 宽度,可改成 spacing/2 (半个笔刷) int effLeft = left + spacing; int effRight = right - spacing; - int effBottom = bottom + spacing; - int effTop = top - spacing; + int effTop = top + spacing; + int effBottom = bottom - spacing; // 若收缩后无空间,则返回空集合 - if (effLeft > effRight || effBottom > effTop) { + if (effLeft > effRight || effTop > effBottom) { System.out.println("内缩后无有效空间,返回空路径"); return new ArrayList<>(); } @@ -72,10 +72,10 @@ public class PathGenerator { // 2) 根据mode选择不同的之字形算法 return switch (mode) { case HORIZONTAL_ZIGZAG_TOP_DOWN -> generateHorizontalZigzagTopDown( - effLeft, effRight, effBottom, effTop, spacing + effLeft, effRight, effTop, effBottom, spacing ); case VERTICAL_ZIGZAG_LEFT_RIGHT -> generateVerticalZigzagLeftRight( - effLeft, effRight, effBottom, effTop, spacing + effLeft, effRight, effTop, effBottom, spacing ); default -> // 预留给更多模式扩展 @@ -84,20 +84,20 @@ public class PathGenerator { } /** - * [effLeft..effRight] x [effBottom..effTop] 区域内, + * [effLeft..effRight] x [effTop..effBottom] 区域内, * 从(左上)开始水平之字形向下扫描。 * 流程: * 1) 第1行: (effLeft, effTop) -> (effRight, effTop) * 2) 下移 spacing - * 3) 第2行: (effRight, effTop - spacing) -> (effLeft, effTop - spacing) + * 3) 第2行: (effRight, effTop + spacing) -> (effLeft, effTop + spacing) * 4) 下移 spacing * 重复,直到无法再下移。 */ private static List generateHorizontalZigzagTopDown( int effLeft, int effRight, - int effBottom, int effTop, + int effBottom, int spacing ) { List result = new ArrayList<>(); @@ -118,8 +118,8 @@ public class PathGenerator { result.add(new Point(currentX, currentY)); // 往下移动 spacing - int nextY = currentY - spacing; - if (nextY < effBottom) { + int nextY = currentY + spacing; + if (nextY > effBottom) { break; // 无法再往下 } currentY = nextY; @@ -132,7 +132,7 @@ public class PathGenerator { } /** - * [effLeft..effRight] x [effBottom..effTop] 区域内, + * [effLeft..effRight] x [effTop..effBottom] 区域内, * 从(左上)开始垂直之字形向右扫描。 *

* 流程: @@ -145,8 +145,8 @@ public class PathGenerator { private static List generateVerticalZigzagLeftRight( int effLeft, int effRight, - int effBottom, int effTop, + int effBottom, int spacing ) { List result = new ArrayList<>(); @@ -183,13 +183,13 @@ public class PathGenerator { // ============= 简单测试 ============= public static void main(String[] args) { int left = 0, right = 10; - int bottom = 0, top = 6; + int top = 0, bottom = 6; int spacing = 2; // 1) 测试水平之字形(从上往下) System.out.println("=== HORIZONTAL_ZIGZAG_TOP_DOWN ==="); List horizontalPath = generatePathPoints( - left, right, bottom, top, spacing, MoveMode.HORIZONTAL_ZIGZAG_TOP_DOWN + left, right, top, bottom, spacing, MoveMode.HORIZONTAL_ZIGZAG_TOP_DOWN ); for (Point p : horizontalPath) { System.out.println(p); @@ -198,11 +198,10 @@ public class PathGenerator { // 2) 测试垂直之字形(从左往右) System.out.println("\n=== VERTICAL_ZIGZAG_LEFT_RIGHT ==="); List verticalPath = generatePathPoints( - left, right, bottom, top, spacing, MoveMode.VERTICAL_ZIGZAG_LEFT_RIGHT + left, right, top, bottom, spacing, MoveMode.VERTICAL_ZIGZAG_LEFT_RIGHT ); for (Point p : verticalPath) { System.out.println(p); } } -} - +} \ No newline at end of file diff --git a/src/main/java/com/qyft/ms/app/common/generator/RectangleGrid.java b/src/main/java/com/qyft/ms/app/common/generator/RectangleGrid.java new file mode 100644 index 0000000..7a2d69a --- /dev/null +++ b/src/main/java/com/qyft/ms/app/common/generator/RectangleGrid.java @@ -0,0 +1,56 @@ +package com.qyft.ms.app.common.generator; + +import java.util.ArrayList; +import java.util.List; + +public class RectangleGrid { + + public static void main(String[] args) { + // 示例输入 + int x1 = 0, y1 = 0; // 左上角坐标 + int x2 = 10, y2 = 10; // 右下角坐标 + int spacing = 2; // 间距值 + String moveType = "horizontal"; // 移动类型:horizontal(横向)或 vertical(纵向) + + // 生成坐标点 + List points = generatePoints(x1, y1, x2, y2, spacing, moveType); + + // 输出结果 + for (int[] point : points) { + System.out.println("(" + point[0] + ", " + point[1] + ")"); + } + } + + /** + * 生成铺满矩形区域的坐标点 + * + * @param x1 左上角 x 坐标 + * @param y1 左上角 y 坐标 + * @param x2 右下角 x 坐标 + * @param y2 右下角 y 坐标 + * @param spacing 间距值 + * @param moveType 移动类型:horizontal(横向)或 vertical(纵向) + * @return 坐标点列表 + */ + public static List generatePoints(int x1, int y1, int x2, int y2, int spacing, String moveType) { + List points = new ArrayList<>(); + + if (moveType.equalsIgnoreCase("horizontal")) { + // 横向移动:每一行的起点和终点 + for (int y = y1; y <= y2; y += spacing) { + points.add(new int[]{x1, y}); // 起点 + points.add(new int[]{x2, y}); // 终点 + } + } else if (moveType.equalsIgnoreCase("vertical")) { + // 纵向移动:每一列的起点和终点 + for (int x = x1; x <= x2; x += spacing) { + points.add(new int[]{x, y1}); // 起点 + points.add(new int[]{x, y2}); // 终点 + } + } else { + throw new IllegalArgumentException("Invalid move type. Use 'horizontal' or 'vertical'."); + } + + return points; + } +} \ No newline at end of file diff --git a/src/main/java/com/qyft/ms/app/controller/CMDController.java b/src/main/java/com/qyft/ms/app/controller/CMDController.java index c07f8c9..160e2bc 100644 --- a/src/main/java/com/qyft/ms/app/controller/CMDController.java +++ b/src/main/java/com/qyft/ms/app/controller/CMDController.java @@ -41,7 +41,7 @@ public class CMDController { if (cmdService.moveMotorToPosition(cmdForm)) { return Result.success(cmdForm.getCommandId()); } else { - return Result.failed("无效命令"); + return Result.failed("参数错误"); } } catch (Exception e) { log.error("指令执行异常: {}", JSONUtil.toJsonStr(cmdForm), e); @@ -64,7 +64,7 @@ public class CMDController { if (cmdService.switchThreeWayValve(cmdForm)) { return Result.success(cmdForm.getCommandId()); } else { - return Result.failed("无效命令"); + return Result.failed("参数错误"); } } catch (Exception e) { log.error("指令执行异常: {}", JSONUtil.toJsonStr(cmdForm), e); @@ -87,7 +87,7 @@ public class CMDController { if (cmdService.controlValve(cmdForm)) { return Result.success(cmdForm.getCommandId()); } else { - return Result.failed("无效命令"); + return Result.failed("参数错误"); } } catch (Exception e) { log.error("指令执行异常: {}", JSONUtil.toJsonStr(cmdForm), e); @@ -110,7 +110,7 @@ public class CMDController { if (cmdService.turnOnHighVoltage(cmdForm)) { return Result.success(cmdForm.getCommandId()); } else { - return Result.failed("无效命令"); + return Result.failed("参数错误"); } } catch (Exception e) { log.error("指令执行异常: {}", JSONUtil.toJsonStr(cmdForm), e); @@ -133,7 +133,7 @@ public class CMDController { if (cmdService.turnOffHighVoltage(cmdForm)) { return Result.success(cmdForm.getCommandId()); } else { - return Result.failed("无效命令"); + return Result.failed("参数错误"); } } catch (Exception e) { log.error("指令执行异常: {}", JSONUtil.toJsonStr(cmdForm), e); @@ -156,7 +156,7 @@ public class CMDController { if (cmdService.turnOnSyringePump(cmdForm)) { return Result.success(cmdForm.getCommandId()); } else { - return Result.failed("无效命令"); + return Result.failed("参数错误"); } } catch (Exception e) { log.error("指令执行异常: {}", JSONUtil.toJsonStr(cmdForm), e); @@ -179,7 +179,7 @@ public class CMDController { if (cmdService.turnOffSyringePump(cmdForm)) { return Result.success(cmdForm.getCommandId()); } else { - return Result.failed("无效命令"); + return Result.failed("参数错误"); } } catch (Exception e) { log.error("指令执行异常: {}", JSONUtil.toJsonStr(cmdForm), e); @@ -199,10 +199,10 @@ public class CMDController { cmdForm.setCommandName("startWork"); } log.info("接收到指令: {}", JSONUtil.toJsonStr(cmdForm)); - if (cmdService.startWork(cmdForm)) { + if(Objects.equals(cmdService.startWork(cmdForm), "ok")) { return Result.success(cmdForm.getCommandId()); - } else { - return Result.failed("无效命令"); + }else { + return Result.failed("参数错误"); } } catch (Exception e) { log.error("指令执行异常: {}", JSONUtil.toJsonStr(cmdForm), e); @@ -225,7 +225,7 @@ public class CMDController { if (cmdService.stopWork(cmdForm)) { return Result.success(cmdForm.getCommandId()); } else { - return Result.failed("无效命令"); + return Result.failed("参数错误"); } } catch (Exception e) { log.error("指令执行异常: {}", JSONUtil.toJsonStr(cmdForm), e); @@ -248,7 +248,7 @@ public class CMDController { if (cmdService.setMotorRunningCurrent(cmdForm)) { return Result.success(cmdForm.getCommandId()); } else { - return Result.failed("无效命令"); + return Result.failed("参数错误"); } } catch (Exception e) { log.error("指令执行异常: {}", JSONUtil.toJsonStr(cmdForm), e); @@ -271,7 +271,7 @@ public class CMDController { if (cmdService.rotate(cmdForm)) { return Result.success(cmdForm.getCommandId()); } else { - return Result.failed("无效命令"); + return Result.failed("参数错误"); } } catch (Exception e) { log.error("指令执行异常: {}", JSONUtil.toJsonStr(cmdForm), e); diff --git a/src/main/java/com/qyft/ms/app/controller/MatrixCraftController.java b/src/main/java/com/qyft/ms/app/controller/MatrixCraftController.java index bc0dde1..4993e21 100644 --- a/src/main/java/com/qyft/ms/app/controller/MatrixCraftController.java +++ b/src/main/java/com/qyft/ms/app/controller/MatrixCraftController.java @@ -2,8 +2,8 @@ package com.qyft.ms.app.controller; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.qyft.ms.app.model.dto.MatrixCraftDTO; -import com.qyft.ms.app.model.entity.Matrix; import com.qyft.ms.app.model.entity.MatrixCraft; +import com.qyft.ms.app.model.vo.MatrixCraftResult; import com.qyft.ms.app.service.MatrixCraftService; import com.qyft.ms.system.common.base.BasePageQuery; import com.qyft.ms.system.common.result.PageResult; @@ -53,9 +53,9 @@ public class MatrixCraftController { @Operation(summary = "所有工艺列表") @GetMapping("/list") - public PageResult getAll(BasePageQuery pageQuery) { - IPage result = matrixCraftService.page(new Page<>(pageQuery.getPageNum(), pageQuery.getPageSize()), null); - return PageResult.success(result); + public PageResult getAll(BasePageQuery pageQuery) { +// IPage result = matrixCraftService.page(new Page<>(pageQuery.getPageNum(), pageQuery.getPageSize()), null); + return PageResult.success(matrixCraftService.getAll(pageQuery)); } @Operation(summary = "基质工艺更新") diff --git a/src/main/java/com/qyft/ms/app/model/vo/MatrixCraftResult.java b/src/main/java/com/qyft/ms/app/model/vo/MatrixCraftResult.java new file mode 100644 index 0000000..1658db1 --- /dev/null +++ b/src/main/java/com/qyft/ms/app/model/vo/MatrixCraftResult.java @@ -0,0 +1,11 @@ +package com.qyft.ms.app.model.vo; + +import com.qyft.ms.app.model.entity.MatrixCraft; +import lombok.Data; + +@Data +public class MatrixCraftResult extends MatrixCraft { + + private String matrixName; + +} diff --git a/src/main/java/com/qyft/ms/app/service/CMDService.java b/src/main/java/com/qyft/ms/app/service/CMDService.java index 43af010..69a89a4 100644 --- a/src/main/java/com/qyft/ms/app/service/CMDService.java +++ b/src/main/java/com/qyft/ms/app/service/CMDService.java @@ -41,6 +41,9 @@ public class CMDService { // 电机移动 public boolean moveMotorToPosition(CMDForm form) { Map params = form.getParams(); + if (params == null || !params.containsKey("axis") || !params.containsKey("position")) { + return false; + } List> cmdList = new ArrayList<>(); String axis = (String) params.get("axis"); double position = Optional.ofNullable(params.get("position")) @@ -56,12 +59,17 @@ public class CMDService { // 切换清洗管路/喷涂管路 public boolean switchThreeWayValve(CMDForm form) { Map params = form.getParams(); + if (params == null || !params.containsKey("type")) { + return false; + } List> cmdList = new ArrayList<>(); String type = (String) params.get("type"); if (type.equals("clean")) { cmdList.add(deviceTcpCMDService::switchThreeWayValveToSubstrate); } else if (type.equals("spray")) { cmdList.add(deviceTcpCMDService::switchThreeWayValveToSpray); + }else { + return false; } initExecutorThread(cmdList, form); return true; @@ -70,6 +78,9 @@ public class CMDService { // 除湿阀、清洗阀、喷嘴阀控制方法 public boolean controlValve(CMDForm form) { Map params = form.getParams(); + if (params == null || !params.containsKey("valveType") || !params.containsKey("isOpen")) { + return false; + } List> cmdList = new ArrayList<>(); if(params.get("valveType") !=null && params.get("isOpen") !=null) { String valveType = (String) params.get("valveType"); @@ -83,6 +94,9 @@ public class CMDService { // 以指定电压值开启高压电 public boolean turnOnHighVoltage(CMDForm form) { Map params = form.getParams(); + if (params == null || !params.containsKey("voltage")) { + return false; + } List> cmdList = new ArrayList<>(); double voltage = Optional.ofNullable(params.get("voltage")) .filter(Number.class::isInstance) @@ -97,6 +111,9 @@ public class CMDService { // 关闭高压电 public boolean turnOffHighVoltage(CMDForm form) { Map params = form.getParams(); + if (params == null) { + return false; + } List> cmdList = new ArrayList<>(); cmdList.add(deviceTcpCMDService::turnOffHighVoltage); initExecutorThread(cmdList, form); @@ -106,6 +123,9 @@ public class CMDService { // 以指定转速、方向和时间开启注射泵 public boolean turnOnSyringePump(CMDForm form) { Map params = form.getParams(); + if (params == null || !params.containsKey("rotationSpeed") || !params.containsKey("time") || !params.containsKey("direction")) { + return false; + } List> cmdList = new ArrayList<>(); double rotationSpeed = Optional.ofNullable(params.get("rotationSpeed")) .filter(Number.class::isInstance) @@ -126,6 +146,9 @@ public class CMDService { // 停止注射泵 public boolean turnOffSyringePump(CMDForm form) { Map params = form.getParams(); + if (params == null) { + return false; + } List> cmdList = new ArrayList<>(); cmdList.add(deviceTcpCMDService::turnOffSyringePump); initExecutorThread(cmdList, form); @@ -135,6 +158,9 @@ public class CMDService { // 设置指定轴的电机运行时电流 public boolean setMotorRunningCurrent(CMDForm form) { Map params = form.getParams(); + if (params == null || !params.containsKey("axis") || !params.containsKey("current")) { + return false; + } List> cmdList = new ArrayList<>(); String axis = (String) params.get("axis"); double current = Optional.ofNullable(params.get("current")) @@ -148,20 +174,32 @@ public class CMDService { } // 开始喷涂 - public boolean startWork(CMDForm form) { + public String startWork(CMDForm form) { Map params = form.getParams(); + if ( + params == null || + !params.containsKey("position") || + !params.containsKey("space") || + !params.containsKey("routeType") || + !params.containsKey("movementSpeed") || + !params.containsKey("height") || + !params.containsKey("matrixFlowVelocity") || + !params.containsKey("matrixCraftId") + ) { + return "参数错误"; + } List> cmdList = new ArrayList<>(); // 托盘位置 List slidePositionList = sysSettingsService.getSlidePositionList(); List> position = (List>) params.get("position"); if (position == null) { - throw new RuntimeException("position参数错误"); + return "position参数错误"; } for (int i = 0; i < position.size(); i++) { Map p = position.get(i); if (p.get("x1") == null || p.get("y1") == null || p.get("x2") == null || p.get("y2") == null || p.get("index") == null) { - throw new RuntimeException("position参数错误"); + return "position参数错误"; } // 玻片的位置 String p1 = slidePositionList.get(p.get("index")).getValue(); @@ -178,10 +216,14 @@ public class CMDService { int bottom = y+ p.get("y2"); int space = (Integer) params.get("space"); - int direction = (Integer) params.get("direction"); + int routeType = (Integer) params.get("routeType"); List horizontalPath = generatePathPoints( - left, right, bottom, top, space, direction == 1 ? PathGenerator.MoveMode.HORIZONTAL_ZIGZAG_TOP_DOWN : PathGenerator.MoveMode.VERTICAL_ZIGZAG_LEFT_RIGHT + left, right, top, bottom, space, routeType == 1 ? PathGenerator.MoveMode.HORIZONTAL_ZIGZAG_TOP_DOWN : PathGenerator.MoveMode.VERTICAL_ZIGZAG_LEFT_RIGHT ); + log.info("horizontalPath:{}", horizontalPath); + if(horizontalPath.isEmpty()) { + return "路径规划失败"; + } // 将三通阀转至喷涂管路 cmdList.add(deviceTcpCMDService::switchThreeWayValveToSpray); @@ -247,12 +289,11 @@ public class CMDService { return true; }); initExecutorThread(cmdList, form); - return true; + return "ok"; } // 结束喷涂 public boolean stopWork(CMDForm form) { - Map params = form.getParams(); List> cmdList = new ArrayList<>(); // 停止喷涂 cmdList.add(deviceTcpCMDService::turnOffSyringePump); @@ -282,7 +323,7 @@ public class CMDService { } - private void run(List> cmdList, CMDForm form) { + public void run(List> cmdList, CMDForm form) { ExecutionResult executionResult = new ExecutionResult(); executionResult.setCommandId(form.getCommandId()); executionResult.setCommandName(form.getCommandName()); diff --git a/src/main/java/com/qyft/ms/app/service/MatrixCraftService.java b/src/main/java/com/qyft/ms/app/service/MatrixCraftService.java index da8d032..ee9e0c8 100644 --- a/src/main/java/com/qyft/ms/app/service/MatrixCraftService.java +++ b/src/main/java/com/qyft/ms/app/service/MatrixCraftService.java @@ -1,8 +1,11 @@ package com.qyft.ms.app.service; +import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.service.IService; import com.qyft.ms.app.model.dto.MatrixCraftDTO; import com.qyft.ms.app.model.entity.MatrixCraft; +import com.qyft.ms.app.model.vo.MatrixCraftResult; +import com.qyft.ms.system.common.base.BasePageQuery; import java.util.List; @@ -22,4 +25,6 @@ public interface MatrixCraftService extends IService { Boolean updateMatrixCraft(MatrixCraft matrixCraft); Boolean deleteMatrixCraft(String ids); + + IPage getAll(BasePageQuery pageQuery); } diff --git a/src/main/java/com/qyft/ms/app/service/WebSocketService.java b/src/main/java/com/qyft/ms/app/service/WebSocketService.java index bbe8c7a..efbfab1 100644 --- a/src/main/java/com/qyft/ms/app/service/WebSocketService.java +++ b/src/main/java/com/qyft/ms/app/service/WebSocketService.java @@ -4,10 +4,13 @@ import cn.hutool.json.JSONUtil; import com.qyft.ms.app.config.WebSocketServer; import com.qyft.ms.app.model.vo.WebsocketResult; import jakarta.annotation.PostConstruct; +import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Service; +@Profile("!test") @Service public class WebSocketService { + public void pushMsg(String type, Object result) { WebsocketResult websocketResult = new WebsocketResult(); diff --git a/src/main/java/com/qyft/ms/app/service/impl/ISysSettingsServiceImpl.java b/src/main/java/com/qyft/ms/app/service/impl/ISysSettingsServiceImpl.java index 478767b..f370e84 100644 --- a/src/main/java/com/qyft/ms/app/service/impl/ISysSettingsServiceImpl.java +++ b/src/main/java/com/qyft/ms/app/service/impl/ISysSettingsServiceImpl.java @@ -30,7 +30,7 @@ public class ISysSettingsServiceImpl extends ServiceImpl queryWrapper = new QueryWrapper<>(); queryWrapper.in("code", "slide_position"); - Long parentId = sysSettingsMapper.selectOne(queryWrapper).getParentId(); + Long parentId = sysSettingsMapper.selectOne(queryWrapper).getId(); slidePositionList = sysSettingsMapper.selectList(new QueryWrapper().eq("parent_id", parentId)); motorSpeedList = sysSettingsMapper.selectList(new QueryWrapper().eq("parent_id", new QueryWrapper().eq("code", "speed"))); } diff --git a/src/main/java/com/qyft/ms/app/service/impl/MatrixCraftServiceImpl.java b/src/main/java/com/qyft/ms/app/service/impl/MatrixCraftServiceImpl.java index f65ba2f..b4144ba 100644 --- a/src/main/java/com/qyft/ms/app/service/impl/MatrixCraftServiceImpl.java +++ b/src/main/java/com/qyft/ms/app/service/impl/MatrixCraftServiceImpl.java @@ -1,13 +1,24 @@ package com.qyft.ms.app.service.impl; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.qyft.ms.app.mapper.MatrixCraftMapper; +import com.qyft.ms.app.mapper.MatrixMapper; import com.qyft.ms.app.model.dto.MatrixCraftDTO; +import com.qyft.ms.app.model.entity.Matrix; import com.qyft.ms.app.model.entity.MatrixCraft; +import com.qyft.ms.app.model.entity.OperationLog; +import com.qyft.ms.app.model.vo.MatrixCraftResult; import com.qyft.ms.app.service.MatrixCraftService; +import com.qyft.ms.app.service.MatrixService; +import com.qyft.ms.system.common.base.BasePageQuery; import lombok.RequiredArgsConstructor; +import org.springframework.beans.BeanUtils; import org.springframework.stereotype.Service; +import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; @@ -19,6 +30,7 @@ import java.util.stream.Collectors; @RequiredArgsConstructor public class MatrixCraftServiceImpl extends ServiceImpl implements MatrixCraftService { private final MatrixCraftMapper matrixCraftMapper; + private final MatrixMapper matrixMapper; @Override public Integer add(MatrixCraftDTO dto) { return matrixCraftMapper.add(dto); @@ -46,4 +58,23 @@ public class MatrixCraftServiceImpl extends ServiceImpl getAll(BasePageQuery pageQuery) { + // 构建分页对象 + Page page = new Page<>(pageQuery.getPageNum(), pageQuery.getPageSize()); + ArrayList matrixCraftResultList = new ArrayList<>(); + // 查询所有工艺 + List matrixCrafts = matrixCraftMapper.selectList(new QueryWrapper<>()); + for (MatrixCraft matrixCraft : matrixCrafts) { + Long matrixId = matrixCraft.getMatrixId(); + Matrix matrix = matrixMapper.selectOne(new QueryWrapper().eq("id", matrixId)); + MatrixCraftResult matrixCraftResult = new MatrixCraftResult(); + BeanUtils.copyProperties(matrixCraft, matrixCraftResult); + matrixCraftResult.setMatrixName(matrix.getName()); + matrixCraftResultList.add((matrixCraftResult)); + } + page.setRecords(matrixCraftResultList); + return page; + } } diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 6d803b8..2f5143b 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -35,7 +35,7 @@ jwt: #与设备TCP链接 tcp: enable: true # 是否开启 TCP 连接 - host: 192.168.1.130 + host: 192.168.1.140 port: 9080 reconnect: 5000 # 断线重连间隔(单位:毫秒) timeout: 10000 # 连接超时时间(单位:毫秒) diff --git a/src/test/java/com/qyft/ms/CMDServiceTest.java b/src/test/java/com/qyft/ms/CMDServiceTest.java new file mode 100644 index 0000000..4b59107 --- /dev/null +++ b/src/test/java/com/qyft/ms/CMDServiceTest.java @@ -0,0 +1,144 @@ +package com.qyft.ms; + +import com.qyft.ms.app.model.form.CMDForm; +import com.qyft.ms.app.model.vo.ExecutionResult; +import com.qyft.ms.app.service.CMDService; +import com.qyft.ms.app.service.OperationLogService; +import com.qyft.ms.app.service.WebSocketService; +import com.qyft.ms.device.service.DeviceTcpCMDService; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.function.Supplier; + +import static org.junit.jupiter.api.Assertions.*; + import static org.mockito.ArgumentMatchers.*; + import static org.mockito.Mockito.*; + +@ActiveProfiles("test") +@SpringBootTest +public class CMDServiceTest { + + @Mock + private DeviceTcpCMDService deviceTcpCMDService; + + @Mock + private WebSocketService webSocketService; + + @Mock + private OperationLogService operationLogService; + + @InjectMocks + private CMDService cmdService; + + private CMDForm form; + + @BeforeEach + void setUp() { + MockitoAnnotations.openMocks(this); + form = new CMDForm(); + form.setCommandId("test-command"); + form.setCommandName("test-command"); + } + + @Test + void testMoveMotorToPosition_Success() { + // 准备参数 + Map params = new HashMap<>(); + params.put("axis", "x"); + params.put("position", 100.0); + form.setParams(params); + + // 模拟设备服务调用 + when(deviceTcpCMDService.moveMotorToPosition(anyString(), anyDouble())).thenReturn(true); + + // 执行测试 + boolean result = cmdService.moveMotorToPosition(form); + + // 验证结果 + assertTrue(result); + verify(deviceTcpCMDService, times(1)).moveMotorToPosition("x", 100.0); + } + + @Test + void testStartWork_InvalidPosition() { + // 准备无效参数 + Map params = new HashMap<>(); + params.put("position", new ArrayList<>()); // 空位置列表 + form.setParams(params); + + // 执行测试 + String result = cmdService.startWork(form); + + // 验证返回错误信息 + assertEquals("position参数错误", result); + } + + @Test + void testStartWork_PathGeneration() { + // 准备有效参数 + Map params = new HashMap<>(); + List> positions = new ArrayList<>(); + Map pos = new HashMap<>(); + pos.put("x1", 10); + pos.put("y1", 20); + pos.put("x2", 30); + pos.put("y2", 40); + pos.put("index", 0); + positions.add(pos); + params.put("position", positions); + params.put("space", 5); + params.put("routeType", 1); + params.put("height", 50); + params.put("movementSpeed", 100); + form.setParams(params); + + // 模拟依赖项 + when(deviceTcpCMDService.switchThreeWayValveToSpray()).thenReturn(true); + when(deviceTcpCMDService.setMotorSpeed(anyString(), anyInt())).thenReturn(true); + when(deviceTcpCMDService.moveMotorToPosition(anyString(), anyDouble())).thenReturn(true); + + // 执行测试 + String result = cmdService.startWork(form); + + // 验证命令链长度 + assertNotNull(result); + verify(deviceTcpCMDService, atLeastOnce()).switchThreeWayValveToSpray(); + } + + @Test + void testControlValve_NozzleOpen() { + Map params = new HashMap<>(); + params.put("valveType", "Nozzle"); + params.put("isOpen", true); + form.setParams(params); + + when(deviceTcpCMDService.controlValve(anyString(), anyBoolean())).thenReturn(true); + + boolean result = cmdService.controlValve(form); + assertTrue(result); + verify(deviceTcpCMDService).controlValve("Nozzle", true); + } + + @Test + void testRun_CommandFailure() { + // 模拟一个失败的指令 + List> cmdList = new ArrayList<>(); + cmdList.add(() -> false); // 直接返回失败 + + // 执行内部方法 + cmdService.run(cmdList, form); + + // 验证WebSocket错误消息推送 + verify(webSocketService).pushMsg(any(), any(ExecutionResult.class)); + } +} \ No newline at end of file diff --git a/src/test/java/com/qyft/ms/SprayTest.java b/src/test/java/com/qyft/ms/SprayTest.java new file mode 100644 index 0000000..6160f36 --- /dev/null +++ b/src/test/java/com/qyft/ms/SprayTest.java @@ -0,0 +1,111 @@ +package com.qyft.ms; + +import com.qyft.ms.app.model.entity.OperationLog; +import com.qyft.ms.app.model.entity.SysSettings; +import com.qyft.ms.app.model.form.CMDForm; +import com.qyft.ms.app.service.*; +import com.qyft.ms.device.service.DeviceTcpCMDService; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.*; + +import java.util.*; + +import static com.qyft.ms.app.common.generator.PathGenerator.generatePathPoints; +import static org.mockito.Mockito.*; + +public class SprayTest { + + @InjectMocks + private CMDService cmdService; + + @Mock + private WebSocketService webSocketService; + @Mock + private DeviceTcpCMDService deviceTcpCMDService; + @Mock + private OperationLogService operationLogService; + @Mock + private MatrixCraftService matrixCraftService; + @Mock + private ISysSettingsService sysSettingsService; + + @BeforeEach + void setUp() { + MockitoAnnotations.openMocks(this); + } + + @Test + void testStartWork() { + // 1. 准备模拟数据 + CMDForm form = new CMDForm(); + form.setCommandId("cmd123"); + form.setCommandName("startWork"); + + Map params = new HashMap<>(); + params.put("space", 1); + params.put("routeType", 1); + params.put("movementSpeed", 100); + params.put("height", 50); + params.put("voltage", 100); + params.put("matrixFlowVelocity", 20); + params.put("matrixCraftId", 1); + + List> positionList = new ArrayList<>(); + Map position = new HashMap<>(); + position.put("x1", 10); + position.put("y1", 20); + position.put("x2", 30); + position.put("y2", 40); + position.put("index", 0); + positionList.add(position); + params.put("position", positionList); + + form.setParams(params); + + // 2. 模拟依赖行为 + SysSettings mockSetting = new SysSettings(); + mockSetting.setValue("100,200,300"); // 模拟托盘坐标 + when(sysSettingsService.getSlidePositionList()).thenReturn(Collections.singletonList(mockSetting)); + + when(deviceTcpCMDService.switchThreeWayValveToSpray()).thenReturn(true); + when(deviceTcpCMDService.setMotorSpeed(anyString(), anyInt())).thenReturn(true); + when(deviceTcpCMDService.moveMotorToPosition(anyString(), anyDouble())).thenReturn(true); + when(deviceTcpCMDService.turnOnHighVoltage(anyDouble())).thenReturn(true); + when(deviceTcpCMDService.controlValve(anyString(), anyBoolean())).thenReturn(true); + when(deviceTcpCMDService.syringePumpMoveAtSpeed(anyInt())).thenReturn(true); + when(deviceTcpCMDService.turnOffSyringePump()).thenReturn(true); + when(deviceTcpCMDService.motorMoveToHome(anyString())).thenReturn(true); + +// OperationLog mockLog = new OperationLog(); +// when(operationLogService.getIng()).thenReturn(mockLog); +// when(operationLogService.add(any())).thenReturn(true); +// when(operationLogService.updateById(any())).thenReturn(true); + + // 3. 调用测试方法 + String result = cmdService.startWork(form); + + // 4. 验证 + verify(deviceTcpCMDService, times(1)).switchThreeWayValveToSpray(); + verify(deviceTcpCMDService, times(1)).setMotorSpeed("x", 100); + verify(deviceTcpCMDService, times(1)).setMotorSpeed("y", 100); + verify(deviceTcpCMDService, times(1)).setMotorSpeed("z", 100); + verify(deviceTcpCMDService, times(1)).moveMotorToPosition("z", 350); // z + height (300+50) + verify(deviceTcpCMDService, times(1)).moveMotorToPosition("x", 110); // x+10 + verify(deviceTcpCMDService, times(1)).moveMotorToPosition("y", 220); // y+20 + verify(deviceTcpCMDService, times(1)).turnOnHighVoltage(100); + + // 日志校验 +// verify(operationLogService, times(1)).add(any(OperationLog.class)); +// verify(operationLogService, times(1)).updateById(any(OperationLog.class)); + + // 轨迹移动和其他控制指令同理,这里可以补充更多verify + + verify(deviceTcpCMDService, atLeastOnce()).moveMotorToPosition(eq("x"), anyDouble()); + verify(deviceTcpCMDService, atLeastOnce()).moveMotorToPosition(eq("y"), anyDouble()); + + + // 6. 说明 + System.out.println("✅ startWork测试通过!"); + } +}