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 applyList = new ArrayList<>(); private HashMap shuttleReportErrorMap = new HashMap<>(); private HashMap pathIdleShuttleMap = new HashMap<>(); private HashMap applyRecordsMap = new HashMap<>(); private HashMap> taskNodesMap = new HashMap<>(); private List trafficControlDataList = new ArrayList<>(); private List 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) 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 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 allTrafficControlList = getAllTrafficControl(); Integer shuttleNo = applyData.getShuttleNo(); Integer taskNo = applyData.getTaskNo(); List nodeList = applyData.getNodeList(); List totalNodeList = applyData.getTotalNodeList(); NavigateNode startNode = totalNodeList.get(0); List 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 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 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() {{ add(shuttleNo); }}, totalNodeList); pathIdleShuttleMap.remove(shuttleProtocol.getShuttleNo()); } }else { pathIdleShuttleMap.put(shuttleProtocol.getShuttleNo(), System.currentTimeMillis()); } } return false;//node has shuttle } } //检测节点是否被使用 for (TrafficControlDataModel controlDataModel : allTrafficControlList) { List 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 totalNodeList, List nodeList, Integer shuttleNo, Integer taskNo) { Set 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 nodeList, Integer shuttleNo, Integer taskNo) { //检测车子是否存在管制 List 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 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 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 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 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 newTotalNodeList = new ArrayList<>(); List totalNodeList = controlDataModel.getTotalNodeList(); List 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() { } }