Browse Source

同步现场代码

master
白凤吉 2 months ago
parent
commit
5d1d9cc6f6
  1. 2
      src/main/java/com/iflytop/gd/app/command/control/DoorCloseCommand.java
  2. 4
      src/main/java/com/iflytop/gd/app/command/control/DoorOpenCommand.java
  3. 31
      src/main/java/com/iflytop/gd/app/command/control/FilledSolutionStopCommand.java
  4. 8
      src/main/java/com/iflytop/gd/app/command/control/SolutionAddCommand.java
  5. 4
      src/main/java/com/iflytop/gd/app/command/debug/DebugDoorOpenCommand.java
  6. 64
      src/main/java/com/iflytop/gd/app/command/debug/step/DebugShowSmogCommand.java
  7. 2
      src/main/java/com/iflytop/gd/app/controller/CraftsController.java
  8. 22
      src/main/java/com/iflytop/gd/app/controller/SystemController.java
  9. 26
      src/main/java/com/iflytop/gd/app/controller/TestController.java
  10. 13
      src/main/java/com/iflytop/gd/app/core/CraftsContext.java
  11. 2
      src/main/java/com/iflytop/gd/app/core/aspect/DeviceStateChangeAspect.java
  12. 10
      src/main/java/com/iflytop/gd/app/model/bo/status/device/CraftsState.java
  13. 18
      src/main/java/com/iflytop/gd/app/model/bo/status/device/DeviceState.java
  14. 3
      src/main/java/com/iflytop/gd/app/model/bo/status/device/HeatModuleState.java
  15. 14
      src/main/java/com/iflytop/gd/app/model/bo/status/device/TrayState.java
  16. 3
      src/main/java/com/iflytop/gd/app/model/bo/status/device/TubeState.java
  17. 3
      src/main/java/com/iflytop/gd/app/model/dto/StartCraftsDTO.java
  18. 2
      src/main/java/com/iflytop/gd/app/model/vo/SetTrayTubeVO.java
  19. 65
      src/main/java/com/iflytop/gd/app/service/api/CraftsService.java
  20. 2
      src/main/java/com/iflytop/gd/app/service/api/SystemConfigService.java
  21. 5
      src/main/java/com/iflytop/gd/app/service/api/TestService.java
  22. 5
      src/main/java/com/iflytop/gd/app/service/api/TrayService.java
  23. 62
      src/main/java/com/iflytop/gd/app/service/crafts/CraftsStepService.java
  24. 18
      src/main/java/com/iflytop/gd/app/service/device/DeviceCommandTempUtilService.java
  25. 2
      src/main/java/com/iflytop/gd/app/service/device/DeviceEmergencyStopService.java
  26. 10
      src/main/java/com/iflytop/gd/app/service/device/DeviceStepCommandService.java
  27. 18
      src/main/java/com/iflytop/gd/app/service/device/module/CapModuleService.java
  28. 9
      src/main/java/com/iflytop/gd/app/service/device/module/DoorModuleService.java
  29. 2
      src/main/java/com/iflytop/gd/app/service/device/module/GantryModuleService.java
  30. 54
      src/main/java/com/iflytop/gd/app/service/device/module/SolutionModuleService.java
  31. 16
      src/main/java/com/iflytop/gd/app/service/scheduled/FetchTemperatureScheduledTask.java
  32. 66
      src/main/java/com/iflytop/gd/app/service/scheduled/HeatCountdownScheduledTask.java
  33. 4
      src/main/java/com/iflytop/gd/app/ws/client/DeviceEmergencyStopConfig.java
  34. 2
      src/main/java/com/iflytop/gd/app/ws/server/WebSocketSender.java
  35. 8
      src/main/java/com/iflytop/gd/common/command/DeviceCommandGenerator.java
  36. 4
      src/main/java/com/iflytop/gd/common/enums/HeatingType.java
  37. 2
      src/main/java/com/iflytop/gd/common/enums/command/CmdAction.java
  38. 3
      src/main/java/com/iflytop/gd/common/result/ResultCode.java
  39. 9
      src/main/java/com/iflytop/gd/common/utils/LocalDateTimeUtil.java
  40. 25
      src/main/java/com/iflytop/gd/hardware/command/handlers/DoorHandler.java
  41. 5
      src/main/java/com/iflytop/gd/hardware/drivers/StepMotorDriver/DoorDriver.java
  42. 2
      src/main/resources/application-dev.yml
  43. 8
      src/main/resources/sql/init.sql

2
src/main/java/com/iflytop/gd/app/command/control/DoorCloseCommand.java

@ -26,7 +26,7 @@ public class DoorCloseCommand extends BaseCommandHandler {
public CompletableFuture<Void> handle(CmdDTO cmdDTO) {
return runAsync(() -> {
deviceStateService.getDeviceState().getDoor().setOpen(false);
doorModuleService.doorMove(cmdDTO.getCommandId(), cmdDTO.getCommand(), 0);
doorModuleService.doorOrigin(cmdDTO.getCommandId(), cmdDTO.getCommand());
});
}
}

4
src/main/java/com/iflytop/gd/app/command/control/DoorOpenCommand.java

@ -22,15 +22,13 @@ import java.util.concurrent.CompletableFuture;
@CommandMapping("door_open")//业务指令注解
public class DoorOpenCommand extends BaseCommandHandler {
private final DoorModuleService doorModuleService;
private final DevicePositionService devicePositionService;
private final DeviceStateService deviceStateService;
@Override
public CompletableFuture<Void> handle(CmdDTO cmdDTO) {
return runAsync(() -> {
Double doorOpenDistance = devicePositionService.getPosition(DevicePositionCode.doorOpen).getDistance();
deviceStateService.getDeviceState().getDoor().setOpen(true);
doorModuleService.doorMove(cmdDTO.getCommandId(), cmdDTO.getCommand(), doorOpenDistance);
doorModuleService.doorMoveEnd(cmdDTO.getCommandId(), cmdDTO.getCommand());
});
}
}

31
src/main/java/com/iflytop/gd/app/command/control/FilledSolutionStopCommand.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.ContainerService;
@ -27,18 +26,26 @@ public class FilledSolutionStopCommand extends BaseCommandHandler {
@Override
public CompletableFuture<Void> 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(() -> {
try {
AcidPumpDeviceCode acidPumpDevice = containerService.getPumpByContainerId(Long.parseLong(idStr));
solutionModuleService.acidPumpStop(cmdDTO.getCommandId(), cmdDTO.getCommand(), acidPumpDevice);
} catch (Exception e) {
log.error("停止预充失败", e);
}
});
// JSONArray idJsonArray = cmdDTO.getJSONArrayParam("list");
// for (int i = 0; i < idJsonArray.size(); i++) {
// String idStr = idJsonArray.getStr(i);
// CompletableFuture.runAsync(() -> {
// try {
// AcidPumpDeviceCode acidPumpDevice = containerService.getPumpByContainerId(Long.parseLong(idStr));
// solutionModuleService.acidPumpStop(cmdDTO.getCommandId(), cmdDTO.getCommand(), acidPumpDevice);
// } catch (Exception e) {
// log.error("停止预充失败", e);
// }
// });
// }
for (AcidPumpDeviceCode acidPumpDeviceCode : AcidPumpDeviceCode.values()) {
try {
solutionModuleService.acidPumpStop(cmdDTO.getCommandId(), cmdDTO.getCommand(), acidPumpDeviceCode);
} catch (Exception e) {
log.error("停止预充错误", e);
}
}
Thread.sleep(1000);
solutionModuleService.dualRobotOrigin();
});
}

8
src/main/java/com/iflytop/gd/app/command/control/SolutionAddCommand.java

@ -22,7 +22,6 @@ import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
/**
@ -68,12 +67,12 @@ public class SolutionAddCommand extends BaseCommandHandler {
List<CommandFuture> futuresList = new ArrayList<>();
for (int k = 0; k < solutionList.size(); k++) {
JSONObject addSolution = solutionList.getJSONObject(k);
Long solId = addSolution.getLong("solutionId");
Long solId = addSolution.getLong("solutionId");//实际前端传递的是容器id
Double volume = addSolution.getDouble("volume");
//AcidPumpDeviceCode acidPumpDevice = containerService.getPumpBySolutionId(solId);//获取溶液对应的泵
Container container = containerService.getContainerBySolutionId(solId);
Container container = containerService.getById(solId);
if (container == null) {
throw new AppException(ResultCode.CRAFT_CONTAINER_NOT_FOUND);//未找到对应溶液容器
throw new AppException(ResultCode.CONTAINER_NOT_FOUND);//未找到对应溶液容器
}
AcidPumpDeviceCode acidPumpDevice = AcidPumpDeviceCode.valueOf(container.getPumpId());//
int scale = container.getScale() == null ? 120 : container.getScale();//系数
@ -86,6 +85,7 @@ public class SolutionAddCommand extends BaseCommandHandler {
CommandUtil.wait(futuresList.toArray(new CommandFuture[0]));
}
}
Thread.sleep(1000);
solutionModuleService.dualRobotOrigin();
deviceStateService.getCommandMutexState().get().setSolutionAddCommandExecuting(false);
deviceStateService.getDeviceState().getSolutionModule().setPumping(false);

4
src/main/java/com/iflytop/gd/app/command/debug/DebugDoorOpenCommand.java

@ -26,13 +26,11 @@ import java.util.concurrent.CompletableFuture;
@CommandMapping("debug_door_open")
public class DebugDoorOpenCommand extends BaseCommandHandler {
private final DeviceCommandService deviceCommandService;
private final DevicePositionService devicePositionService;
@Override
public CompletableFuture<Void> handle(CmdDTO cmdDTO) {
return runAsync(() -> {
DevicePosition devicePosition = devicePositionService.getPosition(DevicePositionCode.doorOpen);
DeviceCommandBundle deviceCommand = DeviceCommandGenerator.doorMove(devicePosition.getDistance());
DeviceCommandBundle deviceCommand = DeviceCommandGenerator.doorMoveToEnd();
CommandFuture deviceCommandFuture = deviceCommandService.sendCommand(cmdDTO.getCommandId(), cmdDTO.getCommand(), deviceCommand);
CommandUtil.wait(deviceCommandFuture);
});

64
src/main/java/com/iflytop/gd/app/command/debug/step/DebugShowSmogCommand.java

@ -0,0 +1,64 @@
package com.iflytop.gd.app.command.debug.step;
import com.iflytop.gd.app.core.BaseCommandHandler;
import com.iflytop.gd.app.model.bo.Point3D;
import com.iflytop.gd.app.model.dto.CmdDTO;
import com.iflytop.gd.app.service.api.DevicePositionService;
import com.iflytop.gd.app.service.device.DeviceCommandService;
import com.iflytop.gd.app.service.device.DeviceCommandTempUtilService;
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.GantryModuleService;
import com.iflytop.gd.app.service.device.module.HeatModuleService;
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.command.DeviceCommandBundle;
import com.iflytop.gd.common.command.DeviceCommandGenerator;
import com.iflytop.gd.common.enums.HeatModuleCode;
import com.iflytop.gd.common.enums.data.DevicePositionCode;
import com.iflytop.gd.common.utils.CommandUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.util.concurrent.CompletableFuture;
/**
* 展示烟雾
*/
@Slf4j
@Component
@RequiredArgsConstructor
@CommandMapping("debug_show_smog")
public class DebugShowSmogCommand extends BaseCommandHandler {
private final HeatModuleService heatModuleService;
private final GantryModuleService gantryModuleService;
private final DevicePositionService devicePositionService;
@Override
public CompletableFuture<Void> handle(CmdDTO cmdDTO) {
String heatId = cmdDTO.getStringParam("heatId");
HeatModuleCode heatModuleCode = HeatModuleCode.valueOf(heatId);
double clawCapPick = devicePositionService.getPosition(DevicePositionCode.clawCapPick).getDistance(); //获取拍子夹取距离
double clawCapGrip = devicePositionService.getPosition(DevicePositionCode.clawCapGrip).getDistance(); //获取拍子夹紧距离
double trayLift = devicePositionService.getPosition(DevicePositionCode.trayLift).getDistance(); //托盘升降抬升距离
double trayLower = devicePositionService.getPosition(DevicePositionCode.trayLower).getDistance();
double heatModuleCapMoveHeight = devicePositionService.getPosition(DevicePositionCode.heatModuleCapMoveHeight).getDistance();//加热模块拍子移动高度
Point3D heatAreaCapClawPointPoint3D = heatModuleService.getHeatAreaCapClawPointPoint3D(heatModuleCode);//获取指定加热模块拍子上方点位
return runAsync(() -> {
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);//将夹爪收紧夹住拍子
gantryModuleService.gantryZMove(cmdDTO.getCommandId(), cmdDTO.getCommand(), 0);//抬升z轴
Thread.sleep(3000);
gantryModuleService.gantryZMove(heatModuleCapMoveHeight);//下降z轴,使夹拍子落入加热模块
gantryModuleService.clawMove(cmdDTO.getCommandId(), cmdDTO.getCommand(), clawCapPick);//将夹爪打开
gantryModuleService.gantryZMove(cmdDTO.getCommandId(), cmdDTO.getCommand(), 0);//抬升z轴
heatModuleService.heaterMotorMove(cmdDTO.getCommandId(), cmdDTO.getCommand(), heatModuleCode, trayLower);
});
}
}

2
src/main/java/com/iflytop/gd/app/controller/CraftsController.java

@ -86,7 +86,7 @@ public class CraftsController {
@Operation(summary = "开始执行工艺")
@PostMapping("/start")
public Result<SetCraftsVO> startCrafts(@Valid @RequestBody StartCraftsDTO startCraftsDTO) {
return Result.success(craftsService.startCrafts(startCraftsDTO.getCraftId(), startCraftsDTO.getHeatId()));
return Result.success(craftsService.startCrafts(startCraftsDTO));
}
@Operation(summary = "暂停执行工艺")

22
src/main/java/com/iflytop/gd/app/controller/SystemController.java

@ -12,6 +12,9 @@ import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import java.time.Instant;
import java.time.LocalDateTime;
@Tag(name = "系统")
@RestController
@RequestMapping("/api/sys")
@ -21,19 +24,6 @@ public class SystemController {
private final SystemConfigService systemConfigService;
private final DeviceStateService deviceStateService;
@Operation(summary = "是否启动虚拟模式")
@PostMapping("/virtual")
public Result<?> changeVirtualMode(Boolean mode) {
deviceStateService.getDeviceState().setVirtual(mode);
return Result.success();
}
@Operation(summary = "模拟向硬件写入完毕")
@PostMapping("/initComplete")
public Result<?> setInitComplete(Boolean initComplete) {
deviceStateService.getDeviceState().setInitComplete(initComplete);
return Result.success();
}
@Operation(summary = "系统状态")
@GetMapping("/device-status")
@ -48,4 +38,10 @@ public class SystemController {
return Result.success();
}
@Operation(summary = "获取系统时间")
@GetMapping("/datetime")
public Result<?> getDatetime() {
return Result.success(Instant.now().toEpochMilli());
}
}

26
src/main/java/com/iflytop/gd/app/controller/TestController.java

@ -7,7 +7,7 @@ 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.OtherModuleService;
import com.iflytop.gd.app.service.device.module.SolutionModuleService;
import com.iflytop.gd.common.enums.HeatModuleCode;
import com.iflytop.gd.common.result.Result;
import com.iflytop.gd.hardware.exception.HardwareException;
import io.swagger.v3.oas.annotations.Operation;
@ -36,6 +36,21 @@ public class TestController {
private final OtherModuleService otherModuleService;
private final DeviceEmergencyStopService deviceEmergencyStopService;
@Operation(summary = "启动虚拟模式")
@PostMapping("/virtual")
public Result<?> changeVirtualMode() {
deviceStateService.getDeviceState().setVirtual(true);
deviceStateService.getDeviceState().setInitComplete(true);
return Result.success();
}
@Operation(summary = "模拟向硬件写入完毕")
@PostMapping("/initComplete")
public Result<?> setInitComplete(Boolean initComplete) {
deviceStateService.getDeviceState().setInitComplete(initComplete);
return Result.success();
}
@Operation(summary = "获取所有传感器读数")
@GetMapping("/all-sensor")
public Result<List<AllSensorDTO>> getAllSensor() throws HardwareException {
@ -57,7 +72,6 @@ public class TestController {
return Result.success();
}
@Operation(summary = "获取指令互斥状态")
@GetMapping("/mutex-state")
public Result<CommandMutexState> getCommandMutexState() throws HardwareException {
@ -71,7 +85,6 @@ public class TestController {
return Result.success();
}
@Operation(summary = "触发急停")
@PostMapping("/press-emergency-stop")
public Result<?> pressEmergencyStop() throws Exception {
@ -92,4 +105,11 @@ public class TestController {
otherModuleService.craftsFinishBeepRemind();
return Result.success();
}
@Operation(summary = "设置当前温度")
@PostMapping("/set-temperature")
public Result<?> setTemperature(HeatModuleCode code, Double temperature) throws Exception {
testService.setTemperature(code, temperature);
return Result.success();
}
}

13
src/main/java/com/iflytop/gd/app/core/CraftsContext.java

@ -2,9 +2,12 @@ package com.iflytop.gd.app.core;
import cn.hutool.json.JSONUtil;
import com.iflytop.gd.app.model.bo.CraftsStep;
import com.iflytop.gd.app.model.bo.status.device.CraftsState;
import com.iflytop.gd.app.model.bo.status.device.TrayState;
import com.iflytop.gd.app.model.entity.Crafts;
import com.iflytop.gd.app.model.entity.Ores;
import com.iflytop.gd.app.service.crafts.CraftsStepService;
import com.iflytop.gd.app.service.device.DeviceStateService;
import com.iflytop.gd.app.ws.server.WebSocketSender;
import com.iflytop.gd.common.constant.WebSocketMessageType;
import com.iflytop.gd.common.enums.HeatModuleCode;
@ -34,6 +37,7 @@ public class CraftsContext implements Runnable {
private final StateMachine<CraftStates, CraftEvents> sm;
private final WebSocketSender webSocketService;
private final CraftsStepService craftsStepService;
private final DeviceStateService deviceStateService;
private int currentIndex = 0;
/**
@ -43,23 +47,30 @@ public class CraftsContext implements Runnable {
Crafts craft,
StateMachineFactory<CraftStates, CraftEvents> factory,
WebSocketSender webSocketService,
CraftsStepService craftsStepService) {
CraftsStepService craftsStepService,
DeviceStateService deviceStateService) {
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.deviceStateService = deviceStateService;
this.sm = factory.getStateMachine(heatModuleCode.toString());
sm.addStateListener(new StateMachineListenerAdapter<>() {
@Override
public void stateEntered(State<CraftStates, CraftEvents> state) {
CraftsState craftsState = deviceStateService.getDeviceState().getTrayStateByHeatModuleCode(heatModuleCode).getCrafts();
craftsState.setState(state.getId());
craftsState.setCurrentIndex(currentIndex);
Map<String, Object> dataMap = new HashMap<>();
dataMap.put("heatId", heatModuleCode);
dataMap.put("state", state.getId());
dataMap.put("index", currentIndex);
webSocketService.push(WebSocketMessageType.CRAFTS_STATE, dataMap);
}
});
Mono.from(sm.startReactively()).block();

2
src/main/java/com/iflytop/gd/app/core/aspect/DeviceStateChangeAspect.java

@ -38,7 +38,7 @@ public class DeviceStateChangeAspect {
if (methodArgs != null && methodArgs.length > 0) {
// 保存修改后的值
Object afterValue = methodArgs[0];
log.info("设备状态发生改变,类型{}.{}({})", className, methodName, afterValue);
// log.info("设备状态发生改变,类型{}.{}({})", className, methodName, afterValue);
webSocketService.push(WebSocketMessageType.STATUS, deviceStateService.getDeviceState());
}
} catch (Exception e) {

10
src/main/java/com/iflytop/gd/app/model/bo/status/crafts/CraftsState.java → src/main/java/com/iflytop/gd/app/model/bo/status/device/CraftsState.java

@ -1,13 +1,21 @@
package com.iflytop.gd.app.model.bo.status.crafts;
package com.iflytop.gd.app.model.bo.status.device;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.iflytop.gd.app.model.entity.Crafts;
import com.iflytop.gd.app.model.entity.Ores;
import com.iflytop.gd.common.enums.automaton.CraftStates;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
@Schema(description = "工艺")
@Data
@Component
@Scope("prototype")
@RequiredArgsConstructor
@JsonIgnoreProperties(value = {"advisors", "frozen", "preFiltered", "proxyTargetClass", "targetSource", "exposeProxy", "advisorCount", "proxiedInterfaces", "targetClass"})
public class CraftsState {
@Schema(description = "工艺状态")
private CraftStates state;

18
src/main/java/com/iflytop/gd/app/model/bo/status/device/DeviceState.java

@ -73,6 +73,24 @@ public class DeviceState {
return null;
}
public synchronized TrayState getTrayStateByHeatModuleCode(HeatModuleCode heatModuleCode) {
for (TrayState t : tray) {
if (heatModuleCode.equals(t.getHeatModuleId())) {
return t;
}
}
return null;
}
public synchronized TrayState getTrayInSolutionModule() {
for (TrayState t : tray) {
if (t.isInSolutionModule()) {
return t;
}
}
return null;
}
public synchronized TrayState getTrayState(String trayUUID) {
for (TrayState t : tray) {
if (t.getUuid().equals(trayUUID)) {

3
src/main/java/com/iflytop/gd/app/model/bo/status/device/HeatModuleState.java

@ -30,6 +30,9 @@ public class HeatModuleState {
@Schema(description = "当前加热类型")
private HeatingType heatingType = HeatingType.stop;
@Schema(description = "是否正在加热,true为正在加热,false为未加热")//可能去掉这个状态
private boolean heating = false;
@Schema(description = "是否启动散热,true为正在散热,false为未在散热")
private boolean fanOpen = false;

14
src/main/java/com/iflytop/gd/app/model/bo/status/device/TrayState.java

@ -1,14 +1,22 @@
package com.iflytop.gd.app.model.bo.status.device;
import com.iflytop.gd.app.model.bo.status.crafts.CraftsState;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.iflytop.gd.common.enums.HeatModuleCode;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.annotation.PostConstruct;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import java.util.UUID;
@Schema(description = "托盘")
@Data
@Component
@Scope("prototype")
@RequiredArgsConstructor
@JsonIgnoreProperties(value = {"advisors", "frozen", "preFiltered", "proxyTargetClass", "targetSource", "exposeProxy", "advisorCount", "proxiedInterfaces", "targetClass"})
public class TrayState {
@Schema(description = "托盘唯一id")
private String uuid = UUID.randomUUID().toString();
@ -28,11 +36,13 @@ public class TrayState {
@Schema(description = "当前托盘的工艺")
private CraftsState crafts = null;
public TrayState() {
@PostConstruct
private void init(){
for (int i = 0; i < tubes.length; i++) {
TubeState tubeState = new TubeState();
tubeState.setTubeNum(i + 1);
tubes[i] = tubeState;
}
}
}

3
src/main/java/com/iflytop/gd/app/model/bo/status/device/TubeState.java

@ -14,4 +14,7 @@ public class TubeState {
@Schema(description = "是否存在试管 true存在")
private boolean exists = true;
@Schema(description = "是否需要添加溶液 true需要")
private boolean needAddSolution = true;
}

3
src/main/java/com/iflytop/gd/app/model/dto/StartCraftsDTO.java

@ -16,4 +16,7 @@ public class StartCraftsDTO {
@Schema(description = "加热区id,非必填,如果不传递则自动分配加热区")
private HeatModuleCode heatId;
@Schema(description = "需要加液的试管")
private int[] tubes;
}

2
src/main/java/com/iflytop/gd/app/model/vo/SetTrayTubeVO.java

@ -12,7 +12,7 @@ public class SetTrayTubeVO {
@Schema(description = "托盘UUID")
private String trayUuid;
@Schema(description = "矿石 ID")
@Schema(description = "试管")
private TubeState[] tubes;
}

65
src/main/java/com/iflytop/gd/app/service/api/CraftsService.java

@ -4,12 +4,17 @@ 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.CraftsState;
import com.iflytop.gd.app.model.bo.status.device.HeatModuleState;
import com.iflytop.gd.app.model.bo.status.device.TrayState;
import com.iflytop.gd.app.model.bo.status.device.TubeState;
import com.iflytop.gd.app.model.dto.StartCraftsDTO;
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.DeviceStateService;
import com.iflytop.gd.app.service.device.module.HeatModuleService;
import com.iflytop.gd.app.ws.server.WebSocketSender;
import com.iflytop.gd.common.enums.HeatModuleCode;
@ -20,12 +25,12 @@ import com.iflytop.gd.common.result.ResultCode;
import jakarta.annotation.PostConstruct;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.ObjectProvider;
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;
@ -44,10 +49,14 @@ public class CraftsService extends ServiceImpl<CraftsMapper, Crafts> {
private final WebSocketSender webSocketService;
private final CraftsStepService craftsStepService;
private final OresService oresService;
private final DeviceStateService deviceStateService;
private final ObjectProvider<CraftsState> craftsStateObjectProvider;
private final ConcurrentHashMap<HeatModuleCode, CraftsContext> contextMap = new ConcurrentHashMap<>();
private final ConcurrentHashMap<HeatModuleCode, Future<?>> futureMap = new ConcurrentHashMap<>();
private ExecutorService executor;
@PostConstruct
public void init() {
this.executor = Executors.newCachedThreadPool();
@ -89,7 +98,9 @@ public class CraftsService extends ServiceImpl<CraftsMapper, Crafts> {
/**
* 启动执行工艺
*/
public synchronized SetCraftsVO startCrafts(Long craftId, HeatModuleCode heatModuleCode) {
public synchronized SetCraftsVO startCrafts(StartCraftsDTO startCraftsDTO) {
long craftId = startCraftsDTO.getCraftId();
HeatModuleCode heatModuleCode = startCraftsDTO.getHeatId();
Crafts craft = this.getById(craftId);
if (craft == null) {
throw new AppException(ResultCode.INVALID_PARAMETER);
@ -98,6 +109,9 @@ public class CraftsService extends ServiceImpl<CraftsMapper, Crafts> {
if (ores == null) {
throw new AppException(ResultCode.INVALID_PARAMETER);
}
if (deviceStateService.getDeviceState().getSolutionModule().getTrayStatus() == 0) {
throw new AppException(ResultCode.SOLUTION_MODULE_NO_TRAY);
}
//判断是否指定加热区id
if (heatModuleCode == null) {
//如果没有指定加热区id则自动获取一个
@ -109,23 +123,23 @@ public class CraftsService extends ServiceImpl<CraftsMapper, Crafts> {
heatModuleCode = heatModuleState.getModuleCode();
}
} else {
if (futureMap.containsKey(heatModuleCode)) {//校验指定加热模块是否正在执行工艺
log.error("工艺正在执行中,不可重复开始执行。");
throw new AppException(ResultCode.CRAFT_RUNNING);
}
// if (futureMap.containsKey(heatModuleCode)) {//校验指定加热模块是否正在执行工艺
// log.error("工艺正在执行中,不可重复开始执行。");
// throw new AppException(ResultCode.CRAFT_RUNNING);
// }
}
log.info("准备开始工艺,加热模块{},工艺{}", heatModuleCode, craft.getName());
//TODO 传感器校验heatModuleCode是否被占用
// 校验已有上下文状态仅允许在 READYSTOPPED FINISHED 状态下重置
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(heatModuleCode);
}
// 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(heatModuleCode);
// }
CraftsContext ctx = new CraftsContext(
heatModuleCode,
@ -133,12 +147,33 @@ public class CraftsService extends ServiceImpl<CraftsMapper, Crafts> {
craft,
stateMachineFactory,
webSocketService,
craftsStepService
craftsStepService,
deviceStateService
);
contextMap.put(heatModuleCode, ctx);
Future<?> future = executor.submit(ctx);
futureMap.put(heatModuleCode, future);
TrayState trayState = deviceStateService.getDeviceState().getTrayInSolutionModule();
//配置可操作试管
TubeState[] tubeStateArr = trayState.getTubes();
List<Integer> needTubeNumArr = Arrays.stream(startCraftsDTO.getTubes()).boxed() .toList();
for (TubeState tubeState : tubeStateArr) {
if(!needTubeNumArr.contains(tubeState.getTubeNum())){
tubeState.setNeedAddSolution(false);
}
}
//配置状态
CraftsState craftsState = craftsStateObjectProvider.getObject();
craftsState.setCraft(craft);
craftsState.setOres(ores);
craftsState.setState(CraftStates.READY);
craftsState.setCurrentIndex(0);
trayState.setHeatModuleId(heatModuleCode);
trayState.setCrafts(craftsState);
//组装返回值
SetCraftsVO setCraftsVO = new SetCraftsVO();
setCraftsVO.setHeatId(heatModuleCode);
setCraftsVO.setCraftsName(craft.getName());

2
src/main/java/com/iflytop/gd/app/service/api/SystemConfigService.java

@ -10,6 +10,8 @@ import org.springframework.stereotype.Service;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
/**
* 系统配置接口服务

5
src/main/java/com/iflytop/gd/app/service/api/TestService.java

@ -2,6 +2,7 @@ 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.common.enums.HeatModuleCode;
import com.iflytop.gd.hardware.exception.HardwareException;
import com.iflytop.gd.hardware.service.GDDeviceStatusService;
import com.iflytop.gd.hardware.type.IO.InputIOMId;
@ -45,4 +46,8 @@ public class TestService {
deviceStateService.getDeviceState().reset();
}
public void setTemperature(HeatModuleCode code, Double temperature){
deviceStateService.getDeviceState().getHeatModuleByCode(code).setTemperature(temperature);
}
}

5
src/main/java/com/iflytop/gd/app/service/api/TrayService.java

@ -1,10 +1,12 @@
package com.iflytop.gd.app.service.api;
import com.iflytop.gd.app.model.bo.status.device.HeatModuleState;
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.beans.factory.ObjectProvider;
import org.springframework.stereotype.Service;
import java.util.List;
@ -17,12 +19,13 @@ import java.util.List;
public class TrayService {
private final DeviceStateService deviceStateService;
private final SolutionModuleService solutionModuleService;
private final ObjectProvider<TrayState> trayStateObjectProvider;
/**
* 放入了新托盘
*/
public synchronized TrayState trayIn() {
TrayState trayState = new TrayState();
TrayState trayState = trayStateObjectProvider.getObject();
trayState.setInSolutionModule(true);
deviceStateService.getDeviceState().getTray().add(trayState);
deviceStateService.getDeviceState().getSolutionModule().setTrayStatus(1);

62
src/main/java/com/iflytop/gd/app/service/crafts/CraftsStepService.java

@ -5,28 +5,25 @@ import cn.hutool.json.JSONObject;
import com.iflytop.gd.app.core.CraftsDebugGenerator;
import com.iflytop.gd.app.model.bo.CraftsStep;
import com.iflytop.gd.app.model.bo.Point3D;
import com.iflytop.gd.app.model.entity.Container;
import com.iflytop.gd.app.service.api.ContainerService;
import com.iflytop.gd.app.service.api.DevicePositionService;
import com.iflytop.gd.app.service.device.DeviceCommandTempUtilService;
import com.iflytop.gd.app.service.device.DeviceStateService;
import com.iflytop.gd.app.service.device.module.*;
import com.iflytop.gd.app.ws.server.WebSocketSender;
import com.iflytop.gd.common.command.CommandFuture;
import com.iflytop.gd.common.enums.AcidPumpDeviceCode;
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;
import com.iflytop.gd.hardware.drivers.DODriver.OutputIOCtrlDriver;
import com.iflytop.gd.hardware.drivers.TricolorLightDriver;
import com.iflytop.gd.hardware.exception.HardwareException;
import com.iflytop.gd.hardware.type.IO.OutputIOMId;
import com.iflytop.gd.hardware.type.MId;
import com.iflytop.gd.common.utils.CommandUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.concurrent.CompletableFuture;
/**
* 工艺步骤执行服务
*/
@ -78,6 +75,15 @@ public class CraftsStepService {
&& deviceStateService.getDeviceState().getHeatModuleByCode(heatModuleCode).getTrayStatus() == 1) {
moveToSolutionModule(heatModuleCode);
}
JSONArray tubeNums = params.getJSONArray("tubeNums");
for (int i = 0; i < tubeNums.size(); i++) {
JSONObject tubeSol = tubeNums.getJSONObject(i);
Integer tubeNum = tubeSol.getInt("tubeNum");
}
JSONArray tubeSolList = params.getJSONArray("tubeSolList");
for (int i = 0; i < tubeSolList.size(); i++) {
JSONObject tubeSol = tubeSolList.getJSONObject(i);
@ -87,14 +93,15 @@ public class CraftsStepService {
JSONObject addLiquid = addLiquidList.getJSONObject(j);
Long solId = addLiquid.getLong("solId");
Double volume = addLiquid.getDouble("volume");
AcidPumpDeviceCode acidPumpDevice = containerService.getPumpBySolutionId(solId);
if (acidPumpDevice == null) {
throw new AppException(ResultCode.CRAFT_CONTAINER_NOT_FOUND);
Container container = containerService.getContainerBySolutionId(solId);
if (container == null) {
throw new AppException(ResultCode.CONTAINER_NOT_FOUND);//未找到对应溶液容器
}
webSocketService.pushCraftsDebug(CraftsDebugGenerator.generateJson(heatModuleCode.toString(), "移动加液机械臂到指定试管", tubeNum));
AcidPumpDeviceCode acidPumpDevice = AcidPumpDeviceCode.valueOf(container.getPumpId());//
int scale = container.getScale() == null ? 120 : container.getScale();//系数
solutionModuleService.dualRobotMovePoint(tubeNum);//移动加液机械臂到指定试管
webSocketService.pushCraftsDebug(CraftsDebugGenerator.generateJson(heatModuleCode.toString(), "添加溶液", addLiquid));
solutionModuleService.acidPumpMoveBy(acidPumpDevice, volume);//添加溶液
CommandFuture deviceCommandFuture = solutionModuleService.acidPumpMoveBy(acidPumpDevice, volume * ((double) scale /100));//添加溶液
CommandUtil.wait(deviceCommandFuture);
}
}
solutionModuleService.dualRobotOrigin();
@ -126,8 +133,15 @@ public class CraftsStepService {
Double temperature = params.getDouble("temperature");
Integer second = params.getInt("second");
heatModuleService.heatRodOpen(heatModuleCode, temperature);//开始加热
deviceStateService.getDeviceState().getHeatModuleByCode(heatModuleCode).setHeatingType(HeatingType.thermostatic);
//达到目标温度后才算开始加热
while (deviceStateService.getDeviceState().getHeatModuleByCode(heatModuleCode).getTemperature() + 1 < temperature) {
delay(1);
}
deviceStateService.getDeviceState().getHeatModuleByCode(heatModuleCode).setHeatingType(HeatingType.constant);
delay(second);
heatModuleService.heatRodClose(heatModuleCode);//停止加热
deviceStateService.getDeviceState().getHeatModuleByCode(heatModuleCode).setHeatingType(HeatingType.finish);
heatModuleService.heaterMotorMove(heatModuleCode, trayLift);//抬升加热位托盘
return true;
}
@ -166,7 +180,7 @@ public class CraftsStepService {
public void finish(HeatModuleCode heatModuleCode) throws Exception {
moveToSolutionModule(heatModuleCode);
//蜂鸣器提示
otherModuleService.craftsFinishBeepRemind();
// otherModuleService.craftsFinishBeepRemind();
}
/**
@ -190,29 +204,30 @@ public class CraftsStepService {
Point3D heatAreaCapClawPointPoint3D = heatModuleService.getHeatAreaCapClawPointPoint3D(heatModuleCode);//获取指定加热模块拍子上方点位
Point3D capStorageCapClawPoint3D = devicePositionService.getPosition(DevicePositionCode.capStorageCapClawPoint).getPoint3D();//获取拍子存放区上方点位;
capModuleService.capUpBalanceNoWait();//提升拍子存放区至拍子夹取的高度
gantryModuleService.gantryMove(liquidAreaTrayPoint3D); //将机械臂移动至加液模块上方
gantryModuleService.clawMove(clawTrayPick);//将夹爪打开准备夹取托盘
gantryModuleService.gantryZMove(solutionModuleTrayMoveHeight);//下降z轴,使夹爪落入托盘孔位
gantryModuleService.clawMove(clawTrayGrip);//将夹爪收紧夹住托盘
gantryModuleService.gantryZMove(0);//抬升z轴
deviceStateService.getDeviceState().getSolutionModule().setTrayStatus(0);//加液模块是否有托盘
deviceCommandTempUtilService.moveTrayHeatModuleAvoidDown(null);//TODO 结构有问题临时避让 开始移动托盘之前先降下所有加热模块
// deviceCommandTempUtilService.moveTrayHeatModuleAvoidDown(null);//TODO 结构有问题临时避让 开始移动托盘之前先降下所有加热模块
gantryModuleService.gantryMove(heatArea4TrayClawPoint3D);//将携带托盘的机械臂移动至4号加热模块上方
gantryModuleService.gantryMove(heatAreaTrayClawPoint3D);//将携带托盘的机械臂移动至加热模块上方
// deviceCommandUtilService.heaterMotorMove( heatModuleId, trayLift);//抬升加热位托盘 TODO 结构有问题临时避让 屏蔽
deviceCommandTempUtilService.moveTrayHeatModuleAvoidUp(heatModuleCode);//TODO 结构有问题临时避让 完毕可以升起了顺带提升目标加热模块
deviceCommandTempUtilService.moveTrayHeatModuleAvoidUpNoWait(heatModuleCode);Thread.sleep(3200);//TODO 结构有问题临时避让 完毕可以升起了顺带提升目标加热模块
gantryModuleService.gantryZMove(heatModuleTrayMoveHeight);//下降z轴,使托盘落入加热模块
gantryModuleService.clawMove(clawTrayPick);//将夹爪打开释放托盘
deviceStateService.getDeviceState().getHeatModuleByCode(heatModuleCode).setTrayStatus(1);//加热模块是否存在托盘
gantryModuleService.gantryZMove(0);//抬升z轴
capModuleService.capUpBalance();//提升拍子存放区至拍子夹取的高度
gantryModuleService.gantryMove(capStorageCapClawPoint3D);//移动机械臂至拍子存放区上方
gantryModuleService.clawMove(clawCapPick);//将夹爪打开准备夹取拍子
gantryModuleService.gantryZMove(capModuleCapMoveHeight);//下降z轴,使夹爪落入拍子升降模块拍子孔位
gantryModuleService.clawMove(clawCapGrip);//将夹爪收紧夹住拍子
gantryModuleService.gantryZMove(0);//抬升z轴
gantryModuleService.gantryMove(heatAreaCapClawPointPoint3D);//将携带拍子的机械臂移动至加热模块拍子上方
capModuleService.capUpBalanceNoWait(); //提升拍子存放区
gantryModuleService.gantryZMove(heatModuleCapMoveHeight);//下降z轴,使夹拍子落入加热模块
gantryModuleService.clawMove(clawCapPick);//将夹爪打开释放拍子
deviceStateService.getDeviceState().getHeatModuleByCode(heatModuleCode).setCapExist(true);//加热模块是否存在拍子
@ -221,11 +236,8 @@ public class CraftsStepService {
// trayState.setInHeatModule(true);
heatModuleService.heaterMotorMove(heatModuleCode, trayLower);//下降加热模块托盘
deviceStateService.getDeviceState().getHeatModuleByCode(heatModuleCode).setTrayUp(0);//加热模块托盘升降状态
capModuleService.capUpBalance(); //提升拍子存放区
gantryModuleService.gantryMove(capStorageCapClawPoint3D);//移动机械臂至拍子存放区上方
heatModuleService.heaterMotorMove(heatModuleCode, trayLower);//下降加热位托盘
deviceStateService.getDeviceState().getHeatModuleByCode(heatModuleCode).setTrayStatus(1);
solutionModuleService.releaseSolutionModule();//释放加液区
}
@ -253,15 +265,15 @@ public class CraftsStepService {
// TrayState trayState = deviceStateService.getTrayInSolutionModule();
solutionModuleService.requestSolutionModule();//申请使用加液区并等待
capModuleService.capUpBalance(); //提升拍子存放区至拍子夹取的高度
capModuleService.capUpBalanceNoWait(); //提升拍子存放区至拍子夹取的高度
gantryModuleService.gantryMove(heatAreaCapClawPointPoint3D);//将机械臂移动至加热模块拍子上方
heatModuleService.heaterMotorMove(heatModuleCode, trayLift);//抬升指定加热位托盘
gantryModuleService.clawMove(clawCapPick);//将夹爪打开准备夹取拍子
gantryModuleService.gantryZMove(heatModuleCapMoveHeight);//下降z轴,使夹爪落入加热模块拍子孔位
gantryModuleService.clawMove(clawCapGrip);//将夹爪收紧夹住拍子
deviceStateService.getDeviceState().getHeatModuleByCode(heatModuleCode).setCapExist(false);//加热模块是否存在拍子
gantryModuleService.gantryZMove(0);//抬升z轴
capModuleService.capMotorMoveByNum(-1);//拍子存放模块下降1个拍子位置
capModuleService.capMotorMoveByNumNoWait(-1);//拍子存放模块下降1个拍子位置
gantryModuleService.gantryZMove(0); Thread.sleep(2000);//抬升z轴
gantryModuleService.gantryMove(capStorageCapClawPoint3D);//将携带拍子的机械臂移动至存放区上方
gantryModuleService.gantryZMove(capModuleCapMoveHeight);//下降z轴,使夹拍子落入存放区
gantryModuleService.clawMove(clawCapPick);//将夹爪打开释放夹取的拍子
@ -274,10 +286,10 @@ public class CraftsStepService {
gantryModuleService.clawMove(clawTrayGrip);//将夹爪收紧夹住托盘
deviceStateService.getDeviceState().getHeatModuleByCode(heatModuleCode).setTrayStatus(0);//加热模块是否存在托盘
// trayState.setInHeatModule(false);//托盘是否在加热模块中
gantryModuleService.gantryZMove(0);//抬升z轴
deviceCommandTempUtilService.moveTrayHeatModuleAvoidDownNoWait(heatModuleCode);//TODO 临时避让下降
gantryModuleService.gantryZMove(0);Thread.sleep(2500);//抬升z轴
// deviceCommandUtilService.heaterMotorMove( heatModuleId, trayLower);//下降加热模块托盘
// deviceStateService.setHeatModuleStateTrayUp(heatModuleId, 0);//加热模块托盘升降状态
deviceCommandTempUtilService.moveTrayHeatModuleAvoidDown(heatModuleCode);//TODO 临时避让下降
gantryModuleService.gantryMove(heatArea4TrayClawPoint3D);//将携带托盘的机械臂移动至4号加热模块上方
gantryModuleService.gantryMove(liquidAreaTrayPoint3D); //将携带托盘的机械臂移动至加液模块上方
deviceCommandTempUtilService.moveTrayHeatModuleAvoidUp(null, heatModuleCode);//TODO 临时避 恢复抬起状态

18
src/main/java/com/iflytop/gd/app/service/device/DeviceCommandTempUtilService.java

@ -38,6 +38,15 @@ public class DeviceCommandTempUtilService {
* 临时移动托盘的时候加热模块升降避让
* 该方法会恢复之前升起的状态
*/
public void moveTrayHeatModuleAvoidUpNoWait(HeatModuleCode targetHeatModuleCode, HeatModuleCode... exceptionHeatModuleCodes) throws Exception {
moveTrayHeatModuleAvoidUpNoWait(null, null, targetHeatModuleCode, exceptionHeatModuleCodes);
}
/**
* 避让抬升
* 临时移动托盘的时候加热模块升降避让
* 该方法会恢复之前升起的状态
*/
public void moveTrayHeatModuleAvoidUp(HeatModuleCode targetHeatModuleCode, HeatModuleCode... exceptionHeatModuleCodes) throws Exception {
moveTrayHeatModuleAvoidUp(null, null, targetHeatModuleCode, exceptionHeatModuleCodes);
}
@ -94,6 +103,15 @@ public class DeviceCommandTempUtilService {
* 临时移动托盘的时候加热模块升降避让
* 该方法会下降所有升起的加热模块并且记录
*/
public void moveTrayHeatModuleAvoidDownNoWait(HeatModuleCode targetHeatModuleCode, HeatModuleCode... exceptionHeatModuleCodes) throws Exception {
moveTrayHeatModuleAvoidDownNoWait(null, null, targetHeatModuleCode, exceptionHeatModuleCodes);
}
/**
* 避让下降
* 临时移动托盘的时候加热模块升降避让
* 该方法会下降所有升起的加热模块并且记录
*/
public void moveTrayHeatModuleAvoidDown(HeatModuleCode targetHeatModuleCode, HeatModuleCode... exceptionHeatModuleCodes) throws Exception {
moveTrayHeatModuleAvoidDown(null, null, targetHeatModuleCode, exceptionHeatModuleCodes);
}

2
src/main/java/com/iflytop/gd/app/service/device/DeviceEmergencyStopService.java

@ -29,7 +29,7 @@ public class DeviceEmergencyStopService {
}
/**
* 处理接触急停
* 处理解除急停
*/
public void release(){
commandPoolManager.restartExecutor();

10
src/main/java/com/iflytop/gd/app/service/device/DeviceStepCommandService.java

@ -92,6 +92,16 @@ public class DeviceStepCommandService {
stepMotorCtrlDriver.stepMotorStop(StepMotorMId.HEATER_4_MOTOR_MID);
stepMotorCtrlDriver.stepMotorStop(StepMotorMId.HEATER_5_MOTOR_MID);
stepMotorCtrlDriver.stepMotorStop(StepMotorMId.HEATER_6_MOTOR_MID);
stepMotorCtrlDriver.stepMotorStop(StepMotorMId.ACID_PUMP_1_MOTOR_MID);
stepMotorCtrlDriver.stepMotorStop(StepMotorMId.ACID_PUMP_2_MOTOR_MID);
stepMotorCtrlDriver.stepMotorStop(StepMotorMId.ACID_PUMP_3_MOTOR_MID);
stepMotorCtrlDriver.stepMotorStop(StepMotorMId.ACID_PUMP_4_MOTOR_MID);
stepMotorCtrlDriver.stepMotorStop(StepMotorMId.ACID_PUMP_5_MOTOR_MID);
stepMotorCtrlDriver.stepMotorStop(StepMotorMId.ACID_PUMP_6_MOTOR_MID);
stepMotorCtrlDriver.stepMotorStop(StepMotorMId.ACID_PUMP_7_MOTOR_MID);
stepMotorCtrlDriver.stepMotorStop(StepMotorMId.ACID_PUMP_8_MOTOR_MID);
stepMotorCtrlDriver.stepMotorStop(StepMotorMId.SHAKE_MOTOR_MID);
liquidDistributionArmDriver.moduleStop(LiquidArmMId.LiquidDistributionArm);
miniServoDriver.miniServoStop(MiniServoMId.CLAW_MID);

18
src/main/java/com/iflytop/gd/app/service/device/module/CapModuleService.java

@ -30,6 +30,13 @@ public class CapModuleService {
/**
* 将拍子升降区抬升至可以获取的位置
*/
public void capUpBalanceNoWait() throws Exception {
capUpBalanceNoWait(null, null);
}
/**
* 将拍子升降区抬升至可以获取的位置
*/
public void capUpBalance() throws Exception {
capUpBalance(null, null);
}
@ -79,7 +86,7 @@ public class CapModuleService {
}
}
if (capNum == 0) {
throw new AppException(ResultCode.CAP_MODULE_NO_CAP);
return;
}
double capLiftingHeight = devicePositionService.getPosition(DevicePositionCode.capLiftingHeight).getDistance();//每个拍子高度
double capLiftingHeightSum = (6 - capNum) * capLiftingHeight + 21;
@ -169,6 +176,15 @@ public class CapModuleService {
*
* @param num 1为上升1格-1为下降1格
*/
public void capMotorMoveByNumNoWait(int num) throws Exception {
capMotorMoveByNumNoWait(null, null, num);
}
/**
* 调整拍子升降电机位置
*
* @param num 1为上升1格-1为下降1格
*/
public void capMotorMoveByNum(int num) throws Exception {
capMotorMoveByNum(null, null, num);
}

9
src/main/java/com/iflytop/gd/app/service/device/module/DoorModuleService.java

@ -85,4 +85,13 @@ public class DoorModuleService {
CommandUtil.wait(deviceCommandFuture);
}
/**
* 门点击移动至最远距离
*/
public void doorMoveEnd(String commandId, String command) throws Exception {
DeviceCommandBundle deviceCommand = DeviceCommandGenerator.doorMoveToEnd();
CommandFuture deviceCommandFuture = deviceCommandService.sendCommand(commandId, command, deviceCommand);
CommandUtil.wait(deviceCommandFuture);
}
}

2
src/main/java/com/iflytop/gd/app/service/device/module/GantryModuleService.java

@ -51,10 +51,10 @@ public class GantryModuleService {
public void gantryMove(String commandId, String command, Point3D point) throws Exception {
DeviceCommandBundle gantryXMoveDeviceCommand = DeviceCommandGenerator.gantryXMove(point.getX());
CommandFuture gantryXMoveDeviceCommandFuture = deviceCommandService.sendCommand(commandId, command, gantryXMoveDeviceCommand);
DeviceCommandBundle gantryYMoveDeviceCommand = DeviceCommandGenerator.gantryYMove(point.getY());
CommandFuture gantryYMoveDeviceCommandFuture = deviceCommandService.sendCommand(commandId, command, gantryYMoveDeviceCommand);
CommandUtil.wait(gantryXMoveDeviceCommandFuture, gantryYMoveDeviceCommandFuture);
DeviceCommandBundle gantryZMoveDeviceCommand = DeviceCommandGenerator.gantryZMove(point.getZ());
CommandFuture gantryZMoveDeviceCommandFuture = deviceCommandService.sendCommand(commandId, command, gantryZMoveDeviceCommand);
CommandUtil.wait(gantryZMoveDeviceCommandFuture);

54
src/main/java/com/iflytop/gd/app/service/device/module/SolutionModuleService.java

@ -69,6 +69,7 @@ public class SolutionModuleService {
* 释放加液区
*/
public synchronized void releaseSolutionModule() throws InterruptedException {
log.info("释放加液模块占用");
deviceStateService.getDeviceState().getSolutionModule().setIdle(true);
// 唤醒队列中的第一个线程
if (!waitingQueue.isEmpty()) {
@ -84,29 +85,60 @@ public class SolutionModuleService {
* 双轴械臂 移动至指定试管
*/
public void dualRobotMovePoint(int index) throws Exception {
liquidDistributionArmDriver.liquidDistributionArmMoveToBlock(LiquidArmMId.LiquidDistributionArm, index);
if (!deviceStateService.getDeviceState().isVirtual()) {
liquidDistributionArmDriver.liquidDistributionArmMoveToBlock(LiquidArmMId.LiquidDistributionArm, index);
} else {
new Thread(() -> {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}).start();
}
}
/**
* 加液机械臂回原点
*/
public void dualRobotOrigin() throws Exception {
liquidDistributionArmDriver.liquidDistributionArmMoveToBlock(LiquidArmMId.LiquidDistributionArm, 0);
if (!deviceStateService.getDeviceState().isVirtual()) {
liquidDistributionArmDriver.liquidDistributionArmMoveToBlock(LiquidArmMId.LiquidDistributionArm, 0);
} else {
new Thread(() -> {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}).start();
}
}
/**
* 加液机械臂回原点
*/
public void dualRobotOrigin(String commandId, String command, CmdAxis cmdAxis) throws Exception {
if (cmdAxis == CmdAxis.joint1) {
DeviceCommandBundle deviceCommand = DeviceCommandGenerator.dualRobotJoint1Origin();
CommandFuture deviceCommandFuture = deviceCommandService.sendCommand(commandId, command, deviceCommand);
CommandUtil.wait(deviceCommandFuture);
if (!deviceStateService.getDeviceState().isVirtual()) {
if (cmdAxis == CmdAxis.joint1) {
DeviceCommandBundle deviceCommand = DeviceCommandGenerator.dualRobotJoint1Origin();
CommandFuture deviceCommandFuture = deviceCommandService.sendCommand(commandId, command, deviceCommand);
CommandUtil.wait(deviceCommandFuture);
} else {
DeviceCommandBundle deviceCommand = DeviceCommandGenerator.dualRobotJoint2Origin();
CommandFuture deviceCommandFuture = deviceCommandService.sendCommand(commandId, command, deviceCommand);
CommandUtil.wait(deviceCommandFuture);
}
} else {
DeviceCommandBundle deviceCommand = DeviceCommandGenerator.dualRobotJoint2Origin();
CommandFuture deviceCommandFuture = deviceCommandService.sendCommand(commandId, command, deviceCommand);
CommandUtil.wait(deviceCommandFuture);
new Thread(() -> {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}).start();
}
}
@ -185,8 +217,8 @@ public class SolutionModuleService {
/**
* 添加溶液
*/
public void acidPumpMoveBy(AcidPumpDeviceCode acidPumpDevice, double position) throws Exception {
acidPumpMoveBy(null, null, acidPumpDevice, position);
public CommandFuture acidPumpMoveBy(AcidPumpDeviceCode acidPumpDevice, double position) throws Exception {
return acidPumpMoveBy(null, null, acidPumpDevice, position);
}
/**

16
src/main/java/com/iflytop/gd/app/service/scheduled/FetchTemperatureScheduledTask.java

@ -19,7 +19,7 @@ public class FetchTemperatureScheduledTask {
private final GDDeviceStatusService gdDeviceStatusService;
private final DeviceStateService deviceStateService;
@Scheduled(fixedRate = 30000)
@Scheduled(fixedRate = 10000)
public void fetchTemperature() {
try {
if (!deviceStateService.getDeviceState().isVirtual()) {
@ -42,12 +42,14 @@ public class FetchTemperatureScheduledTask {
deviceStateService.getDeviceState().getHeatModuleByCode(HeatModuleCode.heat_module_06).setTemperature(heatModule06Temperature);
} else {//虚拟模式随便写个值
// List<HeatModuleState> heatModuleStateList = deviceStateService.getDeviceState().getHeatModule();
// for (HeatModuleState heatModuleState : heatModuleStateList) {
// if (heatModuleState.isHeating()) {
// deviceStateService.getDeviceState().getHeatModuleByCode(heatModuleState.getModuleCode()).setTemperature(123.0);
// }
// }
List<HeatModuleState> heatModuleStateList = deviceStateService.getDeviceState().getHeatModule();
for (HeatModuleState heatModuleState : heatModuleStateList) {
if (heatModuleState.isHeating()) {
heatModuleState.setTemperature(heatModuleState.getTargetTemperature());
} else {
heatModuleState.setTemperature(26.0);
}
}
}
} catch (Exception e) {
log.error("定时采集加热棒温度错误", e);

66
src/main/java/com/iflytop/gd/app/service/scheduled/HeatCountdownScheduledTask.java

@ -1,6 +1,7 @@
package com.iflytop.gd.app.service.scheduled;
import com.iflytop.gd.app.model.bo.status.device.HeatModuleState;
import com.iflytop.gd.app.model.bo.status.device.TrayState;
import com.iflytop.gd.app.model.vo.HeatCountdownVO;
import com.iflytop.gd.app.service.api.DevicePositionService;
import com.iflytop.gd.app.service.device.DeviceStateService;
@ -21,7 +22,7 @@ import java.util.ArrayList;
import java.util.List;
/**
* 加热倒计
* 加热时间到自动抬起
*/
@Slf4j
@Service
@ -32,53 +33,42 @@ public class HeatCountdownScheduledTask {
private final HeatModuleService heatModuleService;
private final WebSocketSender webSocketSender;
@Scheduled(fixedRate = 1000)
@Scheduled(fixedDelay = 1000)
public void fetchTemperature() {
try {
LocalDateTime now = LocalDateTime.now();
List<HeatCountdownVO> heatCountdownVOList = new ArrayList<>();
for (HeatModuleState heatModuleState : deviceStateService.getDeviceState().getHeatModule()) {
//工艺除外
TrayState trayState = deviceStateService.getDeviceState().getTrayStateByHeatModuleCode(heatModuleState.getModuleCode());
if (trayState != null && trayState.getCrafts() != null) {
continue;
}
if (heatModuleState.getHeatingType() == HeatingType.thermostatic) {//如果这个加热模块在加热中
if (heatModuleState.getTemperature() + 1 > heatModuleState.getHeatTemperature()) {//当前温度达到目标温度允许有1度以内的误差
heatModuleState.setStartHeatTime(now);
heatModuleState.setHeatingType(HeatingType.constant);//修改状态为恒温中
if (heatModuleState.getStartHeatTime() == null) {
//设定开始加热时间
heatModuleState.setStartHeatTime(now);
} else {
LocalDateTime endTime = heatModuleState.getStartHeatTime().minusSeconds(heatModuleState.getTargetTime());
//判断是否达到目标加热时间
if (endTime.isBefore(now)) {//加热完毕
double trayLift = devicePositionService.getPosition(DevicePositionCode.trayLift).getDistance();
//抬起托盘
heatModuleService.heaterMotorMove(heatModuleState.getModuleCode(), trayLift);
heatModuleState.setTrayUp(1);
//关闭加棒
heatModuleService.heatRodClose(heatModuleState.getModuleCode());
heatModuleState.setHeatingType(HeatingType.stop);
//还原状态
heatModuleState.setStartHeatTime(null);
heatModuleState.setTargetTime(null);
heatModuleState.setWarmUpTemperature(null);
heatModuleState.setHeatTemperature(null);
heatModuleState.setTargetTemperature(null);
heatModuleState.setHeatingType(HeatingType.stop);
} else {//加热中
long diffSeconds = Duration.between(now, endTime).getSeconds();//计算剩余时间
HeatCountdownVO heatCountdownVO = new HeatCountdownVO();
heatCountdownVO.setHeatModuleCode(heatModuleState.getModuleCode());
heatCountdownVO.setCountdown((int) diffSeconds);
heatCountdownVO.setCountdownStr(LocalDateTimeUtil.formatSecondsToHMS(diffSeconds));
heatCountdownVO.setStartTime(heatModuleState.getStartHeatTime());
heatCountdownVO.setEndTime(endTime);
heatCountdownVOList.add(heatCountdownVO);
}
}
}
} else if (heatModuleState.getHeatingType() == HeatingType.constant) {
LocalDateTime endTime = heatModuleState.getStartHeatTime().plusSeconds(heatModuleState.getTargetTime());
//判断是否达到目标加热时间
long diffSeconds = Duration.between(now, endTime).getSeconds();//计算剩余时间
if (diffSeconds <= 0) {//加热完毕
double trayLift = devicePositionService.getPosition(DevicePositionCode.trayLift).getDistance();
//抬起托盘
heatModuleService.heaterMotorMove(heatModuleState.getModuleCode(), trayLift);
heatModuleState.setTrayUp(1);
//关闭加棒
heatModuleService.heatRodClose(heatModuleState.getModuleCode());
//还原状态
heatModuleState.setStartHeatTime(null);//开始加热时间
heatModuleState.setTargetTime(null);//加热器目标加热时间
heatModuleState.setWarmUpTemperature(null);//加热器预热温度
heatModuleState.setHeatTemperature(null);//加热器加热温度
heatModuleState.setTargetTemperature(null);//加热器目标温度
heatModuleState.setHeatingType(HeatingType.finish);
}
}
}
if (!heatCountdownVOList.isEmpty()) {
webSocketSender.pushHeatCountdown(heatCountdownVOList);
}
} catch (Exception e) {
log.error("加热倒计时错误", e);
}

4
src/main/java/com/iflytop/gd/app/ws/client/DeviceEmergencyStopConfig.java

@ -1,10 +1,6 @@
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;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;

2
src/main/java/com/iflytop/gd/app/ws/server/WebSocketSender.java

@ -16,7 +16,7 @@ public class WebSocketSender {
websocketResult.setType(type);
websocketResult.setData(data);
WebSocketServer.sendMessageToClients(JSONUtil.toJsonStr(websocketResult));
log.info("WS::{}", JSONUtil.toJsonStr(websocketResult));
// log.info("WS::{}", JSONUtil.toJsonStr(websocketResult));
}
public void pushCraftsDebug(Object data) {

8
src/main/java/com/iflytop/gd/common/command/DeviceCommandGenerator.java

@ -10,6 +10,14 @@ public class DeviceCommandGenerator {
/**
* 移动
*/
public static DeviceCommandBundle doorMoveToEnd() {
return controlMotorCmd(CmdDevice.door_motor, CmdAction.move_end, null, "门 移动到最远距离");
}
/**
* 移动
*
* @param position 位置 单位mm
*/

4
src/main/java/com/iflytop/gd/common/enums/HeatingType.java

@ -20,4 +20,8 @@ public enum HeatingType {
* 恒温中
*/
constant,
/**
* 加热完成
*/
finish,
}

2
src/main/java/com/iflytop/gd/common/enums/command/CmdAction.java

@ -1,7 +1,7 @@
package com.iflytop.gd.common.enums.command;
public enum CmdAction {
move, move_by, move_joint, move_point, origin, rotate,
move, move_by, move_joint, move_point, origin, rotate, move_end,
open, close, stop, start, set, get,
open_power, close_power, open_circle, close_circle,

3
src/main/java/com/iflytop/gd/common/result/ResultCode.java

@ -37,9 +37,10 @@ public enum ResultCode implements IResultCode, Serializable {
OPERATION_NOT_ALLOWED("4003", "业务操作不允许"),
DATA_ALREADY_EXISTS("4004", "数据已存在"),
CONTAINER_NOT_FOUND("4005", "未找到对应溶液容器"),
CRAFT_RUNNING("4101", "工艺正在执行"),
CRAFT_CONTEXT_NULL("4102", "请先配置该加热区工艺"),
CRAFT_CONTAINER_NOT_FOUND("4005", "工艺未找到对应溶液容器"),
CRAFT_NO_TRAY("4005", "工艺未找到托盘"),
//============================ 5xxx系统 & 第三方 ============================
SYSTEM_ERROR("5000", "系统内部错误"),

9
src/main/java/com/iflytop/gd/common/utils/LocalDateTimeUtil.java

@ -3,16 +3,13 @@ package com.iflytop.gd.common.utils;
public class LocalDateTimeUtil {
/**
* 秒数格式化为 HH:mm:ss 格式
* @param diffSeconds 两个时间点相差的秒数可以为正或负
* @return 格式化后的 HH:mm:ss 字符串
* 秒数格式化为 mm:ss 格式
*/
public static String formatSecondsToHMS(long diffSeconds) {
long absSeconds = Math.abs(diffSeconds);
long hours = absSeconds / 3600;
long minutes = (absSeconds % 3600) / 60;
long minutes = absSeconds / 60;
long seconds = absSeconds % 60;
return String.format("%02d:%02d:%02d", hours, minutes, seconds);
return String.format("%02d:%02d", minutes, seconds);
}
}

25
src/main/java/com/iflytop/gd/hardware/command/handlers/DoorHandler.java

@ -5,8 +5,8 @@ import com.iflytop.gd.common.enums.command.CmdAction;
import com.iflytop.gd.common.enums.command.CmdDevice;
import com.iflytop.gd.hardware.command.CommandHandler;
import com.iflytop.gd.hardware.drivers.StepMotorDriver.DoorDriver;
import com.iflytop.gd.hardware.type.StepMotor.StepMotorMId;
import com.iflytop.gd.hardware.type.MId;
import com.iflytop.gd.hardware.type.StepMotor.StepMotorMId;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
@ -18,7 +18,7 @@ import java.util.stream.Collectors;
@Slf4j
@Component
@RequiredArgsConstructor
public class DoorHandler extends CommandHandler {
public class DoorHandler extends CommandHandler {
private final DoorDriver driver_;
private final Map<CmdDevice, StepMotorMId> stepMotorMIdMap_ = Map.ofEntries(
@ -26,11 +26,10 @@ public class DoorHandler extends CommandHandler {
);
private final Map<CmdDevice, MId> supportCmdDeviceMIdMap = stepMotorMIdMap_.entrySet().stream().
collect(Collectors.toMap(Map.Entry::getKey, entry -> entry.getValue().mid));
private final Set<CmdAction> supportActions = Set.of(CmdAction.set, CmdAction.origin, CmdAction.move, CmdAction.move_by, CmdAction.stop);
private final Set<CmdAction> supportActions = Set.of(CmdAction.set, CmdAction.origin, CmdAction.move, CmdAction.move_by, CmdAction.stop, CmdAction.move_end);
@Override
protected Map<CmdDevice, MId> getSupportCmdDeviceMIdMap()
{
protected Map<CmdDevice, MId> getSupportCmdDeviceMIdMap() {
return supportCmdDeviceMIdMap;
}
@ -45,24 +44,22 @@ public class DoorHandler extends CommandHandler {
StepMotorMId stepMotorMId = stepMotorMIdMap_.get(command.getDevice());
if (command.getAction() == CmdAction.origin) {
driver_.moveToHome(stepMotorMId);
}
else if(command.getAction() == CmdAction.stop) {
} else if (command.getAction() == CmdAction.stop) {
driver_.stop(stepMotorMId);
}
else if(command.getAction() == CmdAction.move) {
} else if (command.getAction() == CmdAction.move) {
double position = command.getParam().getPosition();
driver_.moveTo(stepMotorMId, position);
}
else if(command.getAction() == CmdAction.move_by) {
} else if (command.getAction() == CmdAction.move_by) {
double distance = command.getParam().getPosition();
driver_.moveBy(stepMotorMId, distance);
}
else if(command.getAction() == CmdAction.set) {
} else if (command.getAction() == CmdAction.set) {
Double speed = command.getParam().getSpeed();
if(speed != null) {
if (speed != null) {
driver_.setSpeed(stepMotorMId, speed);
}
} else if (command.getAction() == CmdAction.move_end) {
driver_.moveToEnd(stepMotorMId);
}
}
}

5
src/main/java/com/iflytop/gd/hardware/drivers/StepMotorDriver/DoorDriver.java

@ -76,4 +76,9 @@ public class DoorDriver{
stepMotorCtrlDriver_.stepMotorStop(stepMotorMId);
motorEnable(stepMotorMId, true);
}
public void moveToEnd(StepMotorMId stepMotorMId) throws Exception {
log.info("Motor {} Move To End", stepMotorMId.mid.getDescription());
stepMotorCtrlDriver_.stepMotorEasyMoveToEndPointBlock(stepMotorMId);
}
}

2
src/main/resources/application-dev.yml

@ -18,7 +18,7 @@ spring:
mybatis-plus:
configuration:
# 开启 SQL 日志输出(可选)
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
# log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
# 如果需要加载 XML 文件(自定义 SQL),可配置 mapper-locations:
mapper-locations: classpath*:mapper/*.xml

8
src/main/resources/sql/init.sql

@ -56,10 +56,10 @@ CREATE TABLE IF NOT EXISTS container
);
INSERT OR IGNORE INTO container (id, type, code, solution_id, pump_id, scale,capacity_total, capacity_used)
VALUES (1, 0, 'container_01', 1, 'acid_pump_01', 120,5000, 0),
(2, 0, 'container_02', 2, 'acid_pump_02', 100,5000, 2500),
(3, 0, 'container_03', 3, 'acid_pump_03', 111,5000, 2600),
(4, 0, 'container_04', 4, 'acid_pump_04', 107,5000, 4000),
VALUES (1, 0, 'container_01', 1, 'acid_pump_01', 364,5000, 0),
(2, 0, 'container_02', 2, 'acid_pump_02', 133,5000, 2500),
(3, 0, 'container_03', 3, 'acid_pump_03', 160,5000, 2600),
(4, 0, 'container_04', 4, 'acid_pump_04', 163,5000, 4000),
(5, 0, 'container_05', 5, 'acid_pump_05', 117,5000, 2400),
(6, 0, 'container_06', 6, 'acid_pump_06', 105,5000, 4500),
(7, 0, 'container_07', 7, 'acid_pump_07', 187,5000, 4900),

Loading…
Cancel
Save