From ce591d1409c87639979f074aaccf14ce12dd1aef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=99=BD=E5=87=A4=E5=90=89?= Date: Mon, 2 Jun 2025 11:44:04 +0800 Subject: [PATCH] =?UTF-8?q?=E5=90=8C=E6=AD=A5=E7=8E=B0=E5=9C=BA=E4=BB=A3?= =?UTF-8?q?=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../gd/app/command/control/FanStartCommand.java | 12 +- .../gd/app/command/control/FanStopCommand.java | 12 +- .../control/FilledSolutionStartCommand.java | 1 + .../command/control/FilledSolutionStopCommand.java | 2 +- .../gd/app/command/control/HeatStartCommand.java | 23 +-- .../gd/app/command/control/HeatStopCommand.java | 19 +-- .../app/command/control/MoveToHeatAreaCommand.java | 23 ++- .../command/control/MoveToSolutionAreaCommand.java | 25 +-- .../gd/app/command/control/SolutionAddCommand.java | 55 ++++--- .../gd/app/command/control/TrayDownCommand.java | 35 +++-- .../gd/app/command/control/TrayUpCommand.java | 24 ++- .../gd/app/command/control/WarmUpStartCommand.java | 40 +++++ .../gd/app/command/selftest/MoveTestCommand.java | 6 + .../gd/app/command/selftest/TrayOutCommand.java | 1 - .../gd/app/controller/CraftsController.java | 11 +- .../gd/app/controller/DeviceParamController.java | 9 +- .../iflytop/gd/app/controller/HeatController.java | 10 +- .../gd/app/controller/SelfTestController.java | 3 +- .../iflytop/gd/app/controller/TestController.java | 87 +++++++++++ .../iflytop/gd/app/controller/TrayController.java | 2 +- .../iflytop/gd/app/core/CommandPoolManager.java | 19 +++ .../com/iflytop/gd/app/core/CraftsContext.java | 18 ++- .../gd/app/model/bo/status/CommandMutexState.java | 30 ++++ .../gd/app/model/bo/status/device/DeviceState.java | 18 +++ .../model/bo/status/device/HeatModuleState.java | 14 +- .../com/iflytop/gd/app/model/dto/AllSensorDTO.java | 16 ++ .../iflytop/gd/app/model/dto/PauseCraftsDto.java | 3 +- .../iflytop/gd/app/model/dto/ResumeCraftsDTO.java | 3 +- .../com/iflytop/gd/app/model/dto/SetHeatDTO.java | 30 ++++ .../iflytop/gd/app/model/dto/StartCraftsDTO.java | 5 +- .../iflytop/gd/app/model/dto/StopCraftsDTO.java | 3 +- .../com/iflytop/gd/app/model/vo/CraftStatusVO.java | 3 +- .../com/iflytop/gd/app/model/vo/SetCraftsVO.java | 3 +- .../gd/app/model/vo/SetTargetTemperatureVO.java | 20 --- .../iflytop/gd/app/service/api/CraftsService.java | 149 +++++++++++++----- .../iflytop/gd/app/service/api/HeatService.java | 6 +- .../iflytop/gd/app/service/api/TestService.java | 48 ++++++ .../iflytop/gd/app/service/api/TrayService.java | 6 +- .../gd/app/service/crafts/CraftsStepService.java | 60 +++++--- .../device/DeviceCommandTempUtilService.java | 88 +++++++++-- .../service/device/DeviceEmergencyStopService.java | 38 +++++ .../gd/app/service/device/DeviceInitService.java | 39 +++-- .../gd/app/service/device/DeviceStateService.java | 5 +- .../service/device/module/CapModuleService.java | 168 ++++++++++++++++----- .../service/device/module/HeatModuleService.java | 29 +++- .../device/module/SolutionModuleService.java | 45 ++---- .../scheduled/FetchTemperatureScheduledTask.java | 12 +- .../app/ws/client/DeviceEmergencyStopConfig.java | 13 +- .../com/iflytop/gd/common/enums/HeatingType.java | 13 ++ .../com/iflytop/gd/common/result/ResultCode.java | 6 +- .../controller/CraftsMonitorController.java | 8 +- 51 files changed, 961 insertions(+), 357 deletions(-) create mode 100644 src/main/java/com/iflytop/gd/app/command/control/WarmUpStartCommand.java create mode 100644 src/main/java/com/iflytop/gd/app/controller/TestController.java create mode 100644 src/main/java/com/iflytop/gd/app/model/dto/AllSensorDTO.java create mode 100644 src/main/java/com/iflytop/gd/app/model/dto/SetHeatDTO.java delete mode 100644 src/main/java/com/iflytop/gd/app/model/vo/SetTargetTemperatureVO.java create mode 100644 src/main/java/com/iflytop/gd/app/service/api/TestService.java create mode 100644 src/main/java/com/iflytop/gd/app/service/device/DeviceEmergencyStopService.java create mode 100644 src/main/java/com/iflytop/gd/common/enums/HeatingType.java diff --git a/src/main/java/com/iflytop/gd/app/command/control/FanStartCommand.java b/src/main/java/com/iflytop/gd/app/command/control/FanStartCommand.java index 1bdb077..33878a4 100644 --- a/src/main/java/com/iflytop/gd/app/command/control/FanStartCommand.java +++ b/src/main/java/com/iflytop/gd/app/command/control/FanStartCommand.java @@ -1,6 +1,5 @@ package com.iflytop.gd.app.command.control; -import cn.hutool.json.JSONArray; import com.iflytop.gd.app.core.BaseCommandHandler; import com.iflytop.gd.app.model.dto.CmdDTO; import com.iflytop.gd.app.service.device.DeviceStateService; @@ -26,14 +25,11 @@ public class FanStartCommand extends BaseCommandHandler { @Override public CompletableFuture handle(CmdDTO cmdDTO) { - JSONArray heatIdJsonArray = cmdDTO.getJSONArrayParam("heatId"); + String heatId = cmdDTO.getStringParam("heatId"); + HeatModuleCode heatModuleCode = HeatModuleCode.valueOf(heatId); return runAsync(() -> { - for (int i = 0; i < heatIdJsonArray.size(); i++) { - String heatId = heatIdJsonArray.getStr(i); - HeatModuleCode heatModuleCode = HeatModuleCode.valueOf(heatId); - heatModuleService.fanStart(cmdDTO.getCommandId(), cmdDTO.getCommand(), heatModuleCode); - deviceStateService.getDeviceState().getHeatModuleByCode(heatModuleCode).setFanOpen(true); - } + heatModuleService.fanStart(cmdDTO.getCommandId(), cmdDTO.getCommand(), heatModuleCode); + deviceStateService.getDeviceState().getHeatModuleByCode(heatModuleCode).setFanOpen(true); }); } } diff --git a/src/main/java/com/iflytop/gd/app/command/control/FanStopCommand.java b/src/main/java/com/iflytop/gd/app/command/control/FanStopCommand.java index 56f42fa..76066b0 100644 --- a/src/main/java/com/iflytop/gd/app/command/control/FanStopCommand.java +++ b/src/main/java/com/iflytop/gd/app/command/control/FanStopCommand.java @@ -1,6 +1,5 @@ package com.iflytop.gd.app.command.control; -import cn.hutool.json.JSONArray; import com.iflytop.gd.app.core.BaseCommandHandler; import com.iflytop.gd.app.model.dto.CmdDTO; import com.iflytop.gd.app.service.device.DeviceStateService; @@ -26,14 +25,11 @@ public class FanStopCommand extends BaseCommandHandler { @Override public CompletableFuture handle(CmdDTO cmdDTO) { - JSONArray heatIdJsonArray = cmdDTO.getJSONArrayParam("heatId"); + String heatId = cmdDTO.getStringParam("heatId"); + HeatModuleCode heatModuleCode = HeatModuleCode.valueOf(heatId); return runAsync(() -> { - for (int i = 0; i < heatIdJsonArray.size(); i++) { - String heatId = heatIdJsonArray.getStr(i); - HeatModuleCode heatModuleCode = HeatModuleCode.valueOf(heatId); - heatModuleService.fanClose(cmdDTO.getCommandId(), cmdDTO.getCommand(), heatModuleCode); - deviceStateService.getDeviceState().getHeatModuleByCode(heatModuleCode).setFanOpen(false); - } + heatModuleService.fanClose(cmdDTO.getCommandId(), cmdDTO.getCommand(), heatModuleCode); + deviceStateService.getDeviceState().getHeatModuleByCode(heatModuleCode).setFanOpen(false); }); } } diff --git a/src/main/java/com/iflytop/gd/app/command/control/FilledSolutionStartCommand.java b/src/main/java/com/iflytop/gd/app/command/control/FilledSolutionStartCommand.java index 8888af7..7ad89a9 100644 --- a/src/main/java/com/iflytop/gd/app/command/control/FilledSolutionStartCommand.java +++ b/src/main/java/com/iflytop/gd/app/command/control/FilledSolutionStartCommand.java @@ -37,6 +37,7 @@ public class FilledSolutionStartCommand extends BaseCommandHandler { throw new AppException(ResultCode.CMD_BUSY); } return runAsync(() -> { + solutionModuleService.dualRobotMovePoint(15); JSONArray idJsonArray = cmdDTO.getJSONArrayParam("list"); for (int i = 0; i < idJsonArray.size(); i++) { String idStr = idJsonArray.getStr(i); diff --git a/src/main/java/com/iflytop/gd/app/command/control/FilledSolutionStopCommand.java b/src/main/java/com/iflytop/gd/app/command/control/FilledSolutionStopCommand.java index 51eb2f4..3f0513c 100644 --- a/src/main/java/com/iflytop/gd/app/command/control/FilledSolutionStopCommand.java +++ b/src/main/java/com/iflytop/gd/app/command/control/FilledSolutionStopCommand.java @@ -28,7 +28,6 @@ public class FilledSolutionStopCommand extends BaseCommandHandler { public CompletableFuture handle(CmdDTO cmdDTO) { return runAsync(() -> { JSONArray idJsonArray = cmdDTO.getJSONArrayParam("list"); - for (int i = 0; i < idJsonArray.size(); i++) { String idStr = idJsonArray.getStr(i); CompletableFuture.runAsync(() -> { @@ -40,6 +39,7 @@ public class FilledSolutionStopCommand extends BaseCommandHandler { } }); } + solutionModuleService.dualRobotOrigin(); }); } } diff --git a/src/main/java/com/iflytop/gd/app/command/control/HeatStartCommand.java b/src/main/java/com/iflytop/gd/app/command/control/HeatStartCommand.java index 3aaadc0..25897f7 100644 --- a/src/main/java/com/iflytop/gd/app/command/control/HeatStartCommand.java +++ b/src/main/java/com/iflytop/gd/app/command/control/HeatStartCommand.java @@ -1,12 +1,12 @@ package com.iflytop.gd.app.command.control; -import cn.hutool.json.JSONArray; import com.iflytop.gd.app.core.BaseCommandHandler; import com.iflytop.gd.app.model.dto.CmdDTO; import com.iflytop.gd.app.service.device.DeviceStateService; import com.iflytop.gd.app.service.device.module.HeatModuleService; import com.iflytop.gd.common.annotation.CommandMapping; import com.iflytop.gd.common.enums.HeatModuleCode; +import com.iflytop.gd.common.enums.HeatingType; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; @@ -26,17 +26,18 @@ public class HeatStartCommand extends BaseCommandHandler { @Override public CompletableFuture handle(CmdDTO cmdDTO) { - JSONArray heatIdJsonArray = cmdDTO.getJSONArrayParam("heatId"); + String heatId = cmdDTO.getStringParam("heatId"); + Integer time = cmdDTO.getIntegerParam("time"); + Integer minutes = cmdDTO.getIntegerParam("minutes"); + Integer seconds = cmdDTO.getIntegerParam("seconds"); + Double temperature = cmdDTO.getDoubleParam("temperature"); + HeatModuleCode heatModuleCode = HeatModuleCode.valueOf(heatId); return runAsync(() -> { - for (int i = 0; i < heatIdJsonArray.size(); i++) { - String heatId = heatIdJsonArray.getStr(i); - HeatModuleCode heatModuleId = HeatModuleCode.valueOf(heatId); - //从系统状态中获取指定加热区设定的温度数值 - double temperature = deviceStateService.getDeviceState().getHeatModuleByCode(heatModuleId).getTemperature(); - //开启加热 - heatModuleService.heatRodOpen(cmdDTO.getCommandId(), cmdDTO.getCommand(), heatModuleId, temperature); - deviceStateService.getDeviceState().getHeatModuleByCode(heatModuleId).setHeating(true); - } + heatModuleService.heatRodOpen(cmdDTO.getCommandId(), cmdDTO.getCommand(), heatModuleCode, temperature); + deviceStateService.getDeviceState().getHeatModuleByCode(heatModuleCode).setTargetTime(time); + deviceStateService.getDeviceState().getHeatModuleByCode(heatModuleCode).setHeatTemperature(temperature); + deviceStateService.getDeviceState().getHeatModuleByCode(heatModuleCode).setTargetTemperature(temperature); + deviceStateService.getDeviceState().getHeatModuleByCode(heatModuleCode).setHeatingType(HeatingType.thermostatic); }); } } diff --git a/src/main/java/com/iflytop/gd/app/command/control/HeatStopCommand.java b/src/main/java/com/iflytop/gd/app/command/control/HeatStopCommand.java index d50c354..e4c8841 100644 --- a/src/main/java/com/iflytop/gd/app/command/control/HeatStopCommand.java +++ b/src/main/java/com/iflytop/gd/app/command/control/HeatStopCommand.java @@ -1,12 +1,12 @@ package com.iflytop.gd.app.command.control; -import cn.hutool.json.JSONArray; import com.iflytop.gd.app.core.BaseCommandHandler; import com.iflytop.gd.app.model.dto.CmdDTO; import com.iflytop.gd.app.service.device.DeviceStateService; import com.iflytop.gd.app.service.device.module.HeatModuleService; import com.iflytop.gd.common.annotation.CommandMapping; import com.iflytop.gd.common.enums.HeatModuleCode; +import com.iflytop.gd.common.enums.HeatingType; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; @@ -26,15 +26,16 @@ public class HeatStopCommand extends BaseCommandHandler { @Override public CompletableFuture handle(CmdDTO cmdDTO) { - JSONArray heatIdJsonArray = cmdDTO.getJSONArrayParam("heatId"); + String heatId = cmdDTO.getStringParam("heatId"); + HeatModuleCode heatModuleCode = HeatModuleCode.valueOf(heatId); return runAsync(() -> { - for (int i = 0; i < heatIdJsonArray.size(); i++) { - String heatId = heatIdJsonArray.getStr(i); - HeatModuleCode heatModuleId = HeatModuleCode.valueOf(heatId); - //关闭加热 - heatModuleService.heatRodClose(cmdDTO.getCommandId(), cmdDTO.getCommand(), heatModuleId); - deviceStateService.getDeviceState().getHeatModuleByCode(heatModuleId).setHeating(false); - } + //关闭加热 + heatModuleService.heatRodClose(cmdDTO.getCommandId(), cmdDTO.getCommand(), heatModuleCode); + deviceStateService.getDeviceState().getHeatModuleByCode(heatModuleCode).setTargetTime(null); + deviceStateService.getDeviceState().getHeatModuleByCode(heatModuleCode).setWarmUpTemperature(null); + deviceStateService.getDeviceState().getHeatModuleByCode(heatModuleCode).setHeatTemperature(null); + deviceStateService.getDeviceState().getHeatModuleByCode(heatModuleCode).setTargetTemperature(null); + deviceStateService.getDeviceState().getHeatModuleByCode(heatModuleCode).setHeatingType(HeatingType.stop); }); } } diff --git a/src/main/java/com/iflytop/gd/app/command/control/MoveToHeatAreaCommand.java b/src/main/java/com/iflytop/gd/app/command/control/MoveToHeatAreaCommand.java index 7f9223d..9f50b16 100644 --- a/src/main/java/com/iflytop/gd/app/command/control/MoveToHeatAreaCommand.java +++ b/src/main/java/com/iflytop/gd/app/command/control/MoveToHeatAreaCommand.java @@ -69,10 +69,10 @@ public class MoveToHeatAreaCommand extends BaseCommandHandler { //校验目标加热位是否有托盘 try { deviceStateService.getCommandMutexState().get().setMoveToHeatAreaCommandExecuting(true); - Boolean heatModuleTray = heatModuleService.heatModuleSensorState(heatModuleCode); - if (heatModuleTray) { - throw new AppException(ResultCode.TARGET_HEAT_MODULE_OCCUPIED); - } +// Boolean heatModuleTray = heatModuleService.heatModuleSensorState(heatModuleCode); +// if (heatModuleTray) { +// throw new AppException(ResultCode.TARGET_HEAT_MODULE_OCCUPIED); +// } } catch (Exception e) { deviceStateService.getCommandMutexState().get().setMoveToHeatAreaCommandExecuting(false); throw e; @@ -80,38 +80,37 @@ public class MoveToHeatAreaCommand extends BaseCommandHandler { return runAsync(() -> { try { // TrayState trayState = deviceStateService.getTrayInSolutionModule(); + capModuleService.capUpBalanceNoWait(cmdDTO.getCommandId(), cmdDTO.getCommand());//提升拍子存放区至拍子夹取的高度 gantryModuleService.gantryMove(cmdDTO.getCommandId(), cmdDTO.getCommand(), liquidAreaTrayPoint3D); //将机械臂移动至加液模块上方 gantryModuleService.clawMove(cmdDTO.getCommandId(), cmdDTO.getCommand(), clawTrayPick);//将夹爪打开,准备夹取托盘 gantryModuleService.gantryZMove(solutionModuleTrayMoveHeight);//下降z轴,使夹爪落入托盘孔位 gantryModuleService.clawMove(cmdDTO.getCommandId(), cmdDTO.getCommand(), clawTrayGrip);//将夹爪收紧,夹住托盘 gantryModuleService.gantryZMove(cmdDTO.getCommandId(), cmdDTO.getCommand(), 0);//抬升z轴 deviceStateService.getDeviceState().getSolutionModule().setTrayStatus(0);//加液模块是否有托盘 - deviceCommandTempUtilService.moveTrayHeatModuleAvoidDown(cmdDTO.getCommandId(), cmdDTO.getCommand(), null);//TODO 结构有问题临时避让 开始,移动托盘之前先降下所有加热模块 +// deviceCommandTempUtilService.moveTrayHeatModuleAvoidDown(cmdDTO.getCommandId(), cmdDTO.getCommand(), null);//TODO 结构有问题临时避让 开始,移动托盘之前先降下所有加热模块 gantryModuleService.gantryMove(cmdDTO.getCommandId(), cmdDTO.getCommand(), heatArea4TrayClawPoint3D);//将携带托盘的机械臂移动至4号加热模块上方 gantryModuleService.gantryMove(cmdDTO.getCommandId(), cmdDTO.getCommand(), heatAreaTrayClawPoint3D);//将携带托盘的机械臂移动至加热模块上方 -// deviceCommandUtilService.heaterMotorMove(cmdDTO.getCommandId(), cmdDTO.getCommand(), heatModuleId, trayLift);//抬升加热位托盘 TODO 结构有问题临时避让 屏蔽 - deviceCommandTempUtilService.moveTrayHeatModuleAvoidUp(cmdDTO.getCommandId(), cmdDTO.getCommand(), heatModuleCode);//TODO 结构有问题临时避让 完毕,可以升起了,顺带提升目标加热模块 +// deviceCommandUtilService.heaterMotorMove(cmdDTO.getCommandId(), cmdDTO.getCommand(), heatModuleId, trayLift);//抬升加热位托盘 + deviceCommandTempUtilService.moveTrayHeatModuleAvoidUpNoWait(cmdDTO.getCommandId(), cmdDTO.getCommand(), heatModuleCode);Thread.sleep(3200);//TODO 结构有问题临时避让 完毕,可以升起了,顺带提升目标加热模块 gantryModuleService.gantryZMove(heatModuleTrayMoveHeight);//下降z轴,使托盘落入加热模块 gantryModuleService.clawMove(cmdDTO.getCommandId(), cmdDTO.getCommand(), clawTrayPick);//将夹爪打开,释放托盘 deviceStateService.getDeviceState().getHeatModuleByCode(heatModuleCode).setTrayStatus(1);//加热模块是否存在托盘 gantryModuleService.gantryZMove(cmdDTO.getCommandId(), cmdDTO.getCommand(), 0);//抬升z轴 - - capModuleService.capUpBalance(cmdDTO.getCommandId(), cmdDTO.getCommand());//提升拍子存放区至拍子夹取的高度 gantryModuleService.gantryMove(cmdDTO.getCommandId(), cmdDTO.getCommand(), capStorageCapClawPoint3D);//移动机械臂至拍子存放区上方 gantryModuleService.clawMove(cmdDTO.getCommandId(), cmdDTO.getCommand(), clawCapPick);//将夹爪打开,准备夹取拍子 gantryModuleService.gantryZMove(capModuleCapMoveHeight);//下降z轴,使夹爪落入拍子升降模块拍子孔位 gantryModuleService.clawMove(cmdDTO.getCommandId(), cmdDTO.getCommand(), clawCapGrip);//将夹爪收紧,夹住拍子 gantryModuleService.gantryZMove(cmdDTO.getCommandId(), cmdDTO.getCommand(), 0);//抬升z轴 gantryModuleService.gantryMove(cmdDTO.getCommandId(), cmdDTO.getCommand(), heatAreaCapClawPointPoint3D);//将携带拍子的机械臂移动至加热模块拍子上方 + capModuleService.capUpBalanceNoWait(cmdDTO.getCommandId(), cmdDTO.getCommand()); //提升拍子存放区 gantryModuleService.gantryZMove(heatModuleCapMoveHeight);//下降z轴,使夹拍子落入加热模块 gantryModuleService.clawMove(cmdDTO.getCommandId(), cmdDTO.getCommand(), clawCapPick);//将夹爪打开,释放拍子 deviceStateService.getDeviceState().getHeatModuleByCode(heatModuleCode).setCapExist(true);//加热模块是否存在拍子 gantryModuleService.gantryZMove(cmdDTO.getCommandId(), cmdDTO.getCommand(), 0);//抬升z轴 // trayState.setHeatModuleId(heatModuleId); // trayState.setInHeatModule(true); - heatModuleService.heaterMotorMove(cmdDTO.getCommandId(), cmdDTO.getCommand(), heatModuleCode, trayLower);//下降加热模块托盘 - deviceStateService.getDeviceState().getHeatModuleByCode(heatModuleCode).setTrayUp(0);//加热模块托盘升降状态 - capModuleService.capUpBalance(cmdDTO.getCommandId(), cmdDTO.getCommand()); //提升拍子存放区 +// heatModuleService.heaterMotorMove(cmdDTO.getCommandId(), cmdDTO.getCommand(), heatModuleCode, trayLower);//下降加热模块托盘 +// deviceStateService.getDeviceState().getHeatModuleByCode(heatModuleCode).setTrayUp(0);//加热模块托盘升降状态 gantryModuleService.gantryMove(cmdDTO.getCommandId(), cmdDTO.getCommand(), capStorageCapClawPoint3D);//移动机械臂至拍子存放区上方 } finally { deviceStateService.getDeviceState().getGantryArm().setIdle(true); diff --git a/src/main/java/com/iflytop/gd/app/command/control/MoveToSolutionAreaCommand.java b/src/main/java/com/iflytop/gd/app/command/control/MoveToSolutionAreaCommand.java index 874f8db..79ba7ad 100644 --- a/src/main/java/com/iflytop/gd/app/command/control/MoveToSolutionAreaCommand.java +++ b/src/main/java/com/iflytop/gd/app/command/control/MoveToSolutionAreaCommand.java @@ -47,6 +47,9 @@ public class MoveToSolutionAreaCommand extends BaseCommandHandler { || deviceStateService.getCommandMutexState().get().isShakeStartCommandExecuting()) { throw new AppException(ResultCode.CMD_BUSY); } + if (!deviceStateService.getDeviceState().getSolutionModule().isIdle()) { + throw new AppException(ResultCode.SOLUTION_MODULE_OCCUPIED); + } String heatId = cmdDTO.getStringParam("heatId"); HeatModuleCode heatModuleCode = HeatModuleCode.valueOf(heatId); double clawCapPick = devicePositionService.getPosition(DevicePositionCode.clawCapPick).getDistance(); //获取拍子夹取距离 @@ -69,10 +72,10 @@ public class MoveToSolutionAreaCommand extends BaseCommandHandler { //校验目标加热位是否有托盘 try { deviceStateService.getCommandMutexState().get().setMoveToSolutionAreaCommandExecuting(true); - Boolean heatModuleTray = heatModuleService.heatModuleSensorState(heatModuleCode); - if (!heatModuleTray) { - throw new AppException(ResultCode.TARGET_HEAT_MODULE_NO_TRAY); - } +// Boolean heatModuleTray = heatModuleService.heatModuleSensorState(heatModuleCode); +// if (!heatModuleTray) { +// throw new AppException(ResultCode.TARGET_HEAT_MODULE_NO_TRAY); +// } } catch (Exception e) { deviceStateService.getCommandMutexState().get().setMoveToSolutionAreaCommandExecuting(false); throw e; @@ -81,15 +84,15 @@ public class MoveToSolutionAreaCommand extends BaseCommandHandler { try { // TrayState trayState = deviceStateService.getTrayInSolutionModule(); solutionModuleService.requestSolutionModule(cmdDTO.getCommandId(), cmdDTO.getCommand());//申请使用加液区并等待 - capModuleService.capUpBalance(cmdDTO.getCommandId(), cmdDTO.getCommand()); //提升拍子存放区至拍子夹取的高度 + capModuleService.capUpBalanceNoWait(cmdDTO.getCommandId(), cmdDTO.getCommand()); //提升拍子存放区至拍子夹取的高度 gantryModuleService.gantryMove(cmdDTO.getCommandId(), cmdDTO.getCommand(), heatAreaCapClawPointPoint3D);//将机械臂移动至加热模块拍子上方 heatModuleService.heaterMotorMove(cmdDTO.getCommandId(), cmdDTO.getCommand(), heatModuleCode, trayLift);//抬升指定加热位托盘 gantryModuleService.clawMove(cmdDTO.getCommandId(), cmdDTO.getCommand(), clawCapPick);//将夹爪打开,准备夹取拍子 gantryModuleService.gantryZMove(heatModuleCapMoveHeight);//下降z轴,使夹爪落入加热模块拍子孔位 gantryModuleService.clawMove(cmdDTO.getCommandId(), cmdDTO.getCommand(), clawCapGrip);//将夹爪收紧,夹住拍子 deviceStateService.getDeviceState().getHeatModuleByCode(heatModuleCode).setCapExist(false);//加热模块是否存在拍子 - gantryModuleService.gantryZMove(cmdDTO.getCommandId(), cmdDTO.getCommand(), 0);//抬升z轴 - capModuleService.capMotorMoveByNum(-1);//拍子存放模块下降1个拍子位置 + capModuleService.capMotorMoveByNumNoWait(cmdDTO.getCommandId(), cmdDTO.getCommand(), -1);//拍子存放模块下降1个拍子位置 + gantryModuleService.gantryZMove(cmdDTO.getCommandId(), cmdDTO.getCommand(), 0); Thread.sleep(2000);//抬升z轴 gantryModuleService.gantryMove(cmdDTO.getCommandId(), cmdDTO.getCommand(), capStorageCapClawPoint3D);//将携带拍子的机械臂移动至存放区上方 gantryModuleService.gantryZMove(capModuleCapMoveHeight);//下降z轴,使夹拍子落入存放区 gantryModuleService.clawMove(cmdDTO.getCommandId(), cmdDTO.getCommand(), clawCapPick);//将夹爪打开,释放夹取的拍子 @@ -102,16 +105,16 @@ public class MoveToSolutionAreaCommand extends BaseCommandHandler { gantryModuleService.clawMove(cmdDTO.getCommandId(), cmdDTO.getCommand(), clawTrayGrip);//将夹爪收紧,夹住托盘 deviceStateService.getDeviceState().getHeatModuleByCode(heatModuleCode).setTrayStatus(0);//加热模块是否存在托盘 // trayState.setInHeatModule(false);//托盘是否在加热模块中 - gantryModuleService.gantryZMove(cmdDTO.getCommandId(), cmdDTO.getCommand(), 0);//抬升z轴 + deviceCommandTempUtilService.moveTrayHeatModuleAvoidDownNoWait(cmdDTO.getCommandId(), cmdDTO.getCommand(), heatModuleCode);//TODO 临时避让下降 + gantryModuleService.gantryZMove(cmdDTO.getCommandId(), cmdDTO.getCommand(), 0);Thread.sleep(2500);//抬升z轴 // deviceCommandUtilService.heaterMotorMove(cmdDTO.getCommandId(), cmdDTO.getCommand(), heatModuleId, trayLower);//下降加热模块托盘 // deviceStateService.setHeatModuleStateTrayUp(heatModuleId, 0);//加热模块托盘升降状态 - deviceCommandTempUtilService.moveTrayHeatModuleAvoidDown(cmdDTO.getCommandId(), cmdDTO.getCommand(), heatModuleCode);//TODO 临时避让下降 gantryModuleService.gantryMove(cmdDTO.getCommandId(), cmdDTO.getCommand(), heatArea4TrayClawPoint3D);//将携带托盘的机械臂移动至4号加热模块上方 gantryModuleService.gantryMove(cmdDTO.getCommandId(), cmdDTO.getCommand(), liquidAreaTrayPoint3D); //将携带托盘的机械臂移动至加液模块上方 - deviceCommandTempUtilService.moveTrayHeatModuleAvoidDown(cmdDTO.getCommandId(), cmdDTO.getCommand(), null);//TODO 临时避 恢复抬起状态 +// deviceCommandTempUtilService.moveTrayHeatModuleAvoidUpNoWait(cmdDTO.getCommandId(), cmdDTO.getCommand(), null, heatModuleCode);//TODO 临时避 恢复抬起状态 gantryModuleService.gantryZMove(solutionModuleTrayMoveHeight);//下降z轴,使托盘落入加液模块 // trayState.setInSolutionModule(true);//托盘是否在加液模块中 - deviceStateService.getDeviceState().getHeatModuleByCode(heatModuleCode).setTrayStatus(1);//加液模块是否存在托盘 + deviceStateService.getDeviceState().getSolutionModule().setTrayStatus(1);//加液模块是否存在托盘 gantryModuleService.clawMove(cmdDTO.getCommandId(), cmdDTO.getCommand(), clawTrayPick);//将夹爪打开,释放托盘 gantryModuleService.gantryZMove(cmdDTO.getCommandId(), cmdDTO.getCommand(), 0);//抬升z轴 gantryModuleService.gantryMove(cmdDTO.getCommandId(), cmdDTO.getCommand(), capStorageCapClawPoint3D);//移动机械臂至拍子存放区上方 diff --git a/src/main/java/com/iflytop/gd/app/command/control/SolutionAddCommand.java b/src/main/java/com/iflytop/gd/app/command/control/SolutionAddCommand.java index 34cf843..b01ce7e 100644 --- a/src/main/java/com/iflytop/gd/app/command/control/SolutionAddCommand.java +++ b/src/main/java/com/iflytop/gd/app/command/control/SolutionAddCommand.java @@ -9,14 +9,18 @@ import com.iflytop.gd.app.service.api.ContainerService; import com.iflytop.gd.app.service.device.DeviceStateService; import com.iflytop.gd.app.service.device.module.SolutionModuleService; import com.iflytop.gd.common.annotation.CommandMapping; +import com.iflytop.gd.common.command.CommandFuture; import com.iflytop.gd.common.enums.AcidPumpDeviceCode; import com.iflytop.gd.common.exception.AppException; import com.iflytop.gd.common.result.ResultCode; +import com.iflytop.gd.common.utils.CommandUtil; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; +import java.util.ArrayList; import java.util.Arrays; +import java.util.List; import java.util.concurrent.CompletableFuture; /** @@ -48,32 +52,39 @@ public class SolutionAddCommand extends BaseCommandHandler { deviceStateService.getCommandMutexState().get().setSolutionAddCommandExecuting(true); deviceStateService.getDeviceState().getSolutionModule().setPumping(true); return runAsync(() -> { - JSONArray dataList = JSONUtil.parseArray(cmdDTO.getParams().get("dataList")); - for (int i = 0; i < dataList.size(); i++) {//遍历前端传入的加液配置 - JSONObject tubeSol = dataList.getJSONObject(i); - String tubeNum = tubeSol.getStr("tubeNum");//获取试管编号 - int[] tubeNums = Arrays.stream(tubeNum.split(",")) - .mapToInt(s -> Integer.parseInt(s.trim())) - .toArray(); - JSONArray solutionList = tubeSol.getJSONArray("solutionList"); - for (int num : tubeNums) { - for (int k = 0; k < solutionList.size(); k++) { - JSONObject addSolution = solutionList.getJSONObject(k); - Long solId = addSolution.getLong("solutionId"); - Double volume = addSolution.getDouble("volume"); - AcidPumpDeviceCode acidPumpDevice = containerService.getPumpBySolutionId(solId);//获取溶液对应的泵 - if (acidPumpDevice == null) { - throw new AppException(ResultCode.CRAFT_CONTAINER_NOT_FOUND);//未找到对应溶液容器 - } + try{ + JSONArray dataList = JSONUtil.parseArray(cmdDTO.getParams().get("dataList")); + for (int i = 0; i < dataList.size(); i++) {//遍历前端传入的加液配置 + JSONObject tubeSol = dataList.getJSONObject(i); + String tubeNum = tubeSol.getStr("tubeNum");//获取试管编号 + int[] tubeNums = Arrays.stream(tubeNum.split(",")) + .mapToInt(s -> Integer.parseInt(s.trim())) + .toArray(); + JSONArray solutionList = tubeSol.getJSONArray("solutionList"); + for (int num : tubeNums) { solutionModuleService.dualRobotMovePoint(num);//移动加液机械臂到指定试管点位 - Thread.sleep(1000); - solutionModuleService.acidPumpMoveBy(cmdDTO.getCommandId(), cmdDTO.getCommand(), acidPumpDevice, volume);//添加溶液 + List futuresList = new ArrayList<>(); + for (int k = 0; k < solutionList.size(); k++) { + JSONObject addSolution = solutionList.getJSONObject(k); + Long solId = addSolution.getLong("solutionId"); + Double volume = addSolution.getDouble("volume"); + AcidPumpDeviceCode acidPumpDevice = containerService.getPumpBySolutionId(solId);//获取溶液对应的泵 + if (acidPumpDevice == null) { + throw new AppException(ResultCode.CRAFT_CONTAINER_NOT_FOUND);//未找到对应溶液容器 + } + CommandFuture deviceCommandFuture = solutionModuleService.acidPumpMoveBy(cmdDTO.getCommandId(), cmdDTO.getCommand(), acidPumpDevice, volume);//添加溶液 + futuresList.add(deviceCommandFuture); + } + CommandUtil.wait(futuresList.toArray(new CommandFuture[0])); } } + solutionModuleService.dualRobotOrigin(); + deviceStateService.getCommandMutexState().get().setSolutionAddCommandExecuting(false); + deviceStateService.getDeviceState().getSolutionModule().setPumping(false); + }finally { + deviceStateService.getCommandMutexState().get().setSolutionAddCommandExecuting(false); } - solutionModuleService.dualRobotOrigin(); - deviceStateService.getCommandMutexState().get().setSolutionAddCommandExecuting(false); - deviceStateService.getDeviceState().getSolutionModule().setPumping(false); + }); } } diff --git a/src/main/java/com/iflytop/gd/app/command/control/TrayDownCommand.java b/src/main/java/com/iflytop/gd/app/command/control/TrayDownCommand.java index 1906358..55971bb 100644 --- a/src/main/java/com/iflytop/gd/app/command/control/TrayDownCommand.java +++ b/src/main/java/com/iflytop/gd/app/command/control/TrayDownCommand.java @@ -1,6 +1,5 @@ package com.iflytop.gd.app.command.control; -import cn.hutool.json.JSONArray; import com.iflytop.gd.app.core.BaseCommandHandler; import com.iflytop.gd.app.model.dto.CmdDTO; import com.iflytop.gd.app.service.api.DevicePositionService; @@ -8,6 +7,7 @@ import com.iflytop.gd.app.service.device.DeviceStateService; import com.iflytop.gd.app.service.device.module.HeatModuleService; import com.iflytop.gd.common.annotation.CommandMapping; import com.iflytop.gd.common.enums.HeatModuleCode; +import com.iflytop.gd.common.enums.HeatingType; import com.iflytop.gd.common.enums.data.DevicePositionCode; import com.iflytop.gd.common.exception.AppException; import com.iflytop.gd.common.result.ResultCode; @@ -16,6 +16,7 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.TimeUnit; /** * 降下托盘 @@ -35,22 +36,28 @@ public class TrayDownCommand extends BaseCommandHandler { || deviceStateService.getCommandMutexState().get().isMoveToSolutionAreaCommandExecuting()) { throw new AppException(ResultCode.CMD_BUSY); } - JSONArray heatIdJsonArray = cmdDTO.getJSONArrayParam("heatId"); + String heatId = cmdDTO.getStringParam("heatId"); + HeatModuleCode heatModuleCode = HeatModuleCode.valueOf(heatId); //从数据库获取加热位下降托盘位置 double trayLower = devicePositionService.getPosition(DevicePositionCode.trayLower).getDistance(); + double trayLift = devicePositionService.getPosition(DevicePositionCode.trayLift).getDistance(); return runAsync(() -> { - for (int i = 0; i < heatIdJsonArray.size(); i++) { - String heatId = heatIdJsonArray.getStr(i); - HeatModuleCode heatModuleCode = HeatModuleCode.valueOf(heatId); - CompletableFuture.runAsync(() -> { - try { - //下降加热位托盘 - heatModuleService.heaterMotorMove(cmdDTO.getCommandId(), cmdDTO.getCommand(), heatModuleCode, trayLower); - deviceStateService.getDeviceState().getHeatModuleByCode(heatModuleCode).setTrayUp(0); - } catch (Exception e) { - log.error("降下托盘失败", e); - } - }); + try { + //下降加热位托盘 + heatModuleService.heaterMotorMove(cmdDTO.getCommandId(), cmdDTO.getCommand(), heatModuleCode, trayLower); + deviceStateService.getDeviceState().getHeatModuleByCode(heatModuleCode).setTrayUp(0); +// if (deviceStateService.getDeviceState().getHeatModuleByCode(heatModuleCode).getHeatingType() == HeatingType.thermostatic) { +// schedulerManager.scheduleOnce(heatModuleCode,() -> { +// try { +// heatModuleService.heaterMotorMove(cmdDTO.getCommandId(), cmdDTO.getCommand(), heatModuleCode, trayLift); +// deviceStateService.getDeviceState().getHeatModuleByCode(heatModuleCode).setTrayUp(1); +// } catch (Exception e) { +// log.error("加热完毕抬起托盘错误{}", heatModuleCode, e); +// } +// }, deviceStateService.getDeviceState().getHeatModuleByCode(heatModuleCode).getTargetTime(), TimeUnit.SECONDS); +// } + } catch (Exception e) { + log.error("降下托盘失败", e); } }); } diff --git a/src/main/java/com/iflytop/gd/app/command/control/TrayUpCommand.java b/src/main/java/com/iflytop/gd/app/command/control/TrayUpCommand.java index 50f3650..5c69bfb 100644 --- a/src/main/java/com/iflytop/gd/app/command/control/TrayUpCommand.java +++ b/src/main/java/com/iflytop/gd/app/command/control/TrayUpCommand.java @@ -1,6 +1,5 @@ package com.iflytop.gd.app.command.control; -import cn.hutool.json.JSONArray; import com.iflytop.gd.app.core.BaseCommandHandler; import com.iflytop.gd.app.model.dto.CmdDTO; import com.iflytop.gd.app.service.api.DevicePositionService; @@ -28,29 +27,24 @@ public class TrayUpCommand extends BaseCommandHandler { private final HeatModuleService heatModuleService; private final DevicePositionService devicePositionService; private final DeviceStateService deviceStateService; + @Override public CompletableFuture handle(CmdDTO cmdDTO) { if (deviceStateService.getCommandMutexState().get().isMoveToHeatAreaCommandExecuting() || deviceStateService.getCommandMutexState().get().isMoveToSolutionAreaCommandExecuting()) { throw new AppException(ResultCode.CMD_BUSY); } - JSONArray heatIdJsonArray = cmdDTO.getJSONArrayParam("heatId"); + String heatId = cmdDTO.getStringParam("heatId"); + HeatModuleCode heatModuleCode = HeatModuleCode.valueOf(heatId); //获取加热位抬升托盘位置 double trayLift = devicePositionService.getPosition(DevicePositionCode.trayLift).getDistance(); return runAsync(() -> { - for (int i = 0; i < heatIdJsonArray.size(); i++) { - String heatId = heatIdJsonArray.getStr(i); - HeatModuleCode heatModuleCode = HeatModuleCode.valueOf(heatId); - - CompletableFuture.runAsync(() -> { - try { - //抬升加热位托盘 - heatModuleService.heaterMotorMove(cmdDTO.getCommandId(), cmdDTO.getCommand(), heatModuleCode, trayLift); - deviceStateService.getDeviceState().getHeatModuleByCode(heatModuleCode).setTrayUp(0); - } catch (Exception e) { - log.error("抬起托盘失败", e); - } - }); + try { + //抬升加热位托盘 + heatModuleService.heaterMotorMove(cmdDTO.getCommandId(), cmdDTO.getCommand(), heatModuleCode, trayLift); + deviceStateService.getDeviceState().getHeatModuleByCode(heatModuleCode).setTrayUp(1); + } catch (Exception e) { + log.error("抬起托盘失败", e); } }); } diff --git a/src/main/java/com/iflytop/gd/app/command/control/WarmUpStartCommand.java b/src/main/java/com/iflytop/gd/app/command/control/WarmUpStartCommand.java new file mode 100644 index 0000000..d65d381 --- /dev/null +++ b/src/main/java/com/iflytop/gd/app/command/control/WarmUpStartCommand.java @@ -0,0 +1,40 @@ +package com.iflytop.gd.app.command.control; + +import com.iflytop.gd.app.core.BaseCommandHandler; +import com.iflytop.gd.app.model.dto.CmdDTO; +import com.iflytop.gd.app.service.device.DeviceStateService; +import com.iflytop.gd.app.service.device.module.HeatModuleService; +import com.iflytop.gd.common.annotation.CommandMapping; +import com.iflytop.gd.common.enums.HeatModuleCode; +import com.iflytop.gd.common.enums.HeatingType; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import java.util.concurrent.CompletableFuture; + +/** + * 开始预热 + */ +@Slf4j +@Component +@RequiredArgsConstructor +@CommandMapping("warm_up_start")//业务指令注解 +public class WarmUpStartCommand extends BaseCommandHandler { + private final HeatModuleService heatModuleService; + private final DeviceStateService deviceStateService; + + @Override + public CompletableFuture handle(CmdDTO cmdDTO) { + String heatId = cmdDTO.getStringParam("heatId"); + HeatModuleCode heatModuleCode = HeatModuleCode.valueOf(heatId); + Double temperature = cmdDTO.getDoubleParam("temperature"); + return runAsync(() -> { + heatModuleService.heatRodOpen(cmdDTO.getCommandId(), cmdDTO.getCommand(), heatModuleCode, temperature); + deviceStateService.getDeviceState().getHeatModuleByCode(heatModuleCode).setWarmUpTemperature(temperature); + deviceStateService.getDeviceState().getHeatModuleByCode(heatModuleCode).setTargetTemperature(temperature); + deviceStateService.getDeviceState().getHeatModuleByCode(heatModuleCode).setHeatingType(HeatingType.warm_up); + }); + } +} + diff --git a/src/main/java/com/iflytop/gd/app/command/selftest/MoveTestCommand.java b/src/main/java/com/iflytop/gd/app/command/selftest/MoveTestCommand.java index f3cd643..a331450 100644 --- a/src/main/java/com/iflytop/gd/app/command/selftest/MoveTestCommand.java +++ b/src/main/java/com/iflytop/gd/app/command/selftest/MoveTestCommand.java @@ -42,6 +42,8 @@ public class MoveTestCommand extends BaseCommandHandler { } Point3D liquidAreaTrayPoint3D = devicePositionService.getPosition(DevicePositionCode.liquidAreaTrayPoint).getPoint3D();//获取加液模块上方点位 Double solutionModuleTrayMoveHeight = devicePositionService.getPosition(DevicePositionCode.solutionModuleTrayMoveHeight).getDistance();//加液模块托盘z轴移动高度 + double clawCapPick = devicePositionService.getPosition(DevicePositionCode.clawCapPick).getDistance(); //获取拍子夹取距离 + double clawCapGrip = devicePositionService.getPosition(DevicePositionCode.clawCapGrip).getDistance(); //获取拍子夹紧距离 deviceStateService.getCommandMutexState().get().setMoveTest(true); return runAsync(() -> { @@ -53,6 +55,9 @@ public class MoveTestCommand extends BaseCommandHandler { gantryModuleService.gantryZMove(solutionModuleTrayMoveHeight);//下降z轴,使托盘落入加液模块 //xyz回0点 gantryModuleService.gantryZMove(cmdDTO.getCommandId(), cmdDTO.getCommand(), 0);//抬升z轴 + gantryModuleService.clawMove(cmdDTO.getCommandId(), cmdDTO.getCommand(), clawCapPick);//将夹爪打开,准备夹取拍子 + gantryModuleService.clawMove(cmdDTO.getCommandId(), cmdDTO.getCommand(), clawCapGrip);//将夹爪收紧,夹住拍子 + gantryModuleService.clawMove(cmdDTO.getCommandId(), cmdDTO.getCommand(), clawCapPick);//将夹爪打开,准备夹取拍子 webSocketService.pushSelfMoveTest(SelfMoveTestGenerator.generateJson(cmdDTO.getCommandId(), cmdDTO.getCommand(), "2、z轴电机检测完毕", 30)); gantryModuleService.gantryMoveZero(); webSocketService.pushSelfMoveTest(SelfMoveTestGenerator.generateJson(cmdDTO.getCommandId(), cmdDTO.getCommand(), "3、xy轴电机检测完毕", 45)); @@ -71,6 +76,7 @@ public class MoveTestCommand extends BaseCommandHandler { webSocketService.pushSelfMoveTest(SelfMoveTestGenerator.generateJson(cmdDTO.getCommandId(), cmdDTO.getCommand(), "6、摇匀电机检测完毕", 90)); //加液机械臂 solutionModuleService.dualRobotMovePoint(16); + Thread.sleep(2000); solutionModuleService.dualRobotOrigin(); webSocketService.pushSelfMoveTest(SelfMoveTestGenerator.generateJson(cmdDTO.getCommandId(), cmdDTO.getCommand(), "7、加液机械臂检测完毕", 100)); }finally { diff --git a/src/main/java/com/iflytop/gd/app/command/selftest/TrayOutCommand.java b/src/main/java/com/iflytop/gd/app/command/selftest/TrayOutCommand.java index e31ce11..fd9a787 100644 --- a/src/main/java/com/iflytop/gd/app/command/selftest/TrayOutCommand.java +++ b/src/main/java/com/iflytop/gd/app/command/selftest/TrayOutCommand.java @@ -37,7 +37,6 @@ public class TrayOutCommand extends BaseCommandHandler { @Override public CompletableFuture handle(CmdDTO cmdDTO) { - //TODO 通过传感器获取一个有托盘的加热模块,顺序按照1-6 String heatId = cmdDTO.getStringParam("heatId"); HeatModuleCode heatModuleCode = HeatModuleCode.valueOf(heatId); diff --git a/src/main/java/com/iflytop/gd/app/controller/CraftsController.java b/src/main/java/com/iflytop/gd/app/controller/CraftsController.java index cdc67e2..122c42d 100644 --- a/src/main/java/com/iflytop/gd/app/controller/CraftsController.java +++ b/src/main/java/com/iflytop/gd/app/controller/CraftsController.java @@ -1,6 +1,9 @@ package com.iflytop.gd.app.controller; -import com.iflytop.gd.app.model.dto.*; +import com.iflytop.gd.app.model.dto.PauseCraftsDto; +import com.iflytop.gd.app.model.dto.ResumeCraftsDTO; +import com.iflytop.gd.app.model.dto.StartCraftsDTO; +import com.iflytop.gd.app.model.dto.StopCraftsDTO; import com.iflytop.gd.app.model.entity.Crafts; import com.iflytop.gd.app.model.vo.SetCraftsVO; import com.iflytop.gd.app.service.api.CraftsService; @@ -82,10 +85,8 @@ public class CraftsController { @Operation(summary = "开始执行工艺") @PostMapping("/start") - public Result startCrafts(@Valid @RequestBody StartCraftsDTO startCraftsDTO) { - craftsService.setCraft(startCraftsDTO.getCraftId(), startCraftsDTO.getHeatId()); - craftsService.startCrafts(startCraftsDTO.getHeatId()); - return Result.success(); + public Result startCrafts(@Valid @RequestBody StartCraftsDTO startCraftsDTO) { + return Result.success(craftsService.startCrafts(startCraftsDTO.getCraftId(), startCraftsDTO.getHeatId())); } @Operation(summary = "暂停执行工艺") diff --git a/src/main/java/com/iflytop/gd/app/controller/DeviceParamController.java b/src/main/java/com/iflytop/gd/app/controller/DeviceParamController.java index 99ea300..eced523 100644 --- a/src/main/java/com/iflytop/gd/app/controller/DeviceParamController.java +++ b/src/main/java/com/iflytop/gd/app/controller/DeviceParamController.java @@ -1,5 +1,7 @@ package com.iflytop.gd.app.controller; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.iflytop.gd.app.model.entity.DeviceParamConfig; import com.iflytop.gd.app.model.vo.DeviceParamGroupVO; import com.iflytop.gd.app.model.vo.ModuleIdVO; @@ -86,12 +88,11 @@ public class DeviceParamController { if (!file.getOriginalFilename().endsWith(".csv")) { return Result.failed(".csv"); } - try (BufferedReader reader = new BufferedReader( - new InputStreamReader(file.getInputStream(), StandardCharsets.UTF_8))) { + try (BufferedReader reader = new BufferedReader(new InputStreamReader(file.getInputStream(), StandardCharsets.UTF_8))) { + deviceParamConfigService.remove(new LambdaQueryWrapper<>()); String line; //是否含有表头 boolean isHeader = true; - List deviceParamConfigList = new ArrayList<>(); while ((line = reader.readLine()) != null) { if (isHeader) { isHeader = false; @@ -105,10 +106,8 @@ public class DeviceParamController { deviceParamConfig.setRegIndex(String.valueOf(data[2])); deviceParamConfig.setRegVal(Integer.valueOf(data[3])); deviceParamConfigService.save(deviceParamConfig); - deviceParamConfigList.add(deviceParamConfig); } } - deviceParamConfigService.saveOrUpdateBatch(deviceParamConfigList); } catch (IOException e) { log.error("csv文件导入数据库失败:{}", e.getMessage()); throw new RuntimeException(e); diff --git a/src/main/java/com/iflytop/gd/app/controller/HeatController.java b/src/main/java/com/iflytop/gd/app/controller/HeatController.java index 809d011..58269cf 100644 --- a/src/main/java/com/iflytop/gd/app/controller/HeatController.java +++ b/src/main/java/com/iflytop/gd/app/controller/HeatController.java @@ -1,6 +1,6 @@ package com.iflytop.gd.app.controller; -import com.iflytop.gd.app.model.vo.SetTargetTemperatureVO; +import com.iflytop.gd.app.model.dto.SetHeatDTO; import com.iflytop.gd.app.service.api.HeatService; import com.iflytop.gd.common.result.Result; import io.swagger.v3.oas.annotations.Operation; @@ -24,10 +24,10 @@ import org.springframework.web.bind.annotation.RestController; public class HeatController { private final HeatService heatModuleService; - @Operation(summary = "加热模块设定目标温度") - @PostMapping("/target-temperature") - public Result setTargetTemperature(@Valid @RequestBody SetTargetTemperatureVO setTargetTemperatureVO) { - heatModuleService.setTargetTemperature(setTargetTemperatureVO); + @Operation(summary = "加热模块设定") + @PostMapping("/set") + public Result setHeat(@Valid @RequestBody SetHeatDTO setHeatDTO) { + heatModuleService.setHeat(setHeatDTO); return Result.success(); } } diff --git a/src/main/java/com/iflytop/gd/app/controller/SelfTestController.java b/src/main/java/com/iflytop/gd/app/controller/SelfTestController.java index cd09f05..37cbced 100644 --- a/src/main/java/com/iflytop/gd/app/controller/SelfTestController.java +++ b/src/main/java/com/iflytop/gd/app/controller/SelfTestController.java @@ -41,8 +41,9 @@ public class SelfTestController { @Operation(summary = "自检完毕") @PostMapping("/finish") - public Result selfTestFinish(){ + public Result selfTestFinish() throws Exception { deviceStateService.getDeviceState().setSelfTest(true); + capModuleService.capMotorMove(21); return Result.success(); } diff --git a/src/main/java/com/iflytop/gd/app/controller/TestController.java b/src/main/java/com/iflytop/gd/app/controller/TestController.java new file mode 100644 index 0000000..cb20f7c --- /dev/null +++ b/src/main/java/com/iflytop/gd/app/controller/TestController.java @@ -0,0 +1,87 @@ +package com.iflytop.gd.app.controller; + +import com.iflytop.gd.app.model.bo.status.CommandMutexState; +import com.iflytop.gd.app.model.dto.AllSensorDTO; +import com.iflytop.gd.app.service.api.TestService; +import com.iflytop.gd.app.service.device.DeviceEmergencyStopService; +import com.iflytop.gd.app.service.device.DeviceStateService; +import com.iflytop.gd.app.service.device.module.CapModuleService; +import com.iflytop.gd.app.service.device.module.SolutionModuleService; +import com.iflytop.gd.common.result.Result; +import com.iflytop.gd.hardware.exception.HardwareException; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; + +/** + * 测试用 + */ +@Tag(name = "测试用") +@RestController +@RequestMapping("/api/test") +@RequiredArgsConstructor +@Slf4j +public class TestController { + private final TestService testService; + private final CapModuleService capModuleService; + private final DeviceStateService deviceStateService; + private final SolutionModuleService solutionModuleService; + private final DeviceEmergencyStopService deviceEmergencyStopService; + + @Operation(summary = "获取所有传感器读数") + @GetMapping("/all-sensor") + public Result> getAllSensor() throws HardwareException { + return Result.success(testService.getAllSensor()); + } + + @Operation(summary = "将拍子升降区抬升至可以获取的位置") + @PostMapping("/cap-up-balance") + public Result capUpBalance() throws Exception { + capModuleService.capUpBalance(); + return Result.success(); + } + + + @Operation(summary = "调整拍子升降电机位置") + @PostMapping("/cap-motor-move-by-num") + public Result capMotorMoveByNum(int num) throws Exception { + capModuleService.capMotorMoveByNum(num); + return Result.success(); + } + + + @Operation(summary = "获取指令互斥状态") + @GetMapping("/mutex-state") + public Result getCommandMutexState() throws HardwareException { + return Result.success(deviceStateService.getCommandMutexState().get()); + } + + @Operation(summary = "重置状态") + @PostMapping("/reset") + public Result reset() throws Exception { + testService.reset(); + return Result.success(); + } + + + @Operation(summary = "触发急停") + @PostMapping("/press-emergency-stop") + public Result pressEmergencyStop() throws Exception { + deviceEmergencyStopService.press(); + return Result.success(); + } + + @Operation(summary = "解除急停") + @PostMapping("/release-emergency-stop") + public Result releaseEmergencyStop() throws Exception { + deviceEmergencyStopService.release(); + return Result.success(); + } +} diff --git a/src/main/java/com/iflytop/gd/app/controller/TrayController.java b/src/main/java/com/iflytop/gd/app/controller/TrayController.java index 96d6ae9..63ba5c2 100644 --- a/src/main/java/com/iflytop/gd/app/controller/TrayController.java +++ b/src/main/java/com/iflytop/gd/app/controller/TrayController.java @@ -32,7 +32,7 @@ public class TrayController { @Operation(summary = "拿走托盘") @PostMapping("/out") - public Result trayOut() { + public Result trayOut() throws InterruptedException { trayService.trayOut(); return Result.success(); } diff --git a/src/main/java/com/iflytop/gd/app/core/CommandPoolManager.java b/src/main/java/com/iflytop/gd/app/core/CommandPoolManager.java index 20a3181..ff0a446 100644 --- a/src/main/java/com/iflytop/gd/app/core/CommandPoolManager.java +++ b/src/main/java/com/iflytop/gd/app/core/CommandPoolManager.java @@ -5,6 +5,7 @@ import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import org.springframework.stereotype.Component; +import java.lang.reflect.Field; import java.util.concurrent.ThreadPoolExecutor; @Slf4j @@ -28,4 +29,22 @@ public class CommandPoolManager { } } + /** + * 重启命令线程池 + */ + public void restartExecutor() { + try { + Field field = ThreadPoolTaskExecutor.class.getDeclaredField("threadPoolExecutor"); + field.setAccessible(true); + field.set(executor, null); + executor.initialize(); + log.info("命令线程池已重建并启动:corePoolSize={}, maxPoolSize={}, queueCapacity={}", + executor.getCorePoolSize(), + executor.getMaxPoolSize(), + executor.getQueueCapacity()); + } catch (NoSuchFieldException | IllegalAccessException e) { + log.error("通过反射重置 threadPoolExecutor 字段失败,无法重启命令线程池", e); + } + } + } diff --git a/src/main/java/com/iflytop/gd/app/core/CraftsContext.java b/src/main/java/com/iflytop/gd/app/core/CraftsContext.java index 4334cea..536d286 100644 --- a/src/main/java/com/iflytop/gd/app/core/CraftsContext.java +++ b/src/main/java/com/iflytop/gd/app/core/CraftsContext.java @@ -7,6 +7,7 @@ import com.iflytop.gd.app.model.entity.Ores; import com.iflytop.gd.app.service.crafts.CraftsStepService; import com.iflytop.gd.app.ws.server.WebSocketSender; import com.iflytop.gd.common.constant.WebSocketMessageType; +import com.iflytop.gd.common.enums.HeatModuleCode; import com.iflytop.gd.common.enums.automaton.CraftEvents; import com.iflytop.gd.common.enums.automaton.CraftStates; import lombok.Getter; @@ -26,7 +27,7 @@ import java.util.Map; @Slf4j @Getter public class CraftsContext implements Runnable { - private final String heatId; + private final HeatModuleCode heatModuleCode; private final Ores ores; private final Crafts craft; private final List craftsStepList; @@ -38,24 +39,24 @@ public class CraftsContext implements Runnable { /** * 构造方法,初始化上下文并启动状态机至 READY */ - public CraftsContext(String heatId, Ores ores, + public CraftsContext(HeatModuleCode heatModuleCode, Ores ores, Crafts craft, StateMachineFactory factory, WebSocketSender webSocketService, CraftsStepService craftsStepService) { - this.heatId = heatId; + this.heatModuleCode = heatModuleCode; this.ores = ores; this.craft = craft; this.craftsStepList = JSONUtil.parseArray(craft.getSteps()).toList(CraftsStep.class); this.webSocketService = webSocketService; this.craftsStepService = craftsStepService; - this.sm = factory.getStateMachine(heatId); + this.sm = factory.getStateMachine(heatModuleCode.toString()); sm.addStateListener(new StateMachineListenerAdapter<>() { @Override public void stateEntered(State state) { Map dataMap = new HashMap<>(); - dataMap.put("heatId", heatId); + dataMap.put("heatId", heatModuleCode); dataMap.put("state", state.getId()); dataMap.put("index", currentIndex); webSocketService.push(WebSocketMessageType.CRAFTS_STATE, dataMap); @@ -93,12 +94,13 @@ public class CraftsContext implements Runnable { } } if (sm.getState().getId() == CraftStates.RUNNING) { + craftsStepService.finish(heatModuleCode); Message finishMsg = MessageBuilder.withPayload(CraftEvents.FINISH).build(); Mono.from(sm.sendEvent(Mono.just(finishMsg))).block(); } } catch (Exception e) { log.error("工艺执行失败", e); - webSocketService.pushCraftsDebug(CraftsDebugGenerator.generateJson(heatId, "工艺执行失败", e.getMessage())); + webSocketService.pushCraftsDebug(CraftsDebugGenerator.generateJson(heatModuleCode.toString(), "工艺执行失败", e.getMessage())); Message stopMsg = MessageBuilder.withPayload(CraftEvents.ERROR_OCCUR).build(); Mono.from(sm.sendEvent(Mono.just(stopMsg))).block(); } @@ -113,10 +115,10 @@ public class CraftsContext implements Runnable { */ private boolean executeStep(CraftsStep step) throws Exception { Map startData = new HashMap<>(); - startData.put("heatId", heatId); + startData.put("heatId", heatModuleCode); startData.put("currentStep", step.getMethod()); webSocketService.push(WebSocketMessageType.CRAFTS_STEP, startData); - return craftsStepService.executeStep(heatId, step); + return craftsStepService.executeStep(heatModuleCode, step); } /** diff --git a/src/main/java/com/iflytop/gd/app/model/bo/status/CommandMutexState.java b/src/main/java/com/iflytop/gd/app/model/bo/status/CommandMutexState.java index 5e18242..bfc47a1 100644 --- a/src/main/java/com/iflytop/gd/app/model/bo/status/CommandMutexState.java +++ b/src/main/java/com/iflytop/gd/app/model/bo/status/CommandMutexState.java @@ -36,4 +36,34 @@ public class CommandMutexState { private boolean moveTest = false; private boolean trayOut = false; + public void reset() { + this.capFreeCommandExecuting = false; + this.capLiftingOriginCommandExecuting = false; + this.capUsedCommandExecuting = false; + this.doorCloseCommandExecuting = false; + this.doorOpenCommandExecuting = false; + this.doorOriginCommandExecuting = false; + this.dualRobotJointOriginCommandExecuting = false; + this.fanStartCommandExecuting = false; + this.fanStopCommandExecuting = false; + this.filledSolutionStartCommandExecuting = false; + this.filledSolutionStopCommandExecuting = false; + this.gantryXOriginCommandExecuting = false; + this.gantryYOriginCommandExecuting = false; + this.gantryZOriginCommandExecuting = false; + this.heatStartCommandExecuting = false; + this.heatStopCommandExecuting = false; + this.moveToHeatAreaCommandExecuting = false; + this.moveToSolutionAreaCommandExecuting = false; + this.shakeStartCommandExecuting = false; + this.shakeStopCommandExecuting = false; + this.solutionAddCommandExecuting = false; + this.takePhotoCommandExecuting = false; + this.trayDownCommandExecuting = false; + this.trayLiftingOriginCommandExecuting = false; + this.trayUpCommandExecuting = false; + this.moveTest = false; + this.trayOut = false; + } + } diff --git a/src/main/java/com/iflytop/gd/app/model/bo/status/device/DeviceState.java b/src/main/java/com/iflytop/gd/app/model/bo/status/device/DeviceState.java index a12dde4..a757790 100644 --- a/src/main/java/com/iflytop/gd/app/model/bo/status/device/DeviceState.java +++ b/src/main/java/com/iflytop/gd/app/model/bo/status/device/DeviceState.java @@ -4,6 +4,7 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.iflytop.gd.app.model.entity.Tasks; import com.iflytop.gd.app.model.entity.User; import com.iflytop.gd.common.enums.HeatModuleCode; +import com.iflytop.gd.common.enums.HeatingType; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.RequiredArgsConstructor; @@ -43,6 +44,23 @@ public class DeviceState { @Schema(description = "当前实验") private Tasks currentTasks; + public synchronized void reset(){ + door.setOpen(false); + gantryArm.setIdle(true); + solutionModule.setIdle(true); + solutionModule.setShaking(false); + solutionModule.setTrayStatus(0); + solutionModule.setPumping(false); + for(HeatModuleState heatModuleState : heatModule){ + heatModuleState.setHeatingType(HeatingType.stop); + heatModuleState.setCapExist(false); + heatModuleState.setTrayStatus(0); + heatModuleState.setFanOpen(false); + heatModuleState.setTrayUp(0); + } + tray.clear(); + } + /** * 获取指定加热模块状态 */ diff --git a/src/main/java/com/iflytop/gd/app/model/bo/status/device/HeatModuleState.java b/src/main/java/com/iflytop/gd/app/model/bo/status/device/HeatModuleState.java index 317325e..2d40dfa 100644 --- a/src/main/java/com/iflytop/gd/app/model/bo/status/device/HeatModuleState.java +++ b/src/main/java/com/iflytop/gd/app/model/bo/status/device/HeatModuleState.java @@ -2,6 +2,7 @@ package com.iflytop.gd.app.model.bo.status.device; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.iflytop.gd.common.enums.HeatModuleCode; +import com.iflytop.gd.common.enums.HeatingType; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.RequiredArgsConstructor; @@ -24,8 +25,8 @@ public class HeatModuleState { @Schema(description = "托盘状态,0为无托盘,1为有托盘") private int trayStatus = 0; - @Schema(description = "是否正在加热,true为正在加热,false为未加热") - private boolean heating = false; + @Schema(description = "当前加热类型") + private HeatingType heatingType = HeatingType.stop; @Schema(description = "是否启动散热,true为正在散热,false为未在散热") private boolean fanOpen = false; @@ -33,9 +34,18 @@ public class HeatModuleState { @Schema(description = "是否存在拍子,true为存在拍子,false无拍子") private boolean capExist = false; + @Schema(description = "加热器加热温度") + private Double heatTemperature = null; + + @Schema(description = "加热器预热温度") + private Double warmUpTemperature = null; + @Schema(description = "加热器目标温度") private Double targetTemperature = null; + @Schema(description = "加热器目标加热时间,单位秒") + private Integer targetTime = null; + @Schema(description = "加热器当前温度") private Double temperature = null; diff --git a/src/main/java/com/iflytop/gd/app/model/dto/AllSensorDTO.java b/src/main/java/com/iflytop/gd/app/model/dto/AllSensorDTO.java new file mode 100644 index 0000000..c59c409 --- /dev/null +++ b/src/main/java/com/iflytop/gd/app/model/dto/AllSensorDTO.java @@ -0,0 +1,16 @@ +package com.iflytop.gd.app.model.dto; + +import com.iflytop.gd.hardware.type.IO.InputIOMId; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +public class AllSensorDTO { + private InputIOMId inputIOMId; + private Boolean state; + + public AllSensorDTO(InputIOMId inputIOMId, Boolean state) { + this.inputIOMId = inputIOMId; + this.state = state; + } +} diff --git a/src/main/java/com/iflytop/gd/app/model/dto/PauseCraftsDto.java b/src/main/java/com/iflytop/gd/app/model/dto/PauseCraftsDto.java index 4518ddd..1a6fadb 100644 --- a/src/main/java/com/iflytop/gd/app/model/dto/PauseCraftsDto.java +++ b/src/main/java/com/iflytop/gd/app/model/dto/PauseCraftsDto.java @@ -1,5 +1,6 @@ package com.iflytop.gd.app.model.dto; +import com.iflytop.gd.common.enums.HeatModuleCode; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; import lombok.Data; @@ -9,5 +10,5 @@ import lombok.Data; public class PauseCraftsDto { @NotNull @Schema(description = "加热区id") - private String heatId; + private HeatModuleCode heatId; } diff --git a/src/main/java/com/iflytop/gd/app/model/dto/ResumeCraftsDTO.java b/src/main/java/com/iflytop/gd/app/model/dto/ResumeCraftsDTO.java index 3e7b058..3b2a5a3 100644 --- a/src/main/java/com/iflytop/gd/app/model/dto/ResumeCraftsDTO.java +++ b/src/main/java/com/iflytop/gd/app/model/dto/ResumeCraftsDTO.java @@ -1,5 +1,6 @@ package com.iflytop.gd.app.model.dto; +import com.iflytop.gd.common.enums.HeatModuleCode; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; import lombok.Data; @@ -9,5 +10,5 @@ import lombok.Data; public class ResumeCraftsDTO { @NotNull @Schema(description = "加热区id") - private String heatId; + private HeatModuleCode heatId; } diff --git a/src/main/java/com/iflytop/gd/app/model/dto/SetHeatDTO.java b/src/main/java/com/iflytop/gd/app/model/dto/SetHeatDTO.java new file mode 100644 index 0000000..debb2f5 --- /dev/null +++ b/src/main/java/com/iflytop/gd/app/model/dto/SetHeatDTO.java @@ -0,0 +1,30 @@ +package com.iflytop.gd.app.model.dto; + +import com.iflytop.gd.common.enums.HeatModuleCode; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.Min; +import lombok.Data; +import lombok.EqualsAndHashCode; + +@EqualsAndHashCode(callSuper = false) +@Data +public class SetHeatDTO { + @Schema(description = "加热模块code") + private HeatModuleCode moduleCode; + + @Max(value = 200, message = "温度不能超过200度") + @Min(value = 0, message = "温度不能低于0度") + @Schema(description = "预热温度") + private Double preheating; + + @Max(value = 200, message = "温度不能超过200度") + @Min(value = 0, message = "温度不能低于0度") + @Schema(description = "加热温度") + private Double temperature; + + @Min(value = 0, message = "时间不能少于0") + @Schema(description = "加热时间 单位秒") + private Double time; + +} diff --git a/src/main/java/com/iflytop/gd/app/model/dto/StartCraftsDTO.java b/src/main/java/com/iflytop/gd/app/model/dto/StartCraftsDTO.java index 17ee073..e1598ba 100644 --- a/src/main/java/com/iflytop/gd/app/model/dto/StartCraftsDTO.java +++ b/src/main/java/com/iflytop/gd/app/model/dto/StartCraftsDTO.java @@ -1,5 +1,6 @@ package com.iflytop.gd.app.model.dto; +import com.iflytop.gd.common.enums.HeatModuleCode; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.Positive; @@ -13,6 +14,6 @@ public class StartCraftsDTO { @Schema(description = "工艺id") private Long craftId; - @Schema(description = "加热区id,如果不传递则自动分配加热区") - private String heatId; + @Schema(description = "加热区id,非必填,如果不传递则自动分配加热区") + private HeatModuleCode heatId; } diff --git a/src/main/java/com/iflytop/gd/app/model/dto/StopCraftsDTO.java b/src/main/java/com/iflytop/gd/app/model/dto/StopCraftsDTO.java index af407de..cfc41f0 100644 --- a/src/main/java/com/iflytop/gd/app/model/dto/StopCraftsDTO.java +++ b/src/main/java/com/iflytop/gd/app/model/dto/StopCraftsDTO.java @@ -1,5 +1,6 @@ package com.iflytop.gd.app.model.dto; +import com.iflytop.gd.common.enums.HeatModuleCode; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; import lombok.Data; @@ -9,5 +10,5 @@ import lombok.Data; public class StopCraftsDTO { @NotNull @Schema(description = "加热区id") - private String heatId; + private HeatModuleCode heatId; } diff --git a/src/main/java/com/iflytop/gd/app/model/vo/CraftStatusVO.java b/src/main/java/com/iflytop/gd/app/model/vo/CraftStatusVO.java index 7a2ca23..4e507e3 100644 --- a/src/main/java/com/iflytop/gd/app/model/vo/CraftStatusVO.java +++ b/src/main/java/com/iflytop/gd/app/model/vo/CraftStatusVO.java @@ -1,6 +1,7 @@ package com.iflytop.gd.app.model.vo; import com.iflytop.gd.app.model.bo.CraftsStep; +import com.iflytop.gd.common.enums.HeatModuleCode; import com.iflytop.gd.common.enums.automaton.CraftStates; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; @@ -14,7 +15,7 @@ import java.util.List; public class CraftStatusVO { @Schema(description = "加热区 ID") - private String heatId; + private HeatModuleCode heatId; @Schema(description = "矿石 ID") private Long oresId; diff --git a/src/main/java/com/iflytop/gd/app/model/vo/SetCraftsVO.java b/src/main/java/com/iflytop/gd/app/model/vo/SetCraftsVO.java index 1a7d372..3a40c47 100644 --- a/src/main/java/com/iflytop/gd/app/model/vo/SetCraftsVO.java +++ b/src/main/java/com/iflytop/gd/app/model/vo/SetCraftsVO.java @@ -1,12 +1,13 @@ package com.iflytop.gd.app.model.vo; +import com.iflytop.gd.common.enums.HeatModuleCode; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; @Data public class SetCraftsVO { @Schema(description = "加热区id") - private String heatId; + private HeatModuleCode heatId; @Schema(description = "工艺名称") private String craftsName; diff --git a/src/main/java/com/iflytop/gd/app/model/vo/SetTargetTemperatureVO.java b/src/main/java/com/iflytop/gd/app/model/vo/SetTargetTemperatureVO.java deleted file mode 100644 index 52f5ea2..0000000 --- a/src/main/java/com/iflytop/gd/app/model/vo/SetTargetTemperatureVO.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.iflytop.gd.app.model.vo; - -import com.iflytop.gd.common.enums.HeatModuleCode; -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.Max; -import jakarta.validation.constraints.Min; -import lombok.Data; -import lombok.EqualsAndHashCode; - -@EqualsAndHashCode(callSuper = false) -@Data -public class SetTargetTemperatureVO { - @Schema(description = "加热模块code") - private HeatModuleCode moduleCode; - - @Max(value = 200, message = "温度不能超过200度") - @Min(value = 0, message = "温度不能低于0度") - @Schema(description = "目标温度") - private Double temperature; -} diff --git a/src/main/java/com/iflytop/gd/app/service/api/CraftsService.java b/src/main/java/com/iflytop/gd/app/service/api/CraftsService.java index b40446f..c17fdac 100644 --- a/src/main/java/com/iflytop/gd/app/service/api/CraftsService.java +++ b/src/main/java/com/iflytop/gd/app/service/api/CraftsService.java @@ -4,23 +4,28 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.iflytop.gd.app.core.CraftsContext; import com.iflytop.gd.app.mapper.CraftsMapper; +import com.iflytop.gd.app.model.bo.status.device.HeatModuleState; import com.iflytop.gd.app.model.entity.Crafts; import com.iflytop.gd.app.model.entity.Ores; import com.iflytop.gd.app.model.vo.CraftStatusVO; import com.iflytop.gd.app.model.vo.SetCraftsVO; import com.iflytop.gd.app.service.crafts.CraftsStepService; +import com.iflytop.gd.app.service.device.module.HeatModuleService; import com.iflytop.gd.app.ws.server.WebSocketSender; +import com.iflytop.gd.common.enums.HeatModuleCode; import com.iflytop.gd.common.enums.automaton.CraftEvents; import com.iflytop.gd.common.enums.automaton.CraftStates; import com.iflytop.gd.common.exception.AppException; import com.iflytop.gd.common.result.ResultCode; import jakarta.annotation.PostConstruct; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.springframework.statemachine.config.StateMachineFactory; import org.springframework.stereotype.Service; import java.util.Arrays; import java.util.List; +import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @@ -30,48 +35,112 @@ import java.util.stream.Collectors; /** * 工艺接口服务 */ +@Slf4j @Service @RequiredArgsConstructor public class CraftsService extends ServiceImpl { + private final HeatModuleService heatModuleService; private final StateMachineFactory stateMachineFactory; private final WebSocketSender webSocketService; private final CraftsStepService craftsStepService; private final OresService oresService; - private final ConcurrentHashMap contextMap = new ConcurrentHashMap<>(); - private final ConcurrentHashMap> futureMap = new ConcurrentHashMap<>(); + private final ConcurrentHashMap contextMap = new ConcurrentHashMap<>(); + private final ConcurrentHashMap> futureMap = new ConcurrentHashMap<>(); private ExecutorService executor; @PostConstruct public void init() { this.executor = Executors.newCachedThreadPool(); } +// +// /** +// * 配置工艺 +// */ +// public synchronized SetCraftsVO setCraft(Long craftId, String heatId) { +// // 校验已有上下文状态,仅允许在 READY、STOPPED 或 FINISHED 状态下重置 +// CraftsContext existing = contextMap.get(heatId); +// if (existing != null) { +// CraftStates state = existing.getSm().getState().getId(); +// if (state == CraftStates.RUNNING || state == CraftStates.PAUSED) { +// throw new AppException(ResultCode.CRAFT_RUNNING); +// } +// clearCraftContext(heatId); +// } +// Crafts craft = this.getById(craftId); +// Ores ores = oresService.getById(craft.getOresId()); +// CraftsContext ctx = new CraftsContext( +// heatId, +// ores, +// craft, +// stateMachineFactory, +// webSocketService, +// craftsStepService +// ); +// contextMap.put(heatId, ctx); +// SetCraftsVO setCraftsVO = new SetCraftsVO(); +// setCraftsVO.setHeatId(heatId); +// setCraftsVO.setCraftsName(craft.getName()); +// setCraftsVO.setCraftsId(craft.getId()); +// setCraftsVO.setOresName(ores.getName()); +// setCraftsVO.setOresId(ores.getId()); +// return setCraftsVO; +// } /** - * 配置工艺 + * 启动执行工艺 */ - public synchronized SetCraftsVO setCraft(Long craftId, String heatId) { + public synchronized SetCraftsVO startCrafts(Long craftId, HeatModuleCode heatModuleCode) { + Crafts craft = this.getById(craftId); + if (craft == null) { + throw new AppException(ResultCode.INVALID_PARAMETER); + } + Ores ores = oresService.getById(craft.getOresId()); + if (ores == null) { + throw new AppException(ResultCode.INVALID_PARAMETER); + } + //判断是否指定加热区id + if (heatModuleCode == null) { + //如果没有指定加热区id,则自动获取一个 + HeatModuleState heatModuleState = heatModuleService.getIdleHeatModule(); + if (heatModuleState == null) { + log.error("自动分配工艺失败,无空闲加热模块。"); + throw new AppException(ResultCode.HEAT_MODULE_NO_IDLE); + } else { + heatModuleCode = heatModuleState.getModuleCode(); + } + } else { + if (futureMap.containsKey(heatModuleCode)) {//校验指定加热模块是否正在执行工艺 + log.error("工艺正在执行中,不可重复开始执行。"); + throw new AppException(ResultCode.CRAFT_RUNNING); + } + } + log.info("准备开始工艺,加热模块{},工艺{}", heatModuleCode, craft.getName()); + //TODO 传感器校验heatModuleCode是否被占用 + // 校验已有上下文状态,仅允许在 READY、STOPPED 或 FINISHED 状态下重置 - CraftsContext existing = contextMap.get(heatId); + CraftsContext existing = contextMap.get(heatModuleCode); if (existing != null) { CraftStates state = existing.getSm().getState().getId(); if (state == CraftStates.RUNNING || state == CraftStates.PAUSED) { throw new AppException(ResultCode.CRAFT_RUNNING); } - clearCraftContext(heatId); + clearCraftContext(heatModuleCode); } - Crafts craft = this.getById(craftId); - Ores ores = oresService.getById(craft.getOresId()); + CraftsContext ctx = new CraftsContext( - heatId, + heatModuleCode, ores, craft, stateMachineFactory, webSocketService, craftsStepService ); - contextMap.put(heatId, ctx); + contextMap.put(heatModuleCode, ctx); + Future future = executor.submit(ctx); + futureMap.put(heatModuleCode, future); + SetCraftsVO setCraftsVO = new SetCraftsVO(); - setCraftsVO.setHeatId(heatId); + setCraftsVO.setHeatId(heatModuleCode); setCraftsVO.setCraftsName(craft.getName()); setCraftsVO.setCraftsId(craft.getId()); setCraftsVO.setOresName(ores.getName()); @@ -80,25 +149,10 @@ public class CraftsService extends ServiceImpl { } /** - * 启动执行工艺(需先调用 setCraft) - */ - public synchronized void startCrafts(String heatId) { - CraftsContext ctx = contextMap.get(heatId); - if (ctx == null) { - throw new AppException(ResultCode.CRAFT_CONTEXT_NULL); - } - if (futureMap.containsKey(heatId)) { - throw new AppException(ResultCode.CRAFT_RUNNING); - } - Future future = executor.submit(ctx); - futureMap.put(heatId, future); - } - - /** * 暂停执行工艺 */ - public synchronized void pauseCrafts(String heatId) { - CraftsContext ctx = contextMap.get(heatId); + public synchronized void pauseCrafts(HeatModuleCode heatModuleCode) { + CraftsContext ctx = contextMap.get(heatModuleCode); if (ctx == null) { throw new AppException(ResultCode.CRAFT_CONTEXT_NULL); } @@ -108,8 +162,8 @@ public class CraftsService extends ServiceImpl { /** * 恢复执行工艺 */ - public synchronized void resumeCrafts(String heatId) { - CraftsContext ctx = contextMap.get(heatId); + public synchronized void resumeCrafts(HeatModuleCode heatModuleCode) { + CraftsContext ctx = contextMap.get(heatModuleCode); if (ctx == null) { throw new AppException(ResultCode.CRAFT_CONTEXT_NULL); } @@ -119,9 +173,9 @@ public class CraftsService extends ServiceImpl { /** * 停止执行工艺,不清除上下文 */ - public synchronized void stopCrafts(String heatId) { - CraftsContext ctx = contextMap.get(heatId); - Future future = futureMap.remove(heatId); + public synchronized void stopCrafts(HeatModuleCode heatModuleCode) { + CraftsContext ctx = contextMap.get(heatModuleCode); + Future future = futureMap.remove(heatModuleCode); if (ctx == null || future == null) { throw new AppException(ResultCode.CRAFT_CONTEXT_NULL); } @@ -130,24 +184,37 @@ public class CraftsService extends ServiceImpl { } /** + * 停止执行所有工艺,不清除上下文 + */ + public synchronized void stopAllCrafts() { + contextMap.forEach((key, ctx) -> { + Future future = futureMap.remove(key); + if (ctx != null && future != null) { + ctx.stop(); + future.cancel(true); + } + }); + } + + /** * 清理指定 heatId 的执行上下文和 Future */ - public synchronized void clearCraftContext(String heatId) { - contextMap.remove(heatId); - Future future = futureMap.remove(heatId); + public synchronized void clearCraftContext(HeatModuleCode heatModuleCode) { + contextMap.remove(heatModuleCode); + Future future = futureMap.remove(heatModuleCode); if (future != null) future.cancel(true); } /** * 查询指定 heatId 的执行状态 */ - public CraftStatusVO getStatus(String heatId) { - CraftsContext ctx = contextMap.get(heatId); + public CraftStatusVO getStatus(HeatModuleCode heatModuleCode) { + CraftsContext ctx = contextMap.get(heatModuleCode); if (ctx == null) { return null; } CraftStatusVO vo = new CraftStatusVO(); - vo.setHeatId(heatId); + vo.setHeatId(heatModuleCode); vo.setOresId(ctx.getOres().getId()); vo.setOresName(ctx.getOres().getName()); vo.setCraftsId(ctx.getCraft().getId()); @@ -163,10 +230,10 @@ public class CraftsService extends ServiceImpl { */ public List getAllStatuses() { return contextMap.entrySet().stream().map(entry -> { - String heatIdKey = entry.getKey(); + HeatModuleCode heatModuleCode = entry.getKey(); CraftsContext ctx = entry.getValue(); CraftStatusVO vo = new CraftStatusVO(); - vo.setHeatId(heatIdKey); + vo.setHeatId(heatModuleCode); vo.setOresId(ctx.getOres().getId()); vo.setOresName(ctx.getOres().getName()); vo.setCraftsId(ctx.getCraft().getId()); diff --git a/src/main/java/com/iflytop/gd/app/service/api/HeatService.java b/src/main/java/com/iflytop/gd/app/service/api/HeatService.java index 319630f..6048100 100644 --- a/src/main/java/com/iflytop/gd/app/service/api/HeatService.java +++ b/src/main/java/com/iflytop/gd/app/service/api/HeatService.java @@ -1,6 +1,6 @@ package com.iflytop.gd.app.service.api; -import com.iflytop.gd.app.model.vo.SetTargetTemperatureVO; +import com.iflytop.gd.app.model.dto.SetHeatDTO; import com.iflytop.gd.app.service.device.DeviceStateService; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -13,7 +13,7 @@ import org.springframework.stereotype.Service; public class HeatService { private final DeviceStateService deviceStateService; - public void setTargetTemperature(SetTargetTemperatureVO setTargetTemperatureVO) { - deviceStateService.getDeviceState().getHeatModuleByCode(setTargetTemperatureVO.getModuleCode()).setTargetTemperature(setTargetTemperatureVO.getTemperature()); + public void setHeat(SetHeatDTO setHeatDTO) { + deviceStateService.getDeviceState().getHeatModuleByCode(setHeatDTO.getModuleCode()).setTargetTemperature(setHeatDTO.getTemperature()); } } diff --git a/src/main/java/com/iflytop/gd/app/service/api/TestService.java b/src/main/java/com/iflytop/gd/app/service/api/TestService.java new file mode 100644 index 0000000..47c9d11 --- /dev/null +++ b/src/main/java/com/iflytop/gd/app/service/api/TestService.java @@ -0,0 +1,48 @@ +package com.iflytop.gd.app.service.api; + +import com.iflytop.gd.app.model.dto.AllSensorDTO; +import com.iflytop.gd.app.service.device.DeviceStateService; +import com.iflytop.gd.hardware.exception.HardwareException; +import com.iflytop.gd.hardware.service.GDDeviceStatusService; +import com.iflytop.gd.hardware.type.IO.InputIOMId; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.List; + +/** + * 测试用 + */ +@Service +@RequiredArgsConstructor +public class TestService { + private final GDDeviceStatusService gdDeviceStatusService; + private final DeviceStateService deviceStateService; + + public List getAllSensor() throws HardwareException { + List allSensorDTOList = new ArrayList<>(); + allSensorDTOList.add(new AllSensorDTO(InputIOMId.HEAT_MODULE01_EXIST, gdDeviceStatusService.getInputState(InputIOMId.HEAT_MODULE01_EXIST))); + allSensorDTOList.add(new AllSensorDTO(InputIOMId.HEAT_MODULE02_EXIST, gdDeviceStatusService.getInputState(InputIOMId.HEAT_MODULE02_EXIST))); + allSensorDTOList.add(new AllSensorDTO(InputIOMId.HEAT_MODULE03_EXIST, gdDeviceStatusService.getInputState(InputIOMId.HEAT_MODULE03_EXIST))); + allSensorDTOList.add(new AllSensorDTO(InputIOMId.HEAT_MODULE04_EXIST, gdDeviceStatusService.getInputState(InputIOMId.HEAT_MODULE04_EXIST))); + allSensorDTOList.add(new AllSensorDTO(InputIOMId.HEAT_MODULE05_EXIST, gdDeviceStatusService.getInputState(InputIOMId.HEAT_MODULE05_EXIST))); + allSensorDTOList.add(new AllSensorDTO(InputIOMId.HEAT_MODULE06_EXIST, gdDeviceStatusService.getInputState(InputIOMId.HEAT_MODULE06_EXIST))); + allSensorDTOList.add(new AllSensorDTO(InputIOMId.HEAT_MODULE06_EXIST, gdDeviceStatusService.getInputState(InputIOMId.HEAT_MODULE06_EXIST))); + + allSensorDTOList.add(new AllSensorDTO(InputIOMId.CAP01_EXIST, gdDeviceStatusService.getInputState(InputIOMId.CAP01_EXIST))); + allSensorDTOList.add(new AllSensorDTO(InputIOMId.CAP02_EXIST, gdDeviceStatusService.getInputState(InputIOMId.CAP02_EXIST))); + allSensorDTOList.add(new AllSensorDTO(InputIOMId.CAP03_EXIST, gdDeviceStatusService.getInputState(InputIOMId.CAP03_EXIST))); + allSensorDTOList.add(new AllSensorDTO(InputIOMId.CAP04_EXIST, gdDeviceStatusService.getInputState(InputIOMId.CAP04_EXIST))); + allSensorDTOList.add(new AllSensorDTO(InputIOMId.CAP05_EXIST, gdDeviceStatusService.getInputState(InputIOMId.CAP05_EXIST))); + allSensorDTOList.add(new AllSensorDTO(InputIOMId.CAP06_EXIST, gdDeviceStatusService.getInputState(InputIOMId.CAP06_EXIST))); + + return allSensorDTOList; + } + + public void reset(){ + deviceStateService.getCommandMutexState().get().reset(); + deviceStateService.getDeviceState().reset(); + } + +} diff --git a/src/main/java/com/iflytop/gd/app/service/api/TrayService.java b/src/main/java/com/iflytop/gd/app/service/api/TrayService.java index cd2bfbc..51fb8c1 100644 --- a/src/main/java/com/iflytop/gd/app/service/api/TrayService.java +++ b/src/main/java/com/iflytop/gd/app/service/api/TrayService.java @@ -3,6 +3,7 @@ package com.iflytop.gd.app.service.api; import com.iflytop.gd.app.model.bo.status.device.TrayState; import com.iflytop.gd.app.model.vo.SetTrayTubeVO; import com.iflytop.gd.app.service.device.DeviceStateService; +import com.iflytop.gd.app.service.device.module.SolutionModuleService; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -15,6 +16,7 @@ import java.util.List; @RequiredArgsConstructor public class TrayService { private final DeviceStateService deviceStateService; + private final SolutionModuleService solutionModuleService; /** * 放入了新托盘 @@ -24,16 +26,18 @@ public class TrayService { trayState.setInSolutionModule(true); deviceStateService.getDeviceState().getTray().add(trayState); deviceStateService.getDeviceState().getSolutionModule().setTrayStatus(1); + deviceStateService.getDeviceState().getSolutionModule().setIdle(false); return trayState; } /** * 拿走了托盘 */ - public synchronized void trayOut() { + public synchronized void trayOut() throws InterruptedException { List trayList = deviceStateService.getDeviceState().getTray(); trayList.removeIf(TrayState::isInSolutionModule); deviceStateService.getDeviceState().getSolutionModule().setTrayStatus(0); + solutionModuleService.releaseSolutionModule(); } /** diff --git a/src/main/java/com/iflytop/gd/app/service/crafts/CraftsStepService.java b/src/main/java/com/iflytop/gd/app/service/crafts/CraftsStepService.java index 9bfac3e..2836a6c 100644 --- a/src/main/java/com/iflytop/gd/app/service/crafts/CraftsStepService.java +++ b/src/main/java/com/iflytop/gd/app/service/crafts/CraftsStepService.java @@ -44,18 +44,18 @@ public class CraftsStepService { /** * 执行单个工艺步骤 * - * @param heatId 加热区 ID - * @param step 工艺步骤,包括 method 和 params + * @param heatModuleCode 加热区 ID + * @param step 工艺步骤,包括 method 和 params * @return true 表示执行成功,false 表示失败 */ - public boolean executeStep(String heatId, CraftsStep step) throws Exception { + public boolean executeStep(HeatModuleCode heatModuleCode, CraftsStep step) throws Exception { String method = step.getMethod(); JSONObject params = step.getParams(); return switch (method) { - case "addLiquid" -> addLiquid(heatId, params); - case "shaking" -> shaking(heatId, params); - case "startHeating" -> heating(heatId, params); - case "takePhoto" -> takePhoto(heatId); + case "addLiquid" -> addLiquid(heatModuleCode, params); + case "shaking" -> shaking(heatModuleCode, params); + case "startHeating" -> heating(heatModuleCode, params); + case "takePhoto" -> takePhoto(heatModuleCode); default -> true; }; } @@ -63,10 +63,16 @@ public class CraftsStepService { /** * 将托盘从加热区移动至加液区并且添加溶液 */ - private boolean addLiquid(String heatId, JSONObject params) throws Exception { - HeatModuleCode heatModuleCode = HeatModuleCode.valueOf(heatId); + private boolean addLiquid(HeatModuleCode heatModuleCode, JSONObject params) throws Exception { //TODO 判断加液区是否有托盘,如果没有托盘的话,判断加热区是否有托盘,然后将其移动至加液区 - moveToSolutionModule(heatModuleCode); + if((deviceStateService.getDeviceState().getSolutionModule().getTrayStatus() == 0 ) + && deviceStateService.getDeviceState().getHeatModuleByCode(heatModuleCode).getTrayStatus() == 0) { + throw new AppException(ResultCode.CRAFT_NO_TRAY); + } + if((deviceStateService.getDeviceState().getSolutionModule().getTrayStatus() == 0 ) + && deviceStateService.getDeviceState().getHeatModuleByCode(heatModuleCode).getTrayStatus() == 1) { + moveToSolutionModule(heatModuleCode); + } JSONArray tubeSolList = params.getJSONArray("tubeSolList"); for (int i = 0; i < tubeSolList.size(); i++) { JSONObject tubeSol = tubeSolList.getJSONObject(i); @@ -80,9 +86,9 @@ public class CraftsStepService { if (acidPumpDevice == null) { throw new AppException(ResultCode.CRAFT_CONTAINER_NOT_FOUND); } - webSocketService.pushCraftsDebug(CraftsDebugGenerator.generateJson(heatId, "移动加液机械臂到指定试管", tubeNum)); + webSocketService.pushCraftsDebug(CraftsDebugGenerator.generateJson(heatModuleCode.toString(), "移动加液机械臂到指定试管", tubeNum)); solutionModuleService.dualRobotMovePoint(tubeNum);//移动加液机械臂到指定试管 - webSocketService.pushCraftsDebug(CraftsDebugGenerator.generateJson(heatId, "添加溶液", addLiquid)); + webSocketService.pushCraftsDebug(CraftsDebugGenerator.generateJson(heatModuleCode.toString(), "添加溶液", addLiquid)); solutionModuleService.acidPumpMoveBy(acidPumpDevice, volume);//添加溶液 } } @@ -93,16 +99,15 @@ public class CraftsStepService { /** * 摇匀操作 */ - private boolean shaking(String heatId, JSONObject params) throws Exception { - HeatModuleCode heatModuleCode = HeatModuleCode.valueOf(heatId); + private boolean shaking(HeatModuleCode heatModuleCode, JSONObject params) throws Exception { if (deviceStateService.getDeviceState().getSolutionModule().getTrayStatus() == 0) {//TODO 实际应该从传感器获取托盘状态 moveToSolutionModule(heatModuleCode); } Integer second = params.getInt("second"); - webSocketService.pushCraftsDebug(CraftsDebugGenerator.generateJson(heatId, "开始摇匀", params)); + webSocketService.pushCraftsDebug(CraftsDebugGenerator.generateJson(heatModuleCode.toString(), "开始摇匀", params)); solutionModuleService.shakeStart();//开始摇匀 delay(second); - webSocketService.pushCraftsDebug(CraftsDebugGenerator.generateJson(heatId, "停止摇匀", null)); + webSocketService.pushCraftsDebug(CraftsDebugGenerator.generateJson(heatModuleCode.toString(), "停止摇匀", null)); solutionModuleService.shakeStop();//停止摇匀 return true; } @@ -110,8 +115,7 @@ public class CraftsStepService { /** * 将托盘从加液区移动至加热区并开启加热 */ - private boolean heating(String heatId, JSONObject params) throws Exception { - HeatModuleCode heatModuleCode = HeatModuleCode.valueOf(heatId); + private boolean heating(HeatModuleCode heatModuleCode, JSONObject params) throws Exception { double trayLift = devicePositionService.getPosition(DevicePositionCode.trayLift).getDistance(); //获取加热位抬升托盘位置 moveToHeatModule(heatModuleCode); Double temperature = params.getDouble("temperature"); @@ -126,16 +130,15 @@ public class CraftsStepService { /** * 拍照操作· */ - private boolean takePhoto(String heatId) throws Exception { - HeatModuleCode heatModuleCode = HeatModuleCode.valueOf(heatId); + private boolean takePhoto(HeatModuleCode heatModuleCode) throws Exception { if (deviceStateService.getDeviceState().getSolutionModule().getTrayStatus() == 0) { moveToSolutionModule(heatModuleCode); } - webSocketService.pushCraftsDebug(CraftsDebugGenerator.generateJson(heatId, "开启补光灯", 100.0)); + webSocketService.pushCraftsDebug(CraftsDebugGenerator.generateJson(heatModuleCode.toString(), "开启补光灯", 100.0)); solutionModuleService.fillLightOpen(100.0);//TODO 开启补光灯 亮度从数据库获取 - webSocketService.pushCraftsDebug(CraftsDebugGenerator.generateJson(heatId, "拍照", null)); + webSocketService.pushCraftsDebug(CraftsDebugGenerator.generateJson(heatModuleCode.toString(), "拍照", null)); solutionModuleService.takePhoto();//拍照 - webSocketService.pushCraftsDebug(CraftsDebugGenerator.generateJson(heatId, "关闭补光灯", null)); + webSocketService.pushCraftsDebug(CraftsDebugGenerator.generateJson(heatModuleCode.toString(), "关闭补光灯", null)); solutionModuleService.fillLightClose();//关闭补光灯 return true; } @@ -153,6 +156,13 @@ public class CraftsStepService { } /** + * 工艺执行完毕 + */ + public void finish(HeatModuleCode heatModuleCode) throws Exception { + moveToSolutionModule(heatModuleCode); + } + + /** * 将托盘移至加热 */ private void moveToHeatModule(HeatModuleCode heatModuleCode) throws Exception { @@ -263,10 +273,10 @@ public class CraftsStepService { deviceCommandTempUtilService.moveTrayHeatModuleAvoidDown(heatModuleCode);//TODO 临时避让下降 gantryModuleService.gantryMove(heatArea4TrayClawPoint3D);//将携带托盘的机械臂移动至4号加热模块上方 gantryModuleService.gantryMove(liquidAreaTrayPoint3D); //将携带托盘的机械臂移动至加液模块上方 - deviceCommandTempUtilService.moveTrayHeatModuleAvoidDown(null);//TODO 临时避 恢复抬起状态 + deviceCommandTempUtilService.moveTrayHeatModuleAvoidUp(null, heatModuleCode);//TODO 临时避 恢复抬起状态 gantryModuleService.gantryZMove(solutionModuleTrayMoveHeight);//下降z轴,使托盘落入加液模块 // trayState.setInSolutionModule(true);//托盘是否在加液模块中 - deviceStateService.getDeviceState().getHeatModuleByCode(heatModuleCode).setTrayStatus(1);//加液模块是否存在托盘 + deviceStateService.getDeviceState().getSolutionModule().setTrayStatus(1);//加液模块是否存在托盘 gantryModuleService.clawMove(clawTrayPick);//将夹爪打开,释放托盘 gantryModuleService.gantryZMove(0);//抬升z轴 gantryModuleService.gantryMove(capStorageCapClawPoint3D);//移动机械臂至拍子存放区上方 diff --git a/src/main/java/com/iflytop/gd/app/service/device/DeviceCommandTempUtilService.java b/src/main/java/com/iflytop/gd/app/service/device/DeviceCommandTempUtilService.java index 21940d6..677b7fa 100644 --- a/src/main/java/com/iflytop/gd/app/service/device/DeviceCommandTempUtilService.java +++ b/src/main/java/com/iflytop/gd/app/service/device/DeviceCommandTempUtilService.java @@ -2,6 +2,7 @@ package com.iflytop.gd.app.service.device; import com.iflytop.gd.app.model.bo.status.device.HeatModuleState; import com.iflytop.gd.app.service.api.DevicePositionService; +import com.iflytop.gd.app.service.device.module.HeatModuleService; import com.iflytop.gd.common.command.CommandFuture; import com.iflytop.gd.common.command.DeviceCommandBundle; import com.iflytop.gd.common.command.DeviceCommandGenerator; @@ -13,8 +14,10 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.List; +import java.util.concurrent.CompletableFuture; /** * 临时方法 以后应该会废弃 @@ -24,8 +27,8 @@ import java.util.List; @RequiredArgsConstructor public class DeviceCommandTempUtilService { private final DeviceCommandService deviceCommandService; + private final HeatModuleService heatModuleService; private final DevicePositionService devicePositionService; - private final DeviceStateService deviceStateService; private final List moveTrayHeatModuleAvoidUpStateList = Collections.synchronizedList(new ArrayList<>()); @@ -35,8 +38,29 @@ public class DeviceCommandTempUtilService { * 临时移动托盘的时候,加热模块升降避让 * 该方法会恢复之前升起的状态 */ - public void moveTrayHeatModuleAvoidUp(HeatModuleCode targetHeatModuleCode) throws Exception { - moveTrayHeatModuleAvoidUp(null, null, targetHeatModuleCode); + public void moveTrayHeatModuleAvoidUp(HeatModuleCode targetHeatModuleCode, HeatModuleCode... exceptionHeatModuleCodes) throws Exception { + moveTrayHeatModuleAvoidUp(null, null, targetHeatModuleCode, exceptionHeatModuleCodes); + } + /** + * 避让抬升 + * 临时移动托盘的时候,加热模块升降避让 + * 该方法会恢复之前升起的状态 + */ + public void moveTrayHeatModuleAvoidUpNoWait(String cmdId, String cmdCode, HeatModuleCode targetHeatModuleCode, HeatModuleCode... exceptionHeatModuleCodes) throws Exception { + double trayLift = devicePositionService.getPosition(DevicePositionCode.trayLift).getDistance(); //托盘升降抬升距离 + for (HeatModuleCode heatModuleCode : moveTrayHeatModuleAvoidUpStateList) { + if (!Arrays.stream(exceptionHeatModuleCodes).toList().contains(heatModuleCode)) { + DeviceCommandBundle deviceCommand = getHeaterMotorMoveDeviceCommand(heatModuleCode, trayLift); + deviceCommandService.sendCommand(cmdId, cmdCode, deviceCommand); + } + } + if (targetHeatModuleCode != null) { + DeviceCommandBundle deviceCommand = getHeaterMotorMoveDeviceCommand(targetHeatModuleCode, trayLift); + deviceCommandService.sendCommand(cmdId, cmdCode, deviceCommand); + } + for (HeatModuleCode heatModuleCode : moveTrayHeatModuleAvoidUpStateList) { + deviceStateService.getDeviceState().getHeatModuleByCode(heatModuleCode).setTrayUp(1);//加热模块托盘升降状态 + } } /** @@ -44,13 +68,15 @@ public class DeviceCommandTempUtilService { * 临时移动托盘的时候,加热模块升降避让 * 该方法会恢复之前升起的状态 */ - public void moveTrayHeatModuleAvoidUp(String cmdId, String cmdCode, HeatModuleCode targetHeatModuleCode) throws Exception { + public void moveTrayHeatModuleAvoidUp(String cmdId, String cmdCode, HeatModuleCode targetHeatModuleCode, HeatModuleCode... exceptionHeatModuleCodes) throws Exception { double trayLift = devicePositionService.getPosition(DevicePositionCode.trayLift).getDistance(); //托盘升降抬升距离 List futuresList = new ArrayList<>(); for (HeatModuleCode heatModuleCode : moveTrayHeatModuleAvoidUpStateList) { - DeviceCommandBundle deviceCommand = getHeaterMotorMoveDeviceCommand(heatModuleCode, trayLift); - CommandFuture deviceCommandFuture = deviceCommandService.sendCommand(cmdId, cmdCode, deviceCommand); - futuresList.add(deviceCommandFuture); + if (!Arrays.stream(exceptionHeatModuleCodes).toList().contains(heatModuleCode)) { + DeviceCommandBundle deviceCommand = getHeaterMotorMoveDeviceCommand(heatModuleCode, trayLift); + CommandFuture deviceCommandFuture = deviceCommandService.sendCommand(cmdId, cmdCode, deviceCommand); + futuresList.add(deviceCommandFuture); + } } if (targetHeatModuleCode != null) { DeviceCommandBundle deviceCommand = getHeaterMotorMoveDeviceCommand(targetHeatModuleCode, trayLift); @@ -68,8 +94,8 @@ public class DeviceCommandTempUtilService { * 临时移动托盘的时候,加热模块升降避让 * 该方法会下降所有升起的加热模块并且记录 */ - public void moveTrayHeatModuleAvoidDown(HeatModuleCode targetHeatModuleCode) throws Exception { - moveTrayHeatModuleAvoidDown(null, null, targetHeatModuleCode); + public void moveTrayHeatModuleAvoidDown(HeatModuleCode targetHeatModuleCode, HeatModuleCode... exceptionHeatModuleCodes) throws Exception { + moveTrayHeatModuleAvoidDown(null, null, targetHeatModuleCode, exceptionHeatModuleCodes); } /** @@ -77,18 +103,48 @@ public class DeviceCommandTempUtilService { * 临时移动托盘的时候,加热模块升降避让 * 该方法会下降所有升起的加热模块并且记录 */ - public void moveTrayHeatModuleAvoidDown(String cmdId, String cmdCode, HeatModuleCode targetHeatModuleCode) throws Exception { + public void moveTrayHeatModuleAvoidDownNoWait(String cmdId, String cmdCode, HeatModuleCode targetHeatModuleCode, HeatModuleCode... exceptionHeatModuleCodes) throws Exception { + moveTrayHeatModuleAvoidUpStateList.clear(); + List heatModuleStateList = deviceStateService.getDeviceState().getHeatModule(); + double trayLower = devicePositionService.getPosition(DevicePositionCode.trayLower).getDistance(); //获取加热位下降托盘位置 + for (HeatModuleState heatModuleState : heatModuleStateList) { + if (!Arrays.stream(exceptionHeatModuleCodes).toList().contains(heatModuleState.getModuleCode())) { + if (heatModuleState.getTrayUp() == 1) { + HeatModuleCode heatModuleCode = heatModuleState.getModuleCode(); + DeviceCommandBundle deviceCommand = getHeaterMotorMoveDeviceCommand(heatModuleCode, trayLower); + deviceCommandService.sendCommand(cmdId, cmdCode, deviceCommand); + moveTrayHeatModuleAvoidUpStateList.add(heatModuleCode); + } + } + } + if (targetHeatModuleCode != null) { + DeviceCommandBundle deviceCommand = getHeaterMotorMoveDeviceCommand(targetHeatModuleCode, trayLower); + deviceCommandService.sendCommand(cmdId, cmdCode, deviceCommand); + } + for (HeatModuleCode heatModuleCode : moveTrayHeatModuleAvoidUpStateList) { + deviceStateService.getDeviceState().getHeatModuleByCode(heatModuleCode).setTrayUp(0);//加热模块托盘升降状态 + } + } + + /** + * 避让下降 + * 临时移动托盘的时候,加热模块升降避让 + * 该方法会下降所有升起的加热模块并且记录 + */ + public void moveTrayHeatModuleAvoidDown(String cmdId, String cmdCode, HeatModuleCode targetHeatModuleCode, HeatModuleCode... exceptionHeatModuleCodes) throws Exception { moveTrayHeatModuleAvoidUpStateList.clear(); List heatModuleStateList = deviceStateService.getDeviceState().getHeatModule(); double trayLower = devicePositionService.getPosition(DevicePositionCode.trayLower).getDistance(); //获取加热位下降托盘位置 List futuresList = new ArrayList<>(); for (HeatModuleState heatModuleState : heatModuleStateList) { - if (heatModuleState.getTrayUp() == 1) { - HeatModuleCode heatModuleCode = heatModuleState.getModuleCode(); - DeviceCommandBundle deviceCommand = getHeaterMotorMoveDeviceCommand(heatModuleCode, trayLower); - CommandFuture deviceCommandFuture = deviceCommandService.sendCommand(cmdId, cmdCode, deviceCommand); - moveTrayHeatModuleAvoidUpStateList.add(heatModuleCode); - futuresList.add(deviceCommandFuture); + if (!Arrays.stream(exceptionHeatModuleCodes).toList().contains(heatModuleState.getModuleCode())) { + if (heatModuleState.getTrayUp() == 1) { + HeatModuleCode heatModuleCode = heatModuleState.getModuleCode(); + DeviceCommandBundle deviceCommand = getHeaterMotorMoveDeviceCommand(heatModuleCode, trayLower); + CommandFuture deviceCommandFuture = deviceCommandService.sendCommand(cmdId, cmdCode, deviceCommand); + moveTrayHeatModuleAvoidUpStateList.add(heatModuleCode); + futuresList.add(deviceCommandFuture); + } } } if (targetHeatModuleCode != null) { diff --git a/src/main/java/com/iflytop/gd/app/service/device/DeviceEmergencyStopService.java b/src/main/java/com/iflytop/gd/app/service/device/DeviceEmergencyStopService.java new file mode 100644 index 0000000..921752a --- /dev/null +++ b/src/main/java/com/iflytop/gd/app/service/device/DeviceEmergencyStopService.java @@ -0,0 +1,38 @@ +package com.iflytop.gd.app.service.device; + +import com.iflytop.gd.app.core.CommandPoolManager; +import com.iflytop.gd.app.service.api.CraftsService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +/** + * 设备急停 + */ +@Slf4j +@Service +@RequiredArgsConstructor +public class DeviceEmergencyStopService { + private final DeviceStepCommandService stepCommandService; + private final DeviceStateService deviceStateService; + private final CommandPoolManager commandPoolManager; + private final CraftsService craftsService; + + /** + * 处理按下急停 + */ + public void press() throws Exception { + commandPoolManager.forceShutdownAll();//强制终止现在运行的所有指令 + craftsService.stopAllCrafts();//停止所有工艺 + stepCommandService.stopAll(); + deviceStateService.getDeviceState().setEmergencyStop(true); + } + + /** + * 处理接触急停 + */ + public void release(){ + commandPoolManager.restartExecutor(); + deviceStateService.getDeviceState().setEmergencyStop(false); + } +} diff --git a/src/main/java/com/iflytop/gd/app/service/device/DeviceInitService.java b/src/main/java/com/iflytop/gd/app/service/device/DeviceInitService.java index 7f0df37..246b874 100644 --- a/src/main/java/com/iflytop/gd/app/service/device/DeviceInitService.java +++ b/src/main/java/com/iflytop/gd/app/service/device/DeviceInitService.java @@ -1,9 +1,10 @@ package com.iflytop.gd.app.service.device; +import cn.hutool.json.JSONUtil; +import com.iflytop.gd.app.model.bo.DeviceInitializationData; import com.iflytop.gd.app.model.bo.status.device.DeviceState; import com.iflytop.gd.app.model.bo.status.device.HeatModuleState; import com.iflytop.gd.app.model.bo.status.device.SolutionContainerState; -import com.iflytop.gd.app.model.bo.DeviceInitializationData; import com.iflytop.gd.app.model.entity.Container; import com.iflytop.gd.app.model.entity.DeviceParamConfig; import com.iflytop.gd.app.service.api.ContainerService; @@ -15,12 +16,12 @@ import com.iflytop.gd.hardware.comm.can.A8kCanBusService; import com.iflytop.gd.hardware.constants.ActionOvertimeConstant; import com.iflytop.gd.hardware.drivers.DODriver.OutputIOCtrlDriver; import com.iflytop.gd.hardware.drivers.LeisaiServoDriver; +import com.iflytop.gd.hardware.drivers.LiquidDistributionArmDriver; import com.iflytop.gd.hardware.drivers.MiniServoDriver.MiniServoDriver; import com.iflytop.gd.hardware.drivers.StepMotorDriver.StepMotorCtrlDriver; import com.iflytop.gd.hardware.drivers.TricolorLightDriver; import com.iflytop.gd.hardware.exception.HardwareException; import com.iflytop.gd.hardware.type.CmdId; -import com.iflytop.gd.hardware.drivers.LiquidDistributionArmDriver; import com.iflytop.gd.hardware.type.IO.OutputIOMId; import com.iflytop.gd.hardware.type.MId; import com.iflytop.gd.hardware.type.RegIndex; @@ -59,6 +60,7 @@ public class DeviceInitService { public void init() { new Thread(() -> { try { + log.info("初始化开始"); CompletableFuture.runAsync(() -> { try { tricolorLightDriver.open(MId.TriColorLight, TricolorLightDriver.Color.BLUE); @@ -76,6 +78,7 @@ public class DeviceInitService { log.error("设备初始化灯光失败,Color.GREEN"); } deviceStateService.getDeviceState().setInitComplete(true); + log.info("初始化完毕"); } catch (Exception e) { try { tricolorLightDriver.open(MId.TriColorLight, TricolorLightDriver.Color.RED); @@ -90,6 +93,7 @@ public class DeviceInitService { * 设置各动作超时时间 */ public void initOvertime() { + log.info("初始化 initOvertime"); actionOvertimeConstant.pushNewConfig(StepMotorMId.DOOR_MOTOR_MID, CmdId.step_motor_easy_move_to_zero, 90 * 1000); actionOvertimeConstant.pushNewConfig(LeisaiServoMId.MainXSV, CmdId.step_motor_easy_move_to_zero, 300 * 1000); actionOvertimeConstant.pushNewConfig(LeisaiServoMId.MainYSV, CmdId.step_motor_easy_move_to_zero, 120 * 1000); @@ -102,12 +106,14 @@ public class DeviceInitService { actionOvertimeConstant.pushNewConfig(StepMotorMId.HEATER_6_MOTOR_MID, CmdId.step_motor_easy_move_to_zero, 60 * 1000); actionOvertimeConstant.pushNewConfig(StepMotorMId.TRAY_MOTOR_MID, CmdId.step_motor_easy_move_to_zero, 300 * 1000); actionOvertimeConstant.pushNewConfig(LiquidArmMId.LiquidDistributionArm, CmdId.liquid_distribution_arm_move_to, 6 * 1000); + log.info("初始化 initOvertime完毕"); } /** * 初始化所有设备使能 */ public void initEnable() throws Exception { + log.info("初始化 initEnable"); stepMotorCtrlDriver.stepMotorEnable(StepMotorMId.DOOR_MOTOR_MID, 1); stepMotorCtrlDriver.stepMotorEnable(StepMotorMId.SHAKE_MOTOR_MID, 1); stepMotorCtrlDriver.stepMotorEnable(StepMotorMId.TRAY_MOTOR_MID, 1); @@ -126,29 +132,32 @@ public class DeviceInitService { outputIOCtrlDriver.open(OutputIOMId.DO_HBOTZ_MOTOR_CLAMP); outputIOCtrlDriver.open(OutputIOMId.DO_TRAY_MOTOR_CLAMP); + log.info("初始化 initEnable完毕"); } public void initDeviceSetData() throws Exception { if (deviceStateService.getDeviceState().isVirtual() || deviceStateService.getDeviceState().isInitComplete()) { return; } + log.info("初始化 initDeviceSetData"); //从数据库中读取数据通过串口进行数据初始化 List deviceParamConfigs = deviceParamConfigService.list(); - for (DeviceParamConfig deviceParamConfig : deviceParamConfigs) { - DeviceInitializationData data = new DeviceInitializationData(); - data.setId(Math.toIntExact(deviceParamConfig.getId())); - data.setMid(deviceParamConfig.getMid()); - data.setRegIndex(deviceParamConfig.getRegIndex()); - data.setRegInitVal(deviceParamConfig.getRegVal()); - try { + try { + for (DeviceParamConfig deviceParamConfig : deviceParamConfigs) { + DeviceInitializationData data = new DeviceInitializationData(); + data.setId(Math.toIntExact(deviceParamConfig.getId())); + data.setMid(deviceParamConfig.getMid()); + data.setRegIndex(deviceParamConfig.getRegIndex()); + data.setRegInitVal(deviceParamConfig.getRegVal()); + log.info("初始化 initDeviceSetData: {}", JSONUtil.toJsonStr(data)); sendToDevice(data); - } catch (Exception e) { - log.error("设备初始化写入参数失败,2秒后重试", e); - Thread.sleep(2000); - initDeviceSetData(); } + } catch (Exception e) { + log.error("设备初始化写入参数失败,2秒后重试", e); + Thread.sleep(2000); + initDeviceSetData(); } - + log.info("初始化 initDeviceSetData完毕"); } public void sendToDevice(DeviceInitializationData data) throws Exception { @@ -156,6 +165,7 @@ public class DeviceInitService { } public void initDeviceState() { + log.info("初始化 initDeviceState"); DeviceState deviceState = deviceStateService.getDeviceState(); List heatArea = deviceState.getHeatModule(); for (HeatModuleCode code : HeatModuleCode.values()) { @@ -171,5 +181,6 @@ public class DeviceInitService { solutionBucket.add(solutionContainerStateProvider.getObject(container.getId(), ContainerCode.valueOf(container.getCode()), ContainerType.neutralization)); } } + log.info("初始化 initDeviceState完毕"); } } diff --git a/src/main/java/com/iflytop/gd/app/service/device/DeviceStateService.java b/src/main/java/com/iflytop/gd/app/service/device/DeviceStateService.java index 40093fb..66158b5 100644 --- a/src/main/java/com/iflytop/gd/app/service/device/DeviceStateService.java +++ b/src/main/java/com/iflytop/gd/app/service/device/DeviceStateService.java @@ -2,7 +2,7 @@ package com.iflytop.gd.app.service.device; import com.iflytop.gd.app.model.bo.status.CommandMutexState; import com.iflytop.gd.app.model.bo.status.device.DeviceState; -import lombok.Getter; +import lombok.Data; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -11,13 +11,12 @@ import java.util.concurrent.atomic.AtomicReference; /** * 设备状态服务 */ +@Data @Service @RequiredArgsConstructor public class DeviceStateService { - @Getter private final DeviceState deviceState; - @Getter private final AtomicReference commandMutexState = new AtomicReference<>(new CommandMutexState()); } diff --git a/src/main/java/com/iflytop/gd/app/service/device/module/CapModuleService.java b/src/main/java/com/iflytop/gd/app/service/device/module/CapModuleService.java index 7a190b7..10e9609 100644 --- a/src/main/java/com/iflytop/gd/app/service/device/module/CapModuleService.java +++ b/src/main/java/com/iflytop/gd/app/service/device/module/CapModuleService.java @@ -1,7 +1,7 @@ package com.iflytop.gd.app.service.device.module; -import com.iflytop.gd.app.service.device.DeviceCommandService; import com.iflytop.gd.app.service.api.DevicePositionService; +import com.iflytop.gd.app.service.device.DeviceCommandService; import com.iflytop.gd.common.command.CommandFuture; import com.iflytop.gd.common.command.DeviceCommandBundle; import com.iflytop.gd.common.command.DeviceCommandGenerator; @@ -35,49 +35,133 @@ public class CapModuleService { } /** - * 将拍子升降区抬升至可以获取的位置 + * 将拍子升降区抬升至可以获取的位置 不等待 */ - public void capUpBalance(String commandId, String command) throws Exception { - Integer capNum = null; + public void capUpBalanceNoWait(String commandId, String command) throws Exception { Boolean capExist01 = gdDeviceStatusService.getInputState(InputIOMId.CAP01_EXIST); - if (capExist01 != null && capExist01) { - capNum = 0; - } else { - Boolean capExist02 = gdDeviceStatusService.getInputState(InputIOMId.CAP02_EXIST); - if (capExist02 != null && capExist02) { - capNum = 1; - } else { - Boolean capExist03 = gdDeviceStatusService.getInputState(InputIOMId.CAP03_EXIST); - if (capExist03 != null && capExist03) { - capNum = 2; - } else { - Boolean capExist04 = gdDeviceStatusService.getInputState(InputIOMId.CAP04_EXIST); - if (capExist04 != null && capExist04) { - capNum = 3; - } else { - Boolean capExist05 = gdDeviceStatusService.getInputState(InputIOMId.CAP05_EXIST); - if (capExist05 != null && capExist05) { - capNum = 4; - } else { - Boolean capExist06 = gdDeviceStatusService.getInputState(InputIOMId.CAP06_EXIST); - if (capExist06 != null && capExist06) { - capNum = 5; - } - } - } - } + Boolean capExist02 = gdDeviceStatusService.getInputState(InputIOMId.CAP02_EXIST); + Boolean capExist03 = gdDeviceStatusService.getInputState(InputIOMId.CAP03_EXIST); + Boolean capExist04 = gdDeviceStatusService.getInputState(InputIOMId.CAP04_EXIST); + Boolean capExist05 = gdDeviceStatusService.getInputState(InputIOMId.CAP05_EXIST); + Boolean capExist06 = gdDeviceStatusService.getInputState(InputIOMId.CAP06_EXIST); + //如果传感器读数存在null,则视为异常 + if (capExist01 == null || capExist02 == null || capExist03 == null || capExist04 == null || capExist05 == null || capExist06 == null) { + log.error("拍子存放区获取传感器状态异常"); + throw new AppException(ResultCode.SENSOR_STATUS_FAILED); + } + //先统计拍子个数 + int capNum = 0; + if (capExist01) { + return; + } + if (capExist02) { + capNum++; + } + if (capExist03) { + capNum++; + } + if (capExist04) { + capNum++; + if (capExist02 && !capExist03) { + throw new AppException(ResultCode.SENSOR_STATUS_FAILED); + } + } + if (capExist05) { + capNum++; + if (capExist03 && !capExist04) { + throw new AppException(ResultCode.SENSOR_STATUS_FAILED); } } - if (capNum == null) { + if (capExist06) { + capNum++; + if (capExist04 && !capExist05) { + throw new AppException(ResultCode.SENSOR_STATUS_FAILED); + } + } + if (capNum == 0) { + throw new AppException(ResultCode.CAP_MODULE_NO_CAP); + } + double capLiftingHeight = devicePositionService.getPosition(DevicePositionCode.capLiftingHeight).getDistance();//每个拍子高度 + double capLiftingHeightSum = (6 - capNum) * capLiftingHeight + 21; + //先留一个空位置,不要完全抬升,防止有传感器坏了的情况,使用第二个传感器做校验 + DeviceCommandBundle deviceCommand = DeviceCommandGenerator.capMotorMove(capLiftingHeightSum); + deviceCommandService.sendCommand(commandId, command, deviceCommand); + } + + /** + * 将拍子升降区抬升至可以获取的位置 + */ + public void capUpBalance(String commandId, String command) throws Exception { + Boolean capExist01 = gdDeviceStatusService.getInputState(InputIOMId.CAP01_EXIST); + Boolean capExist02 = gdDeviceStatusService.getInputState(InputIOMId.CAP02_EXIST); + Boolean capExist03 = gdDeviceStatusService.getInputState(InputIOMId.CAP03_EXIST); + Boolean capExist04 = gdDeviceStatusService.getInputState(InputIOMId.CAP04_EXIST); + Boolean capExist05 = gdDeviceStatusService.getInputState(InputIOMId.CAP05_EXIST); + Boolean capExist06 = gdDeviceStatusService.getInputState(InputIOMId.CAP06_EXIST); + //如果传感器读数存在null,则视为异常 + if (capExist01 == null || capExist02 == null || capExist03 == null || capExist04 == null || capExist05 == null || capExist06 == null) { log.error("拍子存放区获取传感器状态异常"); throw new AppException(ResultCode.SENSOR_STATUS_FAILED); } - - double capLiftingHeight = devicePositionService.getPosition(DevicePositionCode.capLiftingHeight).getDistance(); - double capLiftingHeightSum = capNum * capLiftingHeight + 20; + //先统计拍子个数 + int capNum = 0; + if (capExist01) { + return; + } + if (capExist02) { + capNum++; + } + if (capExist03) { + capNum++; + } + if (capExist04) { + capNum++; + if (capExist02 && !capExist03) { + throw new AppException(ResultCode.SENSOR_STATUS_FAILED); + } + } + if (capExist05) { + capNum++; + if (capExist03 && !capExist04) { + throw new AppException(ResultCode.SENSOR_STATUS_FAILED); + } + } + if (capExist06) { + capNum++; + if (capExist04 && !capExist05) { + throw new AppException(ResultCode.SENSOR_STATUS_FAILED); + } + } + if (capNum == 0) { + throw new AppException(ResultCode.CAP_MODULE_NO_CAP); + } + double capLiftingHeight = devicePositionService.getPosition(DevicePositionCode.capLiftingHeight).getDistance();//每个拍子高度 + double capLiftingHeightSum = (5 - capNum) * capLiftingHeight + 21; + //先留一个空位置,不要完全抬升,防止有传感器坏了的情况,使用第二个传感器做校验 DeviceCommandBundle deviceCommand = DeviceCommandGenerator.capMotorMove(capLiftingHeightSum); CommandFuture deviceCommandFuture = deviceCommandService.sendCommand(commandId, command, deviceCommand); CommandUtil.wait(deviceCommandFuture); + capExist01 = gdDeviceStatusService.getInputState(InputIOMId.CAP01_EXIST); + capExist02 = gdDeviceStatusService.getInputState(InputIOMId.CAP02_EXIST); + if(capExist01 == null || capExist02 == null){ + log.error("拍子存放区获取传感器状态异常"); + throw new AppException(ResultCode.SENSOR_STATUS_FAILED); + } + if (!capExist02 || capExist01) {//此时第二个传感器应该是true,第一个应该是false,如果不正确代表传感器损坏或读数错误 + log.error("拍子存放区获取传感器状态异常"); + throw new AppException(ResultCode.SENSOR_STATUS_FAILED); + } + //传感器校验正确,继续提升 + capLiftingHeightSum = (6 - capNum) * capLiftingHeight + 21; + DeviceCommandBundle continueDeviceCommand = DeviceCommandGenerator.capMotorMove(capLiftingHeightSum); + CommandFuture continueDeviceCommandFuture = deviceCommandService.sendCommand(commandId, command, continueDeviceCommand); + CommandUtil.wait(continueDeviceCommandFuture); + //提升完毕再次校验第一个传感器,此时应该有读数 + capExist01 = gdDeviceStatusService.getInputState(InputIOMId.CAP01_EXIST); + if (capExist01 == null || !capExist01) { + log.error("拍子存放区获取传感器状态异常"); + throw new AppException(ResultCode.SENSOR_STATUS_FAILED); + } } /** @@ -94,6 +178,22 @@ public class CapModuleService { * * @param num 1为上升1格,-1为下降1格 */ + public void capMotorMoveByNumNoWait(String commandId, String command, int num) throws Exception { + double capLiftingHeight = devicePositionService.getPosition(DevicePositionCode.capLiftingHeight).getDistance(); + Double capPosition = gdDeviceStatusService.getStepMotorPostion(StepMotorMId.TRAY_MOTOR_MID); + double toCapPosition = capPosition + (num * capLiftingHeight); + if (toCapPosition < 0) { + throw new AppException(ResultCode.CAP_LIFT_ERROR); + } + DeviceCommandBundle deviceCommand = DeviceCommandGenerator.capMotorMove(toCapPosition); + deviceCommandService.sendCommand(commandId, command, deviceCommand); + } + + /** + * 调整拍子升降电机位置 + * + * @param num 1为上升1格,-1为下降1格 + */ public void capMotorMoveByNum(String commandId, String command, int num) throws Exception { double capLiftingHeight = devicePositionService.getPosition(DevicePositionCode.capLiftingHeight).getDistance(); Double capPosition = gdDeviceStatusService.getStepMotorPostion(StepMotorMId.TRAY_MOTOR_MID); diff --git a/src/main/java/com/iflytop/gd/app/service/device/module/HeatModuleService.java b/src/main/java/com/iflytop/gd/app/service/device/module/HeatModuleService.java index 661020d..020ee55 100644 --- a/src/main/java/com/iflytop/gd/app/service/device/module/HeatModuleService.java +++ b/src/main/java/com/iflytop/gd/app/service/device/module/HeatModuleService.java @@ -1,9 +1,11 @@ package com.iflytop.gd.app.service.device.module; import com.iflytop.gd.app.model.bo.Point3D; +import com.iflytop.gd.app.model.bo.status.device.HeatModuleState; import com.iflytop.gd.app.model.entity.DevicePosition; -import com.iflytop.gd.app.service.device.DeviceCommandService; import com.iflytop.gd.app.service.api.DevicePositionService; +import com.iflytop.gd.app.service.device.DeviceCommandService; +import com.iflytop.gd.app.service.device.DeviceStateService; import com.iflytop.gd.common.command.CommandFuture; import com.iflytop.gd.common.command.DeviceCommandBundle; import com.iflytop.gd.common.command.DeviceCommandGenerator; @@ -27,6 +29,7 @@ public class HeatModuleService { private final DeviceCommandService deviceCommandService; private final DevicePositionService devicePositionService; private final GDDeviceStatusService gdDeviceStatusService; + private final DeviceStateService deviceStateService; /** * 加热模块升降电机移动到指定位置 @@ -164,12 +167,12 @@ public class HeatModuleService { */ public Boolean heatModuleSensorState(HeatModuleCode heatModuleCode) throws HardwareException { return switch (heatModuleCode) { - case heat_module_01 -> gdDeviceStatusService.getInputState(InputIOMId.HEAT_MODULE01_EXIST); - case heat_module_02 -> gdDeviceStatusService.getInputState(InputIOMId.HEAT_MODULE02_EXIST); - case heat_module_03 -> gdDeviceStatusService.getInputState(InputIOMId.HEAT_MODULE03_EXIST); - case heat_module_04 -> gdDeviceStatusService.getInputState(InputIOMId.HEAT_MODULE04_EXIST); - case heat_module_05 -> gdDeviceStatusService.getInputState(InputIOMId.HEAT_MODULE05_EXIST); - case heat_module_06 -> gdDeviceStatusService.getInputState(InputIOMId.HEAT_MODULE06_EXIST); + case heat_module_01 -> gdDeviceStatusService.getInputState(InputIOMId.HEAT_MODULE04_EXIST); + case heat_module_02 -> gdDeviceStatusService.getInputState(InputIOMId.HEAT_MODULE05_EXIST); + case heat_module_03 -> gdDeviceStatusService.getInputState(InputIOMId.HEAT_MODULE06_EXIST); + case heat_module_04 -> gdDeviceStatusService.getInputState(InputIOMId.HEAT_MODULE01_EXIST); + case heat_module_05 -> gdDeviceStatusService.getInputState(InputIOMId.HEAT_MODULE02_EXIST); + case heat_module_06 -> gdDeviceStatusService.getInputState(InputIOMId.HEAT_MODULE03_EXIST); }; } @@ -205,4 +208,16 @@ public class HeatModuleService { return devicePosition.getPoint3D(); } + /** + * 获取一个空闲加热区 + */ + public HeatModuleState getIdleHeatModule() { + for (HeatModuleState heatModuleState : deviceStateService.getDeviceState().getHeatModule()) { + if(heatModuleState.getTrayStatus() == 0 && !heatModuleState.isCapExist()){ + return heatModuleState; + } + } + return null; + } + } diff --git a/src/main/java/com/iflytop/gd/app/service/device/module/SolutionModuleService.java b/src/main/java/com/iflytop/gd/app/service/device/module/SolutionModuleService.java index b776779..1c7f3bd 100644 --- a/src/main/java/com/iflytop/gd/app/service/device/module/SolutionModuleService.java +++ b/src/main/java/com/iflytop/gd/app/service/device/module/SolutionModuleService.java @@ -20,8 +20,6 @@ import org.springframework.stereotype.Service; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantLock; /** * 加液模块 @@ -35,7 +33,6 @@ public class SolutionModuleService { private final LiquidDistributionArmDriver liquidDistributionArmDriver; private final WebSocketSender webSocketService; - private final Lock moduleLock = new ReentrantLock(); private final BlockingQueue waitingQueue = new ArrayBlockingQueue<>(1); /** @@ -48,8 +45,9 @@ public class SolutionModuleService { /** * 申请使用加液模块 */ - public void requestSolutionModule(String commandId, String command) { + public synchronized void requestSolutionModule(String commandId, String command) { try { + log.info("申请使用加液模块"); // 如果加液模块繁忙,加入队列等待 while (!deviceStateService.getDeviceState().getSolutionModule().isIdle()) { if (commandId != null && command != null) { @@ -59,7 +57,8 @@ public class SolutionModuleService { // 把当前线程放到队列中等待 waitingQueue.put(Thread.currentThread()); // 阻塞当前线程直到被唤醒 } - occupySolutionModule(); + deviceStateService.getDeviceState().getSolutionModule().setIdle(false); + log.info("加液模块申请成功"); } catch (InterruptedException e) { Thread.currentThread().interrupt(); throw new RuntimeException("等待加液区空闲错误", e); @@ -67,43 +66,32 @@ public class SolutionModuleService { } /** - * 占用加液模块 - */ - private void occupySolutionModule() { - moduleLock.lock(); - deviceStateService.getDeviceState().getSolutionModule().setIdle(false); - } - - /** * 释放加液区 */ - public void releaseSolutionModule() throws InterruptedException { - try { - deviceStateService.getDeviceState().getSolutionModule().setIdle(true); - // 唤醒队列中的第一个线程 - if (!waitingQueue.isEmpty()) { - Thread waitingThread = waitingQueue.take(); - synchronized (waitingThread) { - waitingThread.notify(); // 唤醒队列中的第一个等待线程 - } + public synchronized void releaseSolutionModule() throws InterruptedException { + deviceStateService.getDeviceState().getSolutionModule().setIdle(true); + // 唤醒队列中的第一个线程 + if (!waitingQueue.isEmpty()) { + Thread waitingThread = waitingQueue.take(); + synchronized (waitingThread) { + waitingThread.notify(); // 唤醒队列中的第一个等待线程 } - } finally { - moduleLock.unlock(); } } + /** * 双轴械臂 移动至指定试管 */ public void dualRobotMovePoint(int index) throws Exception { - liquidDistributionArmDriver.liquidDistributionArmMoveTo(LiquidArmMId.LiquidDistributionArm, index); + liquidDistributionArmDriver.liquidDistributionArmMoveToBlock(LiquidArmMId.LiquidDistributionArm, index); } /** * 加液机械臂回原点 */ public void dualRobotOrigin() throws Exception { - liquidDistributionArmDriver.liquidDistributionArmMoveTo(LiquidArmMId.LiquidDistributionArm, 0); + liquidDistributionArmDriver.liquidDistributionArmMoveToBlock(LiquidArmMId.LiquidDistributionArm, 0); } /** @@ -204,7 +192,7 @@ public class SolutionModuleService { /** * 添加溶液 */ - public void acidPumpMoveBy(String commandId, String command, AcidPumpDeviceCode acidPumpDevice, double position) throws Exception { + public CommandFuture acidPumpMoveBy(String commandId, String command, AcidPumpDeviceCode acidPumpDevice, double position) throws Exception { DeviceCommandBundle deviceCommand; switch (acidPumpDevice) { case acid_pump_01 -> { @@ -233,8 +221,7 @@ public class SolutionModuleService { } default -> throw new RuntimeException("index 未找到"); } - CommandFuture deviceCommandFuture = deviceCommandService.sendCommand(commandId, command, deviceCommand); - CommandUtil.wait(deviceCommandFuture); + return deviceCommandService.sendCommand(commandId, command, deviceCommand); } /** diff --git a/src/main/java/com/iflytop/gd/app/service/scheduled/FetchTemperatureScheduledTask.java b/src/main/java/com/iflytop/gd/app/service/scheduled/FetchTemperatureScheduledTask.java index 57fbac4..63b8278 100644 --- a/src/main/java/com/iflytop/gd/app/service/scheduled/FetchTemperatureScheduledTask.java +++ b/src/main/java/com/iflytop/gd/app/service/scheduled/FetchTemperatureScheduledTask.java @@ -42,12 +42,12 @@ public class FetchTemperatureScheduledTask { deviceStateService.getDeviceState().getHeatModuleByCode(HeatModuleCode.heat_module_06).setTemperature(heatModule06Temperature); } else {//虚拟模式随便写个值 - List heatModuleStateList = deviceStateService.getDeviceState().getHeatModule(); - for (HeatModuleState heatModuleState : heatModuleStateList) { - if (heatModuleState.isHeating()) { - deviceStateService.getDeviceState().getHeatModuleByCode(heatModuleState.getModuleCode()).setTemperature(123.0); - } - } +// List heatModuleStateList = deviceStateService.getDeviceState().getHeatModule(); +// for (HeatModuleState heatModuleState : heatModuleStateList) { +// if (heatModuleState.isHeating()) { +// deviceStateService.getDeviceState().getHeatModuleByCode(heatModuleState.getModuleCode()).setTemperature(123.0); +// } +// } } } catch (Exception e) { log.error("定时采集加热棒温度错误", e); diff --git a/src/main/java/com/iflytop/gd/app/ws/client/DeviceEmergencyStopConfig.java b/src/main/java/com/iflytop/gd/app/ws/client/DeviceEmergencyStopConfig.java index 16a5e82..7123e2c 100644 --- a/src/main/java/com/iflytop/gd/app/ws/client/DeviceEmergencyStopConfig.java +++ b/src/main/java/com/iflytop/gd/app/ws/client/DeviceEmergencyStopConfig.java @@ -1,6 +1,8 @@ package com.iflytop.gd.app.ws.client; import com.iflytop.gd.app.core.CommandPoolManager; +import com.iflytop.gd.app.service.api.CraftsService; +import com.iflytop.gd.app.service.device.DeviceEmergencyStopService; import com.iflytop.gd.app.service.device.DeviceStateService; import com.iflytop.gd.app.service.device.DeviceStepCommandService; import lombok.RequiredArgsConstructor; @@ -15,9 +17,8 @@ import java.net.URI; @Configuration @RequiredArgsConstructor public class DeviceEmergencyStopConfig { - private final DeviceStepCommandService stepCommandService; - private final DeviceStateService deviceStateService; - private final CommandPoolManager commandPoolManager; + private final DeviceEmergencyStopService deviceEmergencyStopService; + @Value("${iflytophald.ip}") String ip; @@ -32,15 +33,13 @@ public class DeviceEmergencyStopConfig { if (s.get("event").equals("press")) { log.info("触发急停{}", s); try { - commandPoolManager.forceShutdownAll();//强制终止现在运行的所有指令 - stepCommandService.stopAll(); - deviceStateService.getDeviceState().setEmergencyStop(true); + deviceEmergencyStopService.press(); } catch (Exception e) { log.error("设备急停失败:{}", e.getMessage()); throw new RuntimeException(e); } } else if (s.get("event").equals("release")) { - deviceStateService.getDeviceState().setEmergencyStop(false); + deviceEmergencyStopService.release(); log.info("解除急停{}", s); } }); diff --git a/src/main/java/com/iflytop/gd/common/enums/HeatingType.java b/src/main/java/com/iflytop/gd/common/enums/HeatingType.java new file mode 100644 index 0000000..dd0c4b2 --- /dev/null +++ b/src/main/java/com/iflytop/gd/common/enums/HeatingType.java @@ -0,0 +1,13 @@ +package com.iflytop.gd.common.enums; + +import lombok.Getter; + +/** + * 加热状态类型 + */ +@Getter +public enum HeatingType { + stop, + warm_up, + thermostatic, +} diff --git a/src/main/java/com/iflytop/gd/common/result/ResultCode.java b/src/main/java/com/iflytop/gd/common/result/ResultCode.java index 9e8f150..3a53727 100644 --- a/src/main/java/com/iflytop/gd/common/result/ResultCode.java +++ b/src/main/java/com/iflytop/gd/common/result/ResultCode.java @@ -40,6 +40,7 @@ public enum ResultCode implements IResultCode, Serializable { CRAFT_RUNNING("4101", "工艺正在执行"), CRAFT_CONTEXT_NULL("4102", "请先配置该加热区工艺"), CRAFT_CONTAINER_NOT_FOUND("4005", "工艺未找到对应溶液容器"), + CRAFT_NO_TRAY("4005", "工艺未找到托盘"), //============================ 5xxx:系统 & 第三方 ============================ SYSTEM_ERROR("5000", "系统内部错误"), SERVICE_UNAVAILABLE("5001", "服务暂不可用"), @@ -47,7 +48,7 @@ public enum ResultCode implements IResultCode, Serializable { COMMAND_EXEC_TIMEOUT("5003", "命令执行超时"), HARDWARE_ERROR("5004", "硬件错误"), EMERGENCY_STOP("5555", "设备急停中"), - //============================ 6xxx:指令相关 ============================ + //============================ 6xxx:设备、指令相关 ============================ COMMAND_NOT_FOUND("6000", "指令未找到"), COMMAND_ALREADY_EXECUTING("6001", "指令正在执行,无法重复执行"), SENSOR_STATUS_FAILED("6010", "获取传感器状态失败"), @@ -56,6 +57,9 @@ public enum ResultCode implements IResultCode, Serializable { SOLUTION_MODULE_NO_TRAY("6023", "加液模块无托盘"), CAP_LIFT_ERROR("6024", "拍子升降错误"), CMD_BUSY("6025", "设备忙,请稍后"), + HEAT_MODULE_NO_IDLE("6026", "加热模块无空闲"), + CAP_MODULE_NO_CAP("6027", "拍子存放区未检测到拍子"), + SOLUTION_MODULE_OCCUPIED("6028", "加液模块被占用"), ; /** 状态码 */ private final String code; diff --git a/src/main/java/com/iflytop/gd/monitor/controller/CraftsMonitorController.java b/src/main/java/com/iflytop/gd/monitor/controller/CraftsMonitorController.java index 6ee701e..b5d47b3 100644 --- a/src/main/java/com/iflytop/gd/monitor/controller/CraftsMonitorController.java +++ b/src/main/java/com/iflytop/gd/monitor/controller/CraftsMonitorController.java @@ -2,6 +2,7 @@ package com.iflytop.gd.monitor.controller; import com.iflytop.gd.app.model.vo.CraftStatusVO; import com.iflytop.gd.app.service.api.CraftsService; +import com.iflytop.gd.common.enums.HeatModuleCode; import com.iflytop.gd.common.result.Result; import com.iflytop.gd.common.result.ResultCode; import io.swagger.v3.oas.annotations.Operation; @@ -27,10 +28,9 @@ public class CraftsMonitorController { private final CraftsService craftsService; @Operation(summary = "获取某个加热区工艺状态") - @GetMapping("/status/{heatId}") - public Result getStatus( - @NotNull @PathVariable String heatId) { - CraftStatusVO vo = craftsService.getStatus(heatId); + @GetMapping("/status/{heatModuleCode}") + public Result getStatus(@NotNull @PathVariable HeatModuleCode heatModuleCode) { + CraftStatusVO vo = craftsService.getStatus(heatModuleCode); if (vo == null) { return Result.failed(ResultCode.NOT_FOUND, "未找到执行任务"); }