Browse Source

调整设备状态推送逻辑

master
白凤吉 2 months ago
parent
commit
0c94fb7b30
  1. 20
      src/main/java/com/iflytop/sgs/SeparateGoldServiceApplication.java
  2. 2
      src/main/java/com/iflytop/sgs/app/cmd/control/LiquidAddCommand.java
  3. 2
      src/main/java/com/iflytop/sgs/app/controller/TrayController.java
  4. 32
      src/main/java/com/iflytop/sgs/app/core/CraftsContext.java
  5. 29
      src/main/java/com/iflytop/sgs/app/core/aspect/DeviceStateChangeAspect.java
  6. 37
      src/main/java/com/iflytop/sgs/app/model/bo/status/device/DeviceState.java
  7. 6
      src/main/java/com/iflytop/sgs/app/model/bo/status/device/DoorModuleState.java
  8. 8
      src/main/java/com/iflytop/sgs/app/model/bo/status/device/HeatModuleState.java
  9. 8
      src/main/java/com/iflytop/sgs/app/model/bo/status/device/SolutionContainerState.java
  10. 13
      src/main/java/com/iflytop/sgs/app/model/bo/status/device/SolutionModuleState.java
  11. 8
      src/main/java/com/iflytop/sgs/app/model/bo/status/device/TransferModuleState.java
  12. 13
      src/main/java/com/iflytop/sgs/app/model/bo/status/device/TrayState.java
  13. 14
      src/main/java/com/iflytop/sgs/app/model/bo/status/device/ValveState.java
  14. 1
      src/main/java/com/iflytop/sgs/app/model/dto/SetCraftsDTO.java
  15. 24
      src/main/java/com/iflytop/sgs/app/service/api/CraftsService.java
  16. 9
      src/main/java/com/iflytop/sgs/app/service/api/TrayService.java
  17. 57
      src/main/java/com/iflytop/sgs/app/service/crafts/CraftsStepService.java
  18. 7
      src/main/java/com/iflytop/sgs/app/service/device/DeviceInitService.java
  19. 2
      src/main/java/com/iflytop/sgs/app/service/device/DeviceStateService.java
  20. 2
      src/main/java/com/iflytop/sgs/common/result/ResultCode.java

20
src/main/java/com/iflytop/sgs/SeparateGoldServiceApplication.java

@ -2,14 +2,28 @@ package com.iflytop.sgs;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.env.ConfigurableEnvironment;
@SpringBootApplication
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class SeparateGoldServiceApplication {
public static void main(String[] args) {
SpringApplication.run(SeparateGoldServiceApplication.class, args);
SpringApplication app = new SpringApplication(SeparateGoldServiceApplication.class);
app.addInitializers(ctx -> {
try {
Thread.sleep(0);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});
ConfigurableApplicationContext ctx = app.run(args);
ConfigurableEnvironment env = ctx.getEnvironment();
String port = env.getProperty("local.server.port", env.getProperty("server.port", "8080"));
System.out.println("应用已启动");
System.out.println("访问地址 → http://localhost:" + port + "/");
System.out.println("文档地址 → http://localhost:" + port + "/doc.html");
}
}

2
src/main/java/com/iflytop/sgs/app/cmd/control/LiquidAddCommand.java

@ -101,7 +101,7 @@ public class LiquidAddCommand extends BaseCommandHandler {
double scale = Double.parseDouble(systemConfigService.getSystemConfigValueByCode(valveStateCode.getSystemConfigCode()));//根据溶液获取转换比
double position = volume * scale * 8 + preFillDistance;//加液泵的转数
solutionModuleService.liquidValveSwitch(cmdDTO.getCommandId(), cmdDTO.getCommand(), valveStateCode);//电磁阀对应通道打开
deviceStateService.getDeviceState().getSolutionModule().getValveState().setState(valveStateCode);//设置阀门状态
deviceStateService.getDeviceState().getSolutionModule().setValveState(valveStateCode);//设置阀门状态
for (int i = 0; i < jsonArray.size(); i++) {
int column = jsonArray.getInt(i);
if (column > 0 && column < 6) {

2
src/main/java/com/iflytop/sgs/app/controller/TrayController.java

@ -32,7 +32,7 @@ public class TrayController {
@Operation(summary = "拿走托盘")
@PostMapping("/out")
public Result<?> trayOut() {
public Result<?> trayOut(){
trayService.trayOut();
return Result.success();
}

32
src/main/java/com/iflytop/sgs/app/core/CraftsContext.java

@ -2,11 +2,14 @@ package com.iflytop.sgs.app.core;
import cn.hutool.json.JSONUtil;
import com.iflytop.sgs.app.model.bo.CraftsStep;
import com.iflytop.sgs.app.model.bo.status.crafts.CraftsState;
import com.iflytop.sgs.app.model.entity.Crafts;
import com.iflytop.sgs.app.model.entity.Ores;
import com.iflytop.sgs.app.service.crafts.CraftsStepService;
import com.iflytop.sgs.app.service.device.DeviceStateService;
import com.iflytop.sgs.app.ws.server.WebSocketSender;
import com.iflytop.sgs.common.constant.WebSocketMessageType;
import com.iflytop.sgs.common.enums.HeatModuleCode;
import com.iflytop.sgs.common.enums.automaton.CraftEvents;
import com.iflytop.sgs.common.enums.automaton.CraftStates;
import lombok.Getter;
@ -26,36 +29,47 @@ 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<CraftsStep> craftsStepList;
private final StateMachine<CraftStates, CraftEvents> sm;
private final WebSocketSender webSocketService;
private final CraftsStepService craftsStepService;
private final DeviceStateService deviceStateService;
private int currentIndex = 0;
/**
* 构造方法初始化上下文并启动状态机至 READY
*/
public CraftsContext(String heatId, Ores ores,
public CraftsContext(HeatModuleCode heatModuleCode, Ores ores,
Crafts craft,
StateMachineFactory<CraftStates, CraftEvents> factory,
WebSocketSender webSocketService,
CraftsStepService craftsStepService) {
this.heatId = heatId;
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());
CraftsState craftsState = new CraftsState();
craftsState.setState(sm.getState().getId());
craftsState.setOres(ores);
craftsState.setCraft(craft);
craftsState.setCurrentIndex(currentIndex);
deviceStateService.getDeviceState().getTrayByHeatModuleCode(heatModuleCode).setCrafts(craftsState);
this.sm = factory.getStateMachine(heatId);
sm.addStateListener(new StateMachineListenerAdapter<>() {
@Override
public void stateEntered(State<CraftStates, CraftEvents> state) {
Map<String, Object> dataMap = new HashMap<>();
dataMap.put("heatId", heatId);
dataMap.put("heatId", heatModuleCode.toString());
dataMap.put("state", state.getId());
dataMap.put("index", currentIndex);
webSocketService.push(WebSocketMessageType.CRAFTS_STATE, dataMap);
@ -98,7 +112,7 @@ public class CraftsContext implements Runnable {
}
} catch (Exception e) {
log.error("工艺执行失败", e);
webSocketService.pushCraftsDebug(CraftsDebugGenerator.generateJson(heatId, "工艺执行失败", e.getMessage()));
webSocketService.pushCraftsDebug(CraftsDebugGenerator.generateJson(heatModuleCode.toString(), "工艺执行失败", e.getMessage()));
Message<CraftEvents> stopMsg = MessageBuilder.withPayload(CraftEvents.ERROR_OCCUR).build();
Mono.from(sm.sendEvent(Mono.just(stopMsg))).block();
}
@ -113,10 +127,10 @@ public class CraftsContext implements Runnable {
*/
private boolean executeStep(CraftsStep step) throws Exception {
Map<String, Object> startData = new HashMap<>();
startData.put("heatId", heatId);
startData.put("heatId", heatModuleCode.toString());
startData.put("currentStep", step.getMethod());
webSocketService.push(WebSocketMessageType.CRAFTS_STEP, startData);
return craftsStepService.executeStep(heatId, step);
return craftsStepService.executeStep(heatModuleCode.toString(), step);
}
/**

29
src/main/java/com/iflytop/sgs/app/core/aspect/DeviceStateChangeAspect.java

@ -8,12 +8,8 @@ import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
@Slf4j
@Aspect
@Component
@ -22,41 +18,20 @@ public class DeviceStateChangeAspect {
private final WebSocketSender webSocketService;
private final DeviceStateService deviceStateService;
private final Lock lock = new ReentrantLock();
private Object beforeValue;
@Before("execution(* com.iflytop.sgs.app.model.bo.status..set*(..))")
public void beforeSetMethod(JoinPoint joinPoint) {
lock.lock();
try {
System.out.println(joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());
Object[] methodArgs = joinPoint.getArgs();
if (methodArgs != null && methodArgs.length > 0) {
beforeValue = methodArgs[0];
}
} catch (Exception e) {
log.error("处理状态变更前的值失败", e);
}
}
@After("execution(* com.iflytop.sgs.app.model.bo.status..set*(..))")
@After("execution(* com.iflytop.sgs.app.model.bo.status.device.*.set*(..))")
public void afterSetMethod(JoinPoint joinPoint) {
try {
String className = joinPoint.getSignature().getDeclaringType().getName(); // 获取类名
String methodName = joinPoint.getSignature().getName();
Object[] methodArgs = joinPoint.getArgs();
System.out.println(joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());
if (methodArgs != null && methodArgs.length > 0) {
// 保存修改后的值
Object afterValue = methodArgs[0];
log.info("设备状态发生改变,类型{}.{} ,from {} to {}", className, methodName, beforeValue, afterValue);
log.info("设备状态发生改变,类型{}.{}({})", className, methodName, afterValue);
webSocketService.push(WebSocketMessageType.STATUS, deviceStateService.getDeviceState());
}
} catch (Exception e) {
log.error("处理状态变更后的值失败", e);
} finally {
lock.unlock();
}
}
}

37
src/main/java/com/iflytop/sgs/app/model/bo/status/device/DeviceState.java

@ -1,27 +1,35 @@
package com.iflytop.sgs.app.model.bo.status.device;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.iflytop.sgs.app.model.entity.Tasks;
import com.iflytop.sgs.app.model.entity.User;
import com.iflytop.sgs.common.enums.HeatModuleCode;
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;
import java.util.ArrayList;
import java.util.List;
@Schema(description = "当前设备")
@Data
@Component
@Scope("prototype")
@RequiredArgsConstructor
@JsonIgnoreProperties(value = {"advisors", "frozen", "preFiltered", "proxyTargetClass", "targetSource", "exposeProxy", "advisorCount", "proxiedInterfaces", "targetClass"})
public class DeviceState {
@Schema(description = "门状态")
private final DoorModuleState doorModule = new DoorModuleState();
private final DoorModuleState doorModule;
@Schema(description = "转运机械臂状态")
private final TransferModuleState transferModule = new TransferModuleState();
private final TransferModuleState transferModule;
@Schema(description = "加液模块属性")
private final SolutionModuleState solutionModule = new SolutionModuleState();
private final SolutionModuleState solutionModule;
@Schema(description = "加热模块属性")
private final List<HeatModuleState> heatModule = new ArrayList<>();
private List<HeatModuleState> heatModule = new ArrayList<>();
@Schema(description = "托盘")
private final List<TrayState> trays = new ArrayList<>();
private List<TrayState> trays = new ArrayList<>();
@Schema(description = "虚拟模式,true为虚拟")
private boolean virtual = false;
@Schema(description = "初始化状态,true初始化完毕")
@ -70,6 +78,7 @@ public class DeviceState {
}
return null;
}
public synchronized TrayState getTrayState(String trayUUID) {
for (TrayState t : trays) {
if (t.getUuid().equals(trayUUID)) {
@ -79,4 +88,22 @@ public class DeviceState {
return null;
}
/**
* 获取一个空闲的加热模块
*/
public synchronized HeatModuleState getFirstIdleHeatModule() {
for (HeatModuleState h : heatModule) {
if (!h.isEnable()) {
continue;
}
for (TrayState t : trays) {
if (h.getModuleCode().equals(t.getHeatModuleCode())) {
break;
}
}
return h;
}
return null;
}
}

6
src/main/java/com/iflytop/sgs/app/model/bo/status/device/DoorModuleState.java

@ -1,10 +1,16 @@
package com.iflytop.sgs.app.model.bo.status.device;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
@Schema(description = "门")
@Data
@Component
@Scope("prototype")
@JsonIgnoreProperties(value = {"advisors", "frozen", "preFiltered", "proxyTargetClass", "targetSource", "exposeProxy", "advisorCount", "proxiedInterfaces", "targetClass"})
public class DoorModuleState {
@Schema(description = "是否开门,true为开启状态,false为关闭状态")
private boolean open = false;

8
src/main/java/com/iflytop/sgs/app/model/bo/status/device/HeatModuleState.java

@ -1,12 +1,20 @@
package com.iflytop.sgs.app.model.bo.status.device;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.iflytop.sgs.common.enums.HeatModuleCode;
import com.iflytop.sgs.common.enums.HeatingType;
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 HeatModuleState {
@Schema(description = "加热模块code")
private HeatModuleCode moduleCode;

8
src/main/java/com/iflytop/sgs/app/model/bo/status/device/SolutionContainerState.java

@ -1,12 +1,20 @@
package com.iflytop.sgs.app.model.bo.status.device;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.iflytop.sgs.common.enums.ContainerCode;
import com.iflytop.sgs.common.enums.ContainerType;
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 SolutionContainerState {
@Schema(description = "容器数据id")
private Long id;

13
src/main/java/com/iflytop/sgs/app/model/bo/status/device/SolutionModuleState.java

@ -1,14 +1,23 @@
package com.iflytop.sgs.app.model.bo.status.device;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.iflytop.sgs.common.enums.ContainerCode;
import com.iflytop.sgs.common.enums.ValveStateCode;
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;
import java.util.ArrayList;
import java.util.List;
@Schema(description = "加液模块")
@Data
@Component
@Scope("prototype")
@RequiredArgsConstructor
@JsonIgnoreProperties(value = {"advisors", "frozen", "preFiltered", "proxyTargetClass", "targetSource", "exposeProxy", "advisorCount", "proxiedInterfaces", "targetClass"})
public class SolutionModuleState {
@Schema(description = "是否空闲,true为空闲,false为占用")
private boolean idle = true;
@ -22,8 +31,8 @@ public class SolutionModuleState {
@Schema(description = "是否正在加液,true正在加液,false未运行")
private boolean pumping = false;
@Schema(description = "电磁阀状态")
private ValveState valveState;
@Schema(description = "当前电磁阀通道")
private ValveStateCode valveState;
/*
* 根据容器code获取容器状态

8
src/main/java/com/iflytop/sgs/app/model/bo/status/device/TransferModuleState.java

@ -1,10 +1,18 @@
package com.iflytop.sgs.app.model.bo.status.device;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
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 TransferModuleState {
@Schema(description = "是否空闲,true为空闲,false为占用")
private boolean idle = true;

13
src/main/java/com/iflytop/sgs/app/model/bo/status/device/TrayState.java

@ -1,14 +1,23 @@
package com.iflytop.sgs.app.model.bo.status.device;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.iflytop.sgs.app.model.bo.status.crafts.CraftsState;
import com.iflytop.sgs.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();
@ -31,11 +40,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.setColumnNum(i + 1);
tubes[i] = tubeState;
}
}
}

14
src/main/java/com/iflytop/sgs/app/model/bo/status/device/ValveState.java

@ -1,14 +0,0 @@
package com.iflytop.sgs.app.model.bo.status.device;
import com.iflytop.sgs.common.enums.ValveStateCode;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(description = "电磁阀状态")
@Data
public class ValveState {
@Schema(description = "当前电磁阀通道")
private ValveStateCode state;
}

1
src/main/java/com/iflytop/sgs/app/model/dto/SetCraftsDTO.java

@ -13,7 +13,6 @@ public class SetCraftsDTO {
@Schema(description = "工艺id")
private Long craftId;
@NotNull
@Schema(description = "加热区id")
private String heatId;
}

24
src/main/java/com/iflytop/sgs/app/service/api/CraftsService.java

@ -4,12 +4,16 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.iflytop.sgs.app.core.CraftsContext;
import com.iflytop.sgs.app.mapper.CraftsMapper;
import com.iflytop.sgs.app.model.bo.status.crafts.CraftsState;
import com.iflytop.sgs.app.model.bo.status.device.HeatModuleState;
import com.iflytop.sgs.app.model.entity.Crafts;
import com.iflytop.sgs.app.model.entity.Ores;
import com.iflytop.sgs.app.model.vo.CraftStatusVO;
import com.iflytop.sgs.app.model.vo.SetCraftsVO;
import com.iflytop.sgs.app.service.crafts.CraftsStepService;
import com.iflytop.sgs.app.service.device.DeviceStateService;
import com.iflytop.sgs.app.ws.server.WebSocketSender;
import com.iflytop.sgs.common.enums.HeatModuleCode;
import com.iflytop.sgs.common.enums.automaton.CraftEvents;
import com.iflytop.sgs.common.enums.automaton.CraftStates;
import com.iflytop.sgs.common.exception.AppException;
@ -33,6 +37,7 @@ import java.util.stream.Collectors;
@Service
@RequiredArgsConstructor
public class CraftsService extends ServiceImpl<CraftsMapper, Crafts> {
private final DeviceStateService deviceStateService;
private final StateMachineFactory<CraftStates, CraftEvents> stateMachineFactory;
private final WebSocketSender webSocketService;
private final CraftsStepService craftsStepService;
@ -50,6 +55,19 @@ public class CraftsService extends ServiceImpl<CraftsMapper, Crafts> {
* 配置工艺
*/
public synchronized SetCraftsVO setCraft(Long craftId, String heatId) {
HeatModuleCode heatModuleCode;
if(heatId == null){
//获取一个空加热模块
HeatModuleState idleHeatModule = deviceStateService.getDeviceState().getFirstIdleHeatModule();
if (idleHeatModule == null) {
throw new AppException(ResultCode.CRAFT_IDLE_HEAT_MODULE_NOT_FOUND);
}
heatModuleCode = idleHeatModule.getModuleCode();
heatId = heatModuleCode.toString();
}else{
heatModuleCode = HeatModuleCode.valueOf(heatId);
}
// 校验已有上下文状态仅允许在 READYSTOPPED FINISHED 状态下重置
CraftsContext existing = contextMap.get(heatId);
if (existing != null) {
@ -62,14 +80,16 @@ public class CraftsService extends ServiceImpl<CraftsMapper, Crafts> {
Crafts craft = this.getById(craftId);
Ores ores = oresService.getById(craft.getOresId());
CraftsContext ctx = new CraftsContext(
heatId,
heatModuleCode,
ores,
craft,
stateMachineFactory,
webSocketService,
craftsStepService
craftsStepService,
deviceStateService
);
contextMap.put(heatId, ctx);
SetCraftsVO setCraftsVO = new SetCraftsVO();
setCraftsVO.setHeatId(heatId);
setCraftsVO.setCraftsName(craft.getName());

9
src/main/java/com/iflytop/sgs/app/service/api/TrayService.java

@ -4,6 +4,8 @@ import com.iflytop.sgs.app.model.bo.status.device.TrayState;
import com.iflytop.sgs.app.model.vo.SetTrayTubeVO;
import com.iflytop.sgs.app.service.device.DeviceStateService;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.stereotype.Service;
import java.util.List;
@ -15,12 +17,13 @@ import java.util.List;
@RequiredArgsConstructor
public class TrayService {
private final DeviceStateService deviceStateService;
private final ObjectProvider<TrayState> trayStateProvider;
/**
* 放入了新托盘
*/
public synchronized TrayState trayIn() {
TrayState trayState = new TrayState();
TrayState trayState = trayStateProvider.getObject();
trayState.setInFeedArea(true);
deviceStateService.getDeviceState().getTrays().add(trayState);
deviceStateService.getDeviceState().getSolutionModule().setFeedAreaTrayStatus(true);
@ -30,9 +33,9 @@ public class TrayService {
/**
* 拿走了托盘
*/
public synchronized void trayOut() {
public synchronized void trayOut(){
List<TrayState> trayList = deviceStateService.getDeviceState().getTrays();
trayList.removeIf(TrayState::isInSolutionPositon);
trayList.removeIf(TrayState::isInFeedArea);
deviceStateService.getDeviceState().getSolutionModule().setFeedAreaTrayStatus(false);
}

57
src/main/java/com/iflytop/sgs/app/service/crafts/CraftsStepService.java

@ -30,61 +30,12 @@ public class CraftsStepService {
String method = step.getMethod();
JSONObject params = step.getParams();
//设备包含分步运行模式以及自动调度模式分步运行模式共分为5步自动调度模式则是根据五个步骤按照时间间隔以及优先级顺序进行自动执行
//分步模式
//人员将准备好的样品手动放入试管中再放置到设备的上料工位后
//加液
//抽取
//加热温度时间
//退火温度时间
//第一步
//夹具将托盘取走转移至自动化加酸工位进行逐排加酸加酸后放置再相应的石墨炉中进行加热加热温度约100
//第二步
//将托盘从石墨炉中取出进行抽酸抽酸后逐排添加第二种酸液然后再放回石墨炉中进行加热 加热温度约100
//第三步将托盘从石墨炉中取出进行抽酸抽酸后逐排添加满蒸馏水再将水抽走重复清洗两遍将托盘放置回石墨炉中进行烘干水分温度升高至150烘干15min
//第四步烘干后将托盘转移至退火工位在400下退火5min
//第五步将托盘取走放置在下料工位
//具体操作流程单批样品操作流程
//1 人员上料设定及开始
// 人员手动将样品放至上料工位设定分金时间记录分金编号按开始键开始分金
//2 执行分步程序第一步加酸
//如果三个电炉当中有空闲电炉并且空闲电炉的温度在120摄氏度以下则具备自动流程开始条件自动执行分步程序第一步
//3 等待一段时间进行反应默认时间20min可在开始之前单独设置
//4 执行分步程序第二步换酸
// 到时间后系统对此炉样品自动执行分步程序第二步
//5 再次等待一段时间进行反应默认时间19min可在开始之前单独设置
//6 执行分步程序第三步清洗及烘干
//到时间后系统对此炉样品自动执行分步程序第三步
//7 再次等待一段时间进行反应默认时间20min可在开始之前单独设置
//8 执行分步程序第四步退火
//到时间后系统对此炉样品自动执行分步程序第四步
//9 再次等待一段时间进行反应默认时间5min可在开始之前单独设置
//10 执行分步程序第五步下料
//到时间后系统对此炉样品自动执行分步程序第五步流程结束
//下料时需判断下料工位传感器无托盘否则发出报错提示
//每批样品的工艺流程均为上述10个步骤其中有五个自动操作步骤操作步骤耗时一般在几分钟之内加热时间稍微延长对检测结果没有影响夹具忙碌没有立即执行对检测检测结果没有影响
//多批样品自动调度规则
//由于设备具备三个电炉 可交错处理三批样品每批样品均是同样的流程但上料的时间不固定也就是每批样品 被人员准备好并拿到上料工位 的时间不固定以下为处理原则
//1每批样品上料的时间不固定只要上/下料工位上没有样品并且有电炉空余且电炉温度小于120度均可上料开始流程
//3工艺开始时若三个电炉均无样品优先将样品放置在左边的电炉电炉A中有样品时则将样品放置在电炉B中若电炉AB均有样品则放置在电炉C中
//4样品处理的时间均可延后没有必须立即执行的步骤当有某一批样品到时间需要执行某一步时若此时机械臂正在处理其他样品则当前任务挂起等待夹具处理完上一个任务再进行处理即可
//如果有多个任务先后到达处理时间需要进行处理此时有任务正在执行则需要将这些任务按照时间顺序都挂起等待任务执行完毕之后再依次执行在执行过程中如果有新的任务生成则继续依次挂起逐个操作
//需求功能统计
//1 开始自动调度模式之前开始界面显示四个等待时间上述第3579步按照默认数值进行显示可以支持修改
//2 可单独中断某一批次样品中断后人员把托盘取走不继续执行流程需要回原位的人员手动将机械臂等回原位以便出现问题时可以再次重新执行流程
//3 可以选择直接从五步中的某一步进行执行也就是从中间开始执行不从第一步开始执行也可以设置n分钟后开始不立即执行
//4 系统故障重启后可以恢复断电前状态继续自动流程
//5 遇到有电炉损坏不具备上料开始自动流程条件时可以手动把这条线关掉执行第一步时不会选择向这条线进行放置样品
return switch (method) {
default -> true;

7
src/main/java/com/iflytop/sgs/app/service/device/DeviceInitService.java

@ -6,7 +6,7 @@ import com.iflytop.sgs.common.enums.HeatModuleCode;
import jakarta.annotation.PostConstruct;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.stereotype.Service;
import java.util.List;
@ -16,6 +16,7 @@ import java.util.List;
@RequiredArgsConstructor
public class DeviceInitService {
private final DeviceStateService deviceStateService;
private final ObjectProvider<HeatModuleState> heatModuleStateProvider;
@PostConstruct
public void init() {
@ -38,11 +39,11 @@ public class DeviceInitService {
}
public void initDeviceState() {
//初始化加热模块属性
DeviceState deviceState = deviceStateService.getDeviceState();
List<HeatModuleState> heatArea = deviceState.getHeatModule();
for (HeatModuleCode code : HeatModuleCode.values()) {
heatArea.add(new HeatModuleState(code));
heatArea.add(heatModuleStateProvider.getObject(code));
}
}
}

2
src/main/java/com/iflytop/sgs/app/service/device/DeviceStateService.java

@ -15,7 +15,7 @@ import java.util.concurrent.atomic.AtomicReference;
@RequiredArgsConstructor
public class DeviceStateService {
@Getter
private final DeviceState deviceState = new DeviceState();
private final DeviceState deviceState;
@Getter
private final AtomicReference<CommandMutexState> commandMutexState = new AtomicReference<>(new CommandMutexState());

2
src/main/java/com/iflytop/sgs/common/result/ResultCode.java

@ -36,10 +36,10 @@ public enum ResultCode implements IResultCode, Serializable {
INVALID_CREDENTIALS("4002", "用户名或密码错误"),
OPERATION_NOT_ALLOWED("4003", "业务操作不允许"),
DATA_ALREADY_EXISTS("4004", "数据已存在"),
CRAFT_RUNNING("4101", "工艺正在执行"),
CRAFT_CONTEXT_NULL("4102", "请先配置该加热区工艺"),
CRAFT_CONTAINER_NOT_FOUND("4005", "工艺未找到对应溶液容器"),
CRAFT_IDLE_HEAT_MODULE_NOT_FOUND("4005", "工艺未找到空闲的加热模块"),
//============================ 5xxx系统 & 第三方 ============================
SYSTEM_ERROR("5000", "系统内部错误"),
SERVICE_UNAVAILABLE("5001", "服务暂不可用"),

Loading…
Cancel
Save