|
|
|
|
@ -22,6 +22,7 @@ import org.springblade.desk.logistics.service.*; |
|
|
|
|
import org.springblade.desk.logistics.utils.AgvTaskTypeUtil; |
|
|
|
|
import org.springframework.beans.factory.annotation.Autowired; |
|
|
|
|
import org.springframework.stereotype.Service; |
|
|
|
|
import org.springframework.transaction.annotation.Transactional; |
|
|
|
|
import org.springframework.util.StringUtils; |
|
|
|
|
|
|
|
|
|
import java.util.ArrayList; |
|
|
|
|
@ -191,6 +192,15 @@ public class TaskExecuteRecordServiceImpl extends BaseServiceImpl<TaskExecuteRec |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// 6. 任务走出储位状态,将站点设置为空闲
|
|
|
|
|
if (method.equals(TaskExecuteRecord.STATUS_OUTBIN)){ |
|
|
|
|
boolean conCtuReturn = releaseSite(agvCallBack.getTaskCode()); |
|
|
|
|
if (!conCtuReturn) { |
|
|
|
|
return R.fail("站点释放失败"); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 回调处理成功
|
|
|
|
|
log.info("AGV回调成功:任务单号{}的执行记录已更新,状态为{}", agvCallBack.getTaskCode(), method); |
|
|
|
|
R r = new R(); |
|
|
|
|
@ -199,6 +209,41 @@ public class TaskExecuteRecordServiceImpl extends BaseServiceImpl<TaskExecuteRec |
|
|
|
|
return r; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
public boolean releaseSite(String taskCode) { |
|
|
|
|
try { |
|
|
|
|
TaskExecuteRecord taskExecuteRecord = baseMapper.selectByTaskCode(taskCode); |
|
|
|
|
if (null == taskExecuteRecord) { |
|
|
|
|
log.error("未根据taskCode查询到有效数据,请求参数:{}", taskCode); |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
Station startStation = stationService.getByStationCode(taskExecuteRecord.getStartPos()); |
|
|
|
|
Station endStation = stationService.getByStationCode(taskExecuteRecord.getEndPos()); |
|
|
|
|
log.info("走出储位,开始位置:{},结束位置:{}", taskExecuteRecord.getStartPos(), taskExecuteRecord.getEndPos()); |
|
|
|
|
|
|
|
|
|
// 业务规则:起点必须是站点,且终点是传送线(1001)或有效站点时,才释放起点站点
|
|
|
|
|
if (null != startStation && (DROPOFF_CONVEYOR_LINE.equals(taskExecuteRecord.getEndPos()) || null != endStation)) { |
|
|
|
|
|
|
|
|
|
startStation.setStationStatus(Station.STATUS_FREE); |
|
|
|
|
boolean update = stationService.updateById(startStation); |
|
|
|
|
if (update) { |
|
|
|
|
log.info("站点释放成功:{}", startStation.getStationCode()); |
|
|
|
|
return true; |
|
|
|
|
} else { |
|
|
|
|
log.error("站点释放失败:{}", startStation.getStationCode()); |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return true; |
|
|
|
|
|
|
|
|
|
} catch (Exception e) { |
|
|
|
|
log.error("releaseSite执行异常,taskCode:{}", taskCode, e); |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private boolean updateMesCtuLocation(String taskCode) { |
|
|
|
|
log.info("开始执行updateMesCtuLocation,taskCode:{}", taskCode); |
|
|
|
|
|
|
|
|
|
@ -424,17 +469,17 @@ public class TaskExecuteRecordServiceImpl extends BaseServiceImpl<TaskExecuteRec |
|
|
|
|
log.info("任务{}不需要送到库位,直接完成", taskCode); |
|
|
|
|
log.info("终点位置为站点信息:{},直接完成", taskExecuteRecord.getEndPos()); |
|
|
|
|
|
|
|
|
|
Station startStation = stationService.getByStationCode(taskExecuteRecord.getStartPos()); |
|
|
|
|
// 起点位置为站点 将站点状态改为空闲
|
|
|
|
|
if(null != startStation){ |
|
|
|
|
startStation.setStationStatus(Station.STATUS_FREE); |
|
|
|
|
boolean update = stationService.updateById(startStation); |
|
|
|
|
if (update) { |
|
|
|
|
log.info("站点释放成功:{}", startStation.getStationCode()); |
|
|
|
|
} else { |
|
|
|
|
log.error("站点释放失败:{}", startStation.getStationCode()); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
// Station startStation = stationService.getByStationCode(taskExecuteRecord.getStartPos());
|
|
|
|
|
// // 起点位置为站点 将站点状态改为空闲
|
|
|
|
|
// if(null != startStation){
|
|
|
|
|
// startStation.setStationStatus(Station.STATUS_FREE);
|
|
|
|
|
// boolean update = stationService.updateById(startStation);
|
|
|
|
|
// if (update) {
|
|
|
|
|
// log.info("站点释放成功:{}", startStation.getStationCode());
|
|
|
|
|
// } else {
|
|
|
|
|
// log.error("站点释放失败:{}", startStation.getStationCode());
|
|
|
|
|
// }
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
// 终点位置为站点将状态修改为占用
|
|
|
|
|
if(null != endStation){ |
|
|
|
|
@ -719,65 +764,112 @@ public class TaskExecuteRecordServiceImpl extends BaseServiceImpl<TaskExecuteRec |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
@Transactional(rollbackFor = Exception.class) |
|
|
|
|
public boolean genAgvSchedulingTask(String taskType, String startPos, String endPos, String type, Task task) { |
|
|
|
|
|
|
|
|
|
// 获取虚拟货架
|
|
|
|
|
VirtualShelves virtualShelves = virtualShelvesService.getVirtualShelvesCode(); |
|
|
|
|
if (null == virtualShelves) { |
|
|
|
|
throw new ServiceException("获取虚拟货架失败"); |
|
|
|
|
} |
|
|
|
|
VirtualShelves virtualShelves = null; |
|
|
|
|
String boundShelvesCode = null; |
|
|
|
|
|
|
|
|
|
// 站点绑定虚拟货架
|
|
|
|
|
JSONObject response = boundVirtualShelves( |
|
|
|
|
virtualShelves.getVirtualShelvesCode(), |
|
|
|
|
startPos |
|
|
|
|
); |
|
|
|
|
String code = response.getString("code"); |
|
|
|
|
String message = response.getString("message"); |
|
|
|
|
try { |
|
|
|
|
// 1. 获取虚拟货架
|
|
|
|
|
virtualShelves = virtualShelvesService.getVirtualShelvesCode(); |
|
|
|
|
if (null == virtualShelves) { |
|
|
|
|
log.error("获取虚拟货架失败"); |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// 2. 绑定虚拟货架
|
|
|
|
|
JSONObject response = boundVirtualShelves( |
|
|
|
|
virtualShelves.getVirtualShelvesCode(), |
|
|
|
|
startPos |
|
|
|
|
); |
|
|
|
|
String code = response.getString("code"); |
|
|
|
|
String message = response.getString("message"); |
|
|
|
|
|
|
|
|
|
if ("0".equals(code)) { |
|
|
|
|
log.info("绑定虚拟货架成功,虚拟货架:{},站点:{}", virtualShelves.getVirtualShelvesCode(), startPos); |
|
|
|
|
if ("0".equals(code)) { |
|
|
|
|
// 绑定成功,记录绑定的货架号
|
|
|
|
|
boundShelvesCode = virtualShelves.getVirtualShelvesCode(); |
|
|
|
|
log.info("绑定虚拟货架成功,虚拟货架:{},站点:{}", boundShelvesCode, startPos); |
|
|
|
|
} else { |
|
|
|
|
// 绑定失败,尝试使用错误消息中的货架号
|
|
|
|
|
log.warn("首次绑定失败,响应:{}", response); |
|
|
|
|
|
|
|
|
|
virtualShelves.setIsBound(VirtualShelves.BOUND_YES); |
|
|
|
|
virtualShelvesService.updateById(virtualShelves); |
|
|
|
|
// 提取货架号
|
|
|
|
|
String number = extractShelfCodeFromMessage(message); |
|
|
|
|
if (number == null) { |
|
|
|
|
log.error("绑定失败且无法解析货架号:" + message); |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} else { |
|
|
|
|
log.error("绑定虚拟货架失败,虚拟货架:{},站点:{},响应:{}", |
|
|
|
|
virtualShelves.getVirtualShelvesCode(), startPos, response); |
|
|
|
|
VirtualShelves existedShelves = virtualShelvesService.selectByVirtualShelvesCode(number); |
|
|
|
|
if (existedShelves == null) { |
|
|
|
|
log.error("指定的虚拟货架不存在:" + number); |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
//修改Task状态
|
|
|
|
|
task.setTaskStatus(Task.BOUND_VIRTUAL_SHELVES); |
|
|
|
|
task.setRemark(message); |
|
|
|
|
taskService.updateById(task); |
|
|
|
|
// 使用已存在的货架重新绑定
|
|
|
|
|
JSONObject retryResponse = boundVirtualShelves(number, startPos); |
|
|
|
|
String retryCode = retryResponse.getString("code"); |
|
|
|
|
String retryMessage = retryResponse.getString("message"); |
|
|
|
|
|
|
|
|
|
if (!"0".equals(retryCode)) { |
|
|
|
|
// 重试失败,更新任务状态
|
|
|
|
|
task.setTaskStatus(Task.BOUND_VIRTUAL_SHELVES); |
|
|
|
|
task.setRemark(retryMessage); |
|
|
|
|
taskService.updateById(task); |
|
|
|
|
log.error("重新绑定虚拟货架失败:" + retryMessage); |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
// 重试成功,使用重试的货架
|
|
|
|
|
boundShelvesCode = number; |
|
|
|
|
virtualShelves = existedShelves; |
|
|
|
|
log.info("重新绑定虚拟货架成功,虚拟货架:{},站点:{}", boundShelvesCode, startPos); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// 3. 调用AGV调度
|
|
|
|
|
AgvSchedulingTaskVO agvSchedulingTaskVO = genAgvSchedulingTask( |
|
|
|
|
taskType, |
|
|
|
|
startPos, |
|
|
|
|
endPos, |
|
|
|
|
type, |
|
|
|
|
boundShelvesCode |
|
|
|
|
); |
|
|
|
|
if (null == agvSchedulingTaskVO || !"0".equals(agvSchedulingTaskVO.getCode())) { |
|
|
|
|
throw new ServiceException("调用AGV调度失败"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// 4. 入库记录
|
|
|
|
|
if (null == task) { |
|
|
|
|
throw new ServiceException("任务信息为空"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
boolean record = inboundRecord(agvSchedulingTaskVO, task, boundShelvesCode); |
|
|
|
|
if (!record) { |
|
|
|
|
throw new ServiceException("入库记录保存失败"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// 调用AGV
|
|
|
|
|
AgvSchedulingTaskVO agvSchedulingTaskVO = genAgvSchedulingTask( |
|
|
|
|
taskType, |
|
|
|
|
startPos, |
|
|
|
|
endPos, |
|
|
|
|
type, |
|
|
|
|
virtualShelves.getVirtualShelvesCode() |
|
|
|
|
); |
|
|
|
|
if (null == agvSchedulingTaskVO || !"0".equals(agvSchedulingTaskVO.getCode())) { |
|
|
|
|
throw new ServiceException("调用AGV调度失败"); |
|
|
|
|
} |
|
|
|
|
// 5. 所有步骤成功后,更新虚拟货架状态
|
|
|
|
|
virtualShelves.setIsBound(VirtualShelves.BOUND_YES); |
|
|
|
|
virtualShelvesService.updateById(virtualShelves); |
|
|
|
|
|
|
|
|
|
// 入库记录
|
|
|
|
|
if (null == task) { |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
return true; |
|
|
|
|
|
|
|
|
|
boolean record = inboundRecord(agvSchedulingTaskVO, task, virtualShelves.getVirtualShelvesCode()); |
|
|
|
|
if (!record) { |
|
|
|
|
throw new ServiceException("入库记录保存失败"); |
|
|
|
|
} catch (Exception e) { |
|
|
|
|
log.error("genAgvSchedulingTask执行异常", e); |
|
|
|
|
if (boundShelvesCode != null) { |
|
|
|
|
log.warn("流程失败,已绑定的虚拟货架:{} 可能需要手动解绑", boundShelvesCode); |
|
|
|
|
} |
|
|
|
|
throw e; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return true; |
|
|
|
|
private String extractShelfCodeFromMessage(String message) { |
|
|
|
|
if (message == null || !message.contains(":")) { |
|
|
|
|
return null; |
|
|
|
|
} |
|
|
|
|
return message.substring(message.lastIndexOf(":") + 1).trim(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|