package com.zy.asrs.wcs.core.action;
|
|
import com.alibaba.fastjson.JSON;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.zy.asrs.wcs.core.entity.Loc;
|
import com.zy.asrs.wcs.core.entity.Task;
|
import com.zy.asrs.wcs.core.model.NavigateNode;
|
import com.zy.asrs.wcs.core.model.command.ShuttleAssignCommand;
|
import com.zy.asrs.wcs.core.model.command.ShuttleCommand;
|
import com.zy.asrs.wcs.core.model.command.ShuttleRedisCommand;
|
import com.zy.asrs.wcs.core.model.enums.ShuttleCommandModeType;
|
import com.zy.asrs.wcs.core.model.enums.ShuttleTaskModeType;
|
import com.zy.asrs.wcs.core.service.BasShuttleService;
|
import com.zy.asrs.wcs.core.service.LocService;
|
import com.zy.asrs.wcs.core.utils.NavigateMapUtils;
|
import com.zy.asrs.wcs.core.utils.RedisUtil;
|
import com.zy.asrs.wcs.core.utils.ShuttleDispatcher;
|
import com.zy.asrs.wcs.core.utils.Utils;
|
import com.zy.asrs.wcs.rcs.News;
|
import com.zy.asrs.wcs.rcs.cache.SlaveConnection;
|
import com.zy.asrs.wcs.rcs.constant.DeviceRedisConstant;
|
import com.zy.asrs.wcs.rcs.entity.Device;
|
import com.zy.asrs.wcs.rcs.model.enums.ShuttleProtocolStatusType;
|
import com.zy.asrs.wcs.rcs.model.enums.SlaveType;
|
import com.zy.asrs.wcs.rcs.model.protocol.ShuttleProtocol;
|
import com.zy.asrs.wcs.rcs.thread.ShuttleThread;
|
import org.aspectj.apache.bcel.generic.RET;
|
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.stereotype.Component;
|
|
import java.util.ArrayList;
|
import java.util.List;
|
|
@Component
|
public class ShuttleAction {
|
|
@Autowired
|
private RedisUtil redisUtil;
|
@Autowired
|
private NavigateMapUtils navigateMapUtils;
|
@Autowired
|
private BasShuttleService basShuttleService;
|
@Autowired
|
private LocService locService;
|
@Autowired
|
private ShuttleDispatcher shuttleDispatcher;
|
@Autowired
|
private ObjectMapper objectMapper;
|
|
public synchronized boolean assignWork(Device device, ShuttleAssignCommand assignCommand) {
|
ShuttleThread shuttleThread = (ShuttleThread) SlaveConnection.get(SlaveType.Shuttle, device.getId().intValue());
|
if (shuttleThread == null) {
|
return false;
|
}
|
|
ShuttleProtocol shuttleProtocol = shuttleThread.getStatus();
|
if (shuttleProtocol == null) {
|
return false;
|
}
|
|
ShuttleRedisCommand redisCommand = new ShuttleRedisCommand();
|
|
redisCommand.setShuttleNo(assignCommand.getShuttleNo());//四向穿梭车号
|
redisCommand.setWrkNo(assignCommand.getTaskNo());//工作号
|
redisCommand.setCommandStep(0);//命令执行步序
|
redisCommand.setAssignCommand(assignCommand);//命令
|
//任务数据保存到redis
|
if (redisUtil.set(DeviceRedisConstant.SHUTTLE_WORK_FLAG + assignCommand.getTaskNo(), JSON.toJSONString(redisCommand))) {
|
if (assignCommand.getTaskMode() == ShuttleTaskModeType.PAK_IN.id
|
|| assignCommand.getTaskMode() == ShuttleTaskModeType.PAK_OUT.id
|
|| assignCommand.getTaskMode() == ShuttleTaskModeType.MOVE_LOC_NO.id
|
|| assignCommand.getTaskMode() == ShuttleTaskModeType.SHUTTLE_MOVE_LOC_NO.id) {
|
//下发行驶路径
|
boolean result = shuttleThread.movePath(assignCommand.getNodes(), assignCommand.getTaskNo());
|
if (!result) {
|
return false;
|
}
|
}
|
shuttleProtocol.setSyncTaskNo(assignCommand.getTaskNo());
|
return true;
|
}
|
return false;
|
}
|
|
public synchronized boolean executeWork(Device device, Integer taskNo) {
|
Object obj = redisUtil.get(DeviceRedisConstant.SHUTTLE_WORK_FLAG + taskNo);
|
if (obj == null) {
|
return false;
|
}
|
|
ShuttleRedisCommand redisCommand = null;
|
try {
|
redisCommand = objectMapper.readValue(String.valueOf(obj), ShuttleRedisCommand.class);
|
} catch (JsonProcessingException e) {
|
throw new RuntimeException(e);
|
}
|
|
if (redisCommand == null) {
|
return false;
|
}
|
|
ShuttleThread shuttleThread = (ShuttleThread) SlaveConnection.get(SlaveType.Shuttle, device.getId().intValue());
|
if (shuttleThread == null) {
|
return false;
|
}
|
|
ShuttleProtocol shuttleProtocol = shuttleThread.getStatus();
|
if (shuttleProtocol == null) {
|
return false;
|
}
|
|
//判断设备是否空闲
|
if (!shuttleThread.isDeviceIdle()) {
|
return false;
|
}
|
// if (!shuttleThread.isIdle(() -> {
|
// return shuttleProtocol.getTaskNo().equals(taskNo);
|
// })) {
|
// return false;
|
// }
|
|
//判断工作号是否相同
|
if (!shuttleProtocol.getTaskNo().equals(taskNo)) {
|
return false;
|
}
|
|
List<ShuttleCommand> commands = redisCommand.getAssignCommand().getCommands();
|
if (commands.isEmpty()) {
|
return false;
|
}
|
|
ShuttleAssignCommand assignCommand = redisCommand.getAssignCommand();
|
int commandStep = redisCommand.getCommandStep();
|
|
// 完结上一条命令
|
if (commandStep != 0) {
|
ShuttleCommand command = commands.get(commandStep - 1);
|
if (command.getMode() == ShuttleCommandModeType.MOVE.id) {
|
// 正常移动
|
if (command.getTargetLocNo().equals(shuttleProtocol.getCurrentLocNo())) {
|
command.setComplete(true);
|
//解锁锁定路径,上一条路径
|
List<NavigateNode> nodes = JSON.parseArray(JSON.toJSONString(command.getNodes()), NavigateNode.class);//进行深度copy
|
if (nodes != null) {
|
NavigateNode targetNode = assignCommand.getNodes().get(assignCommand.getNodes().size() - 1);//最终节点
|
NavigateNode node = nodes.get(nodes.size() - 1);
|
if (!(targetNode.getX() == node.getX() && targetNode.getY() == node.getY())) {
|
nodes.remove(nodes.size() - 1);//剔除尾节点
|
}
|
boolean result = navigateMapUtils.writeNavigateNodeToRedisMap(Utils.getLev(shuttleProtocol.getCurrentLocNo()), shuttleProtocol.getShuttleNo(), nodes, false);//解锁路径
|
if (!result) {
|
return false;//解锁失败
|
}
|
}
|
}
|
} else if (command.getMode() == ShuttleCommandModeType.PALLET_LIFT.id) {
|
// 托盘顶升
|
//判断是否顶升到位
|
if (shuttleProtocol.getHasLift()) {
|
command.setComplete(true);
|
// //判断是否有物
|
// if (shuttleProtocol.getHasPallet()) {
|
// command.setComplete(true);
|
// }
|
}
|
} else if (command.getMode() == ShuttleCommandModeType.PALLET_DOWN.id) {
|
// 托盘下降命令
|
// 判断是否下降到位
|
if (!shuttleProtocol.getHasLift()) {
|
command.setComplete(true);
|
}
|
} else if (command.getMode() == ShuttleCommandModeType.CHARGE_OPEN.id) {
|
// 充电开
|
//判断小车充电状态
|
if (shuttleProtocol.getHasCharge()) {
|
command.setComplete(true);
|
}
|
}else {
|
command.setComplete(true);//其他命令默认认为完成
|
}
|
|
// 更新redis数据
|
redisUtil.set(DeviceRedisConstant.SHUTTLE_WORK_FLAG + redisCommand.getWrkNo(), JSON.toJSONString(redisCommand));
|
|
if (!command.getComplete()) {
|
return false;
|
}
|
|
//判断是否为最后一条命令且命令执行完成,抛出等待确认状态
|
ShuttleCommand endCommand = commands.get(commands.size() - 1);
|
if (endCommand.getComplete()) {
|
News.info("四向穿梭车任务执行下发完成等待执行结束,穿梭车号={},任务数据={}", shuttleProtocol.getShuttleNo(), JSON.toJSON(commands));
|
|
// 系统任务
|
if (assignCommand.getAuto()) {
|
if (!assignCommand.getCharge()) {
|
//对主线程抛出等待确认状态waiting
|
shuttleProtocol.setProtocolStatus(ShuttleProtocolStatusType.WAITING);
|
}else {
|
shuttleProtocol.setProtocolStatus(ShuttleProtocolStatusType.CHARGING_WAITING);
|
}
|
News.info("四向穿梭车任务执行下发完成等待执行结束,穿梭车号={},任务数据={}", shuttleProtocol.getShuttleNo(), JSON.toJSON(command));
|
|
// 手动任务
|
} else {
|
//手动模式不抛出等待状态,直接复位空闲状态
|
shuttleProtocol.setProtocolStatus(ShuttleProtocolStatusType.IDLE);
|
//任务号清零
|
shuttleProtocol.setSyncTaskNo(0);
|
//标记复位
|
shuttleProtocol.setPakMk(true);
|
News.info("四向穿梭车手动任务执行完成,穿梭车号={},任务数据={}", shuttleProtocol.getShuttleNo(), JSON.toJSON(command));
|
}
|
|
//删除redis
|
redisUtil.del(DeviceRedisConstant.SHUTTLE_WORK_FLAG + redisCommand.getWrkNo());
|
return false;//禁止再下发命令
|
}
|
}
|
|
//取出命令
|
ShuttleCommand command = commands.get(commandStep);
|
|
// 下发命令
|
if (!write(command, device)) {
|
News.error("四向穿梭车命令下发失败,穿梭车号={},任务数据={}", shuttleProtocol.getShuttleNo(), JSON.toJSON(command));
|
return false;
|
}
|
|
shuttleProtocol.setProtocolStatus(ShuttleProtocolStatusType.WORKING);
|
commandStep++;
|
//更新redis数据
|
redisCommand.setCommandStep(commandStep);
|
//任务数据保存到redis
|
redisUtil.set(DeviceRedisConstant.SHUTTLE_WORK_FLAG + redisCommand.getWrkNo(), JSON.toJSONString(redisCommand));
|
return true;
|
}
|
|
//跑库程序
|
public synchronized void moveLoc(Device device) {
|
ShuttleThread shuttleThread = (ShuttleThread) SlaveConnection.get(SlaveType.Shuttle, device.getId().intValue());
|
if (shuttleThread == null) {
|
return;
|
}
|
|
ShuttleProtocol shuttleProtocol = shuttleThread.getStatus();
|
if (shuttleProtocol == null) {
|
return;
|
}
|
|
//小车开启跑库模式
|
if (!shuttleProtocol.getMoveLoc()) {
|
return;
|
}
|
|
//小车空闲
|
if (!shuttleThread.isIdle()) {
|
return;
|
}
|
|
int lev = Utils.getLev(shuttleProtocol.getCurrentLocNo());//小车当前楼层
|
if (shuttleProtocol.getYCurrent() > shuttleProtocol.getYTarget()) {
|
//跑库结束
|
shuttleProtocol.setMoveLoc(false);
|
shuttleProtocol.setMoveType(0);
|
shuttleProtocol.setXStart(0);
|
shuttleProtocol.setXTarget(0);
|
shuttleProtocol.setXCurrent(0);
|
shuttleProtocol.setYStart(0);
|
shuttleProtocol.setYTarget(0);
|
shuttleProtocol.setYCurrent(0);
|
return;
|
}
|
|
if (shuttleProtocol.getMoveType() == 0) {//跑轨道
|
ArrayList<String> locs = new ArrayList<>();
|
for (int i = shuttleProtocol.getXCurrent(); i <= shuttleProtocol.getXTarget(); i++) {
|
String locNo = Utils.getLocNo(i, shuttleProtocol.getYCurrent(), lev);
|
locs.add(locNo);
|
}
|
|
List<Loc> locList = locService.list(new LambdaQueryWrapper<Loc>()
|
.in(Loc::getLocNo, locs));
|
if (locList.isEmpty()) {
|
//空库位
|
shuttleProtocol.setYCurrent(shuttleProtocol.getYCurrent() + 1);
|
return;
|
}
|
|
Loc start = locList.get(0);
|
Loc target = locList.get(locList.size() - 1);
|
//判断小车是否在起点位置
|
if (!shuttleProtocol.getCurrentLocNo().equals(start.getLocNo())) {//不在起点位置,调度去起点位置
|
shuttleDispatcher.generateMoveTask(device, start.getLocNo());
|
}else {
|
//在起点位置,调度去目标位置
|
if (shuttleProtocol.getCurrentLocNo().equals(target.getLocNo())) {
|
shuttleProtocol.setYCurrent(shuttleProtocol.getYCurrent() + 1);//小车和目标位置一致,跳过
|
}else {
|
shuttleDispatcher.generateMoveTask(device, start.getLocNo());
|
shuttleProtocol.setYCurrent(shuttleProtocol.getYCurrent() + 1);
|
}
|
}
|
} else if (shuttleProtocol.getMoveType() == 1) {//跑库位
|
Integer xCurrent = shuttleProtocol.getXCurrent();
|
if (xCurrent > shuttleProtocol.getXTarget()) {//当X值大于X目标值,进行归零且Y方向+1
|
shuttleProtocol.setXCurrent(shuttleProtocol.getXStart());
|
shuttleProtocol.setYCurrent(shuttleProtocol.getYCurrent() + 1);
|
return;
|
}
|
|
Integer yCurrent = shuttleProtocol.getYCurrent();
|
String locNo = Utils.getLocNo(xCurrent, yCurrent, lev);
|
Loc target = locService.getOne(new LambdaQueryWrapper<Loc>()
|
.eq(Loc::getLocNo, locNo)
|
.eq(Loc::getHostId, device.getHostId()));
|
if (target == null) {
|
shuttleProtocol.setXCurrent(shuttleProtocol.getXCurrent() + 1);
|
return;
|
}
|
|
// if (!target.getLocSts().equals("O")) {
|
// shuttleProtocol.setXCurrent(shuttleProtocol.getXCurrent() + 1);
|
// return;
|
// }
|
|
//调度去目标位置
|
if (shuttleProtocol.getCurrentLocNo().equals(target.getLocNo())) {
|
shuttleProtocol.setXCurrent(shuttleProtocol.getXCurrent() + 1);//小车和目标位置一致,跳过
|
} else {
|
shuttleDispatcher.generateMoveTask(device, target.getLocNo());
|
shuttleProtocol.setXCurrent(shuttleProtocol.getXCurrent() + 1);
|
}
|
} else if (shuttleProtocol.getMoveType() == 2) {//母轨道循环跑
|
Integer xCurrent = shuttleProtocol.getXCurrent();
|
Integer yCurrent = shuttleProtocol.getYCurrent();
|
|
String locNo = Utils.getLocNo(xCurrent, yCurrent, lev);
|
//调度去目标位置
|
if (shuttleProtocol.getCurrentLocNo().equals(locNo)) {
|
if (yCurrent.equals(shuttleProtocol.getYStart())) {
|
shuttleProtocol.setYCurrent(shuttleProtocol.getYTarget());//小车和目标位置一致,切换库位
|
} else {
|
shuttleProtocol.setYCurrent(shuttleProtocol.getYStart());//小车和目标位置一致,切换库位
|
}
|
} else {
|
Task result = shuttleDispatcher.generateMoveTask(device, locNo);
|
if (result != null) {//调度成功
|
if (yCurrent.equals(shuttleProtocol.getYStart())) {
|
shuttleProtocol.setYCurrent(shuttleProtocol.getYTarget());//切换库位
|
} else {
|
shuttleProtocol.setYCurrent(shuttleProtocol.getYStart());//切换库位
|
}
|
}
|
}
|
} else if (shuttleProtocol.getMoveType() == 3) {//子轨道循环跑
|
Integer xCurrent = shuttleProtocol.getXCurrent();
|
Integer yCurrent = shuttleProtocol.getYCurrent();
|
|
String locNo = Utils.getLocNo(xCurrent, yCurrent, lev);
|
//调度去目标位置
|
if (shuttleProtocol.getCurrentLocNo().equals(locNo)) {
|
if (xCurrent.equals(shuttleProtocol.getXStart())) {
|
shuttleProtocol.setXCurrent(shuttleProtocol.getXTarget());//小车和目标位置一致,切换库位
|
} else {
|
shuttleProtocol.setXCurrent(shuttleProtocol.getXStart());//小车和目标位置一致,切换库位
|
}
|
} else {
|
Task result = shuttleDispatcher.generateMoveTask(device, locNo);
|
if (result != null) {//调度成功
|
if (xCurrent.equals(shuttleProtocol.getXStart())) {
|
shuttleProtocol.setXCurrent(shuttleProtocol.getXTarget());//切换库位
|
} else {
|
shuttleProtocol.setXCurrent(shuttleProtocol.getXStart());//切换库位
|
}
|
}
|
}
|
}
|
}
|
|
private synchronized boolean write(ShuttleCommand command, Device device) {
|
if (null == command) {
|
News.error("四向穿梭车写入命令为空");
|
return false;
|
}
|
ShuttleThread shuttleThread = (ShuttleThread) SlaveConnection.get(SlaveType.Shuttle, device.getId().intValue());
|
boolean result = false;
|
if (command.getMode() == ShuttleCommandModeType.MOVE.id
|
|| command.getMode() == ShuttleCommandModeType.IN_LIFT.id
|
|| command.getMode() == ShuttleCommandModeType.OUT_LIFT.id) {//移动
|
result = shuttleThread.move(command);
|
} else if (command.getMode() == ShuttleCommandModeType.PALLET_LIFT.id
|
|| command.getMode() == ShuttleCommandModeType.PALLET_DOWN.id) {//顶升
|
result = shuttleThread.lift(command);
|
} else if (command.getMode() == ShuttleCommandModeType.CHARGE_OPEN.id
|
|| command.getMode() == ShuttleCommandModeType.CHARGE_CLOSE.id) {//充电
|
result = shuttleThread.charge(command);
|
} else if (command.getMode() == ShuttleCommandModeType.RESET.id) {//复位
|
result = shuttleThread.reset(command);
|
}
|
return result;
|
}
|
|
}
|