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

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

@ -1,13 +1,12 @@
package com.iflytop.gd.app.core; package com.iflytop.gd.app.core;
import cn.hutool.json.JSONUtil; 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.CraftEvents;
import com.iflytop.gd.app.common.enums.CraftStates; import com.iflytop.gd.app.common.enums.CraftStates;
import com.iflytop.gd.app.model.bo.CraftsStep; 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.model.entity.Crafts;
import com.iflytop.gd.app.service.WebSocketService; import com.iflytop.gd.app.service.WebSocketService;
import com.iflytop.gd.common.constant.WebSocketMessageType;
import lombok.Getter; import lombok.Getter;
import org.springframework.messaging.Message; import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder; import org.springframework.messaging.support.MessageBuilder;
@ -27,13 +26,11 @@ public class CraftsContext implements Runnable {
private final List<CraftsStep> craftsStepList; private final List<CraftsStep> craftsStepList;
private final StateMachine<CraftStates, CraftEvents> sm; private final StateMachine<CraftStates, CraftEvents> sm;
private final WebSocketService ws; private final WebSocketService ws;
private final CraftsStepService craftsStepService;
private int currentIndex = 0; 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.heatId = heatId;
this.craftsStepList = JSONUtil.parseArray(craft.getSteps()).toList(CraftsStep.class); this.craftsStepList = JSONUtil.parseArray(craft.getSteps()).toList(CraftsStep.class);
this.craftsStepService = craftsStepService;
this.ws = ws; this.ws = ws;
this.sm = factory.getStateMachine(heatId); this.sm = factory.getStateMachine(heatId);
@ -46,8 +43,7 @@ public class CraftsContext implements Runnable {
Map<String, Object> dataMap = new HashMap<>(); Map<String, Object> dataMap = new HashMap<>();
dataMap.put("heatId", heatId); dataMap.put("heatId", heatId);
dataMap.put("event", to.getId()); 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 服务执行具体命令 // TODO: 调用 craftsStepService device 服务执行具体命令
return true; 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; package com.iflytop.gd.app.model.bo;
import cn.hutool.json.JSONObject; import cn.hutool.json.JSONObject;
import lombok.Data;
@Data
public class CraftsStep { 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.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 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.mapper.CraftsMapper;
import com.iflytop.gd.app.model.entity.Crafts; import com.iflytop.gd.app.model.entity.Crafts;
import jakarta.annotation.PostConstruct;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.springframework.statemachine.config.StateMachineFactory;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.concurrent.*;
import java.util.stream.Collectors; import java.util.stream.Collectors;
/** /**
* 工艺
* 工艺执行管理服务每个 heatId 对应一个独立线程执行任务
*/ */
@Service @Service
@RequiredArgsConstructor @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) { public List<Crafts> selectAllByOresId(Long oresId) {
return this.baseMapper.selectAllByOresId(oresId); return this.baseMapper.selectAllByOresId(oresId);
@ -40,5 +121,4 @@ public class CraftsService extends ServiceImpl<CraftsMapper, Crafts>{
.collect(Collectors.toList()); .collect(Collectors.toList());
return this.removeByIds(ids); 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 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