package com.zy.core.plugin;
|
|
import com.alibaba.fastjson.JSON;
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
import com.zy.asrs.entity.*;
|
import com.zy.asrs.service.*;
|
import com.zy.common.utils.RedisUtil;
|
import com.zy.core.News;
|
import com.zy.core.cache.MessageQueue;
|
import com.zy.core.cache.SlaveConnection;
|
import com.zy.core.dispatch.StationCommandDispatcher;
|
import com.zy.core.enums.*;
|
import com.zy.core.model.StationObjModel;
|
import com.zy.core.model.Task;
|
import com.zy.core.model.command.CrnCommand;
|
import com.zy.core.model.command.StationCommand;
|
import com.zy.core.model.protocol.CrnProtocol;
|
import com.zy.core.network.fake.FakeConfigKeys;
|
import com.zy.core.network.fake.FakeConfigSupport;
|
import com.zy.core.plugin.api.MainProcessPluginApi;
|
import com.zy.core.plugin.station.FakeStationMonitor;
|
import com.zy.core.plugin.station.FakeTaskGenerator;
|
import com.zy.core.plugin.store.StoreInTaskContext;
|
import com.zy.core.plugin.store.StoreInTaskGenerationService;
|
import com.zy.core.plugin.store.StoreInTaskPolicy;
|
import com.zy.core.task.MainProcessLane;
|
import com.zy.core.task.MainProcessTaskSubmitter;
|
import com.zy.core.thread.CrnThread;
|
import com.zy.core.thread.StationThread;
|
import com.zy.core.utils.CrnOperateProcessUtils;
|
import com.zy.core.utils.DualCrnOperateProcessUtils;
|
import com.zy.core.utils.StationOperateProcessUtils;
|
import com.zy.system.entity.Config;
|
import com.zy.system.service.ConfigService;
|
import lombok.extern.slf4j.Slf4j;
|
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.stereotype.Component;
|
|
import java.util.*;
|
|
@Slf4j
|
@Component
|
public class FakeProcess implements MainProcessPluginApi, StoreInTaskPolicy {
|
private long getMainDispatchIntervalMs() {
|
return FakeConfigSupport.getLong(FakeConfigKeys.FAKE_STATION_IDLE_LOOP_DELAY_MS, 200L);
|
}
|
|
private long getAsyncDispatchIntervalMs() {
|
return Math.max(50L, FakeConfigSupport.getLong(FakeConfigKeys.FAKE_STATION_INITIALIZE_DELAY_MS, 50L));
|
}
|
|
private long getOutStationStayTimeoutMs() {
|
return FakeConfigSupport.getLong(FakeConfigKeys.FAKE_OUT_STATION_STAY_TIMEOUT_MS, 3000L);
|
}
|
|
private static volatile String enableFake = "N";
|
|
private static volatile String fakeRealTaskRequestWms = "N";
|
private static volatile String fakeGenerateInTask = "Y";
|
private static volatile String fakeGenerateOutTask = "Y";
|
|
private static final Map<String, Long> OUT_STATION_STAY_MARKER = new HashMap<String, Long>();
|
|
private final Object outStationStayLock = new Object();
|
|
private boolean shouldDispatchOutStationWriteInfo(String taskNo) {
|
long now = System.currentTimeMillis();
|
long timeoutMs = getOutStationStayTimeoutMs();
|
synchronized (outStationStayLock) {
|
Long lastTime = OUT_STATION_STAY_MARKER.get(taskNo);
|
if (lastTime == null || now - lastTime >= timeoutMs) {
|
OUT_STATION_STAY_MARKER.put(taskNo, now);
|
return true;
|
}
|
return false;
|
}
|
}
|
|
private void clearOutStationStayMarker(String taskNo) {
|
synchronized (outStationStayLock) {
|
OUT_STATION_STAY_MARKER.remove(taskNo);
|
}
|
}
|
|
private void dispatchOutStationWriteInfoIfReady(WrkMast wrkMast, BasCrnp basCrnp) {
|
String taskNo = wrkMast == null ? null : wrkMast.getWmsWrkNo();
|
if (taskNo == null || !shouldDispatchOutStationWriteInfo(taskNo)) {
|
return;
|
}
|
List<StationObjModel> outStationList = basCrnp.getOutStationList$();
|
if (outStationList.isEmpty()) {
|
News.info("堆垛机:{} 出库站点未设置", basCrnp.getCrnNo());
|
return;
|
}
|
for (StationObjModel stationObjModel : outStationList) {
|
if (!stationObjModel.getStationId().equals(wrkMast.getSourceStaNo())) {
|
continue;
|
}
|
StationThread stationThread = (StationThread) SlaveConnection.get(SlaveType.Devp, stationObjModel.getDeviceNo());
|
if (stationThread == null) {
|
continue;
|
}
|
StationCommand command = stationThread.getCommand(StationCommandType.WRITE_INFO, 9998,
|
wrkMast.getSourceStaNo(), 0, 0);
|
stationCommandDispatcher.dispatch(stationObjModel.getDeviceNo(), command, "fake-process", "crn-out-complete-write-info");
|
}
|
}
|
|
@Autowired
|
private ConfigService configService;
|
@Autowired
|
private WrkMastService wrkMastService;
|
@Autowired
|
private WrkAnalysisService wrkAnalysisService;
|
@Autowired
|
private BasCrnpService basCrnpService;
|
@Autowired
|
private RedisUtil redisUtil;
|
@Autowired
|
private CrnOperateProcessUtils crnOperateUtils;
|
@Autowired
|
private StationOperateProcessUtils stationOperateProcessUtils;
|
@Autowired
|
private DualCrnOperateProcessUtils dualCrnOperateProcessUtils;
|
@Autowired
|
private StationCommandDispatcher stationCommandDispatcher;
|
@Autowired
|
private MainProcessTaskSubmitter mainProcessTaskSubmitter;
|
@Autowired
|
private FakeStationMonitor fakeStationMonitor;
|
@Autowired
|
private FakeTaskGenerator fakeTaskGenerator;
|
|
@Override
|
public void run() {
|
long startTime = System.currentTimeMillis();
|
refreshFakeConfig();
|
syncConfigToComponents();
|
|
long asyncDispatchIntervalMs = getAsyncDispatchIntervalMs();
|
long mainDispatchIntervalMs = getMainDispatchIntervalMs();
|
// 仿真异步任务
|
fakeStationMonitor.submitMonitorTasks(asyncDispatchIntervalMs);
|
// 仿真输送线堵塞检测
|
stationOperateProcessUtils.submitCheckStationRunBlockTasks(MainProcessLane.FAKE_STATION_RUN_BLOCK, asyncDispatchIntervalMs);
|
|
// 请求生成入库任务
|
fakeTaskGenerator.submitGenerateTasks();
|
|
// 执行堆垛机任务
|
crnOperateUtils.submitCrnIoTasks(MainProcessLane.FAKE_CRN_IO, mainDispatchIntervalMs);
|
// 堆垛机任务执行完成
|
submitCrnIoExecuteFinishTasks(mainDispatchIntervalMs);
|
// 执行输送站点入库任务
|
stationOperateProcessUtils.submitStationInTasks(MainProcessLane.FAKE_STATION_IN, mainDispatchIntervalMs);
|
// 检测入库任务是否已经到达目标站台
|
stationOperateProcessUtils.submitInboundStationArrivalTasks(mainDispatchIntervalMs);
|
// 输送线执行堆垛机出库后的站台流转
|
stationOperateProcessUtils.submitCrnStationOutTasks(MainProcessLane.FAKE_STATION_OUT, mainDispatchIntervalMs);
|
// 检测出库任务是否已经到达目标站台
|
stationOperateProcessUtils.submitStationOutExecuteFinishTasks(mainDispatchIntervalMs);
|
// 检测站台运行完成后的任务转完成
|
stationOperateProcessUtils.submitCheckTaskToCompleteTasks(mainDispatchIntervalMs);
|
// 检测并处理出库排序
|
stationOperateProcessUtils.submitCheckStationOutOrderTasks(MainProcessLane.FAKE_STATION_OUT_ORDER, mainDispatchIntervalMs);
|
// 执行双工位堆垛机任务
|
dualCrnOperateProcessUtils.submitDualCrnIoTasks(MainProcessLane.FAKE_DUAL_CRN_IO, mainDispatchIntervalMs);
|
// 双工位堆垛机任务执行完成
|
dualCrnOperateProcessUtils.submitDualCrnIoExecuteFinishTasks(MainProcessLane.FAKE_DUAL_CRN_IO_FINISH, mainDispatchIntervalMs);
|
|
News.info("[WCS Debug] 主线程Run执行完成,耗时:{}ms", System.currentTimeMillis() - startTime);
|
}
|
|
private void refreshFakeConfig() {
|
Config enableFakeConfig = configService.getOne(new QueryWrapper<Config>().eq("code", "enableFake"));
|
if (enableFakeConfig != null) {
|
enableFake = enableFakeConfig.getValue();
|
}
|
|
Config fakeRealTaskRequestWmsConfig = configService
|
.getOne(new QueryWrapper<Config>().eq("code", "fakeRealTaskRequestWms"));
|
if (fakeRealTaskRequestWmsConfig != null) {
|
fakeRealTaskRequestWms = fakeRealTaskRequestWmsConfig.getValue();
|
}
|
|
Config fakeGenerateInTaskConfig = configService
|
.getOne(new QueryWrapper<Config>().eq("code", "fakeGenerateInTask"));
|
if (fakeGenerateInTaskConfig != null) {
|
fakeGenerateInTask = fakeGenerateInTaskConfig.getValue();
|
}
|
|
Config fakeGenerateOutTaskConfig = configService
|
.getOne(new QueryWrapper<Config>().eq("code", "fakeGenerateOutTask"));
|
if (fakeGenerateOutTaskConfig != null) {
|
fakeGenerateOutTask = fakeGenerateOutTaskConfig.getValue();
|
}
|
}
|
|
private void syncConfigToComponents() {
|
fakeStationMonitor.setEnableFake(enableFake);
|
fakeStationMonitor.setFakeGenerateInTask(fakeGenerateInTask);
|
fakeTaskGenerator.setFakeRealTaskRequestWms(fakeRealTaskRequestWms);
|
fakeTaskGenerator.setFakeGenerateInTask(fakeGenerateInTask);
|
fakeTaskGenerator.setFakeGenerateOutTask(fakeGenerateOutTask);
|
}
|
|
private void submitCrnIoExecuteFinishTasks(long minIntervalMs) {
|
List<BasCrnp> basCrnps = basCrnpService.list(new QueryWrapper<>());
|
for (BasCrnp basCrnp : basCrnps) {
|
Integer crnNo = basCrnp == null ? null : basCrnp.getCrnNo();
|
if (crnNo == null) {
|
continue;
|
}
|
mainProcessTaskSubmitter.submitKeyedSerialTask(
|
MainProcessLane.FAKE_CRN_IO_FINISH,
|
crnNo,
|
"crnIoExecuteFinish",
|
minIntervalMs,
|
() -> crnIoExecuteFinish(basCrnp)
|
);
|
}
|
}
|
|
@Override
|
public boolean isEnabled() {
|
return fakeTaskGenerator.isEnabled();
|
}
|
|
@Override
|
public void onRequestPermitGranted(StoreInTaskContext context) {
|
fakeTaskGenerator.onRequestPermitGranted(context);
|
}
|
|
@Override
|
public void afterTaskCreated(StoreInTaskContext context, WrkMast wrkMast) {
|
fakeTaskGenerator.afterTaskCreated(context, wrkMast);
|
}
|
|
// 堆垛机任务执行完成
|
public void crnIoExecuteFinish() {
|
List<BasCrnp> basCrnps = basCrnpService.list(new QueryWrapper<>());
|
for (BasCrnp basCrnp : basCrnps) {
|
crnIoExecuteFinish(basCrnp);
|
}
|
}
|
|
private void crnIoExecuteFinish(BasCrnp basCrnp) {
|
CrnThread crnThread = (CrnThread) SlaveConnection.get(SlaveType.Crn, basCrnp.getCrnNo());
|
if (crnThread == null) {
|
return;
|
}
|
|
CrnProtocol crnProtocol = crnThread.getStatus();
|
if (crnProtocol == null) {
|
return;
|
}
|
|
if (crnProtocol.getMode() != CrnModeType.AUTO.id
|
|| crnProtocol.getTaskNo() <= 0
|
|| crnProtocol.getStatus() != CrnStatusType.WAITING.id) {
|
return;
|
}
|
|
Object lock = redisUtil.get(RedisKeyType.CRN_IO_EXECUTE_FINISH_LIMIT.key + basCrnp.getCrnNo());
|
if (lock != null) {
|
return;
|
}
|
|
// 获取待确认工作档
|
WrkMast wrkMast = wrkMastService.selectByWorkNo(crnProtocol.getTaskNo());
|
if (wrkMast == null) {
|
News.error("堆垛机处于等待确认且任务完成状态,但未找到工作档。堆垛机号={},工作号={}", basCrnp.getCrnNo(), crnProtocol.getTaskNo());
|
return;
|
}
|
|
Long updateWrkSts = null;
|
if (wrkMast.getWrkSts() == WrkStsType.INBOUND_RUN.sts) {
|
updateWrkSts = WrkStsType.COMPLETE_INBOUND.sts;
|
} else if (wrkMast.getWrkSts() == WrkStsType.OUTBOUND_RUN.sts) {
|
updateWrkSts = WrkStsType.OUTBOUND_RUN_COMPLETE.sts;
|
|
dispatchOutStationWriteInfoIfReady(wrkMast, basCrnp);
|
} else if (wrkMast.getWrkSts() == WrkStsType.LOC_MOVE_RUN.sts) {
|
updateWrkSts = WrkStsType.COMPLETE_LOC_MOVE.sts;
|
} else if (wrkMast.getWrkSts() == WrkStsType.CRN_MOVE_RUN.sts) {
|
updateWrkSts = WrkStsType.COMPLETE_CRN_MOVE.sts;
|
} else {
|
News.error("堆垛机处于等待确认且任务完成状态,但工作状态异常。堆垛机号={},工作号={}", basCrnp.getCrnNo(), crnProtocol.getTaskNo());
|
return;
|
}
|
|
Date now = new Date();
|
wrkMast.setWrkSts(updateWrkSts);
|
wrkMast.setSystemMsg("");
|
wrkMast.setIoTime(now);
|
wrkMast.setModiTime(now);
|
if (wrkMastService.updateById(wrkMast)) {
|
clearOutStationStayMarker(wrkMast.getWmsWrkNo());
|
wrkAnalysisService.markCraneComplete(wrkMast, now, updateWrkSts);
|
CrnCommand resetCommand = crnThread.getResetCommand(crnProtocol.getTaskNo(), crnProtocol.getCrnNo());
|
MessageQueue.offer(SlaveType.Crn, crnProtocol.getCrnNo(), new Task(2, resetCommand));
|
News.info("堆垛机任务状态更新成功,堆垛机号={},工作号={}", basCrnp.getCrnNo(), crnProtocol.getTaskNo());
|
}
|
|
redisUtil.set(RedisKeyType.CRN_IO_EXECUTE_FINISH_LIMIT.key + basCrnp.getCrnNo(), "lock", 10);
|
}
|
|
}
|