Browse Source

fix:完善工艺

tags/freeze
白凤吉 3 months ago
parent
commit
bac4490fd0
  1. 14
      src/main/java/com/iflytop/gd/app/controller/CraftsController.java
  2. 17
      src/main/java/com/iflytop/gd/app/core/CraftsContext.java
  3. 6
      src/main/java/com/iflytop/gd/app/model/bo/CraftsStep.java
  4. 86
      src/main/java/com/iflytop/gd/app/service/CraftsService.java
  5. 100
      src/main/java/com/iflytop/gd/app/service/CraftsStepService.java
  6. 10
      src/main/java/com/iflytop/gd/common/constant/WebSocketMessageType.java

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

@ -4,11 +4,10 @@ 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.service.CraftsStepService;
import com.iflytop.gd.common.result.Result;
import com.iflytop.gd.common.result.ResultCode;
import com.iflytop.gd.app.model.entity.Crafts;
import com.iflytop.gd.app.service.CraftsService;
import com.iflytop.gd.common.result.Result;
import com.iflytop.gd.common.result.ResultCode;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
@ -25,7 +24,6 @@ import java.util.List;
@Slf4j
public class CraftsController {
private final CraftsService craftsService;
private final CraftsStepService craftsStepService;
@Operation(summary = "根据矿石id获取工艺列表")
@GetMapping("/list/{oresId}")
@ -73,7 +71,7 @@ public class CraftsController {
@Operation(summary = "开始执行工艺")
@PostMapping("/start")
public Result<String> startCrafts(@RequestBody StartCraftsDTO startCraftsDTO) {
boolean isSuccess = craftsStepService.startCrafts(startCraftsDTO.getCraftId(), startCraftsDTO.getHeatId());
boolean isSuccess = craftsService.startCrafts(startCraftsDTO.getCraftId(), startCraftsDTO.getHeatId());
if (isSuccess) {
return Result.success();
}
@ -83,21 +81,21 @@ public class CraftsController {
@Operation(summary = "暂停执行工艺")
@PostMapping("/pause")
public Result<String> pauseCrafts(@RequestBody PauseCraftsDto pauseCraftsDto) {
craftsStepService.pauseCrafts(pauseCraftsDto.getHeatId());
craftsService.pauseCrafts(pauseCraftsDto.getHeatId());
return Result.success();
}
@Operation(summary = "恢复执行工艺")
@PostMapping("/resume")
public Result<String> resumeCrafts(@RequestBody ResumeCraftsDto resumeCraftsDto) {
craftsStepService.resumeCrafts(resumeCraftsDto.getHeatId());
craftsService.resumeCrafts(resumeCraftsDto.getHeatId());
return Result.success();
}
@Operation(summary = "停止执行工艺")
@PostMapping("/stop")
public Result<String> stopCrafts(@RequestBody StopCraftsDto stopCraftsDto) {
boolean isSuccess = craftsStepService.stopCrafts(stopCraftsDto.getHeatId());
boolean isSuccess = craftsService.stopCrafts(stopCraftsDto.getHeatId());
if (isSuccess) {
return Result.success();
}

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

@ -1,13 +1,12 @@
package com.iflytop.gd.app.core;
import cn.hutool.json.JSONUtil;
import com.iflytop.gd.common.constant.WebSocketMessageType;
import com.iflytop.gd.app.common.enums.CraftEvents;
import com.iflytop.gd.app.common.enums.CraftStates;
import com.iflytop.gd.app.model.bo.CraftsStep;
import com.iflytop.gd.app.service.CraftsStepService;
import com.iflytop.gd.app.model.entity.Crafts;
import com.iflytop.gd.app.service.WebSocketService;
import com.iflytop.gd.common.constant.WebSocketMessageType;
import lombok.Getter;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
@ -27,13 +26,11 @@ public class CraftsContext implements Runnable {
private final List<CraftsStep> craftsStepList;
private final StateMachine<CraftStates, CraftEvents> sm;
private final WebSocketService ws;
private final CraftsStepService craftsStepService;
private int currentIndex = 0;
public CraftsContext(String heatId, Crafts craft, StateMachineFactory<CraftStates, CraftEvents> factory, CraftsStepService craftsStepService, WebSocketService ws) {
public CraftsContext(String heatId, Crafts craft, StateMachineFactory<CraftStates, CraftEvents> factory, WebSocketService ws) {
this.heatId = heatId;
this.craftsStepList = JSONUtil.parseArray(craft.getSteps()).toList(CraftsStep.class);
this.craftsStepService = craftsStepService;
this.ws = ws;
this.sm = factory.getStateMachine(heatId);
@ -46,8 +43,7 @@ public class CraftsContext implements Runnable {
Map<String, Object> dataMap = new HashMap<>();
dataMap.put("heatId", heatId);
dataMap.put("event", to.getId());
dataMap.put("index", currentIndex);
ws.push(WebSocketMessageType.CRAFTS, dataMap);
ws.push(WebSocketMessageType.CRAFTS_STATE, dataMap);
}
});
}
@ -82,7 +78,12 @@ public class CraftsContext implements Runnable {
}
}
private boolean executeStep(CraftsStep step) {
private boolean executeStep(CraftsStep step) throws InterruptedException {
Map<String, Object> dataMap = new HashMap<>();
dataMap.put("heatId", heatId);
dataMap.put("currentStep", step.getMethod());
ws.push(WebSocketMessageType.CRAFTS_STEP, dataMap);
Thread.sleep(3000);
// TODO: 调用 craftsStepService device 服务执行具体命令
return true;
}

6
src/main/java/com/iflytop/gd/app/model/bo/CraftsStep.java

@ -1,8 +1,10 @@
package com.iflytop.gd.app.model.bo;
import cn.hutool.json.JSONObject;
import lombok.Data;
@Data
public class CraftsStep {
String name;
JSONObject params;
private String method;
private JSONObject params;
}

86
src/main/java/com/iflytop/gd/app/service/CraftsService.java

@ -2,21 +2,102 @@ package com.iflytop.gd.app.service;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.iflytop.gd.app.common.enums.CraftEvents;
import com.iflytop.gd.app.common.enums.CraftStates;
import com.iflytop.gd.app.core.CraftsContext;
import com.iflytop.gd.app.mapper.CraftsMapper;
import com.iflytop.gd.app.model.entity.Crafts;
import jakarta.annotation.PostConstruct;
import lombok.RequiredArgsConstructor;
import org.springframework.statemachine.config.StateMachineFactory;
import org.springframework.stereotype.Service;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.*;
import java.util.stream.Collectors;
/**
* 工艺
* 工艺执行管理服务每个 heatId 对应一个独立线程执行任务
*/
@Service
@RequiredArgsConstructor
public class CraftsService extends ServiceImpl<CraftsMapper, Crafts>{
public class CraftsService extends ServiceImpl<CraftsMapper, Crafts> {
private final StateMachineFactory<CraftStates, CraftEvents> stateMachineFactory;
private final WebSocketService webSocketService;
private ExecutorService executor;
private final ConcurrentHashMap<String, CraftsContext> contextMap = new ConcurrentHashMap<>();
private final ConcurrentHashMap<String, Future<?>> futureMap = new ConcurrentHashMap<>();
@PostConstruct
public void init() {
this.executor = Executors.newCachedThreadPool();
}
/**
* 开始执行工艺
*/
public synchronized boolean startCrafts(Long craftId, String heatId) {
if (futureMap.containsKey(heatId)) { // 已有任务在执行不重复启动
return false;
}
Crafts craft = this.getById(craftId);
if (craft == null) {
return false;
}
CraftsContext ctx = new CraftsContext(heatId, craft, stateMachineFactory, webSocketService);
CompletableFuture<Void> cf = CompletableFuture.runAsync(() -> {
try {
ctx.run();
} finally {
contextMap.remove(heatId);
futureMap.remove(heatId);
}
}, executor);
contextMap.put(heatId, ctx);
futureMap.put(heatId, cf);
return true;
}
/**
* 暂停执行工艺
*/
public synchronized void pauseCrafts(String heatId) {
CraftsContext ctx = contextMap.get(heatId);
if (ctx != null) {
ctx.pause();
}
}
/**
* 恢复执行工艺
*/
public synchronized void resumeCrafts(String heatId) {
CraftsContext ctx = contextMap.get(heatId);
if (ctx != null) {
ctx.resume();
}
}
/**
* 停止执行工艺
*/
public synchronized boolean stopCrafts(String heatId) {
CraftsContext ctx = contextMap.get(heatId);
Future<?> future = futureMap.get(heatId);
if (ctx != null && future != null) {
ctx.stop();
future.cancel(true);
contextMap.remove(heatId);
futureMap.remove(heatId);
return true;
}
return false;
}
// TODO: 如需提供查询当前执行状态可添加 getStatus(heatId) 方法返回 ctx.getCurrentIndex(), ctx.getSm().getState().getId(), ctx.getRemainingSteps()
public List<Crafts> selectAllByOresId(Long oresId) {
return this.baseMapper.selectAllByOresId(oresId);
@ -40,5 +121,4 @@ public class CraftsService extends ServiceImpl<CraftsMapper, Crafts>{
.collect(Collectors.toList());
return this.removeByIds(ids);
}
}

100
src/main/java/com/iflytop/gd/app/service/CraftsStepService.java

@ -1,100 +0,0 @@
package com.iflytop.gd.app.service;
import com.iflytop.gd.app.common.enums.CraftEvents;
import com.iflytop.gd.app.common.enums.CraftStates;
import com.iflytop.gd.app.core.CraftsContext;
import com.iflytop.gd.app.model.entity.Crafts;
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.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
/**
* 设备步骤操作
*/
@Slf4j
@Service
@RequiredArgsConstructor
public class CraftsStepService {
private final CraftsService craftsService;
private final StateMachineFactory<CraftStates, CraftEvents> stateMachineFactory;
private final WebSocketService webSocketService;
private ExecutorService executor;
private final ConcurrentHashMap<String, CraftsContext> contextMap = new ConcurrentHashMap<>();
private final ConcurrentHashMap<String, Future<?>> futureMap = new ConcurrentHashMap<>();
@PostConstruct
public void init() {
this.executor = Executors.newCachedThreadPool();
}
/**
* 开始执行工艺
*/
public synchronized boolean startCrafts(Long craftId, String heatId) {
if (futureMap.containsKey(heatId)) {// 已有任务在执行不重复启动
return false;
}
Crafts craft = craftsService.getById(craftId);
if (craft == null) {
return false;
}
CraftsContext ctx = new CraftsContext(
heatId,
craft,
stateMachineFactory,
this,
webSocketService
);
Future<?> future = executor.submit(ctx);
contextMap.put(heatId, ctx);
futureMap.put(heatId, future);
return true;
}
/**
* 暂停执行工艺
*/
public synchronized void pauseCrafts(String heatId) {
CraftsContext ctx = contextMap.get(heatId);
if (ctx != null) {
ctx.pause();
}
}
/**
* 恢复执行工艺
*/
public synchronized void resumeCrafts(String heatId) {
CraftsContext ctx = contextMap.get(heatId);
if (ctx != null) {
ctx.resume();
}
}
/**
* 停止执行工艺
*/
public synchronized boolean stopCrafts(String heatId) {
CraftsContext ctx = contextMap.get(heatId);
Future<?> future = futureMap.get(heatId);
if (ctx != null && future != null) {
ctx.stop();
future.cancel(true);
contextMap.remove(heatId);
futureMap.remove(heatId);
return true;
}
return false;
}
// TODO: 如需提供查询当前执行状态可在此类添加 getStatus(heatId) 方法返回 ctx.getCurrentIndex(), ctx.getSm().getState().getId(), ctx.getRemainingSteps()
}

10
src/main/java/com/iflytop/gd/common/constant/WebSocketMessageType.java

@ -13,10 +13,16 @@ public class WebSocketMessageType {
* 设备指令反馈
*/
public static final String CMD = "cmd";
/**
* 工艺执行步骤反馈
*/
public static final String CRAFTS_STEP = "crafts_step";
/**
* 工艺执行反馈
* 工艺执行状态反馈
*/
public static final String CRAFTS = "crafts";
public static final String CRAFTS_STATE = "crafts_state";
/**
* 容器剩余状态
*/

Loading…
Cancel
Save