package com.zy.core.thread.impl;
|
|
import com.core.common.SpringUtils;
|
import com.zy.asrs.utils.Utils;
|
import com.zy.common.model.NavigateNode;
|
import com.zy.common.utils.RedisUtil;
|
import com.zy.common.utils.ShuttleOperaUtils;
|
import com.zy.core.News;
|
import com.zy.core.cache.SlaveConnection;
|
import com.zy.core.enums.RedisKeyType;
|
import com.zy.core.enums.SlaveType;
|
import com.zy.core.model.TrafficControlDataModel;
|
import com.zy.core.model.param.OperateTrafficControlParam;
|
import com.zy.core.model.protocol.ShuttleProtocol;
|
import com.zy.core.thread.ShuttleThread;
|
import com.zy.core.thread.TrafficControlThread;
|
import org.springframework.scheduling.annotation.Async;
|
|
import java.util.*;
|
import java.util.stream.Collectors;
|
|
public class TrafficControlImplThread implements TrafficControlThread {
|
|
private RedisUtil redisUtil;
|
|
private List<TrafficControlDataModel> applyList = new ArrayList<>();
|
private HashMap<Integer,Long> shuttleReportErrorMap = new HashMap<>();
|
private HashMap<Integer,Long> pathIdleShuttleMap = new HashMap<>();
|
private HashMap<Integer,Long> applyRecordsMap = new HashMap<>();
|
private HashMap<String, List<NavigateNode>> taskNodesMap = new HashMap<>();
|
private List<TrafficControlDataModel> trafficControlDataList = new ArrayList<>();
|
private List<TrafficControlDataModel> trafficControlDataListRead = new ArrayList<>();
|
|
public TrafficControlImplThread(RedisUtil redisUtil) {
|
this.redisUtil = redisUtil;
|
}
|
|
@Override
|
public void run() {
|
//从缓存恢复交管信息
|
Object object = redisUtil.get(RedisKeyType.TRAFFIC_CONTROL_MAP.key);
|
if(object != null) {
|
trafficControlDataList = (List<TrafficControlDataModel>) object;
|
trafficControlDataListRead = trafficControlDataList.stream()
|
.map(model -> new TrafficControlDataModel(
|
model.getShuttleNo(),
|
model.getTaskNo(),
|
new ArrayList<>(model.getNodeList()),
|
new ArrayList<>(model.getTotalNodeList())
|
))
|
.collect(Collectors.toList());
|
}
|
|
while (true) {
|
try {
|
List<TrafficControlDataModel> allTrafficControl = getAllTrafficControl();
|
//更新交管信息
|
redisUtil.set(RedisKeyType.TRAFFIC_CONTROL_MAP.key, allTrafficControl);
|
|
for (TrafficControlDataModel dataModel : allTrafficControl) {
|
Integer shuttleNo = dataModel.getShuttleNo();
|
Integer taskNo = dataModel.getTaskNo();
|
|
Object object1 = redisUtil.get(RedisKeyType.TRAFFIC_CONTROL_SUCCESS_APPLY.key + shuttleNo + "_" + taskNo);
|
if(object1 == null) {
|
redisUtil.set(RedisKeyType.TRAFFIC_CONTROL_SUCCESS_APPLY.key + shuttleNo + "_" + taskNo, 1, 60 * 60);
|
}
|
}
|
|
Thread.sleep(200);
|
}catch (Exception e){
|
e.printStackTrace();
|
}
|
}
|
|
}
|
|
@Override
|
public synchronized boolean processApply(TrafficControlDataModel applyData) {
|
ShuttleOperaUtils shuttleOperaUtils = SpringUtils.getBean(ShuttleOperaUtils.class);
|
if (shuttleOperaUtils == null) {
|
return false;
|
}
|
|
if (applyData == null) {
|
return false;
|
}
|
|
if (applyData.getShuttleNo() == null || applyData.getTaskNo() == null || applyData.getNodeList() == null || applyData.getTotalNodeList() == null) {
|
return false;
|
}
|
|
List<TrafficControlDataModel> allTrafficControlList = getAllTrafficControl();
|
|
Integer shuttleNo = applyData.getShuttleNo();
|
Integer taskNo = applyData.getTaskNo();
|
List<NavigateNode> nodeList = applyData.getNodeList();
|
List<NavigateNode> totalNodeList = applyData.getTotalNodeList();
|
|
NavigateNode startNode = totalNodeList.get(0);
|
List<int[]> shuttlePoints = Utils.getShuttlePoints(shuttleNo, startNode.getZ());
|
|
int[] currentShuttlePoint = Utils.getShuttlePoint(shuttleNo);
|
if(currentShuttlePoint == null) {
|
return false;
|
}
|
String currentShuttleLoc = Utils.getLocNo(currentShuttlePoint[0], currentShuttlePoint[1], startNode.getZ());
|
|
List<String> shuttleLocList = new ArrayList<>();
|
for (int[] shuttlePoint : shuttlePoints) {
|
String locNo = Utils.getLocNo(shuttlePoint[0], shuttlePoint[1], startNode.getZ());
|
shuttleLocList.add(locNo);
|
}
|
|
//检测车子是否存在管制
|
for (int i = 0; i < allTrafficControlList.size(); i++) {
|
TrafficControlDataModel controlDataModel = allTrafficControlList.get(i);
|
if(shuttleNo.equals(controlDataModel.getShuttleNo())) {
|
//存在管制
|
if(!controlDataModel.getTaskNo().equals(taskNo)) {
|
return false;
|
}
|
|
for (NavigateNode node : nodeList) {
|
String locNo = Utils.getLocNo(node.getX(), node.getY(), node.getZ());
|
if(shuttleLocList.contains(locNo)) {
|
ShuttleThread shuttleThread = Utils.searchShuttle(locNo);
|
if(shuttleThread != null) {
|
shuttleThread.restartCalcPath();
|
}
|
}
|
}
|
|
// News.info("traffic running {},{}", shuttleNo, taskNo);
|
return true;//已经管制允许执行
|
}
|
}
|
|
ShuttleThread shuttleThread = (ShuttleThread) SlaveConnection.get(SlaveType.Shuttle, shuttleNo);
|
if (shuttleThread == null) {
|
return false;
|
}
|
|
if (!applyRecordsMap.containsKey(shuttleNo)) {
|
applyRecordsMap.put(shuttleNo, System.currentTimeMillis());
|
}
|
|
Long applyRecordTime = applyRecordsMap.get(shuttleNo);
|
if ((System.currentTimeMillis() - applyRecordTime) > 1000 * 10) {
|
shuttleThread.restartCalcPath();
|
}
|
|
List<String> totalLocList = new ArrayList<>();
|
for (NavigateNode node : totalNodeList) {
|
String locNo = Utils.getLocNo(node.getX(), node.getY(), node.getZ());
|
totalLocList.add(locNo);
|
}
|
|
//检测路径是否有小车
|
for (String loc : totalLocList) {
|
if(shuttleLocList.contains(loc)) {
|
ShuttleThread pathShuttleThread = Utils.searchShuttle(loc);
|
if (pathShuttleThread == null) {
|
return false;
|
}
|
|
ShuttleProtocol shuttleProtocol = pathShuttleThread.getStatus();
|
if(shuttleProtocol == null) {
|
return false;
|
}
|
|
if (pathShuttleThread.isIdle()) {
|
if(pathIdleShuttleMap.containsKey(shuttleProtocol.getShuttleNo())) {
|
Long idleTime = pathIdleShuttleMap.get(shuttleProtocol.getShuttleNo());
|
if((System.currentTimeMillis() - idleTime) > 1000 * 10) {
|
//检测障碍物车
|
boolean checkObstacle = shuttleOperaUtils.checkObstacle(shuttleProtocol.getCurrentLocNo(), new ArrayList<Integer>() {{
|
add(shuttleNo);
|
}}, totalNodeList);
|
pathIdleShuttleMap.remove(shuttleProtocol.getShuttleNo());
|
}
|
}else {
|
pathIdleShuttleMap.put(shuttleProtocol.getShuttleNo(), System.currentTimeMillis());
|
}
|
}
|
return false;//node has shuttle
|
}
|
}
|
|
//检测节点是否被使用
|
for (TrafficControlDataModel controlDataModel : allTrafficControlList) {
|
List<NavigateNode> list = controlDataModel.getTotalNodeList();
|
for (int i = 0; i < list.size(); i++) {
|
NavigateNode node = list.get(i);
|
String locNo = Utils.getLocNo(node.getX(), node.getY(), node.getZ());
|
if (i == 0 && currentShuttleLoc.equals(locNo)) {
|
continue;//..todo wait watch problem
|
}
|
|
if(totalLocList.contains(locNo)) {
|
return false;
|
}
|
}
|
}
|
|
//交管接收
|
OperateTrafficControlParam param = new OperateTrafficControlParam();
|
param.setDataModel(applyData);
|
param.setOperaType("add");
|
operateTrafficControl(param);
|
|
applyRecordsMap.remove(shuttleNo);
|
redisUtil.set(RedisKeyType.TRAFFIC_CONTROL_SUCCESS_APPLY.key + shuttleNo + "_" + taskNo, 1, 60 * 60);
|
News.info("receipt traffic {},{}", shuttleNo, taskNo);
|
return true;
|
}
|
|
@Override
|
public boolean applyTrafficControl(List<NavigateNode> totalNodeList, List<NavigateNode> nodeList, Integer shuttleNo, Integer taskNo) {
|
Set<String> keys = redisUtil.searchKeys(RedisKeyType.TRAFFIC_CONTROL_APPLY.key + shuttleNo + "_");
|
if (!keys.isEmpty()) {
|
return false;
|
}
|
|
TrafficControlDataModel model = new TrafficControlDataModel();
|
model.setShuttleNo(shuttleNo);
|
model.setTaskNo(taskNo);
|
model.setNodeList(nodeList);
|
model.setTotalNodeList(totalNodeList);
|
redisUtil.set(RedisKeyType.TRAFFIC_CONTROL_APPLY.key + shuttleNo + "_" + System.currentTimeMillis(), model);
|
return true;
|
}
|
|
@Override
|
public boolean trafficReport(List<NavigateNode> nodeList, Integer shuttleNo, Integer taskNo) {
|
//检测车子是否存在管制
|
List<TrafficControlDataModel> allTrafficControlList = getAllTrafficControl();
|
for (int i = 0; i < allTrafficControlList.size(); i++) {
|
TrafficControlDataModel controlDataModel = allTrafficControlList.get(i);
|
if(shuttleNo.equals(controlDataModel.getShuttleNo())) {
|
if(controlDataModel.getTaskNo().equals(taskNo)) {
|
OperateTrafficControlParam param = new OperateTrafficControlParam();
|
param.setDataModel(controlDataModel);
|
param.setOperaType("report");
|
param.setReportNodeList(nodeList);
|
redisUtil.set(RedisKeyType.TRAFFIC_CONTROL_REPORT_LIST.key + shuttleNo + "_" + System.currentTimeMillis(), param);
|
return true;
|
}
|
}
|
}
|
return false;
|
}
|
|
@Override
|
public synchronized boolean trafficReportError(Integer shuttleNo, Integer taskNo) {
|
ShuttleThread shuttleThread = (ShuttleThread) SlaveConnection.get(SlaveType.Shuttle, shuttleNo);
|
if (shuttleThread == null) {
|
return false;
|
}
|
|
if(shuttleReportErrorMap.containsKey(shuttleNo)) {
|
Long errorTime = shuttleReportErrorMap.get(shuttleNo);
|
if((System.currentTimeMillis() - errorTime) > 1000 * 10) {
|
shuttleReportErrorMap.remove(shuttleNo);
|
shuttleThread.restartCalcPath();
|
}
|
}else {
|
shuttleReportErrorMap.put(shuttleNo, System.currentTimeMillis());
|
}
|
return true;
|
}
|
|
@Override
|
public boolean cancelTrafficControl(Integer shuttleNo, Integer taskNo) {
|
TrafficControlDataModel dataModel = queryTrafficControl(shuttleNo, taskNo);
|
if (dataModel == null) {
|
return false;
|
}
|
|
OperateTrafficControlParam param = new OperateTrafficControlParam();
|
param.setDataModel(dataModel);
|
param.setOperaType("cancel");
|
param.setForceCancel(false);
|
return operateTrafficControl(param);
|
}
|
|
@Override
|
public boolean forceCancelTrafficControl(Integer shuttleNo) {
|
TrafficControlDataModel dataModel = queryTrafficControl(shuttleNo);
|
if (dataModel == null) {
|
return false;
|
}
|
|
OperateTrafficControlParam param = new OperateTrafficControlParam();
|
param.setDataModel(dataModel);
|
param.setOperaType("cancel");
|
param.setForceCancel(true);
|
return operateTrafficControl(param);
|
}
|
|
@Override
|
public TrafficControlDataModel queryTrafficControl(Integer shuttleNo, Integer taskNo) {
|
//检测车子是否存在管制
|
List<TrafficControlDataModel> allTrafficControlList = getAllTrafficControl();
|
for (int i = 0; i < allTrafficControlList.size(); i++) {
|
TrafficControlDataModel controlDataModel = allTrafficControlList.get(i);
|
if(shuttleNo.equals(controlDataModel.getShuttleNo())) {
|
if(controlDataModel.getTaskNo().equals(taskNo)) {
|
return controlDataModel;
|
}
|
}
|
}
|
return null;
|
}
|
|
@Override
|
public TrafficControlDataModel queryTrafficControl(Integer shuttleNo) {
|
//检测车子是否存在管制
|
List<TrafficControlDataModel> allTrafficControlList = getAllTrafficControl();
|
for (int i = 0; i < allTrafficControlList.size(); i++) {
|
TrafficControlDataModel controlDataModel = allTrafficControlList.get(i);
|
if(shuttleNo.equals(controlDataModel.getShuttleNo())) {
|
return controlDataModel;
|
}
|
}
|
return null;
|
}
|
|
@Override
|
public List<TrafficControlDataModel> getAllTrafficControl() {
|
return trafficControlDataListRead;
|
}
|
|
@Override
|
public synchronized boolean operateTrafficControl(OperateTrafficControlParam param) {
|
long startTime = System.currentTimeMillis();
|
String operaType = param.getOperaType();
|
News.info("Operate Traffic Control is Start " + operaType);
|
|
boolean result = false;
|
if (operaType.equals("add")) {
|
result = addTrafficControlDataList(param);
|
} else if (operaType.equals("cancel")) {
|
result = removeTrafficControlDataList(param);
|
} else if (operaType.equals("report")) {
|
result = reportTrafficControlDataList(param);
|
}
|
|
this.trafficControlDataListRead = trafficControlDataList.stream()
|
.map(model -> new TrafficControlDataModel(
|
model.getShuttleNo(),
|
model.getTaskNo(),
|
new ArrayList<>(model.getNodeList()),
|
new ArrayList<>(model.getTotalNodeList())
|
))
|
.collect(Collectors.toList());
|
News.info("Operate Traffic Control is end " + (System.currentTimeMillis() - startTime) + "ms");
|
return result;
|
}
|
|
public synchronized boolean addTrafficControlDataList(OperateTrafficControlParam param) {
|
TrafficControlDataModel dataModel = param.getDataModel();
|
trafficControlDataList.add(dataModel);
|
return true;
|
}
|
|
public synchronized boolean removeTrafficControlDataList(OperateTrafficControlParam param) {
|
//检测车子是否存在管制
|
TrafficControlDataModel dataModel = param.getDataModel();
|
Boolean forceCancel = param.getForceCancel();
|
|
Integer shuttleNo = dataModel.getShuttleNo();
|
Integer taskNo = dataModel.getTaskNo();
|
|
int idx = -1;
|
for (int i = 0; i < trafficControlDataList.size(); i++) {
|
TrafficControlDataModel controlDataModel = trafficControlDataList.get(i);
|
if(shuttleNo.equals(controlDataModel.getShuttleNo())) {
|
if (forceCancel) {
|
idx = i;
|
break;
|
}else {
|
if(controlDataModel.getTaskNo().equals(taskNo)) {
|
idx = i;
|
break;
|
}
|
}
|
}
|
}
|
|
if(idx == -1) {
|
return false;
|
}
|
|
trafficControlDataList.remove(idx);//取消管制
|
redisUtil.del(RedisKeyType.TRAFFIC_CONTROL_SUCCESS_APPLY.key + shuttleNo + "_" + taskNo);
|
return true;
|
}
|
|
public synchronized boolean reportTrafficControlDataList(OperateTrafficControlParam param) {
|
//检测车子是否存在管制
|
TrafficControlDataModel dataModel = param.getDataModel();
|
List<NavigateNode> reportNodeList = param.getReportNodeList();
|
|
Integer shuttleNo = dataModel.getShuttleNo();
|
Integer taskNo = dataModel.getTaskNo();
|
|
for (int i = 0; i < trafficControlDataList.size(); i++) {
|
TrafficControlDataModel controlDataModel = trafficControlDataList.get(i);
|
if(shuttleNo.equals(controlDataModel.getShuttleNo())) {
|
if(controlDataModel.getTaskNo().equals(taskNo)) {
|
List<NavigateNode> newTotalNodeList = new ArrayList<>();
|
List<NavigateNode> totalNodeList = controlDataModel.getTotalNodeList();
|
|
List<String> reportList = new ArrayList<>();
|
for (NavigateNode node : reportNodeList) {
|
reportList.add(Utils.getLocNo(node.getX(), node.getY(), node.getZ()));
|
}
|
|
for (NavigateNode node : totalNodeList) {
|
String locNo = Utils.getLocNo(node.getX(), node.getY(), node.getZ());
|
if(reportList.contains(locNo)) {
|
continue;
|
}
|
newTotalNodeList.add(node);
|
}
|
|
controlDataModel.setTotalNodeList(newTotalNodeList);
|
trafficControlDataList.set(i, controlDataModel);
|
shuttleReportErrorMap.remove(shuttleNo);
|
return true;
|
}
|
}
|
}
|
return false;
|
}
|
|
@Override
|
public boolean connect() {
|
return false;
|
}
|
|
@Override
|
public void close() {
|
|
}
|
|
}
|