package com.zy.core.thread;
|
|
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSONObject;
|
import com.core.common.DateUtils;
|
import com.core.common.SpringUtils;
|
import com.zy.asrs.entity.*;
|
import com.zy.asrs.mapper.WrkMastMapper;
|
import com.zy.asrs.service.*;
|
|
import com.zy.asrs.utils.Utils;
|
import com.zy.common.model.NavigateNode;
|
import com.zy.common.model.NyShuttleOperaResult;
|
import com.zy.common.utils.*;
|
import com.zy.core.News;
|
import com.zy.core.ThreadHandler;
|
import com.zy.core.cache.MessageQueue;
|
import com.zy.core.cache.OutputQueue;
|
import com.zy.core.cache.SlaveConnection;
|
import com.zy.core.enums.*;
|
import com.zy.core.model.LiftSlave;
|
import com.zy.core.model.ShuttleSlave;
|
import com.zy.core.model.Task;
|
import com.zy.core.model.command.*;
|
import com.zy.core.model.protocol.LiftProtocol;
|
import com.zy.core.model.protocol.NyShuttleProtocol;
|
import com.zy.core.properties.SlaveProperties;
|
import lombok.Data;
|
import lombok.extern.slf4j.Slf4j;
|
|
import java.io.IOException;
|
import java.net.Socket;
|
import java.text.MessageFormat;
|
import java.util.ArrayList;
|
import java.util.Date;
|
import java.util.List;
|
|
/**
|
* 牛眼四向穿梭车线程
|
*/
|
@Data
|
@Slf4j
|
public class NyShuttleThread implements Runnable, ThreadHandler {
|
|
private ShuttleSlave slave;
|
private NyShuttleProtocol shuttleProtocol;
|
private RedisUtil redisUtil;
|
private Socket socket;
|
|
public NyShuttleThread(ShuttleSlave slave,RedisUtil redisUtil) {
|
this.slave = slave;
|
this.redisUtil = redisUtil;
|
}
|
|
@Override
|
public void run() {
|
this.connect();
|
while (true) {
|
try {
|
int step = 1;
|
Task task = MessageQueue.poll(SlaveType.Shuttle, slave.getId());
|
if (task != null) {
|
step = task.getStep();
|
}
|
switch (step) {
|
// 读数据
|
case 1:
|
read();
|
break;
|
// // 写入数据
|
// case 2:
|
// write((NyShuttleHttpCommand) task.getData());
|
// break;
|
//下发任务
|
case 3:
|
assignWork((ShuttleAssignCommand) task.getData());
|
break;
|
default:
|
break;
|
}
|
Thread.sleep(500);
|
} catch (Exception e) {
|
e.printStackTrace();
|
}
|
}
|
}
|
|
private void read() {
|
try {
|
if (this.socket == null || this.socket.isClosed()) {
|
//链接断开重新链接
|
this.connect();
|
}
|
readStatus();
|
//四向穿梭车空闲、有任务、标记为true、存在任务指令,需要执行任务的下一条指令
|
if (shuttleProtocol.getFree() == ShuttleStatusType.IDLE.id
|
&& shuttleProtocol.getTaskNo() != 0
|
&& !shuttleProtocol.getPakMk()) {
|
//执行下一步指令
|
executeWork(shuttleProtocol.getTaskNo().shortValue());
|
}
|
} catch (Exception e) {
|
e.printStackTrace();
|
OutputQueue.SHUTTLE.offer(MessageFormat.format("【{0}】四向穿梭车plc状态信息失败 ===>> [id:{1}] [ip:{2}] [port:{3}]", DateUtils.convert(new Date()), slave.getId(), slave.getIp(), slave.getPort()));
|
}
|
}
|
|
private void readStatus() {
|
try {
|
if (null == shuttleProtocol) {
|
shuttleProtocol = new NyShuttleProtocol();
|
shuttleProtocol.setShuttleNo(slave.getId().shortValue());
|
shuttleProtocol.setProtocolStatus(ShuttleProtocolStatusType.IDLE);
|
}
|
|
//----------读取四向穿梭车状态-----------
|
NyShuttleHttpCommand readStatusCommand = NyHttpUtils.getReadStatusCommand(slave.getId());
|
JSONObject jsonObject = NyHttpUtils.requestCommand(socket, readStatusCommand);
|
if (jsonObject == null) {
|
shuttleProtocol.setProtocolStatus(ShuttleProtocolStatusType.OFFLINE);
|
OutputQueue.SHUTTLE.offer(MessageFormat.format("【{0}】四向穿梭车Socket状态信息失败 ===>> [id:{1}] [ip:{2}] [port:{3}]", DateUtils.convert(new Date()), slave.getId(), slave.getIp(), slave.getPort()));
|
}else {
|
//手动状态/自动状态
|
shuttleProtocol.setWorkingMode(jsonObject.getInteger("workingMode"));
|
//允许状态 0:运行中1:空闲
|
shuttleProtocol.setFree(jsonObject.getInteger("free"));
|
//当前速度
|
shuttleProtocol.setSpeed(jsonObject.getInteger("speed"));
|
//负载状态
|
shuttleProtocol.setLoadState(jsonObject.getInteger("loadState"));
|
//管制状态
|
shuttleProtocol.setSuspendState(jsonObject.getInteger("suspendState"));
|
//顶升位置
|
shuttleProtocol.setLiftPosition(jsonObject.getInteger("liftPosition"));
|
//运行方向
|
shuttleProtocol.setRunDir(jsonObject.getInteger("runDir"));
|
//运行方向
|
shuttleProtocol.setRunDir2(jsonObject.getInteger("runDir2"));
|
//充电状态
|
shuttleProtocol.setChargState(jsonObject.getInteger("chargState"));
|
//电池电量
|
shuttleProtocol.setPowerPercent(jsonObject.getInteger("powerPercent"));
|
//最高电芯电压(mV)
|
shuttleProtocol.setMaxCellVoltage(jsonObject.getInteger("maxCellVoltage"));
|
//最低电芯电压(mV)
|
shuttleProtocol.setMinCellVoltage(jsonObject.getInteger("minCellVoltage"));
|
//电池电压
|
shuttleProtocol.setVoltage(jsonObject.getInteger("voltage"));
|
//充放电循环次数
|
shuttleProtocol.setChargeCycleTimes(jsonObject.getInteger("chargeCycleTimes"));
|
//剩余电量
|
shuttleProtocol.setSurplusQuantity(jsonObject.getInteger("surplusQuantity"));
|
//总电量
|
shuttleProtocol.setCountQuantity(jsonObject.getInteger("countQuantity"));
|
//实际库位xyz
|
shuttleProtocol.setPoint(jsonObject.getObject("point", NyShuttleProtocol.NyShuttlePointClass.class));
|
//实际坐标xyz
|
shuttleProtocol.setCoord(jsonObject.getObject("coord", NyShuttleProtocol.NyShuttlePointClass.class));
|
//任务目的库位
|
shuttleProtocol.setTask(jsonObject.getObject("task", NyShuttleProtocol.TaskClass.class));
|
//任务状态
|
shuttleProtocol.setTaskState(jsonObject.getInteger("taskState"));
|
//故障状态
|
shuttleProtocol.setErrState(jsonObject.getInteger("errState"));
|
ArrayList<Integer> errCode = new ArrayList<>();
|
for (Object o : jsonObject.getJSONArray("errCode")) {
|
errCode.add(Integer.parseInt(o.toString()));
|
}
|
//故障码
|
shuttleProtocol.setErrCode(errCode.get(0));
|
//总里程数
|
shuttleProtocol.setStatusSum(jsonObject.getObject("statusSum", NyShuttleProtocol.StatusSumClass.class));
|
//非自动状态时间计时
|
shuttleProtocol.setErrTime(jsonObject.getInteger("errTime"));
|
|
//小车处于运行中,将标记置为false
|
if (shuttleProtocol.getFree() == 0) {
|
shuttleProtocol.setPakMk(false);
|
}
|
|
//将四向穿梭车状态保存至数据库
|
BasShuttleService shuttleService = SpringUtils.getBean(BasShuttleService.class);
|
BasShuttle basShuttle = shuttleService.selectById(slave.getId());
|
if (basShuttle == null) {
|
basShuttle = new BasShuttle();
|
//四向穿梭车号
|
basShuttle.setShuttleNo(slave.getId());
|
shuttleService.insert(basShuttle);
|
}
|
//工作模式
|
basShuttle.setWorkingMode(shuttleProtocol.getWorkingMode());
|
//运行状态
|
basShuttle.setFree(shuttleProtocol.getFree());
|
//当前速度
|
basShuttle.setSpeed(shuttleProtocol.getSpeed());
|
//负载状态
|
basShuttle.setLoadState(shuttleProtocol.getLoadState());
|
//管制状态
|
basShuttle.setSuspendState(shuttleProtocol.getSuspendState());
|
//顶升位置
|
basShuttle.setLiftPosition(shuttleProtocol.getLiftPosition());
|
//运行方向
|
basShuttle.setRunDir(shuttleProtocol.getRunDir());
|
//运行方向
|
basShuttle.setRunDir2(shuttleProtocol.getRunDir2());
|
//充电状态
|
basShuttle.setChargState(shuttleProtocol.getChargState());
|
//电池电量
|
basShuttle.setPowerPercent(shuttleProtocol.getPowerPercent());
|
//最高电芯电压
|
basShuttle.setMaxCellVoltage(shuttleProtocol.getMaxCellVoltage());
|
//电池电压
|
basShuttle.setVoltage(shuttleProtocol.getVoltage());
|
//充放电循环次数
|
basShuttle.setChargeCycleTimes(shuttleProtocol.getChargeCycleTimes());
|
//剩余电量
|
basShuttle.setSurplusQuantity(shuttleProtocol.getSurplusQuantity());
|
//总电量
|
basShuttle.setCountQuantity(shuttleProtocol.getCountQuantity());
|
//实际库位
|
basShuttle.setPoint(JSONObject.toJSONString(shuttleProtocol.getPoint()));
|
//实际坐标
|
basShuttle.setCoord(JSONObject.toJSONString(shuttleProtocol.getCoord()));
|
//任务目的库位
|
basShuttle.setTask(JSONObject.toJSONString(shuttleProtocol.getTask()));
|
//任务状态
|
basShuttle.setTaskState(shuttleProtocol.getTaskState());
|
//故障状态
|
basShuttle.setErrState(shuttleProtocol.getErrState());
|
//总里程数
|
basShuttle.setStatusSum(JSONObject.toJSONString(shuttleProtocol.getStatusSum()));
|
//非自动状态时间计时
|
basShuttle.setErrTime(shuttleProtocol.getErrTime());
|
//任务号
|
basShuttle.setWrkNo(shuttleProtocol.getTaskNo().intValue());
|
//修改时间
|
basShuttle.setUpdateTime(new Date());
|
//作业标记
|
basShuttle.setPakMk(shuttleProtocol.getPakMk());
|
if (shuttleService.updateById(basShuttle)) {
|
OutputQueue.SHUTTLE.offer(MessageFormat.format("【{0}】[id:{1}] <<<<< 实时数据更新成功",DateUtils.convert(new Date()), slave.getId()));
|
// log.info(MessageFormat.format("【{0}】[id:{1}] <<<<< 实时数据更新成功",DateUtils.convert(new Date()), slave.getId()));
|
}
|
}
|
} catch (Exception e) {
|
e.printStackTrace();
|
OutputQueue.SHUTTLE.offer(MessageFormat.format("【{0}】四向穿梭车Socket状态信息失败 ===>> [id:{1}] [ip:{2}] [port:{3}]", DateUtils.convert(new Date()), slave.getId(), slave.getIp(), slave.getPort()));
|
try {
|
this.socket.close();
|
this.socket = null;
|
Thread.sleep(1000);
|
this.connect();
|
} catch (IOException | InterruptedException exception) {
|
e.printStackTrace();
|
}
|
}
|
}
|
|
@Override
|
public boolean connect() {
|
try {
|
Socket socket = new Socket(slave.getIp(),slave.getPort());
|
socket.setSoTimeout(60000);
|
socket.setKeepAlive(true);
|
this.socket = socket;
|
log.info(MessageFormat.format("【{0}】四向穿梭车Socket链接成功 ===>> [id:{1}] [ip:{2}] [port:{3}]", DateUtils.convert(new Date()), slave.getId(), slave.getIp(), slave.getPort()));
|
} catch (IOException e) {
|
OutputQueue.SHUTTLE.offer(MessageFormat.format("【{0}】四向穿梭车Socket链接失败 ===>> [id:{1}] [ip:{2}] [port:{3}]", DateUtils.convert(new Date()), slave.getId(), slave.getIp(), slave.getPort()));
|
}
|
return true;
|
}
|
|
@Override
|
public void close() {
|
|
}
|
|
private boolean write(NyShuttleHttpCommand command, ShuttleAssignCommand assignCommand) {
|
if (null == command) {
|
News.error("四向穿梭车写入命令为空");
|
return false;
|
}
|
BasShuttleService shuttleService = SpringUtils.getBean(BasShuttleService.class);
|
if (shuttleService == null) {
|
News.error("系统错误");
|
return false;
|
}
|
|
BasShuttle basShuttle = shuttleService.selectById(slave.getId().shortValue());
|
if (basShuttle == null) {
|
News.error("四向穿梭车不存在");
|
return false;
|
}
|
|
//发出请求
|
JSONObject result = null;
|
try {
|
result = NyHttpUtils.requestCommand(socket, command);
|
} catch (IOException e) {
|
try {
|
this.socket.close();
|
this.socket = null;
|
Thread.sleep(1000);
|
this.connect();
|
} catch (IOException exception) {
|
exception.printStackTrace();
|
} catch (InterruptedException ex) {
|
throw new RuntimeException(ex);
|
}
|
}
|
|
//保存数据到数据库做流水
|
BasShuttleOptService shuttleOptService = SpringUtils.getBean(BasShuttleOptService.class);
|
BasShuttleOpt opt = null;
|
if (shuttleOptService != null) {
|
opt = new BasShuttleOpt(
|
assignCommand.getTaskNo().intValue(),
|
assignCommand.getShuttleNo().intValue(),
|
new Date(),
|
ShuttleTaskModeType.get(assignCommand.getTaskMode()).desc,
|
assignCommand.getSourceLocNo(),
|
assignCommand.getLocNo(),
|
null,
|
null,
|
null,
|
JSON.toJSONString(command),
|
null,
|
JSON.toJSONString(shuttleProtocol)
|
);
|
opt.setSend(1);//已下发
|
opt.setResponse(JSON.toJSONString(result));//请求响应
|
shuttleOptService.insert(opt);
|
}
|
|
if (result == null) {
|
return false;//请求失败
|
}
|
return true;
|
}
|
|
//分配任务
|
private void assignWork(ShuttleAssignCommand assignCommand) {
|
ShuttleRedisCommand redisCommand = new ShuttleRedisCommand();
|
redisCommand.setShuttleNo(assignCommand.getShuttleNo());//四向穿梭车号
|
redisCommand.setWrkNo(assignCommand.getTaskNo());//工作号
|
redisCommand.setCommandStep(0);//命令执行步序
|
redisCommand.setAssignCommand(assignCommand);//命令
|
shuttleProtocol.setTaskNo(assignCommand.getTaskNo().intValue());
|
shuttleProtocol.setAssignCommand(assignCommand);
|
shuttleProtocol.setProtocolStatus(ShuttleProtocolStatusType.WORKING);
|
//任务数据保存到redis
|
redisUtil.set("shuttle_wrk_no_" + assignCommand.getTaskNo(), JSON.toJSONString(redisCommand));
|
//执行下发任务
|
executeWork(assignCommand.getTaskNo());
|
}
|
|
//执行下发的指令
|
private boolean executeWork(Short wrkNo) {
|
//读取redis数据
|
if (wrkNo == null) {
|
return false;
|
}
|
|
WrkMastMapper wrkMastMapper = SpringUtils.getBean(WrkMastMapper.class);
|
|
Object o = redisUtil.get("shuttle_wrk_no_" + wrkNo);
|
if (o == null) {
|
return false;
|
}
|
|
ShuttleRedisCommand redisCommand = JSON.parseObject(o.toString(), ShuttleRedisCommand.class);
|
ShuttleAssignCommand assignCommand = redisCommand.getAssignCommand();
|
List<NyShuttleHttpCommand> commands = redisCommand.getAssignCommand().getCommands();
|
//当前步序
|
int commandStep = redisCommand.getCommandStep();
|
if (commands.size() == 0) {
|
return false;
|
}
|
|
NavigateMapData navigateMapData = new NavigateMapData(Utils.getLev(shuttleProtocol.getCurrentLocNo()));
|
|
//取出命令
|
NyShuttleHttpCommand command = null;
|
if (commandStep < commands.size()) {
|
command = commands.get(commandStep);//当前命令
|
}
|
if (commandStep != 0) {
|
//判断上一条指令是否完成
|
NyShuttleHttpCommand lastCommand = commands.get(commandStep - 1);
|
String requestType = lastCommand.getRequest().getBody().get("requestType").toString();
|
if (requestType.equals("move") || requestType.equals("intoLift") || requestType.equals("outLift")) {
|
//移动命令、出入提升机命令
|
NyShuttleProtocol.NyShuttlePointClass target = JSON.parseObject(lastCommand.getRequest().getBody().get("target").toString(), NyShuttleProtocol.NyShuttlePointClass.class);
|
if (shuttleProtocol.getPoint().equals(target)) {
|
//上一条指令的目标位置和当前小车位置相同,则认定上一条任务完成
|
lastCommand.setComplete(true);
|
//解锁锁定路径,上一条路径和当前路径
|
List<NavigateNode> nodes = lastCommand.getNodes();
|
if (command != null && command.getNodes() != null) {
|
nodes.addAll(command.getNodes());
|
}
|
if (nodes != null) {
|
navigateMapData.writeNavigateNodeToRedisMap(nodes, false);//解锁路径
|
}
|
}
|
}else {
|
lastCommand.setComplete(true);//其他命令默认认为完成
|
}
|
//任务数据保存到redis
|
redisUtil.set("shuttle_wrk_no_" + redisCommand.getWrkNo(), JSON.toJSONString(redisCommand));
|
|
if (!lastCommand.getComplete()) {
|
//上一条任务未完成,禁止下发命令
|
return false;
|
}
|
|
//判断是否为最后一条命令且命令执行完成,抛出等待确认状态
|
NyShuttleHttpCommand endCommand = commands.get(commands.size() - 1);
|
if (endCommand.getComplete()) {
|
//删除redis
|
redisUtil.del("shuttle_wrk_no_" + redisCommand.getWrkNo());
|
|
if (!assignCommand.getCharge()) {
|
//对主线程抛出等待确认状态waiting
|
shuttleProtocol.setProtocolStatus(ShuttleProtocolStatusType.WAITING);
|
}else {
|
shuttleProtocol.setProtocolStatus(ShuttleProtocolStatusType.CHARGING_WAITING);
|
}
|
News.info("四向穿梭车任务执行下发完成等待执行结束,穿梭车号={},任务数据={}", shuttleProtocol.getShuttleNo(), JSON.toJSON(commands));
|
|
return false;//禁止再下发命令
|
}
|
}
|
|
List<NavigateNode> nextNodes = null;//下一步命令行走路径
|
if (commandStep + 1 < commands.size()) {
|
NyShuttleHttpCommand nextCommand = commands.get(commandStep + 1);//下一步命令
|
nextNodes = nextCommand.getNodes();//下一步命令行走路径
|
}
|
|
if (shuttleProtocol.getFree() == ShuttleStatusType.BUSY.id) {
|
//停止充电
|
if(!(command.getRequest().getBody().get("requestType").equals("stopCharge") && shuttleProtocol.getChargState() == 1)){
|
return false;//小车状态忙,禁止执行命令
|
}
|
}
|
|
// //检测小车是否要进提升机,如需要进提升机则调度提升机
|
// if (!checkLiftStation(wrkNo)) {
|
// return false;
|
// }
|
|
//检测穿梭车是否在提升机内
|
if (!checkShuttleInTheLift(wrkNo)) {
|
return false;
|
}
|
|
if (command.getRequest().getBody().get("requestType").equals("move")) {
|
//检测路径是否可行走
|
if (!checkPath(command.getNodes(), nextNodes, redisCommand)) {
|
return false;
|
}
|
|
//锁定路径,锁定当前路径和下一步路径
|
List<NavigateNode> nodes = command.getNodes();
|
if (nextNodes != null) {
|
nodes.addAll(nextNodes);
|
}
|
if (nodes != null) {
|
navigateMapData.writeNavigateNodeToRedisMap(nodes, true);//所使用的路径进行锁定禁用
|
}
|
}
|
|
//可执行命令
|
if (!write(command, assignCommand)) {
|
News.error("四向穿梭车命令下发失败,穿梭车号={},任务数据={}", shuttleProtocol.getShuttleNo(), JSON.toJSON(command));
|
return false;
|
}
|
|
News.info("四向穿梭车命令下发成功,穿梭车号={},任务数据={}", shuttleProtocol.getShuttleNo(), JSON.toJSON(command));
|
//将标记置为false(防止重发)
|
shuttleProtocol.setPakMk(true);
|
|
String requestType = command.getRequest().getBody().get("requestType").toString();
|
if (requestType.equals("updateFloor")) {
|
//更新楼层命令
|
shuttleProtocol.setPakMk(false);//恢复标记
|
}
|
|
commandStep++;
|
//更新redis数据
|
redisCommand.setCommandStep(commandStep);
|
//任务数据保存到redis
|
redisUtil.set("shuttle_wrk_no_" + redisCommand.getWrkNo(), JSON.toJSONString(redisCommand));
|
|
// //判断数据是否执行完成
|
// if (commandStep < commands.size() - 1) {
|
// commandStep++;
|
// //更新redis数据
|
// redisCommand.setCommandStep(commandStep);
|
// //任务数据保存到redis
|
// redisUtil.set("shuttle_wrk_no_" + redisCommand.getWrkNo(), JSON.toJSONString(redisCommand));
|
// }else {
|
// //已执行完成
|
//
|
// commandStep = commands.size();
|
// //更新redis数据
|
// redisCommand.setCommandStep(commandStep);
|
// //任务数据保存到redis
|
// redisUtil.set("shuttle_wrk_no_" + redisCommand.getWrkNo(), JSON.toJSONString(redisCommand));
|
//// //最后一段命令为移动命令,则暂缓删除redis等待清除路径时一次性删除
|
//// //最后一段命令为不是移动命令,则删除redis
|
//// if (!command.getRequest().getBody().get("requestType").equals("move")) {
|
//// //删除redis
|
//// redisUtil.del("shuttle_wrk_no_" + redisCommand.getWrkNo());
|
//// }
|
////
|
//// if (!assignCommand.getCharge()) {
|
//// //对主线程抛出等待确认状态waiting
|
//// shuttleProtocol.setProtocolStatus(ShuttleProtocolStatusType.WAITING);
|
//// }else {
|
//// shuttleProtocol.setProtocolStatus(ShuttleProtocolStatusType.CHARGING_WAITING);
|
//// }
|
//// News.info("四向穿梭车任务执行下发完成等待执行结束,穿梭车号={},任务数据={}", shuttleProtocol.getShuttleNo(), JSON.toJSON(command));
|
// }
|
|
return true;
|
}
|
|
//检测小车是否要进提升机,如需要进提升机则调度提升机
|
private boolean checkLiftStation(Short wrkNo) {
|
//读取redis数据
|
if (wrkNo == null) {
|
return false;
|
}
|
|
Object o = redisUtil.get("shuttle_wrk_no_" + wrkNo);
|
if (o == null) {
|
return false;
|
}
|
|
WrkMastMapper wrkMastMapper = SpringUtils.getBean(WrkMastMapper.class);
|
|
ShuttleRedisCommand redisCommand = JSON.parseObject(o.toString(), ShuttleRedisCommand.class);
|
//当前步序
|
int commandStep = redisCommand.getCommandStep();
|
|
//检测是否存在提升机口的指令
|
List<NyShuttleHttpCommand> commands = redisCommand.getAssignCommand().getCommands();
|
if (commands.isEmpty()) {
|
return false;
|
}
|
NyShuttleHttpCommand command = commands.get(commandStep);//当前命令
|
if (!command.getMsgType().equals("intoLift")) {
|
return true;//不是入提升机命令,直接放行
|
}
|
|
//获取起点(输送站点)
|
NyShuttleProtocol.NyShuttlePointClass start = JSON.parseObject(command.getRequest().getBody().get("start").toString(), NyShuttleProtocol.NyShuttlePointClass.class);
|
//将牛眼坐标转换成WCS库位号
|
String startLocNo = NavigatePositionConvert.nyXyzToLocNo(start.getX(), start.getY(), start.getZ());
|
|
BasDevpService basDevpService = SpringUtils.getBean(BasDevpService.class);
|
BasDevp basDevp = basDevpService.queryByLocNo(startLocNo);
|
if (basDevp == null) {
|
return false;//查不到站点,禁止下发
|
}
|
|
//拿到提升机线程
|
LiftThread liftThread = (LiftThread) SlaveConnection.get(SlaveType.Lift, basDevp.getLiftNo());
|
if (liftThread == null) {
|
return false;
|
}
|
LiftProtocol liftProtocol = liftThread.getLiftProtocol();
|
if (liftProtocol == null) {
|
return false;
|
}
|
if (!liftProtocol.isIdle()) {
|
return false;
|
}
|
|
if (liftProtocol.getLev().intValue() == Utils.getLev(shuttleProtocol.getCurrentLocNo())) {
|
return true;//提升机达到小车楼层,放行
|
}
|
|
//搜索是否有其他任务占用了提升机,如果占用提升机的任务和当前任务相同,则运行执行
|
WrkMast wrkMast1 = wrkMastMapper.selectLiftWrkMast(liftProtocol.getLiftNo().intValue());
|
if (wrkMast1 != null && wrkMast1.getWrkNo() != wrkNo.intValue()) {
|
return false;
|
}
|
|
//提升机未到达小车楼层,呼叫提升机
|
//获取提升机命令
|
NyLiftCommand liftCommand = NyLiftUtils.getLiftCommand(liftProtocol.getLiftNo().intValue(), NyLiftTaskModelType.MOVE_CAR.id, null, basDevp.getDevNo(), wrkNo.intValue());
|
ArrayList<NyLiftCommand> liftCommands = new ArrayList<>();
|
liftCommands.add(liftCommand);
|
|
//提交到线程去工作
|
LiftAssignCommand assignCommand = new LiftAssignCommand();
|
assignCommand.setCommands(liftCommands);
|
assignCommand.setLiftNo(liftProtocol.getLiftNo());
|
assignCommand.setTaskNo(wrkNo);
|
assignCommand.setTaskMode(NyLiftTaskModelType.MOVE_CAR.id.shortValue());
|
|
//下发任务
|
MessageQueue.offer(SlaveType.Lift, liftProtocol.getLiftNo().intValue(), new Task(3, assignCommand));
|
|
return false;//默认不放行
|
}
|
|
/**
|
* 检测穿梭车是否在提升机内
|
* 如穿梭车在提升机内,必须等待提升机空闲才可执行穿梭车命令
|
*/
|
private boolean checkShuttleInTheLift(Short wrkNo) {
|
//读取redis数据
|
if (wrkNo == null) {
|
return false;
|
}
|
|
Object o = redisUtil.get("shuttle_wrk_no_" + wrkNo);
|
if (o == null) {
|
return false;
|
}
|
|
SlaveProperties slaveProperties = SpringUtils.getBean(SlaveProperties.class);
|
BasLiftService liftService = SpringUtils.getBean(BasLiftService.class);
|
for (LiftSlave liftSlave : slaveProperties.getLift()) {
|
BasLift basLift = liftService.selectById(liftSlave.getId());
|
if (basLift == null) {
|
continue;
|
}
|
Integer liftX = basLift.getPoint$().getX();
|
Integer liftY = basLift.getPoint$().getY();
|
if (liftX.equals(shuttleProtocol.getPoint().getX()) && liftY.equals(shuttleProtocol.getPoint().getY())) {
|
//小车在提升机内
|
//判断提升机是否空闲
|
LiftThread liftThread = (LiftThread) SlaveConnection.get(SlaveType.Lift, liftSlave.getId());
|
if (liftThread == null) {
|
return false;
|
}
|
LiftProtocol liftProtocol = liftThread.getLiftProtocol();
|
if (liftProtocol == null) {
|
return false;
|
}
|
if (liftProtocol.isIdle()) {
|
//提升机处于空闲,放行
|
return true;
|
}
|
}else {
|
return true;//不在提升机内,放行
|
}
|
}
|
return false;//默认不放行
|
}
|
|
/**
|
* 检测路径是否可行走
|
* 如果路径为目标库位,但不可行走,系统将尝试重新计算路径
|
*/
|
private boolean checkPath(List<NavigateNode> currentNodes, List<NavigateNode> nextNodes, ShuttleRedisCommand redisCommand) {
|
//检测路径是否可行走(检查路径锁定状态,检测路径是否有其他小车)
|
//检测当前行走路径,和下一步路径
|
boolean checkPathIsAvailable = NavigateUtils.checkPathIsAvailable(currentNodes, shuttleProtocol.getShuttleNo().intValue(), Utils.getLev(shuttleProtocol.getCurrentLocNo()));
|
if (nextNodes == null) {
|
if (checkPathIsAvailable) {
|
return true;//可行走
|
}
|
return false;
|
}else {
|
boolean checkPathIsAvailable2 = NavigateUtils.checkPathIsAvailable(nextNodes, shuttleProtocol.getShuttleNo().intValue(), Utils.getLev(shuttleProtocol.getCurrentLocNo()));
|
if (checkPathIsAvailable && checkPathIsAvailable2) {
|
return true;//可行走
|
}
|
}
|
|
// ShuttleAssignCommand assignCommand = redisCommand.getAssignCommand();
|
// NavigateNode currentTarget = currentNodes.get(currentNodes.size() - 1);
|
// String currentLocNo = NavigatePositionConvert.nodeToLocNo(currentTarget);
|
// NavigateNode nextTarget = nextNodes.get(nextNodes.size() - 1);
|
// String nextLocNo = NavigatePositionConvert.nodeToLocNo(nextTarget);
|
// if (assignCommand.getLocNo().equals(currentLocNo) || assignCommand.getLocNo().equals(nextLocNo)) {
|
// //当前路径最后一个节点是目标库位,进行路径检测,如果不可行走,重新计算路径
|
// //不可行走,重新计算路径
|
// NyShuttleOperaResult result = NyShuttleOperaUtils.getStartToTargetCommands(shuttleProtocol.getShuttleNo().intValue(), shuttleProtocol.getTaskNo(), shuttleProtocol.getCurrentLocNo(), assignCommand.getLocNo());
|
// if (result == null) {
|
// return false;//路径计算失败,不可行走
|
// }
|
//
|
// List<NyShuttleHttpCommand> newCommands = result.getCommands();//新路径
|
//
|
// //当前步序
|
// int commandStep = redisCommand.getCommandStep();
|
// List<NyShuttleHttpCommand> commands = assignCommand.getCommands();
|
//
|
// commands.remove(commandStep);//移除当前步序指令
|
// if (assignCommand.getLocNo().equals(currentLocNo)) {
|
// //当前路径,需要再多移除下一步指令
|
// commands.remove(commandStep + 1);
|
// }
|
//
|
// //将新路径添加进指令集合
|
// commands.addAll(commandStep, newCommands);
|
// assignCommand.setCommands(commands);
|
// redisCommand.setAssignCommand(assignCommand);
|
// //任务数据保存到redis
|
// redisUtil.set("shuttle_wrk_no_" + redisCommand.getWrkNo(), JSON.toJSONString(redisCommand));
|
// return false;//当前不可行走,等待下一次执行走新路径
|
// }
|
|
return false;//不可行走
|
}
|
|
}
|