zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/MainProcess.java
@@ -1,5 +1,6 @@ package com.zy.asrs.wcs.core; import com.zy.asrs.wcs.core.properties.SystemProperties; import com.zy.asrs.wcs.core.service.impl.MainServiceImpl; import lombok.Data; import lombok.extern.slf4j.Slf4j; @@ -35,17 +36,17 @@ // 间隔 Thread.sleep(300); // // 系统运行状态判断 // if (!SystemProperties.WCS_RUNNING_STATUS.get()) { // continue; // } // // // 入库 ===>> 入库站到堆垛机站,根据条码扫描生成入库工作档 // mainService.generateInboundWrk(); // 组托 // // // 间隔 // Thread.sleep(500); // // 系统运行状态判断 if (!SystemProperties.WCS_RUNNING_STATUS.get()) { continue; } // 入库 ===>> 入库站到堆垛机站,根据条码扫描生成入库工作档 mainService.generateInboundWrk(); // 组托 // 间隔 Thread.sleep(500); // //初始化实时地图 // mainService.initRealtimeBasMap(); // // 拣料、并板、盘点再入库 zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/kernel/command/AgvCommandService.java
New file @@ -0,0 +1,19 @@ package com.zy.asrs.wcs.core.kernel.command; import com.zy.asrs.wcs.rcs.entity.Motion; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; /** * Created by vincent on 2023/10/23 */ @Slf4j @Service public class AgvCommandService { public Boolean accept(Motion motion) { return Boolean.TRUE; } } zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/kernel/command/CraneCommandService.java
New file @@ -0,0 +1,19 @@ package com.zy.asrs.wcs.core.kernel.command; import com.zy.asrs.wcs.rcs.entity.Motion; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; /** * Created by vincent on 2023/10/23 */ @Slf4j @Service public class CraneCommandService { public Boolean accept(Motion motion) { return Boolean.TRUE; } } zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/mapper/TaskMapper.java
@@ -14,4 +14,8 @@ List<Task> selectOutboundByShuttleNo(@Param("shuttleNo") Integer shuttleNo); List<Task> selectByAnalyzeSts(); List<Task> selectByExecuteSts(); } zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/properties/SystemProperties.java
New file @@ -0,0 +1,17 @@ package com.zy.asrs.wcs.core.properties; import java.util.concurrent.atomic.AtomicBoolean; /** * Created by vincent on 2020-06-03 */ public class SystemProperties { public static final String WCS_PASSWORD = "root"; // 系统运行状态 public static final AtomicBoolean WCS_RUNNING_STATUS = new AtomicBoolean(Boolean.TRUE); public static final String WMS_URL = "localhost"; } zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/service/TaskService.java
@@ -2,7 +2,6 @@ import com.baomidou.mybatisplus.extension.service.IService; import com.zy.asrs.wcs.core.entity.Task; import org.apache.ibatis.annotations.Param; import java.util.List; @@ -12,4 +11,8 @@ Boolean hasBusyOutboundByShuttle(Integer shuttleNo); List<Task> selectByAnalyzeSts(); List<Task> selectByExecuteSts(); } zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/service/impl/MainServiceImpl.java
@@ -1,8 +1,14 @@ package com.zy.asrs.wcs.core.service.impl; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.interceptor.TransactionAspectSupport; import java.util.Date; import java.util.List; /** * 立体仓库WCS系统主流程业务 @@ -13,6 +19,12 @@ @Transactional public class MainServiceImpl { /** * 组托 * 入库站,根据条码扫描生成入库工作档,工作状态 2 */ public synchronized void generateInboundWrk() { } } zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/service/impl/TaskServiceImpl.java
@@ -54,4 +54,14 @@ } return false; } @Override public List<Task> selectByAnalyzeSts() { return this.baseMapper.selectByAnalyzeSts(); } @Override public List<Task> selectByExecuteSts() { return this.baseMapper.selectByExecuteSts(); } } zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/timer/MotionTimer.java
New file @@ -0,0 +1,248 @@ package com.zy.asrs.wcs.core.timer; import com.zy.asrs.framework.exception.CoolException; import com.zy.asrs.wcs.core.entity.Task; import com.zy.asrs.wcs.core.kernel.command.AgvCommandService; import com.zy.asrs.wcs.core.kernel.command.CraneCommandService; import com.zy.asrs.wcs.core.kernel.command.ShuttleCommandService; import com.zy.asrs.wcs.core.model.enums.DeviceCtgType; import com.zy.asrs.wcs.core.model.enums.MotionCtgType; import com.zy.asrs.wcs.core.model.enums.MotionStsType; import com.zy.asrs.wcs.core.model.enums.TaskStsType; import com.zy.asrs.wcs.core.service.TaskService; import com.zy.asrs.wcs.rcs.entity.Motion; import com.zy.asrs.wcs.rcs.service.MotionService; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; import java.util.Date; import java.util.List; import java.util.Objects; /** * Created by vincent on 2023/10/10 */ @Slf4j @Component public class MotionTimer { @Autowired private TaskService taskService; @Autowired private MotionService motionService; @Autowired private AgvCommandService agvCommandService; // @Autowired // private ConveyorCommandService conveyorCommandService; @Autowired private CraneCommandService craneCommandService; // @Autowired // private LiftCommandService liftCommandService; @Autowired private ShuttleCommandService shuttleCommandService; @Scheduled(cron = "0/1 * * * * ? ") public synchronized void executeWrkMast() { Date now = new Date(); // ANALYZE_INBOUND for (Task task : taskService.selectByAnalyzeSts()) { Motion executingMotion = motionService.selectOfTop1(task.getUuid(), MotionStsType.EXECUTING.val(), task.getHostId()); if (executingMotion != null) {//存在正在执行的motion continue; } Motion motion = motionService.selectOfTop1(task.getUuid(), MotionStsType.INIT.val(), task.getHostId()); if (null != motion) { boolean result = this.executeMotion(motion); if (!result) { continue; } // 更新wrkMast switch (TaskStsType.query(task.getTaskSts())) { case ANALYZE_INBOUND: task.setTaskSts(TaskStsType.EXECUTE_INBOUND.sts); break; case ANALYZE_OUTBOUND: task.setTaskSts(TaskStsType.EXECUTE_OUTBOUND.sts); break; } task.setUpdateTime(now); if (!taskService.updateById(task)) { log.error("{}工作档更新状态失败!", task.getTaskNo()); } } } // EXECUTE_INBOUND for (Task task : taskService.selectByExecuteSts()) { if (!motionService.hasRunningMotion(task.getUuid(), task.getHostId())) { Motion motion = motionService.selectOfTop1(task.getUuid(), MotionStsType.WAITING.val(), task.getHostId()); if (null != motion) { boolean result = this.executeMotion(motion); if (!result) { continue; } } else { if (motionService.selectOfTop1(task.getUuid(), MotionStsType.EXECUTING.val(), task.getHostId()) != null) { continue; } // 更新wrkMast switch (TaskStsType.query(task.getTaskSts())) { case EXECUTE_INBOUND: task.setTaskSts(TaskStsType.COMPLETE_INBOUND.sts); break; case EXECUTE_OUTBOUND: task.setTaskSts(TaskStsType.COMPLETE_OUTBOUND.sts); break; } task.setUpdateTime(now); if (!taskService.updateById(task)) { log.error("{}工作档更新状态失败!", task.getTaskNo()); } } } } } // @Scheduled(cron = "0/1 * * * * ? ") // public synchronized void executeWrkCharge() { // Date now = new Date(); // // ANALYZE_INBOUND // for (WrkCharge wrkCharge : wrkChargeMapper.selectByAnalyzeSts()) { // Motion executingMotion = motionService.selectOfTop1(wrkCharge.getUuid(), MotionStsType.EXECUTING.val()); // if (executingMotion != null) {//存在正在执行的motion // continue; // } // // Motion motion = motionService.selectOfTop1(wrkCharge.getUuid(), MotionStsType.INIT.val()); // if (null != motion) { // boolean result = this.executeMotion(motion); // if (!result) { // continue; // } // // 更新wrkMast // switch (WrkMastStsType.query(wrkCharge.getWrkSts())) { // case ANALYZE_CHARGE: // wrkCharge.setWrkSts(WrkMastStsType.EXECUTE_CHARGE.sts); // break; // case ANALYZE_MOVE: // wrkCharge.setWrkSts(WrkMastStsType.EXECUTE_MOVE.sts); // break; // } // wrkCharge.setModiTime(now); // if (wrkChargeMapper.updateById(wrkCharge) == 0) { // log.error("{}其他工作档更新状态失败!", wrkCharge.getWrkNo()); // } // } // } // // EXECUTE_INBOUND // for (WrkCharge wrkCharge : wrkChargeMapper.selectByExecuteSts()) { // if (!motionService.hasRunningMotion(wrkCharge.getUuid())) { // Motion motion = motionService.selectOfTop1(wrkCharge.getUuid(), MotionStsType.WAITING.val()); // if (null != motion) { // boolean result = this.executeMotion(motion); // if (!result) { // continue; // } // } else { // if (motionService.selectOfTop1(wrkCharge.getUuid(), MotionStsType.EXECUTING.val()) != null) { // continue; // } // // // 更新wrkMast // switch (WrkMastStsType.query(wrkCharge.getWrkSts())) { // case EXECUTE_CHARGE: // wrkCharge.setWrkSts(WrkMastStsType.CHARGE_WORKING.sts); // break; // case EXECUTE_MOVE: // wrkCharge.setWrkSts(WrkMastStsType.COMPLETE_MOVE.sts); // break; // } // wrkCharge.setModiTime(now); // if (wrkChargeMapper.updateById(wrkCharge) == 0) { // log.error("{}他工作档更新状态失败!", wrkCharge.getWrkNo()); // } // } // } // } // } @Scheduled(cron = "0/1 * * * * ? ") public void scanMotionByExecuting() { List<Motion> motionList = motionService.selectBySts(MotionStsType.EXECUTING.val()); for (Motion motion : motionList) { this.finishMotion(motion); } } private synchronized boolean executeMotion(Motion motion) { Boolean executeRes = Boolean.FALSE; switch (Objects.requireNonNull(MotionCtgType.get(motion.getMotionCtgEl())).deviceCtg) { case CONVEYOR: // executeRes = conveyorCommandService.accept(motion); break; case CRANE: executeRes = craneCommandService.accept(motion); break; case SHUTTLE: executeRes = shuttleCommandService.accept(motion); break; case LIFT: // executeRes = liftCommandService.accept(motion); break; case AGV: executeRes = agvCommandService.accept(motion); break; default: break; } if (executeRes) { Date now = new Date(); motion.setMotionSts(MotionStsType.EXECUTING.val()); motion.setUpdateTime(now); motion.setIoTime(now); if (!motionService.updateById(motion)) { throw new CoolException(motion.generateFlag() + "动作更新失败状态"); } motionService.theNextBeWaiting(motion.getUuid(), motion); return true; } return false; } private synchronized void finishMotion(Motion motion) { Boolean executeRes = Boolean.FALSE; switch (Objects.requireNonNull(DeviceCtgType.get(motion.getDeviceCtgEl()))){ case AGV: break; case CRANE: break; case LIFT: // executeRes = liftCommandService.finish(motion); break; case SHUTTLE: executeRes = shuttleCommandService.finish(motion); break; case CONVEYOR: // executeRes = conveyorCommandService.finish(motion); break; default: break; } if (executeRes) { Date now = new Date(); motion.setMotionSts(MotionStsType.COMPLETE.val()); motion.setUpdateTime(now); if (!motionService.updateById(motion)) { throw new CoolException(motion.generateFlag() + "动作更新失败状态"); } } } } zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/rcs/entity/Motion.java
@@ -468,5 +468,18 @@ return null; } public String generateFlag() { return this.getUuid() + "【" + this.getPriority() + " - " + this.getMotionCtg$() + "】"; } public String getDeviceCtgEl(){ DeviceCtgService service = SpringUtils.getBean(DeviceCtgService.class); DeviceCtg entity = service.getById(this.deviceCtg); if (!Cools.isEmpty(entity)){ return String.valueOf(entity.getFlag()); } return null; } } zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/rcs/mapper/MotionMapper.java
@@ -3,10 +3,15 @@ import com.zy.asrs.wcs.rcs.entity.Motion; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; import org.springframework.stereotype.Repository; @Mapper @Repository public interface MotionMapper extends BaseMapper<Motion> { Motion selectOfTop1(@Param("uuid") String uuid, @Param("motionSts") Long motionSts, @Param("hostId") Long hostId); Motion selectOfNext(@Param("uuid") String uuid, @Param("priority") Integer priority, @Param("hostId") Long hostId); } zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/rcs/service/MotionService.java
@@ -10,4 +10,14 @@ List<Motion> selectUnCompleteByUuidAndDeviceCtg(String uuid, DeviceCtgType deviceCtgType); Motion selectOfTop1(String uuid, Long motionSts, Long hostId); Boolean hasRunningMotion(String uuid, Long hostId); List<Motion> selectBySts(Long motionSts); Boolean theNextBeWaiting(String uuid, Motion motion); Motion selectOfNext(String uuid, Motion motion); } zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/rcs/service/impl/MotionServiceImpl.java
@@ -1,6 +1,7 @@ package com.zy.asrs.wcs.rcs.service.impl; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.zy.asrs.framework.exception.CoolException; import com.zy.asrs.wcs.core.model.enums.DeviceCtgType; import com.zy.asrs.wcs.core.model.enums.MotionStsType; import com.zy.asrs.wcs.core.service.DeviceCtgService; @@ -12,6 +13,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.Date; import java.util.List; @Service("motionService") @@ -31,4 +33,45 @@ .orderByDesc(Motion::getPriority) ); } @Override public Motion selectOfTop1(String uuid, Long motionSts, Long hostId) { return this.baseMapper.selectOfTop1(uuid, motionSts, hostId); } @Override public Boolean hasRunningMotion(String uuid, Long hostId) { return null != this.selectOfTop1(uuid, MotionStsType.EXECUTING.val(), hostId) || null != this.selectOfTop1(uuid, MotionStsType.ERROR.val(), hostId); } @Override public List<Motion> selectBySts(Long motionSts) { return this.list(new LambdaQueryWrapper<Motion>() .eq(Motion::getMotionSts, motionSts) .orderByDesc(Motion::getPriority)); } @Override public Boolean theNextBeWaiting(String uuid, Motion motion) { Motion next = null; if (null == motion) { next = this.baseMapper.selectOfTop1(uuid, MotionStsType.INIT.val(), motion.getHostId()); } else { next = this.selectOfNext(uuid, motion); } if (null != next) { next.setMotionSts(MotionStsType.WAITING.val()); next.setUpdateTime(new Date()); if (!this.updateById(next)) { throw new CoolException(uuid + " - [" + (motion == null ? 0 : (motion.getPriority() - 1)) + "] 动作更新状态失败"); } } return Boolean.TRUE; } @Override public Motion selectOfNext(String uuid, Motion motion) { return this.baseMapper.selectOfNext(uuid, motion.getPriority(), motion.getHostId()); } } zy-asrs-wcs/src/main/resources/mapper/core/TaskMapper.xml
@@ -10,4 +10,18 @@ order by priority desc,start_time,task_no asc </select> <select id="selectByAnalyzeSts" resultType="com.zy.asrs.wcs.core.entity.Task"> select * from wcs_task where 1=1 and task_sts in (2, 102, 202, 302) order by priority desc,start_time,task_no asc </select> <select id="selectByExecuteSts" resultType="com.zy.asrs.wcs.core.entity.Task"> select * from wcs_task where 1=1 and task_sts in (3, 103, 203, 303) order by priority desc,start_time,task_no asc </select> </mapper> zy-asrs-wcs/src/main/resources/mapper/rcs/MotionMapper.xml
@@ -2,4 +2,20 @@ <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.zy.asrs.wcs.rcs.mapper.MotionMapper"> <select id="selectOfTop1" resultType="com.zy.asrs.wcs.rcs.entity.Motion"> select top 1 * from rcs_motion where 1=1 and uuid = #{uuid} and motion_sts = #{motionSts} order by priority desc </select> <select id="selectOfNext" resultType="com.zy.asrs.wcs.rcs.entity.Motion"> select * from rcs_motion where 1=1 and uuid = #{uuid} and priority = #{priority} - 1 order by priority desc </select> </mapper>