no message
parent
d8b84477ad
commit
31d08765ab
|
|
@ -56,7 +56,6 @@ public interface AgvTaskMapper extends BaseMapper<AgvTask> {
|
||||||
*
|
*
|
||||||
* @param endCode 终点
|
* @param endCode 终点
|
||||||
*/
|
*/
|
||||||
@Select(value = "select * from data_agv_task where end_code = #{endCode} and type='OUTBOUND' and status = 4 and agv_vendor = 'TES' order by create_time desc limit 1 ")
|
|
||||||
AgvTask queryByLastEndCode(@Param("endCode") String endCode);
|
AgvTask queryByLastEndCode(@Param("endCode") String endCode);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,21 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
<mapper namespace="org.cpte.modules.agvTask.mapper.AgvTaskMapper">
|
<mapper namespace="org.cpte.modules.agvTask.mapper.AgvTaskMapper">
|
||||||
|
<select id="queryByLastEndCode" resultType="org.cpte.modules.agvTask.entity.AgvTask">
|
||||||
|
(SELECT * FROM data_agv_task
|
||||||
|
WHERE start_code = #{endCode}
|
||||||
|
AND type IN ('INBOUND','OUTBOUND')
|
||||||
|
AND agv_vendor = 'TES'
|
||||||
|
ORDER BY create_time DESC
|
||||||
|
LIMIT 1)
|
||||||
|
UNION ALL
|
||||||
|
(SELECT * FROM data_agv_task
|
||||||
|
WHERE end_code = #{endCode}
|
||||||
|
AND type IN ('INBOUND','OUTBOUND')
|
||||||
|
AND agv_vendor = 'TES'
|
||||||
|
ORDER BY create_time DESC
|
||||||
|
LIMIT 1)
|
||||||
|
ORDER BY create_time DESC
|
||||||
|
LIMIT 1
|
||||||
|
</select>
|
||||||
</mapper>
|
</mapper>
|
||||||
|
|
@ -22,4 +22,7 @@ public interface AreaMapper extends BaseMapper<Area> {
|
||||||
*/
|
*/
|
||||||
@Select("select * from base_area where area_code = #{areaCode}")
|
@Select("select * from base_area where area_code = #{areaCode}")
|
||||||
Area queryByAreaCode(@Param("areaCode") String areaCode);
|
Area queryByAreaCode(@Param("areaCode") String areaCode);
|
||||||
|
|
||||||
|
@Select("select * from base_area where id in (select area_id from base_point where point_code = #{pointCode})")
|
||||||
|
Area queryByPointCode(@Param("pointCode") String pointCode);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,9 @@ public class SyncPointProcessor {
|
||||||
|
|
||||||
public Boolean syncPoint(Area area, JSONObject pointJsonObject) {
|
public Boolean syncPoint(Area area, JSONObject pointJsonObject) {
|
||||||
try {
|
try {
|
||||||
|
if(pointJsonObject==null){
|
||||||
|
return Boolean.TRUE;
|
||||||
|
}
|
||||||
JSONArray laneListArray = extractLaneList(pointJsonObject);
|
JSONArray laneListArray = extractLaneList(pointJsonObject);
|
||||||
if (CollectionUtils.isEmpty(laneListArray)) {
|
if (CollectionUtils.isEmpty(laneListArray)) {
|
||||||
return Boolean.TRUE;
|
return Boolean.TRUE;
|
||||||
|
|
@ -136,15 +139,43 @@ public class SyncPointProcessor {
|
||||||
if (CollectionUtils.isEmpty(nodeArray)) {
|
if (CollectionUtils.isEmpty(nodeArray)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int lineNo = 1;
|
|
||||||
boolean isDoubleLane = faceDirArray != null && faceDirArray.size() > 1;
|
boolean isDoubleLane = faceDirArray != null && faceDirArray.size() > 1;
|
||||||
|
if(isDoubleLane){
|
||||||
|
processNodesForward(area, nodeArray, colNum, true, pointMap, data, processedPointCodes);
|
||||||
|
}else{
|
||||||
|
String faceDir=faceDirArray.getString(0);
|
||||||
|
if("E".equals(faceDir)){
|
||||||
|
//反方向
|
||||||
|
processNodesReverse(area, nodeArray, colNum, pointMap, data, processedPointCodes);
|
||||||
|
}else if("W".equals(faceDir)){
|
||||||
|
processNodesForward(area, nodeArray, colNum, false, pointMap, data, processedPointCodes);
|
||||||
|
}else {
|
||||||
|
log.error("处理库位数据失败: 巷道方向错误");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//正向添加库位
|
||||||
|
private void processNodesForward(Area area, JSONArray nodeArray, String colNum,
|
||||||
|
boolean isDoubleLane, Map<String, Point> pointMap,
|
||||||
|
SyncPointData data, Set<String> processedPointCodes) {
|
||||||
for (int j = 0; j < nodeArray.size(); j++) {
|
for (int j = 0; j < nodeArray.size(); j++) {
|
||||||
JSONObject nodeObject = nodeArray.getJSONObject(j);
|
JSONObject nodeObject = nodeArray.getJSONObject(j);
|
||||||
processSingleNode(area, nodeObject, colNum, String.valueOf(lineNo),
|
processSingleNode(area, nodeObject, colNum, String.valueOf(j + 1),
|
||||||
isDoubleLane, pointMap, data, processedPointCodes);
|
isDoubleLane, pointMap, data, processedPointCodes);
|
||||||
lineNo++;
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 逆向处理节点的方法
|
||||||
|
private void processNodesReverse(Area area, JSONArray nodeArray, String colNum,
|
||||||
|
Map<String, Point> pointMap,
|
||||||
|
SyncPointData data, Set<String> processedPointCodes) {
|
||||||
|
for (int j = nodeArray.size() - 1; j >= 0; j--) {
|
||||||
|
JSONObject nodeObject = nodeArray.getJSONObject(j);
|
||||||
|
// 计算正向行号(从1开始)
|
||||||
|
int forwardLineNo = nodeArray.size() - j;
|
||||||
|
processSingleNode(area, nodeObject, colNum, String.valueOf(forwardLineNo),
|
||||||
|
false, pointMap, data, processedPointCodes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -177,12 +208,9 @@ public class SyncPointProcessor {
|
||||||
rowNum, positionX, positionY, izDoubleLane);
|
rowNum, positionX, positionY, izDoubleLane);
|
||||||
data.addInsertPoint(newPoint);
|
data.addInsertPoint(newPoint);
|
||||||
} else {
|
} else {
|
||||||
if (isPointChanged(existingPoint, colNum, layerNum, rowNum,
|
updatePointFrom(existingPoint, rowNum, colNum, layerNum,
|
||||||
positionX, positionY, izDoubleLane)) {
|
|
||||||
updatePointFrom(existingPoint, colNum, layerNum, rowNum,
|
|
||||||
positionX, positionY, izDoubleLane);
|
positionX, positionY, izDoubleLane);
|
||||||
data.addUpdatePoint(existingPoint);
|
data.addUpdatePoint(existingPoint);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
log.debug("处理库位: {}", pointCode);
|
log.debug("处理库位: {}", pointCode);
|
||||||
|
|
@ -218,14 +246,14 @@ public class SyncPointProcessor {
|
||||||
/**
|
/**
|
||||||
* 检查库位是否发生变化
|
* 检查库位是否发生变化
|
||||||
*/
|
*/
|
||||||
private boolean isPointChanged(Point point, String rowNum, String colNum, String layerNum, Integer positionX, Integer positionY, Integer izDoubleLane) {
|
/* private boolean isPointChanged(Point point, String rowNum, String colNum, String layerNum, Integer positionX, Integer positionY, Integer izDoubleLane) {
|
||||||
return !Objects.equals(point.getRowNum(), rowNum) ||
|
return !Objects.equals(point.getRowNum(), rowNum) ||
|
||||||
!Objects.equals(point.getColNum(), colNum) ||
|
!Objects.equals(point.getColNum(), colNum) ||
|
||||||
!Objects.equals(point.getLayerNum(), layerNum) ||
|
!Objects.equals(point.getLayerNum(), layerNum) ||
|
||||||
!Objects.equals(point.getPositionX(), positionX) ||
|
!Objects.equals(point.getPositionX(), positionX) ||
|
||||||
!Objects.equals(point.getPositionY(), positionY) ||
|
!Objects.equals(point.getPositionY(), positionY) ||
|
||||||
!Objects.equals(point.getIzDoubleLane(), izDoubleLane);
|
!Objects.equals(point.getIzDoubleLane(), izDoubleLane);
|
||||||
}
|
}*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 更新物料信息
|
* 更新物料信息
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,8 @@ import org.apache.commons.collections4.CollectionUtils;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.cpte.modules.agvTask.entity.AgvTask;
|
import org.cpte.modules.agvTask.entity.AgvTask;
|
||||||
import org.cpte.modules.agvTask.mapper.AgvTaskMapper;
|
import org.cpte.modules.agvTask.mapper.AgvTaskMapper;
|
||||||
|
import org.cpte.modules.base.entity.Area;
|
||||||
|
import org.cpte.modules.base.mapper.AreaMapper;
|
||||||
import org.cpte.modules.constant.enums.*;
|
import org.cpte.modules.constant.enums.*;
|
||||||
import org.cpte.modules.conveyorLine.request.ScanTrayRequest;
|
import org.cpte.modules.conveyorLine.request.ScanTrayRequest;
|
||||||
import org.cpte.modules.conveyorLine.service.IConveyorLineService;
|
import org.cpte.modules.conveyorLine.service.IConveyorLineService;
|
||||||
|
|
@ -23,7 +25,7 @@ import java.util.List;
|
||||||
public class IConveyorLineServiceImpl implements IConveyorLineService {
|
public class IConveyorLineServiceImpl implements IConveyorLineService {
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private TaskMapper taskMapper;
|
private AreaMapper areaMapper;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private AgvTaskMapper agvTaskMapper;
|
private AgvTaskMapper agvTaskMapper;
|
||||||
|
|
@ -63,22 +65,32 @@ public class IConveyorLineServiceImpl implements IConveyorLineService {
|
||||||
jsonObject.put("endCode", "");
|
jsonObject.put("endCode", "");
|
||||||
jsonObject.put("izAll", "");
|
jsonObject.put("izAll", "");
|
||||||
jsonObject.put("description", "");
|
jsonObject.put("description", "");
|
||||||
|
String description;
|
||||||
|
//工作站库区
|
||||||
|
Area area = areaMapper.queryByPointCode(conveyorLine);
|
||||||
|
if(area==null){
|
||||||
|
return jsonObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(AreaTypeEnum.RK_DOCK.getValue().equals(area.getAreaCode())){
|
||||||
|
|
||||||
|
}else{
|
||||||
|
|
||||||
|
}
|
||||||
AgvTask agvTask = agvTaskMapper.queryByLastEndCode(conveyorLine);
|
AgvTask agvTask = agvTaskMapper.queryByLastEndCode(conveyorLine);
|
||||||
if (agvTask == null) {
|
if (agvTask == null) {
|
||||||
return jsonObject;
|
return jsonObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Task> tasks = taskMapper.queryByAgvTask(agvTask.getId());
|
if(BusinessTypeEnum.INBOUND.getValue().equals(agvTask.getType())){
|
||||||
if (CollectionUtils.isEmpty(tasks)) {
|
//先查询扫描成功的日志并返回成功描述信息,如果没有则返回扫描异常信息
|
||||||
return jsonObject;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
String stockCode = tasks.get(0).getStockCode();
|
String stockCode = agvTask.getCarrierCode();
|
||||||
String taskType = BusinessTypeEnum.getDescByValue(agvTask.getType());
|
String taskType = BusinessTypeEnum.getDescByValue(agvTask.getType());
|
||||||
String endCode = agvTask.getEndCode();
|
String endCode = agvTask.getEndCode();
|
||||||
String izAll = agvTask.getIzAll() == 1 ? "拆托" : "整托";
|
String izAll = agvTask.getIzAll() == 1 ? "拆托" : "整托";
|
||||||
String description = izAll.equals("拆托")
|
description = izAll.equals("拆托")
|
||||||
? "请人工将托盘【" + stockCode + "】叉走,避免任务拥堵"
|
? "请人工将托盘【" + stockCode + "】叉走,避免任务拥堵"
|
||||||
: "请等待AGV将托盘【" + stockCode + "】叉走";
|
: "请等待AGV将托盘【" + stockCode + "】叉走";
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,10 +11,7 @@ import org.quartz.Job;
|
||||||
import org.quartz.JobExecutionContext;
|
import org.quartz.JobExecutionContext;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
|
@ -30,9 +27,6 @@ public class AllocateJob implements Job {
|
||||||
@Autowired
|
@Autowired
|
||||||
private IPickService pickService;
|
private IPickService pickService;
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private ITaskService iTaskService;
|
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private BaseCommonService baseCommonService;
|
private BaseCommonService baseCommonService;
|
||||||
|
|
||||||
|
|
@ -42,58 +36,63 @@ public class AllocateJob implements Job {
|
||||||
// 缓存最大大小,防止内存溢出
|
// 缓存最大大小,防止内存溢出
|
||||||
private static final int MAX_CACHE_SIZE = 1000;
|
private static final int MAX_CACHE_SIZE = 1000;
|
||||||
|
|
||||||
// 使用静态变量跟踪当前分配位置
|
// 记录上次分配的索引
|
||||||
private static volatile int currentIndex = 0;
|
private int lastProcessedIndex = -1;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void execute(JobExecutionContext jobExecutionContext) {
|
public void execute(JobExecutionContext jobExecutionContext) {
|
||||||
// 查询未分配或者部分分配的出库
|
// 查询未分配或者部分分配的出库
|
||||||
List<Long> pickList = pickMapper.queryUnallocatedPick();
|
List<Long> pickList = pickMapper.queryUnallocatedPick();
|
||||||
if (CollectionUtils.isNotEmpty(pickList)) {
|
if (CollectionUtils.isEmpty(pickList)) {
|
||||||
// 轮询分配,每次只处理一个ID
|
log.info("没有待分配的出库单");
|
||||||
if (currentIndex < pickList.size()) {
|
lastProcessedIndex = -1; // 重置索引
|
||||||
Long currentPickId = pickList.get(currentIndex);
|
return;
|
||||||
List<Long> singlePickList = List.of(currentPickId);
|
}
|
||||||
long startTime = System.currentTimeMillis();
|
pickList.sort(Long::compareTo);
|
||||||
List<String> resultMsg;
|
|
||||||
try {
|
|
||||||
resultMsg = pickService.allocatePick(singlePickList);
|
|
||||||
}catch (Exception e){
|
|
||||||
resultMsg=List.of(e.getMessage());
|
|
||||||
}
|
|
||||||
long endTime = System.currentTimeMillis();
|
|
||||||
log.info("分配出库明细耗时:{}ms,处理ID:{}", endTime - startTime, currentPickId);
|
|
||||||
|
|
||||||
if (CollectionUtils.isNotEmpty(resultMsg)) {
|
int currentIndex = (lastProcessedIndex + 1) % pickList.size();
|
||||||
// 生成缓存键
|
Long pickId = pickList.get(currentIndex);
|
||||||
String cacheKey = generateCacheKey(resultMsg);
|
|
||||||
|
|
||||||
// 检查是否已经处理过相同的内容
|
log.info("上次分配索引: {}, 本次分配索引: {}, 分配出库单ID: {}", lastProcessedIndex, currentIndex, pickId);
|
||||||
if (!processedCache.containsKey(cacheKey)) {
|
|
||||||
// 新内容,记录日志
|
|
||||||
baseCommonService.addLog("出库任务分配:" + "\n" + cacheKey, CommonConstant.LOG_TYPE_2, CommonConstant.OPERATE_TYPE_1);
|
|
||||||
|
|
||||||
// 添加到缓存
|
|
||||||
processedCache.put(cacheKey, true);
|
|
||||||
|
|
||||||
// 控制缓存大小
|
// 分配单个出库单
|
||||||
if (processedCache.size() > MAX_CACHE_SIZE) {
|
long startTime = System.currentTimeMillis();
|
||||||
processedCache.clear();
|
List<String> resultMsg;
|
||||||
}
|
try {
|
||||||
|
// 每次只分配一个出库单
|
||||||
|
resultMsg = pickService.allocatePick(Collections.singletonList(pickId));
|
||||||
|
if (CollectionUtils.isNotEmpty(resultMsg)) {
|
||||||
|
// 生成缓存键
|
||||||
|
String cacheKey = generateCacheKey(resultMsg);
|
||||||
|
|
||||||
|
// 检查是否已经处理过相同的内容
|
||||||
|
if (!processedCache.containsKey(cacheKey)) {
|
||||||
|
// 新内容,记录日志
|
||||||
|
baseCommonService.addLog("出库任务分配:" + "\n" + cacheKey, CommonConstant.LOG_TYPE_2, CommonConstant.OPERATE_TYPE_1);
|
||||||
|
|
||||||
|
// 添加到缓存
|
||||||
|
processedCache.put(cacheKey, true);
|
||||||
|
|
||||||
|
// 控制缓存大小
|
||||||
|
if (processedCache.size() > MAX_CACHE_SIZE) {
|
||||||
|
processedCache.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 更新索引,循环使用
|
|
||||||
currentIndex = (currentIndex + 1) % pickList.size();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 更新索引
|
||||||
|
lastProcessedIndex = currentIndex;
|
||||||
|
} catch (Exception e) {
|
||||||
|
resultMsg = List.of(e.getMessage());
|
||||||
|
log.error("分配出库单失败,ID: {}, 错误: {}", pickId, e.getMessage());
|
||||||
|
// 失败也更新索引,等待下次继续分配
|
||||||
|
lastProcessedIndex = currentIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
long endTime = System.currentTimeMillis();
|
||||||
|
log.info("分配出库明细耗时:{}ms,处理ID:{}", endTime - startTime, pickId);
|
||||||
|
|
||||||
//生成出库AGV出库任务
|
|
||||||
long startTime2 = System.currentTimeMillis();
|
|
||||||
iTaskService.generateAgvTask();
|
|
||||||
long endTime2 = System.currentTimeMillis();
|
|
||||||
log.info("生成AGV出库任务耗时:{}ms", endTime2 - startTime2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -46,16 +46,10 @@ public class SyncPointJob implements Job {
|
||||||
Integer pageSize = Integer.parseInt(params.getString("pageSize"));
|
Integer pageSize = Integer.parseInt(params.getString("pageSize"));
|
||||||
Integer pageNum = Integer.parseInt(params.getString("pageNum"));
|
Integer pageNum = Integer.parseInt(params.getString("pageNum"));
|
||||||
|
|
||||||
// 检查是否需要处理
|
|
||||||
if (pageNum >= MAX_PAGE_NUM) {
|
|
||||||
log.info("已处理到最新页数,无需继续查询");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
pageNum = getLastProcessedKey(pageNum);
|
|
||||||
log.info("当前页数: {} - 每页条数: {}", pageNum, pageSize);
|
log.info("当前页数: {} - 每页条数: {}", pageNum, pageSize);
|
||||||
boolean success = pointService.syncPoint(regionCode, pageNum, pageSize);
|
boolean success = pointService.syncPoint(regionCode, pageNum, pageSize);
|
||||||
if (success) {
|
if (success) {
|
||||||
updateLastProcessedDate(pageNum);
|
log.info("同步库位成功");
|
||||||
}
|
}
|
||||||
log.info("同步库位完成,耗时: {} ms", System.currentTimeMillis() - startTime);
|
log.info("同步库位完成,耗时: {} ms", System.currentTimeMillis() - startTime);
|
||||||
|
|
||||||
|
|
@ -63,31 +57,4 @@ public class SyncPointJob implements Job {
|
||||||
baseCommonService.addLog(String.valueOf(e), CommonConstant.LOG_TYPE_4, null);
|
baseCommonService.addLog(String.valueOf(e), CommonConstant.LOG_TYPE_4, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取上次处理的页数+1页数
|
|
||||||
*/
|
|
||||||
private Integer getLastProcessedKey(Integer pageNum) {
|
|
||||||
try {
|
|
||||||
Object dateObj = redisUtil.get(PAGE_NUM_KEY);
|
|
||||||
if (dateObj != null) {
|
|
||||||
return Integer.parseInt(dateObj.toString())+1;
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.warn("从Redis获取上次处理页数失败,使用默认页数", e);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 默认页数
|
|
||||||
pageNum = 1;
|
|
||||||
redisUtil.set(PAGE_NUM_KEY, pageNum);
|
|
||||||
return pageNum;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 更新上次处理页数
|
|
||||||
*/
|
|
||||||
private void updateLastProcessedDate(Integer pageNum) {
|
|
||||||
redisUtil.set(PAGE_NUM_KEY, pageNum);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ import org.cpte.modules.constant.GeneralConstant;
|
||||||
import org.cpte.modules.constant.enums.AgvStatusEnum;
|
import org.cpte.modules.constant.enums.AgvStatusEnum;
|
||||||
import org.cpte.modules.constant.enums.AgvVendorEnum;
|
import org.cpte.modules.constant.enums.AgvVendorEnum;
|
||||||
import org.cpte.modules.hikAgv.service.IHikAgvService;
|
import org.cpte.modules.hikAgv.service.IHikAgvService;
|
||||||
|
import org.cpte.modules.shipping.service.ITaskService;
|
||||||
import org.cpte.modules.tesAgv.service.ITesAgvService;
|
import org.cpte.modules.tesAgv.service.ITesAgvService;
|
||||||
import org.quartz.Job;
|
import org.quartz.Job;
|
||||||
import org.quartz.JobExecutionContext;
|
import org.quartz.JobExecutionContext;
|
||||||
|
|
@ -17,6 +18,10 @@ import java.util.List;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class TesAgvJob implements Job {
|
public class TesAgvJob implements Job {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ITaskService iTaskService;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private AgvTaskMapper agvTaskMapper;
|
private AgvTaskMapper agvTaskMapper;
|
||||||
|
|
||||||
|
|
@ -25,6 +30,13 @@ public class TesAgvJob implements Job {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
|
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
|
||||||
|
|
||||||
|
//生成出库AGV出库任务
|
||||||
|
long startTime2 = System.currentTimeMillis();
|
||||||
|
iTaskService.generateAgvTask();
|
||||||
|
long endTime2 = System.currentTimeMillis();
|
||||||
|
log.info("生成AGV出库任务耗时:{}ms", endTime2 - startTime2);
|
||||||
|
|
||||||
// 查询待执行任务
|
// 查询待执行任务
|
||||||
List<AgvTask> agvTaskList = agvTaskMapper.queryAgvTaskList(AgvStatusEnum.CREATED.getValue(), AgvVendorEnum.TES.getValue());
|
List<AgvTask> agvTaskList = agvTaskMapper.queryAgvTaskList(AgvStatusEnum.CREATED.getValue(), AgvVendorEnum.TES.getValue());
|
||||||
if (agvTaskList.isEmpty()) {
|
if (agvTaskList.isEmpty()) {
|
||||||
|
|
|
||||||
|
|
@ -95,7 +95,7 @@ public class AsnDetailServiceImpl extends ServiceImpl<AsnDetailMapper, AsnDetail
|
||||||
public void processInboundTask(InboundRequest inboundRequest, Map<String, Item> itemMap, Point srcPoint, Stock stock) {
|
public void processInboundTask(InboundRequest inboundRequest, Map<String, Item> itemMap, Point srcPoint, Stock stock) {
|
||||||
//1.获取工作站
|
//1.获取工作站
|
||||||
Point station = null;
|
Point station = null;
|
||||||
if (AsnOrderTypeEnum.PRODUCT.getValue().equals(inboundRequest.getType())) {
|
if (AsnOrderTypeEnum.PRODUCT.getValue().equals(inboundRequest.getType()) && srcPoint != null) {
|
||||||
station = getStationPoint(inboundRequest.getType());
|
station = getStationPoint(inboundRequest.getType());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -108,9 +108,9 @@ public class AsnDetailServiceImpl extends ServiceImpl<AsnDetailMapper, AsnDetail
|
||||||
stockService.bindStock(stock);
|
stockService.bindStock(stock);
|
||||||
|
|
||||||
//4.成品入库,生成AGV任务
|
//4.成品入库,生成AGV任务
|
||||||
/*if (AsnOrderTypeEnum.PRODUCT.getValue().equals(inboundRequest.getType()) && station != null) {
|
if (AsnOrderTypeEnum.PRODUCT.getValue().equals(inboundRequest.getType()) && station != null) {
|
||||||
agvTaskService.createAgvTask(asn.getId(), stock.getStockCode(), srcPoint.getPointCode(), station.getPointCode(), null, BusinessTypeEnum.INBOUND.getValue(), 0, AgvVendorEnum.HIK.getValue());
|
agvTaskService.createAgvTask(asn.getId(), stock.getStockCode(), srcPoint.getPointCode(), station.getPointCode(), null, BusinessTypeEnum.INBOUND.getValue(), 0, AgvVendorEnum.HIK.getValue());
|
||||||
}*/
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -189,7 +189,7 @@ public class AsnDetailServiceImpl extends ServiceImpl<AsnDetailMapper, AsnDetail
|
||||||
.receivedQty(BigDecimal.ZERO)
|
.receivedQty(BigDecimal.ZERO)
|
||||||
.stockId(stock.getId())
|
.stockId(stock.getId())
|
||||||
.fromPointId(srcPoint == null ? null : srcPoint.getId())
|
.fromPointId(srcPoint == null ? null : srcPoint.getId())
|
||||||
.stationId(station== null ? null : station.getId())
|
.stationId(station == null ? null : station.getId())
|
||||||
.status(AsnStatusEnum.CREATED.getValue())
|
.status(AsnStatusEnum.CREATED.getValue())
|
||||||
.project(detail.getProject())
|
.project(detail.getProject())
|
||||||
.taskNo(detail.getTaskNo())
|
.taskNo(detail.getTaskNo())
|
||||||
|
|
|
||||||
|
|
@ -105,11 +105,11 @@ public class InBoundTaskProcessor {
|
||||||
throw new RuntimeException("【" + inboundRequest.getType() + "】任务类型错误");
|
throw new RuntimeException("【" + inboundRequest.getType() + "】任务类型错误");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (AsnOrderTypeEnum.PRODUCT.getValue().equals(inboundRequest.getType())) {
|
/* if (AsnOrderTypeEnum.PRODUCT.getValue().equals(inboundRequest.getType())) {
|
||||||
if (StringUtils.isBlank(inboundRequest.getLocationFrom())) {
|
if (StringUtils.isBlank(inboundRequest.getLocationFrom())) {
|
||||||
throw new RuntimeException("起点(LocationFrom)必填");
|
throw new RuntimeException("起点(LocationFrom)必填");
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
|
|
||||||
if (CollectionUtils.isEmpty(inboundRequest.getDetails())) {
|
if (CollectionUtils.isEmpty(inboundRequest.getDetails())) {
|
||||||
throw new RuntimeException("入库信息不能为空");
|
throw new RuntimeException("入库信息不能为空");
|
||||||
|
|
@ -214,7 +214,7 @@ public class InBoundTaskProcessor {
|
||||||
*/
|
*/
|
||||||
private Point validateSrcPoint(Integer orderType, String srcPointCode) {
|
private Point validateSrcPoint(Integer orderType, String srcPointCode) {
|
||||||
Point srcPoint = null;
|
Point srcPoint = null;
|
||||||
if (AsnOrderTypeEnum.PRODUCT.getValue().equals(orderType)) {
|
if (AsnOrderTypeEnum.PRODUCT.getValue().equals(orderType) && StringUtils.isNotBlank(srcPointCode)) {
|
||||||
srcPoint = pointService.validatePoint(srcPointCode);
|
srcPoint = pointService.validatePoint(srcPointCode);
|
||||||
}
|
}
|
||||||
return srcPoint;
|
return srcPoint;
|
||||||
|
|
|
||||||
|
|
@ -68,7 +68,7 @@ public class OutBoundTaskProcessor {
|
||||||
Map<String, Stock> stockMap = validateStock(outboundRequest.getDetails());
|
Map<String, Stock> stockMap = validateStock(outboundRequest.getDetails());
|
||||||
|
|
||||||
//5.出库处理
|
//5.出库处理
|
||||||
pickDetailService.processOutBoundTask(outboundRequest, itemMap,stockMap);
|
pickDetailService.processOutBoundTask(outboundRequest, itemMap, stockMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -159,8 +159,8 @@ public class OutBoundTaskProcessor {
|
||||||
* @param detail 明细
|
* @param detail 明细
|
||||||
*/
|
*/
|
||||||
private Map<String, Stock> validateStock(List<OutboundRequest.OutboundDetail> detail) {
|
private Map<String, Stock> validateStock(List<OutboundRequest.OutboundDetail> detail) {
|
||||||
//获取明细中所有的容器
|
//获取明细中所有的容器,
|
||||||
List<String> stockCodes = detail.stream().map(OutboundRequest.OutboundDetail::getLpn).toList();
|
List<String> stockCodes = detail.stream().map(OutboundRequest.OutboundDetail::getLpn).filter(StringUtils::isNotBlank).toList();
|
||||||
if (CollectionUtils.isNotEmpty(stockCodes)) {
|
if (CollectionUtils.isNotEmpty(stockCodes)) {
|
||||||
//获取数据库已存在容器
|
//获取数据库已存在容器
|
||||||
Map<String, Stock> exitStockMap = stockService.queryByStockCodesToMap(stockCodes);
|
Map<String, Stock> exitStockMap = stockService.queryByStockCodesToMap(stockCodes);
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ import org.cpte.modules.base.service.processor.BatchProcessor;
|
||||||
import org.cpte.modules.constant.GeneralConstant;
|
import org.cpte.modules.constant.GeneralConstant;
|
||||||
import org.cpte.modules.constant.enums.*;
|
import org.cpte.modules.constant.enums.*;
|
||||||
import org.cpte.modules.conveyorLine.service.processor.ScanTrayProcessor;
|
import org.cpte.modules.conveyorLine.service.processor.ScanTrayProcessor;
|
||||||
|
import org.cpte.modules.conveyorLine.vo.Station;
|
||||||
import org.cpte.modules.inventory.entity.Inventory;
|
import org.cpte.modules.inventory.entity.Inventory;
|
||||||
import org.cpte.modules.inventory.mapper.InventoryMapper;
|
import org.cpte.modules.inventory.mapper.InventoryMapper;
|
||||||
import org.cpte.modules.inventoryLog.service.IInventoryLogService;
|
import org.cpte.modules.inventoryLog.service.IInventoryLogService;
|
||||||
|
|
@ -155,11 +156,11 @@ public class AllocateProcessor {
|
||||||
data.setItemMap(itemMap);
|
data.setItemMap(itemMap);
|
||||||
|
|
||||||
//筛选查询库存的条件(非空去重)外部仓库、项目号、任务号、批次、外部库存状态
|
//筛选查询库存的条件(非空去重)外部仓库、项目号、任务号、批次、外部库存状态
|
||||||
List<String> whCodeList = pickMap.values().stream().map(Pick::getWhCode).filter(StringUtils::isNotBlank).distinct().toList();
|
List<String> whCodeList = pickMap.values().stream().map(Pick::getWhCode).distinct().toList();
|
||||||
List<String> projectList = pickDetails.stream().map(PickDetail::getProject).filter(StringUtils::isNotBlank).distinct().toList();
|
List<String> projectList = pickDetails.stream().map(PickDetail::getProject).distinct().toList();
|
||||||
List<String> taskNoList = pickDetails.stream().map(PickDetail::getTaskNo).filter(StringUtils::isNotBlank).distinct().toList();
|
List<String> taskNoList = pickDetails.stream().map(PickDetail::getTaskNo).distinct().toList();
|
||||||
List<String> propC1List = pickDetails.stream().map(PickDetail::getPropC1).filter(StringUtils::isNotBlank).distinct().toList();
|
List<String> propC1List = pickDetails.stream().map(PickDetail::getPropC1).distinct().toList();
|
||||||
List<String> propC3List = pickDetails.stream().map(PickDetail::getPropC3).filter(StringUtils::isNotBlank).distinct().toList();
|
List<String> propC3List = pickDetails.stream().map(PickDetail::getPropC3).distinct().toList();
|
||||||
List<ItemKey> itemKeys = itemKeyMapper.queryItemKeys(itemIds, whCodeList, projectList, taskNoList, propC1List, propC3List);
|
List<ItemKey> itemKeys = itemKeyMapper.queryItemKeys(itemIds, whCodeList, projectList, taskNoList, propC1List, propC3List);
|
||||||
|
|
||||||
//根据物料属性分组
|
//根据物料属性分组
|
||||||
|
|
@ -481,15 +482,76 @@ public class AllocateProcessor {
|
||||||
* @return 最佳出库口
|
* @return 最佳出库口
|
||||||
*/
|
*/
|
||||||
private Point getBestOutboundPoint(Point currPoint, List<Point> outPoints) {
|
private Point getBestOutboundPoint(Point currPoint, List<Point> outPoints) {
|
||||||
//获取距离最近的出库口
|
//提升机第一层的坐标
|
||||||
return outPoints.stream()
|
Station oneHoist = new Station(4160, 12080);
|
||||||
.min(Comparator.comparingDouble(point ->
|
//提升机第二层的坐标
|
||||||
Math.abs(currPoint.getPositionX() - point.getPositionX()) +
|
Station twoHoist = new Station(94160, 12080);
|
||||||
Math.abs(currPoint.getPositionY() - point.getPositionY())))
|
// 获取当前库位所在的层数
|
||||||
.orElse(null);
|
int currentLayer = Integer.parseInt(currPoint.getLayerNum());
|
||||||
|
// 用于存储最佳出库口
|
||||||
|
Point bestOutPoint = null;
|
||||||
|
//最小总距离
|
||||||
|
double minTotalDistance = Double.MAX_VALUE;
|
||||||
|
|
||||||
|
// 遍历所有出库口,计算每个出库口的总距离
|
||||||
|
for (Point outPoint : outPoints) {
|
||||||
|
double totalDistance = 0;
|
||||||
|
|
||||||
|
if (CommonStatusEnum.ONE.getValue().equals(currentLayer)) {
|
||||||
|
// 如果是第一层:当前库位到第一层提升机的距离 + 第一层提升机到出库口的距离
|
||||||
|
double currToHoist = calculateManhattanDistance(currPoint, oneHoist);
|
||||||
|
double hoistToOut = calculateManhattanDistance(oneHoist, outPoint);
|
||||||
|
totalDistance = currToHoist + hoistToOut;
|
||||||
|
|
||||||
|
} else if (CommonStatusEnum.TWO.getValue().equals(currentLayer)) {
|
||||||
|
|
||||||
|
// 当前库位到第二层提升机的距离
|
||||||
|
double currToTwoHoist = calculateManhattanDistance(currPoint, twoHoist);
|
||||||
|
|
||||||
|
// 第二层提升机到第一层提升机的距离
|
||||||
|
double twoHoistToOneHoist = calculateManhattanDistance(twoHoist, oneHoist);
|
||||||
|
|
||||||
|
// 第一层提升机到出库口的距离
|
||||||
|
double oneHoistToOut = calculateManhattanDistance(oneHoist, outPoint);
|
||||||
|
|
||||||
|
totalDistance = currToTwoHoist + twoHoistToOneHoist + oneHoistToOut;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果当前出库口的总距离更小,更新最佳出库口
|
||||||
|
if (totalDistance < minTotalDistance) {
|
||||||
|
minTotalDistance = totalDistance;
|
||||||
|
bestOutPoint = outPoint;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return bestOutPoint;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 重载方法,用于计算Station和Station之间的曼哈顿距离
|
||||||
|
private double calculateManhattanDistance(Station station, Station station2) {
|
||||||
|
int dx = Math.abs(station.getPositionX() - station2.getPositionX());
|
||||||
|
int dy = Math.abs(station.getPositionY() - station2.getPositionY());
|
||||||
|
return dx + dy; // 曼哈顿距离
|
||||||
|
}
|
||||||
|
|
||||||
|
// 重载方法,用于计算Station和Point之间的曼哈顿距离
|
||||||
|
private double calculateManhattanDistance(Station station, Point point) {
|
||||||
|
// 假设Station也有getX()和getY()方法
|
||||||
|
int dx = Math.abs(station.getPositionX() - point.getPositionX());
|
||||||
|
int dy = Math.abs(station.getPositionY() - point.getPositionY());
|
||||||
|
return dx + dy; // 曼哈顿距离
|
||||||
|
}
|
||||||
|
|
||||||
|
// 重载方法,用于计算Point和Station之间的曼哈顿距离
|
||||||
|
private double calculateManhattanDistance(Point point,Station station) {
|
||||||
|
// 假设Station也有getX()和getY()方法
|
||||||
|
int dx = Math.abs(station.getPositionX() - point.getPositionX());
|
||||||
|
int dy = Math.abs(station.getPositionY() - point.getPositionY());
|
||||||
|
return dx + dy; // 曼哈顿距离
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 计算距离评分
|
* 计算距离评分
|
||||||
* 基于出库口位置和库位坐标计算最短路径距离
|
* 基于出库口位置和库位坐标计算最短路径距离
|
||||||
|
|
@ -611,7 +673,7 @@ public class AllocateProcessor {
|
||||||
Point fromPoint = data.getPointMap().get(inventory.getPointId());
|
Point fromPoint = data.getPointMap().get(inventory.getPointId());
|
||||||
|
|
||||||
// 判断是否整托分配
|
// 判断是否整托分配
|
||||||
BigDecimal originalAvailableQty = BigDecimalUtil.subtract(inventory.getQuantity(), inventory.getQueuedQty(), 0);
|
BigDecimal originalAvailableQty = inventory.getQuantity();
|
||||||
Integer izAll = originalAvailableQty.compareTo(allocateQty) == 0 ? 0 : 1;
|
Integer izAll = originalAvailableQty.compareTo(allocateQty) == 0 ? 0 : 1;
|
||||||
|
|
||||||
// 目标库位
|
// 目标库位
|
||||||
|
|
|
||||||
|
|
@ -155,7 +155,7 @@ spring:
|
||||||
password: Youchain@56
|
password: Youchain@56
|
||||||
driver-class-name: com.mysql.cj.jdbc.Driver
|
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||||
# # shardingjdbc数据源
|
# # shardingjdbc数据源
|
||||||
# sharding-db:
|
# sharding-db: 47.103.100.52 10.254.27.192
|
||||||
# driver-class-name: org.apache.shardingsphere.driver.ShardingSphereDriver
|
# driver-class-name: org.apache.shardingsphere.driver.ShardingSphereDriver
|
||||||
# url: jdbc:shardingsphere:classpath:sharding.yaml
|
# url: jdbc:shardingsphere:classpath:sharding.yaml
|
||||||
#redis 配置
|
#redis 配置
|
||||||
|
|
@ -280,6 +280,7 @@ jeecg:
|
||||||
#分布式锁配置
|
#分布式锁配置
|
||||||
redisson:
|
redisson:
|
||||||
address: 47.117.45.79:6379
|
address: 47.117.45.79:6379
|
||||||
|
#address: 10.254.27.192:6379
|
||||||
password: cpte@123
|
password: cpte@123
|
||||||
type: STANDALONE
|
type: STANDALONE
|
||||||
enabled: true
|
enabled: true
|
||||||
|
|
|
||||||
2336
hs_err_pid20204.log
2336
hs_err_pid20204.log
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue