package com.zy.core.action;
|
|
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.serializer.SerializerFeature;
|
import com.baomidou.mybatisplus.mapper.EntityWrapper;
|
import com.fasterxml.jackson.core.type.TypeReference;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.zy.asrs.domain.param.CreateLocMoveTaskParam;
|
import com.zy.asrs.entity.BasShuttleOpt;
|
import com.zy.asrs.entity.LocMast;
|
import com.zy.asrs.entity.WrkMast;
|
import com.zy.asrs.service.BasShuttleOptService;
|
import com.zy.asrs.service.LocMastService;
|
import com.zy.asrs.service.WrkMastService;
|
import com.zy.asrs.utils.Utils;
|
import com.zy.common.model.NavigateNode;
|
import com.zy.common.service.CommonService;
|
import com.zy.common.utils.NavigateMapUtils;
|
import com.zy.common.utils.RedisUtil;
|
import com.zy.core.News;
|
import com.zy.core.cache.SlaveConnection;
|
import com.zy.core.dispatcher.ShuttleDispatchUtils;
|
import com.zy.core.enums.*;
|
import com.zy.core.model.CommandResponse;
|
import com.zy.core.model.command.ShuttleAssignCommand;
|
import com.zy.core.model.command.ShuttleCommand;
|
import com.zy.core.model.command.ShuttleRedisCommand;
|
import com.zy.core.model.protocol.ShuttleProtocol;
|
import com.zy.core.thread.ShuttleThread;
|
import com.zy.core.thread.TrafficControlThread;
|
import com.zy.system.entity.Config;
|
import com.zy.system.service.ConfigService;
|
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.stereotype.Component;
|
|
import java.io.IOException;
|
import java.util.*;
|
|
@Component
|
public class ShuttleAction {
|
|
@Autowired
|
private RedisUtil redisUtil;
|
@Autowired
|
private NavigateMapUtils navigateMapUtils;
|
@Autowired
|
private LocMastService locMastService;
|
@Autowired
|
private ObjectMapper objectMapper;
|
@Autowired
|
private ConfigService configService;
|
@Autowired
|
private BasShuttleOptService basShuttleOptService;
|
@Autowired
|
private WrkMastService wrkMastService;
|
@Autowired
|
private ShuttleDispatchUtils shuttleDispatchUtils;
|
@Autowired
|
private CommonService commonService;
|
|
public synchronized boolean assignWork(Integer shuttleNo, ShuttleAssignCommand assignCommand) {
|
ShuttleThread shuttleThread = (ShuttleThread) SlaveConnection.get(SlaveType.Shuttle, shuttleNo);
|
if (shuttleThread == null) {
|
return false;
|
}
|
|
TrafficControlThread trafficControlThread = (TrafficControlThread) SlaveConnection.get(SlaveType.TrafficControl, 1);
|
if(trafficControlThread == null){
|
return false;
|
}
|
|
//清空下发索引
|
Set<String> keys = redisUtil.searchKeys(RedisKeyType.SHUTTLE_SEND_COMMAND_INDEX.key + shuttleNo);
|
for (String key : keys) {
|
redisUtil.del(key);
|
}
|
|
ShuttleRedisCommand redisCommand = new ShuttleRedisCommand();
|
|
redisCommand.setShuttleNo(assignCommand.getShuttleNo());//四向穿梭车号
|
redisCommand.setWrkNo(assignCommand.getTaskNo());//工作号
|
redisCommand.setCommandStep(0);//命令执行步序
|
redisCommand.setAssignCommand(assignCommand);//命令
|
//任务数据保存到redis
|
if (redisUtil.set(RedisKeyType.SHUTTLE_WORK_FLAG.key + assignCommand.getTaskNo(), JSON.toJSONString(redisCommand, SerializerFeature.DisableCircularReferenceDetect))) {
|
shuttleThread.setSyncTaskNo(assignCommand.getTaskNo());
|
return true;
|
}
|
return false;
|
}
|
|
public synchronized boolean executeWork(Integer shuttleNo, Integer taskNo) {
|
Object obj = redisUtil.get(RedisKeyType.SHUTTLE_WORK_FLAG.key + taskNo);
|
if (obj == null) {
|
return false;
|
}
|
|
ShuttleRedisCommand redisCommand = null;
|
try {
|
redisCommand = objectMapper.readValue(String.valueOf(obj), ShuttleRedisCommand.class);
|
} catch (IOException e) {
|
throw new RuntimeException(e);
|
}
|
|
if (redisCommand == null) {
|
return false;
|
}
|
|
ShuttleThread shuttleThread = (ShuttleThread) SlaveConnection.get(SlaveType.Shuttle, shuttleNo);
|
if (shuttleThread == null) {
|
return false;
|
}
|
|
ShuttleProtocol shuttleProtocol = shuttleThread.getStatus();
|
if (shuttleProtocol == null) {
|
return false;
|
}
|
|
//判断工作号是否相同
|
if (!shuttleProtocol.getTaskNo().equals(taskNo)) {
|
return false;
|
}
|
|
//检测命令
|
int checked = checkCommand(redisCommand, shuttleNo);
|
if (checked == 0) {
|
return false;
|
}
|
|
ShuttleAssignCommand assignCommand = redisCommand.getAssignCommand();
|
List<ShuttleCommand> commands = assignCommand.getCommands();
|
if (commands.isEmpty()) {
|
return false;
|
}
|
|
int commandStep = redisCommand.getCommandStep();
|
if(commandStep >= commands.size()){
|
return false;
|
}
|
|
//取出命令
|
ShuttleCommand command = null;
|
if (checked == 1) {
|
//非连续指令,需要检测上一条指令是否完成
|
if (commandStep > 0) {
|
ShuttleCommand lastCommand = commands.get(commandStep - 1);
|
if (!lastCommand.getComplete()) {
|
return false;//指令未完成
|
}
|
}
|
|
command = commands.get(commandStep);
|
} else if (checked == 2) {
|
//连续指令直接取数据
|
command = commands.get(commandStep);
|
}
|
|
if(command == null){
|
return false;
|
}
|
|
//移动命令,锁定路径
|
if (command.getMode() == ShuttleCommandModeType.MOVE.id) {
|
List<NavigateNode> nodes = JSON.parseArray(JSON.toJSONString(command.getNodes()), NavigateNode.class);
|
//申请管制
|
boolean apply = applyTrafficControl(commands, nodes, shuttleNo, taskNo);
|
if(!apply){
|
return false;//申请失败
|
}
|
// //检测路径是否冲突
|
// int conflict = searchShuttlePathConflict(nodes, shuttleNo);
|
// if(conflict == 2){
|
// return false;//检测后有冲突
|
// }
|
|
if (checked == 2) {
|
nodes.remove(0);
|
}
|
|
boolean result = navigateMapUtils.writeNavigateNodeToRedisMap(Utils.getLev(command.getTargetLocNo()), shuttleNo, nodes, true);//锁定路径
|
if (!result) {
|
News.error("{} device can't lock path!", shuttleNo);
|
shuttleThread.offerSystemMsg("{} device can't lock path!", shuttleNo);
|
return false;//路径锁定失败
|
}
|
}
|
|
// 下发命令
|
CommandResponse response = write(command, shuttleNo);
|
|
//保存命令日志
|
BasShuttleOpt basShuttleOpt = new BasShuttleOpt();
|
basShuttleOpt.setWrkNo(redisCommand.getWrkNo());
|
basShuttleOpt.setShuttleNo(shuttleNo);
|
|
basShuttleOpt.setMode(ShuttleTaskModeType.get(assignCommand.getTaskMode()).desc);
|
basShuttleOpt.setSourceLocNo(assignCommand.getSourceLocNo());
|
basShuttleOpt.setDistLocNo(assignCommand.getLocNo());
|
basShuttleOpt.setCommand(JSON.toJSONString(command));
|
basShuttleOpt.setSystemStatus(JSON.toJSONString(shuttleProtocol));
|
basShuttleOpt.setDeviceWrk(String.valueOf(command.getTaskNo()));
|
basShuttleOpt.setResponse(response.getMessage());//获取响应
|
basShuttleOpt.setSendTime(new Date());//指令下发时间
|
basShuttleOpt.setSend(response.getResult() ? 1 : 0);
|
//保存命令流水
|
basShuttleOptService.insert(basShuttleOpt);
|
|
if (!response.getResult()) {
|
News.error("四向穿梭车命令下发失败,穿梭车号={},任务数据={}", shuttleProtocol.getShuttleNo(), JSON.toJSON(command));
|
return false;
|
}
|
|
shuttleThread.setProtocolStatus(ShuttleProtocolStatusType.WORKING);
|
|
//存储下发指令索引
|
redisUtil.set(RedisKeyType.SHUTTLE_SEND_COMMAND_INDEX.key + shuttleNo + "_" + taskNo + "_" + commandStep, commandStep);
|
|
commandStep += 1;
|
//更新redis数据
|
redisCommand.setCommandStep(commandStep);
|
|
//任务数据保存到redis
|
redisUtil.set(RedisKeyType.SHUTTLE_WORK_FLAG.key + redisCommand.getWrkNo(), JSON.toJSONString(redisCommand));
|
return true;
|
}
|
|
/**
|
* 检测命令
|
* 0:未通过 1:通过 2:通过且可提前下发指令
|
*/
|
private int checkCommand(ShuttleRedisCommand redisCommand, Integer shuttleNo) {
|
TrafficControlThread trafficControlThread = (TrafficControlThread) SlaveConnection.get(SlaveType.TrafficControl, 1);
|
if(trafficControlThread == null){
|
return 0;
|
}
|
|
ShuttleThread shuttleThread = (ShuttleThread) SlaveConnection.get(SlaveType.Shuttle, shuttleNo);
|
if (shuttleThread == null) {
|
return 0;
|
}
|
|
ShuttleProtocol shuttleProtocol = shuttleThread.getStatus();
|
if (shuttleProtocol == null) {
|
return 0;
|
}
|
|
int commandStep = redisCommand.getCommandStep();
|
if (commandStep == 0) {
|
return 1;//第一条命令无需检测
|
}
|
|
ShuttleAssignCommand assignCommand = redisCommand.getAssignCommand();
|
List<ShuttleCommand> commands = assignCommand.getCommands();
|
if (commands.isEmpty()) {
|
return 0;
|
}
|
|
//上一条指令
|
String searchKey = RedisKeyType.SHUTTLE_SEND_COMMAND_INDEX.key + shuttleNo + "_" + redisCommand.getWrkNo() + "_";
|
Set<String> keys = redisUtil.searchKeys(searchKey);
|
TreeSet<Integer> treeSet = new TreeSet<>();
|
for (String key : keys) {
|
String[] split = key.split(searchKey);
|
treeSet.add(Integer.parseInt(split[1]));
|
}
|
if (treeSet.isEmpty()) {
|
return 1;
|
}
|
|
String firstKey = searchKey + treeSet.first();
|
Integer lastCommandIdx = (Integer) redisUtil.get(firstKey);
|
ShuttleCommand lastCommand = commands.get(lastCommandIdx);
|
if (!lastCommand.getComplete()) {
|
//检测更新命令完成
|
boolean checked = updateCommandComplete(lastCommandIdx, commands, shuttleNo);
|
if (checked) {
|
//删除索引
|
redisUtil.del(firstKey);
|
|
// 更新redis数据
|
redisUtil.set(RedisKeyType.SHUTTLE_WORK_FLAG.key + redisCommand.getWrkNo(), JSON.toJSONString(redisCommand, SerializerFeature.DisableCircularReferenceDetect));
|
}else {
|
//小车移动连续下发指令
|
if (assignCommand.getShuttleMoveCommandsContinuously()) {
|
if (treeSet.size() <= 1) {
|
if(commandStep >= commands.size()) {
|
return 0;
|
}
|
|
//移动指令
|
if(lastCommand.getMode() != ShuttleCommandModeType.MOVE.id) {
|
return 0;
|
}
|
|
List<NavigateNode> nodes = lastCommand.getNodes();
|
NavigateNode startNode = nodes.get(0);
|
if (!startNode.getLinePartAllowGo()) {//直线段部分,允许直接行走
|
return 0;
|
}
|
|
//直线段数据标识
|
Long linePartFlag = startNode.getLinePartFlag();
|
|
//取指令
|
ShuttleCommand currentCommand = commands.get(commandStep);
|
if(currentCommand.getMode() != ShuttleCommandModeType.MOVE.id) {
|
return 0;
|
}
|
|
List<NavigateNode> currentNodes = currentCommand.getNodes();
|
NavigateNode currentStartNode = currentNodes.get(0);
|
if(!currentStartNode.getLinePartAllowGo()) {//直线段部分,允许直接行走
|
return 0;
|
}
|
|
if(currentStartNode.getLinePartFlag().equals(linePartFlag)) {
|
//数据标识一致
|
return 2;//允许小车移动连续下发指令
|
}
|
|
}
|
}
|
|
return 0;
|
}
|
}
|
|
//判断是否为最后一条命令且命令执行完成,抛出等待确认状态
|
ShuttleCommand endCommand = commands.get(commands.size() - 1);
|
if (endCommand.getComplete()) {
|
News.info("四向穿梭车任务执行下发完成等待执行结束,穿梭车号={},任务数据={}", shuttleProtocol.getShuttleNo(), JSON.toJSON(commands));
|
|
// 系统任务
|
if (assignCommand.getAuto()) {
|
if (!assignCommand.getCharge()) {
|
//对主线程抛出等待确认状态waiting
|
shuttleThread.setProtocolStatus(ShuttleProtocolStatusType.WAITING);
|
} else {
|
shuttleThread.setProtocolStatus(ShuttleProtocolStatusType.CHARGING_WAITING);
|
}
|
News.info("四向穿梭车任务执行下发完成等待执行结束,穿梭车号={},任务数据={}", shuttleProtocol.getShuttleNo(), JSON.toJSON(endCommand));
|
|
// 手动任务
|
} else {
|
//手动模式不抛出等待状态,直接复位空闲状态
|
shuttleThread.setProtocolStatus(ShuttleProtocolStatusType.IDLE);
|
//任务号清零
|
shuttleThread.setSyncTaskNo(0);
|
//标记复位
|
shuttleThread.setPakMk(true);
|
News.info("四向穿梭车手动任务执行完成,穿梭车号={},任务数据={}", shuttleProtocol.getShuttleNo(), JSON.toJSON(endCommand));
|
}
|
|
//申请取消管制
|
trafficControlThread.cancelTrafficControl(shuttleNo, shuttleProtocol.getTaskNo());
|
//删除redis
|
redisUtil.del(RedisKeyType.SHUTTLE_WORK_FLAG.key + redisCommand.getWrkNo());
|
return 0;//禁止再下发命令
|
}
|
|
return 1;
|
}
|
|
//检测更新命令完成
|
private boolean updateCommandComplete(Integer commandIdx, List<ShuttleCommand> commands, Integer shuttleNo) {
|
ShuttleThread shuttleThread = (ShuttleThread) SlaveConnection.get(SlaveType.Shuttle, shuttleNo);
|
if (shuttleThread == null) {
|
return false;
|
}
|
|
ShuttleProtocol shuttleProtocol = shuttleThread.getStatus();
|
if (shuttleProtocol == null) {
|
return false;
|
}
|
|
//判断设备是否空闲
|
boolean deviceIdle = shuttleThread.isDeviceIdle();
|
|
ShuttleCommand command = commands.get(commandIdx);
|
if (command.getMode() == ShuttleCommandModeType.MOVE.id) {
|
// 正常移动
|
List<String> targetPoints = new ArrayList<>();
|
|
//解锁锁定路径,上一条路径
|
List<NavigateNode> nodes = null;
|
try {
|
String nodesStr = objectMapper.writeValueAsString(command.getNodes());
|
nodes = objectMapper.readValue(nodesStr, new TypeReference<List<NavigateNode>>() {
|
});
|
} catch (IOException e) {
|
throw new RuntimeException(e);
|
}
|
|
NavigateNode startNode = nodes.get(0);
|
Long linePartFlag = startNode.getLinePartFlag();
|
|
NavigateNode targetNode = nodes.get(nodes.size() - 1);
|
targetPoints.add(targetNode.getX() + "-" + targetNode.getY());
|
|
for (int i = commandIdx + 1; i < commands.size(); i++) {
|
ShuttleCommand nextCommand = commands.get(i);
|
if (nextCommand.getMode() == ShuttleCommandModeType.MOVE.id) {
|
List<NavigateNode> nextCommandNodes = nextCommand.getNodes();
|
NavigateNode nextStartNode = nextCommandNodes.get(0);
|
Long nextLinePartFlag = nextStartNode.getLinePartFlag();
|
if(nextLinePartFlag.equals(linePartFlag)) {
|
for (NavigateNode node : nextCommandNodes) {
|
String key = node.getX() + "-" + node.getY();
|
if(!targetPoints.contains(key)) {
|
targetPoints.add(key);
|
}
|
}
|
}
|
}
|
}
|
|
TrafficControlThread trafficControlThread = (TrafficControlThread) SlaveConnection.get(SlaveType.TrafficControl, 1);
|
if (trafficControlThread == null) {
|
return false;
|
}
|
//上报交管
|
trafficControlThread.trafficReport(command.getNodesDeepCopy(), shuttleNo, shuttleProtocol.getTaskNo());
|
|
String currentLocNo = shuttleProtocol.getCurrentLocNo();
|
if (targetPoints.contains(Utils.getRow(currentLocNo) + "-" + Utils.getBay(currentLocNo))) {
|
command.setComplete(true);
|
boolean result = navigateMapUtils.writeNavigateNodeToRedisMap(Utils.getLev(shuttleProtocol.getCurrentLocNo()), shuttleProtocol.getShuttleNo(), nodes, false);//解锁路径
|
if (!result) {
|
return false;//解锁失败
|
}
|
}else {
|
return false;
|
}
|
} else if (command.getMode() == ShuttleCommandModeType.PALLET_LIFT.id) {
|
// 托盘顶升
|
if (!deviceIdle) {
|
return false;//设备不空闲
|
}
|
|
//判断是否顶升到位
|
if (shuttleProtocol.getHasLift()) {
|
command.setComplete(true);
|
// //判断是否有物
|
// if (shuttleProtocol.getHasPallet()) {
|
// command.setComplete(true);
|
// }
|
}else {
|
return false;
|
}
|
} else if (command.getMode() == ShuttleCommandModeType.PALLET_DOWN.id) {
|
// 托盘下降命令
|
if (!deviceIdle) {
|
return false;//设备不空闲
|
}
|
|
// 判断是否下降到位
|
if (!shuttleProtocol.getHasLift()) {
|
command.setComplete(true);
|
}else {
|
return false;
|
}
|
} else if (command.getMode() == ShuttleCommandModeType.CHARGE_OPEN.id) {
|
// 充电开
|
//判断小车充电状态
|
if (shuttleProtocol.getHasCharge()) {
|
command.setComplete(true);
|
}else {
|
return false;
|
}
|
} else if (command.getMode() == ShuttleCommandModeType.CHARGE_CLOSE.id) {
|
//关闭充电
|
command.setComplete(true);
|
} else {
|
command.setComplete(true);//其他命令默认认为完成
|
}
|
|
return true;
|
}
|
|
//申请管制
|
public boolean applyTrafficControl(List<ShuttleCommand> commands, List<NavigateNode> nodeList, Integer shuttleNo, Integer taskNo) {
|
TrafficControlThread trafficControlThread = (TrafficControlThread) SlaveConnection.get(SlaveType.TrafficControl, 1);
|
if (trafficControlThread == null) {
|
return false;
|
}
|
|
List<NavigateNode> totalNodeList = new ArrayList<>();
|
for (ShuttleCommand command : commands) {
|
if (command.getMode() == ShuttleCommandModeType.MOVE.id) {
|
List<NavigateNode> deepCopy = command.getNodesDeepCopy();
|
if (deepCopy != null) {
|
totalNodeList.addAll(deepCopy);
|
}
|
}
|
}
|
return trafficControlThread.applyTrafficControl(totalNodeList, nodeList, shuttleNo, taskNo);
|
}
|
|
// /**
|
// * 搜索小车路径是否存在冲突
|
// * 0:未检测 1:检测无冲突 2:检测有冲突
|
// */
|
// public int searchShuttlePathConflict(List<NavigateNode> nodeList, Integer shuttleNo) {
|
// ShuttleThread shuttleThread = (ShuttleThread) SlaveConnection.get(SlaveType.Shuttle, shuttleNo);
|
// if (shuttleThread == null) {
|
// return 0;
|
// }
|
//
|
// ShuttleProtocol shuttleProtocol = shuttleThread.getStatus();
|
// if (shuttleProtocol == null) {
|
// return 0;
|
// }
|
//
|
// int lev = Utils.getLev(shuttleProtocol.getCurrentLocNo());
|
//
|
// TrafficControlThread trafficControlThread = (TrafficControlThread) SlaveConnection.get(SlaveType.TrafficControl, 1);
|
// if (trafficControlThread == null) {
|
// return 2;
|
// }
|
// HashMap<String, List<Integer>> nodeMap = trafficControlThread.getNodesMapByLev(lev);
|
// if (nodeMap == null || nodeMap.isEmpty()) {
|
// return 2;
|
// }
|
//
|
// List<String> conflictLocList = new ArrayList<>();
|
// for (NavigateNode node : nodeList) {
|
// String locNo = Utils.getLocNo(node.getX(), node.getY(), lev);
|
// if(!nodeMap.containsKey(locNo)) {
|
// return 2;
|
// }
|
//
|
// List<Integer> shuttleNos = nodeMap.get(locNo);
|
// if (shuttleNos.size() > 1) {
|
// //路径存在多车,冲突
|
// conflictLocList.add(locNo);
|
// }
|
// }
|
//
|
// if (conflictLocList.isEmpty()) {
|
// //无冲突,解除交通管制
|
// shuttleThread.setTrafficControl(false, null);
|
// return 1;//检测后无冲突
|
// }
|
//
|
// //路径存在冲突,检测可执行车辆是否为当前小车
|
// //上报小车状态-交通管制中
|
// shuttleThread.setTrafficControl(true, nodeList);
|
//
|
// HashMap<String, Integer> deviceMap = trafficControlThread.getDeviceMap();
|
// if(deviceMap == null) {
|
// return 2;
|
// }
|
//
|
// boolean detected = false;
|
//// for (Map.Entry<String, Integer> entry : deviceMap.entrySet()) {
|
//// List<String> mainList = JSON.parseArray(entry.getKey(), String.class);
|
//// Integer device = entry.getValue();
|
//// if(result) {
|
//// //判断管制车辆是否匹配
|
//// if(shuttleNo.equals(device)) {
|
//// detected = true;
|
//// break;
|
//// }
|
//// }
|
//// }
|
//
|
// for (Map.Entry<String, Integer> entry : deviceMap.entrySet()) {
|
// String key = entry.getKey();
|
// Integer value = entry.getValue();
|
// if(shuttleNo.equals(value)) {
|
// //判断管制车辆是否匹配
|
// detected = true;
|
// break;
|
// }
|
// }
|
//
|
// if (detected) {
|
// return 1;//检测后无冲突,交通管制已允许此小车运行
|
// }
|
//
|
// return 2;//检测后有冲突
|
// }
|
|
//演示模式
|
public synchronized void demo(Integer shuttleNo) {
|
ShuttleThread shuttleThread = (ShuttleThread) SlaveConnection.get(SlaveType.Shuttle, shuttleNo);
|
if (shuttleThread == null) {
|
return;
|
}
|
|
ShuttleProtocol shuttleProtocol = shuttleThread.getStatus();
|
if (shuttleProtocol == null) {
|
return;
|
}
|
|
if (!shuttleProtocol.getDemo()) {
|
return;
|
}
|
|
WrkMast moveWorking = wrkMastService.selectShuttleHasMoveWorking(shuttleNo);
|
if (moveWorking != null) {
|
return;
|
}
|
|
WrkMast shuttleWorking = wrkMastService.selectShuttleWorking(shuttleNo);
|
if(shuttleWorking != null) {
|
return;
|
}
|
|
WrkMast chargeWorking = wrkMastService.selectChargeWorking(shuttleNo);
|
if (chargeWorking != null) {
|
return;
|
}
|
|
if (shuttleThread.isRequireCharge()) {
|
return;
|
}
|
|
if (!shuttleThread.isIdle()) {
|
return;
|
}
|
|
boolean demoSwitchLev = false;
|
Config demoSwitchLevConfig = configService.selectOne(new EntityWrapper<Config>().eq("code", "demoSwitchLev"));
|
if (demoSwitchLevConfig != null) {
|
if (demoSwitchLevConfig.getValue().equals("Y")) {
|
demoSwitchLev = true;
|
}
|
}
|
|
Config demoRunLevConfig = configService.selectOne(new EntityWrapper<Config>().eq("code", "demoRunLev"));
|
if (demoRunLevConfig == null) {
|
return;
|
}
|
List<Integer> levList = JSON.parseArray(demoRunLevConfig.getValue(), Integer.class);
|
|
if (!demoSwitchLev) {
|
String currentLocNo = shuttleProtocol.getCurrentLocNo();
|
levList = new ArrayList<>();
|
levList.add(Utils.getLev(currentLocNo));
|
}
|
|
LocMast targetLoc = null;
|
EntityWrapper<LocMast> wrapper = new EntityWrapper<>();
|
wrapper.in("lev1", levList);
|
wrapper.eq("loc_sts", "O");
|
wrapper.last("ORDER BY RAND() LIMIT 1");
|
for (int i = 0; i < 3; i++) {
|
LocMast locMast = locMastService.selectOne(wrapper);
|
if(locMast == null) {
|
continue;
|
}
|
|
ArrayList<String> locs = new ArrayList<>();
|
locs.add(locMast.getLocNo());
|
Integer shuttle = Utils.checkGroupLocHasShuttle(locs);
|
if(shuttle != null) {
|
continue;
|
}
|
|
targetLoc = locMast;
|
break;
|
}
|
|
if(targetLoc == null) {
|
return;
|
}
|
|
shuttleDispatchUtils.dispatchShuttle(null, targetLoc.getLocNo(), shuttleProtocol.getShuttleNo());
|
}
|
|
public synchronized void demoModeCargoMove() {
|
Config demoCargoMoveConfig = configService.selectOne(new EntityWrapper<Config>().eq("code", "demoCargoMove"));
|
if (demoCargoMoveConfig == null) {
|
return;
|
}
|
|
if (!demoCargoMoveConfig.getValue().equals("Y")) {
|
return;
|
}
|
|
|
Config demoRunLevConfig = configService.selectOne(new EntityWrapper<Config>().eq("code", "demoRunLev"));
|
if (demoRunLevConfig == null) {
|
return;
|
}
|
List<Integer> levList = JSON.parseArray(demoRunLevConfig.getValue(), Integer.class);
|
Random random = new Random();
|
int index = random.nextInt(levList.size());
|
Integer lev = levList.get(index);
|
|
//获取楼层小车数量
|
int shuttleCountByLev = shuttleDispatchUtils.getShuttleCountByLev(lev);
|
//获取楼层货物搬运任务
|
int currentLevTask = 0;
|
for (WrkMast wrkMast : wrkMastService.selectList(new EntityWrapper<WrkMast>().eq("io_type", WrkIoType.LOC_MOVE.id))) {
|
if (Utils.getLev(wrkMast.getLocNo()) == lev) {
|
currentLevTask += 1;
|
}
|
}
|
|
//搬运任务数量超过小车数量,暂时不生成新任务
|
if (currentLevTask > shuttleCountByLev) {
|
return;
|
}
|
|
LocMast sourceLoc = null;
|
EntityWrapper<LocMast> wrapper = new EntityWrapper<>();
|
wrapper.eq("lev1", lev);
|
wrapper.eq("loc_sts", "F");
|
wrapper.last("ORDER BY RAND() LIMIT 1");
|
for (int i = 0; i < 3; i++) {
|
LocMast locMast = locMastService.selectOne(wrapper);
|
if(locMast == null) {
|
continue;
|
}
|
|
sourceLoc = locMast;
|
break;
|
}
|
|
if(sourceLoc == null) {
|
return;
|
}
|
|
LocMast targetLoc = null;
|
EntityWrapper<LocMast> targetWrapper = new EntityWrapper<>();
|
targetWrapper.eq("lev1", lev);
|
targetWrapper.eq("loc_sts", "O");
|
targetWrapper.last("ORDER BY RAND() LIMIT 1");
|
for (int i = 0; i < 3; i++) {
|
LocMast locMast = locMastService.selectOne(targetWrapper);
|
if(locMast == null) {
|
continue;
|
}
|
|
targetLoc = locMast;
|
break;
|
}
|
|
if(targetLoc == null) {
|
return;
|
}
|
|
try {
|
CreateLocMoveTaskParam param = new CreateLocMoveTaskParam();
|
param.setSourceLocNo(sourceLoc.getLocNo());
|
param.setLocNo(targetLoc.getLocNo());
|
param.setTaskPri(13);
|
|
boolean result = commonService.createLocMoveTask(param);
|
} catch (Exception e) {
|
e.printStackTrace();
|
}
|
}
|
|
// //跑库程序
|
// public synchronized void moveLoc(Integer shuttleNo) {
|
// ShuttleThread shuttleThread = (ShuttleThread) SlaveConnection.get(SlaveType.Shuttle, shuttleNo);
|
// if (shuttleThread == null) {
|
// return;
|
// }
|
// ShuttleProtocol shuttleProtocol = shuttleThread.getStatus(false);
|
// if (shuttleProtocol == null) {
|
// return;
|
// }
|
//
|
// //小车开启跑库模式
|
// if (!shuttleProtocol.getMoveLoc()) {
|
// return;
|
// }
|
//
|
// //小车空闲
|
// if (!shuttleThread.isIdle()) {
|
// return;
|
// }
|
//
|
// int lev = Utils.getLev(shuttleProtocol.getCurrentLocNo());//小车当前楼层
|
//
|
// if (shuttleProtocol.getMoveType() == 0) {//跑轨道
|
// //根据地图方向决定跑x或y
|
// Config config = configService.selectOne(new EntityWrapper<Config>()
|
// .eq("code", "direction_map")
|
// .eq("status", 1));
|
// if (config == null) {
|
// //跑库结束
|
// 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;
|
// }
|
// String direction = config.getValue();
|
//
|
// if (direction.equals("y")) {//跑x轴方向,跑完x轴再切换y轴
|
// 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<LocMast> locList = locMastService.selectList(new EntityWrapper<LocMast>()
|
// .eq("loc_sts", LocStsType.O.toString())
|
// .in("loc_no", locs));
|
// if (locList.isEmpty()) {
|
// //空库位
|
// shuttleProtocol.setYCurrent(shuttleProtocol.getYCurrent() + 1);
|
// return;
|
// }
|
//
|
// LocMast start = locList.get(0);
|
// LocMast target = locList.get(locList.size() - 1);
|
// //判断小车是否在起点位置
|
// if (!shuttleProtocol.getCurrentLocNo().equals(start.getLocNo())) {//不在起点位置,调度去起点位置
|
// shuttleDispatcher.generateMoveTask(device, start.getLocNo());
|
// }else {
|
// //在起点位置,调度去目标位置
|
// Task task = shuttleDispatcher.generateMoveTask(device, target.getLocNo());
|
// if (task != null) {
|
// shuttleProtocol.setYCurrent(shuttleProtocol.getYCurrent() + 1);//切换y轴
|
// }
|
//
|
// if(shuttleProtocol.getYCurrent() > shuttleProtocol.getYTarget()) {
|
// //y轴也跑完了,结束跑库
|
// 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;
|
// }
|
// }
|
// }else {//跑y轴方向,跑完y轴再切换x轴
|
// ArrayList<String> locs = new ArrayList<>();
|
// for (int i = shuttleProtocol.getYCurrent(); i <= shuttleProtocol.getYTarget(); i++) {
|
// String locNo = Utils.getLocNo(shuttleProtocol.getXCurrent(), i, lev);
|
// locs.add(locNo);
|
// }
|
//
|
// List<Loc> locList = locService.list(new LambdaQueryWrapper<Loc>()
|
// .eq(Loc::getLocSts, LocStsType.O.val())
|
// .in(Loc::getLocNo, locs));
|
// if (locList.isEmpty()) {
|
// //空库位
|
// shuttleProtocol.setXCurrent(shuttleProtocol.getXCurrent() + 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 {
|
// //在起点位置,调度去目标位置
|
// Task task = shuttleDispatcher.generateMoveTask(device, target.getLocNo());
|
// if (task != null) {
|
// shuttleProtocol.setXCurrent(shuttleProtocol.getXCurrent() + 1);//切换x轴
|
// }
|
//
|
// if(shuttleProtocol.getXCurrent() > shuttleProtocol.getXTarget()) {
|
// //y轴也跑完了,结束跑库
|
// 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;
|
// }
|
// }
|
// }
|
//
|
// } else if (shuttleProtocol.getMoveType() == 1) {//跑库位
|
// //根据地图方向决定跑x或y
|
// Dict dict = dictService.getOne(new LambdaQueryWrapper<Dict>()
|
// .eq(Dict::getFlag, "direction_map")
|
// .eq(Dict::getStatus, 1));
|
// if (dict == null) {
|
// //跑库结束
|
// 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;
|
// }
|
// String direction = dict.getValue();
|
//
|
// if (direction.equals("y")) {//跑x轴方向,跑完x轴再切换y轴
|
// Integer xCurrent = shuttleProtocol.getXCurrent();
|
//
|
// //获取待跑库位号
|
// String locNo = Utils.getLocNo(xCurrent, shuttleProtocol.getYCurrent(), lev);
|
// Loc target = locService.getOne(new LambdaQueryWrapper<Loc>()
|
// .eq(Loc::getLocNo, locNo)
|
// .eq(Loc::getLocSts, LocStsType.O.val())
|
// .eq(Loc::getHostId, device.getHostId()));
|
// if (target == null || shuttleProtocol.getCurrentLocNo().equals(locNo)) {//库位不存在或小车已在当前位置
|
// shuttleProtocol.setXCurrent(xCurrent + 1);
|
// if (shuttleProtocol.getXCurrent() > shuttleProtocol.getXTarget()) {
|
// //x轴跑完,切换y轴
|
// shuttleProtocol.setXCurrent(shuttleProtocol.getXStart());
|
// shuttleProtocol.setYCurrent(shuttleProtocol.getYCurrent() + 1);
|
//
|
// if(shuttleProtocol.getYCurrent() > shuttleProtocol.getYTarget()) {
|
// //y轴也跑完了,结束跑库
|
// 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;
|
// }
|
// }
|
// return;
|
// }
|
//
|
// //调度去库位
|
// Task task = shuttleDispatcher.generateMoveTask(device, locNo);
|
// if (task == null) {
|
// return;//调度失败
|
// }
|
//
|
// shuttleProtocol.setXCurrent(xCurrent + 1);
|
// if (shuttleProtocol.getXCurrent() > shuttleProtocol.getXTarget()) {
|
// //x轴跑完,切换y轴
|
// shuttleProtocol.setXCurrent(shuttleProtocol.getXStart());
|
// shuttleProtocol.setYCurrent(shuttleProtocol.getYCurrent() + 1);
|
//
|
// if(shuttleProtocol.getYCurrent() > shuttleProtocol.getYTarget()) {
|
// //y轴也跑完了,结束跑库
|
// 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;
|
// }
|
// }
|
//
|
// }else {//跑y轴方向,跑完y轴再切换x轴
|
// Integer yCurrent = shuttleProtocol.getYCurrent();
|
//
|
// //获取待跑库位号
|
// String locNo = Utils.getLocNo(shuttleProtocol.getXCurrent(), yCurrent, lev);
|
// Loc target = locService.getOne(new LambdaQueryWrapper<Loc>()
|
// .eq(Loc::getLocNo, locNo)
|
// .eq(Loc::getLocSts, LocStsType.O.val())
|
// .eq(Loc::getHostId, device.getHostId()));
|
// if (target == null || shuttleProtocol.getCurrentLocNo().equals(locNo)) {//库位不存在或小车已在当前位置
|
// shuttleProtocol.setYCurrent(yCurrent + 1);
|
// if (shuttleProtocol.getYCurrent() > shuttleProtocol.getYTarget()) {
|
// //y轴跑完,切换x轴
|
// shuttleProtocol.setYCurrent(shuttleProtocol.getYStart());
|
// shuttleProtocol.setXCurrent(shuttleProtocol.getXCurrent() + 1);
|
//
|
// if(shuttleProtocol.getXCurrent() > shuttleProtocol.getXTarget()) {
|
// //x轴也跑完了,结束跑库
|
// 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;
|
// }
|
// }
|
// return;
|
// }
|
//
|
// //调度去库位
|
// Task task = shuttleDispatcher.generateMoveTask(device, locNo);
|
// if (task == null) {
|
// return;//调度失败
|
// }
|
//
|
// shuttleProtocol.setYCurrent(yCurrent + 1);
|
// if (shuttleProtocol.getYCurrent() > shuttleProtocol.getYTarget()) {
|
// //y轴跑完,切换x轴
|
// shuttleProtocol.setYCurrent(shuttleProtocol.getYStart());
|
// shuttleProtocol.setXCurrent(shuttleProtocol.getXCurrent() + 1);
|
//
|
// if(shuttleProtocol.getXCurrent() > shuttleProtocol.getXTarget()) {
|
// //x轴也跑完了,结束跑库
|
// 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;
|
// }
|
// }
|
//
|
// }
|
// } 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());//切换库位
|
// }
|
// }
|
// }
|
// } else if (shuttleProtocol.getMoveType() == 4) {//取放货
|
// Integer xCurrent = shuttleProtocol.getXCurrent();
|
// if (xCurrent > shuttleProtocol.getXTarget()) {//当X值大于X目标值
|
// shuttleProtocol.setXCurrent(shuttleProtocol.getXStart());
|
// shuttleProtocol.setYCurrent(shuttleProtocol.getYStart());
|
// return;
|
// }
|
//
|
// //判断x轴货位是否放满
|
// boolean flag = true;
|
// for (Loc loc : locService.list(new LambdaQueryWrapper<Loc>()
|
// .eq(Loc::getHostId, device.getHostId())
|
// .eq(Loc::getRow, xCurrent)
|
// .ge(Loc::getBay, shuttleProtocol.getYStart())
|
// .le(Loc::getBay, shuttleProtocol.getYTarget()))) {
|
// if (loc.getLocSts() != LocStsType.F.val()) {
|
// flag = false;//未满
|
// break;
|
// }
|
// }
|
// if (flag) {
|
// shuttleProtocol.setXCurrent(shuttleProtocol.getXCurrent() + 1);
|
// return;
|
// }
|
//
|
// //搜索有货库位
|
// List<Loc> list = locService.list(new LambdaQueryWrapper<Loc>()
|
// .eq(Loc::getLocSts, LocStsType.F.val())
|
// .eq(Loc::getHostId, device.getHostId())
|
// .notIn(Loc::getRow, xCurrent)
|
// .eq(Loc::getStatus, 1));
|
// if (list.isEmpty()) {
|
// return;
|
// }
|
//
|
// Loc start = list.get(0);
|
//
|
// List<Loc> locList = locService.list(new LambdaQueryWrapper<Loc>()
|
// .eq(Loc::getHostId, device.getHostId())
|
// .eq(Loc::getStatus, 1)
|
// .eq(Loc::getLocSts, LocStsType.O.val())
|
// .eq(Loc::getRow, xCurrent)
|
// .orderByDesc(Loc::getBay)
|
// .orderByAsc(Loc::getRow));
|
// if (locList.isEmpty()) {
|
// return;
|
// }
|
//
|
// Loc target = locList.get(0);
|
// if (target == null) {
|
// return;
|
// }
|
//
|
// //调度去目标位置
|
// if (!shuttleProtocol.getCurrentLocNo().equals(target.getLocNo())) {
|
// Task task = shuttleDispatcher.generateManuaTakeMoveTask(device, start.getLocNo(), target.getLocNo());
|
//// if(task != null) {//调度成功
|
//// shuttleProtocol.setXCurrent(shuttleProtocol.getXCurrent() + 1);
|
//// }
|
// }
|
// }
|
// }
|
|
private synchronized CommandResponse write(ShuttleCommand command, Integer shuttleNo) {
|
CommandResponse response = new CommandResponse(false);
|
if (null == command) {
|
News.error("四向穿梭车写入命令为空");
|
response.setMessage("四向穿梭车写入命令为空");
|
return response;
|
}
|
ShuttleThread shuttleThread = (ShuttleThread) SlaveConnection.get(SlaveType.Shuttle, shuttleNo);
|
if (command.getMode() == ShuttleCommandModeType.MOVE.id
|
|| command.getMode() == ShuttleCommandModeType.IN_LIFT.id
|
|| command.getMode() == ShuttleCommandModeType.OUT_LIFT.id) {//移动
|
response = shuttleThread.move(command);
|
} else if (command.getMode() == ShuttleCommandModeType.PALLET_LIFT.id
|
|| command.getMode() == ShuttleCommandModeType.PALLET_DOWN.id) {//顶升
|
response = shuttleThread.lift(command);
|
} else if (command.getMode() == ShuttleCommandModeType.CHARGE_OPEN.id
|
|| command.getMode() == ShuttleCommandModeType.CHARGE_CLOSE.id) {//充电
|
response = shuttleThread.charge(command);
|
} else if (command.getMode() == ShuttleCommandModeType.RESET.id) {//复位
|
response = shuttleThread.reset(command);
|
} else if (command.getMode() == ShuttleCommandModeType.UPDATE_LOCATION.id) {//更新坐标
|
response = shuttleThread.updateLocation(command);
|
}
|
|
News.info("四向穿梭车命令下发,穿梭车号={},任务数据={}", shuttleNo, JSON.toJSON(command));
|
return response;
|
}
|
|
}
|