package com.zy.asrs.service.impl;
|
|
import com.alibaba.fastjson.JSON;
|
import com.baomidou.mybatisplus.mapper.EntityWrapper;
|
import com.core.common.Cools;
|
import com.zy.asrs.entity.BasCircularShuttle;
|
import com.zy.asrs.entity.BasDevpPosition;
|
import com.zy.asrs.entity.BasRgv;
|
import com.zy.asrs.entity.WrkMast;
|
import com.zy.asrs.service.BasCircularShuttleService;
|
import com.zy.asrs.service.BasDevpPositionService;
|
import com.zy.asrs.service.WrkMastService;
|
import com.zy.common.service.CommonService;
|
import com.zy.core.cache.MessageQueue;
|
import com.zy.core.cache.SlaveConnection;
|
import com.zy.core.enums.RgvModeType;
|
import com.zy.core.enums.RgvStatusType;
|
import com.zy.core.enums.RgvTaskModeType;
|
import com.zy.core.enums.SlaveType;
|
import com.zy.core.model.RgvSlave;
|
import com.zy.core.model.Task;
|
import com.zy.core.model.command.RgvCommand;
|
import com.zy.core.model.protocol.RgvProtocol;
|
import com.zy.core.properties.SlaveProperties;
|
import com.zy.core.thread.RgvThread;
|
import lombok.extern.slf4j.Slf4j;
|
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.stereotype.Service;
|
import org.springframework.transaction.annotation.Transactional;
|
|
import java.util.*;
|
|
/**
|
* 立体仓库WCS系统主流程业务
|
* Created by IX on 2024/10/01
|
*/
|
@Slf4j
|
@Service("mainService")
|
@Transactional
|
public class MainServiceImpl {
|
|
@Autowired
|
private SlaveProperties slaveProperties;
|
@Autowired
|
private BasRgvServiceImpl basRgvService;
|
@Autowired
|
private BasDevpPositionService basDevpPositionService;
|
@Autowired
|
private BasCircularShuttleService basCircularShuttleService;
|
@Autowired
|
private WrkMastService wrkMastService;
|
@Autowired
|
private CommonService commonService;
|
|
@Value("${constant-parameters.perimeter}")
|
private Long perimeter;
|
@Value("${constant-parameters.proportion}")
|
private Long proportion;
|
@Value("${constant-parameters.acceleration}")
|
private Long acceleration;
|
@Value("${constant-parameters.rgvCount}")
|
private Long rgvCount;
|
@Value("${constant-parameters.rgvDate}")
|
private Double rgvDate;
|
@Value("${wms.url}")
|
private String wmsUrl;
|
@Value("${wms.reportOutPath}")
|
private String wmsOutPath;
|
@Value("${wms.reportSwitch}")
|
private boolean reportSwitch;
|
@Value("${wms.reportSwitchAuto}")
|
private boolean reportSwitchAuto;
|
|
|
public synchronized void rgvTheHandlingTaskIsIssued() {
|
try {
|
List<WrkMast> wrkMasts = wrkMastService.selectList(new EntityWrapper<WrkMast>().eq("rgv_no", 0).eq("wrk_sts", 9)
|
.orderBy("io_pri", false)
|
.orderBy("modi_time", true));
|
if (wrkMasts.isEmpty()) {
|
return;
|
}
|
|
List<BasCircularShuttle> basCircularShuttleList = basCircularShuttleService.selectList(new EntityWrapper<BasCircularShuttle>().eq("status", 0));
|
|
LinkedList<RgvProtocol> rgvProtocolList = new LinkedList<>();
|
for (BasCircularShuttle basCircularShuttle : basCircularShuttleList) {
|
RgvThread rgvThread = (RgvThread) SlaveConnection.get(SlaveType.Rgv, basCircularShuttle.getRgvNo());
|
RgvProtocol rgvProtocol = rgvThread.getRgvProtocol();
|
if (rgvProtocol == null) {
|
continue;
|
}
|
rgvProtocolList.add(rgvProtocol);
|
}
|
|
runRgv:
|
for (WrkMast wrkMast : wrkMasts) {
|
Integer rgvSstaNo = wrkMast.getRgvSstaNo();
|
BasDevpPosition basDevpPositions = basDevpPositionService.selectOne(new EntityWrapper<BasDevpPosition>().eq("dev_no", rgvSstaNo)); // 站点
|
long position = basDevpPositions.getPlcPosition(); // 起始站位置
|
position += 50; // 小车取货定位精度 +- 50,站点位置10000,小车在10050也是可以取的
|
TreeMap<Long, RgvProtocol> map = new TreeMap<>();
|
for (RgvProtocol rgvProtocol : rgvProtocolList) {
|
long distance;
|
if (rgvProtocol.getRgvPos() <= position) {
|
distance = position - rgvProtocol.getRgvPos();
|
} else {
|
distance = position + (perimeter - rgvProtocol.getRgvPos());
|
}
|
map.put(distance, rgvProtocol);
|
}
|
position -= 50;
|
// log.info("取货站点:{},后面小车排序", basDevpPositions.getDevNo());
|
// StringBuilder sb = new StringBuilder();
|
// for (Map.Entry<Long, RgvProtocol> rgvProtocolMap : map.entrySet()) {
|
// RgvProtocol rgvProtocol = rgvProtocolMap.getValue();
|
// sb.append("[").append(rgvProtocol.getRgvNo()).append(",").append(rgvProtocol.getRgvPos()).append(",").append(rgvProtocol.getStatusType().desc).append("]");
|
// }
|
// log.info(sb.toString());
|
|
for (Map.Entry<Long, RgvProtocol> rgvProtocolMap : map.entrySet()) {
|
RgvProtocol rgvProtocol = rgvProtocolMap.getValue(); // 最近距离小车
|
// log.info("取货站点:{},后面最近小车:{},状态:{}", basDevpPositions.getDevNo(), rgvProtocol.getRgvNo(), rgvProtocol.getStatusType().desc);
|
int count = wrkMastService.selectCount(new EntityWrapper<WrkMast>().eq("rgv_no", rgvProtocol.getRgvNo()).eq("wrk_sts", 10));
|
if (rgvProtocol.modeType == RgvModeType.AUTO
|
&& (rgvProtocol.getStatusType() == RgvStatusType.IDLE || rgvProtocol.getStatusType() == RgvStatusType.ROAM)
|
&& rgvProtocol.getTaskNo1() == 0
|
&& rgvProtocol.getAlarm() == 0) {
|
if (count != 0) {
|
log.error("{}呼叫小车:{}号小车空闲,但工作档显示该小车有任务",wrkMast.getWrkNo(),rgvProtocol.getRgvNo());
|
break ;
|
}
|
RgvCommand rgvCommand = new RgvCommand();
|
rgvCommand.setRgvNo(rgvProtocol.getRgvNo());
|
rgvCommand.setAckFinish1((short) 0); // 工位1任务完成确认位
|
rgvCommand.setTaskNo1(wrkMast.getWrkNo().shortValue());
|
rgvCommand.setTaskMode1(RgvTaskModeType.FETCH_PUT); // 工位1任务模式: 取放货
|
rgvCommand.setSourceStaNo1(wrkMast.getRgvSstaNo().shortValue()); //工位1起点
|
rgvCommand.setDestinationStaNo1(wrkMast.getRgvDstaNo().shortValue()); //工位1目标站点
|
rgvCommand.setCommand((short) 1); //工位1任务确认
|
if (!MessageQueue.offer(SlaveType.Rgv, rgvProtocol.getRgvNo(), new Task(2, rgvCommand))) {
|
log.error("RGV命令下发失败,RGV号={},任务数据={}", rgvProtocol.getRgvNo(), JSON.toJSON(rgvCommand));
|
break runRgv;
|
}
|
log.info("RGV命令下发成功,RGV号={},任务数据={}", rgvProtocol.getRgvNo(), JSON.toJSON(rgvCommand));
|
Date now = new Date();
|
wrkMast.setRgvNo(rgvProtocol.getRgvNo());
|
wrkMast.setWrkSts(10L);
|
wrkMast.setRgvCreateTime(now);
|
wrkMastService.updateById(wrkMast);
|
break runRgv;
|
} else if(rgvProtocol.modeType == RgvModeType.AUTO
|
&& rgvProtocol.getTaskNo1() != 0){ // 当前小车放货目标位置在当前任务取货点之后,跳过任务分配,不再则判断下个小车目标位置
|
WrkMast wrkMast1 = wrkMastService.selectOne(new EntityWrapper<WrkMast>().eq("wrk_no", rgvProtocol.getTaskNo1())); // 当前rgv任务
|
if(wrkMast1!= null && !Cools.isEmpty(wrkMast1.getRgvDstaNo())) {
|
// 当前rgv任务目标站点
|
BasDevpPosition rgvDstaNoDevPosition = basDevpPositionService.selectOne(new EntityWrapper<BasDevpPosition>().eq("dev_no", wrkMast1.getRgvDstaNo()));
|
long rgvDstaNoPosition = rgvDstaNoDevPosition.getPlcPosition(); // 当前rgv任务目标站点位置
|
// 获取RGV当前位置和状态
|
long currentRgvPos = rgvProtocol.getRgvPos();
|
int rgvStatus = rgvProtocol.getStatusType().id;
|
|
// 定义浮动范围(仅停靠状态适用)
|
long posTolerance = (rgvStatus == 0 || rgvStatus == 2 || rgvStatus == 3 || rgvStatus == 6 || rgvStatus == 7 || rgvStatus == 8 || rgvStatus == 100) ? 50 : 0;
|
if(currentRgvPos < rgvDstaNoPosition + posTolerance) { // 小车当前位置 < rgv目标位置
|
if(!(currentRgvPos - posTolerance < position && position < rgvDstaNoPosition + posTolerance)) { // 这个任务位置是在当前rgv位置前面并且这个任务起点在当前rgv目标站点之后
|
break; // 当前rgv放货完成后,可以取当前任务
|
}
|
} else {
|
if(!(currentRgvPos + posTolerance < position || position < rgvDstaNoPosition - posTolerance)) {
|
break;
|
}
|
}
|
}
|
}
|
}
|
}
|
} catch (Exception e) {
|
log.error("自动下发小车取放任务失败,异常:" + e);
|
}
|
}
|
|
//任务完成
|
public synchronized void rgvCompleteWrkMastSta(int[] autoZ) {
|
try {
|
for (RgvSlave rgvSlave : slaveProperties.getRgv()) {
|
RgvThread rgvThread = (RgvThread) SlaveConnection.get(SlaveType.Rgv, rgvSlave.getId());
|
RgvProtocol rgvProtocol = rgvThread.getRgvProtocol();
|
if (rgvProtocol == null) {
|
continue;
|
}
|
BasRgv basRgv = basRgvService.selectById(rgvSlave.getId());
|
if (basRgv == null) {
|
log.error("{}号RGV尚未在数据库进行维护!", rgvSlave.getId());
|
continue;
|
}
|
|
// 只有当RGV等待WCS确认、自动
|
if (rgvProtocol.getStatusType() == RgvStatusType.WAITING
|
&& rgvProtocol.getModeType() == RgvModeType.AUTO
|
&& rgvProtocol.getTaskNo1() != 0
|
) {
|
log.info("{}号小车等待wcs确认,状态{},参数{}",rgvProtocol.getRgvNo(),rgvProtocol.getStatusType(),rgvProtocol);
|
WrkMast wrkMast = wrkMastService.selectOne(new EntityWrapper<WrkMast>().eq("wrk_no", rgvProtocol.getTaskNo1().longValue()));
|
if (Cools.isEmpty(wrkMast)) {
|
log.error("未查到小车执行任务!" + rgvProtocol.getTaskNo1());
|
continue;
|
} else if(wrkMast.getWrkSts() != 10) {
|
log.warn("执行任务状态不符合!" + rgvProtocol.getTaskNo1());
|
continue;
|
}
|
boolean rgvComplete = rgvComplete(rgvProtocol.getRgvNo());
|
if (!rgvComplete) {
|
log.error("小车复位失败,小车号{}!", rgvProtocol.getRgvNo());
|
break;
|
}
|
wrkMast.setWrkSts(2L);
|
if (wrkMast.getIoType()==120){
|
wrkMast.setWrkSts(53L);
|
}
|
Date now = new Date();
|
wrkMast.setRgvFinishTime(now);
|
wrkMastService.updateById(wrkMast);
|
}
|
}
|
} catch (Exception e) {
|
log.error("小车复位线程报错!" + e);
|
}
|
}
|
|
// 小车取货越位,任务取消
|
public synchronized void rgvTaskCancel() {
|
try {
|
for (RgvSlave rgvSlave : slaveProperties.getRgv()) {
|
RgvThread rgvThread = (RgvThread) SlaveConnection.get(SlaveType.Rgv, rgvSlave.getId());
|
RgvProtocol rgvProtocol = rgvThread.getRgvProtocol();
|
if (rgvProtocol == null) {
|
continue;
|
}
|
|
// 只有当RGV等待WCS确认、自动
|
if (rgvProtocol.getStatusType() == RgvStatusType.PICK_UP_OFFSIDE
|
&& rgvProtocol.getModeType() == RgvModeType.AUTO
|
&& rgvProtocol.getTaskNo1() != 0
|
) {
|
WrkMast wrkMast = wrkMastService.selectOne(new EntityWrapper<WrkMast>().eq("wrk_no", rgvProtocol.getTaskNo1().longValue())
|
.eq("rgv_no",rgvProtocol.getRgvNo()));
|
if (Cools.isEmpty(wrkMast)) {
|
log.error(rgvProtocol.getRgvNo() + "小车取货越位未查到小车执行任务!" + rgvProtocol.getTaskNo1());
|
continue;
|
} else if(wrkMast.getWrkSts() != 10) {
|
log.warn(rgvProtocol.getRgvNo() + "小车取货越位执行任务状态不符合!" + rgvProtocol.getTaskNo1());
|
continue;
|
}
|
log.info("{}号小车小车取货越位,状态{},参数{}",rgvProtocol.getRgvNo(),rgvProtocol.getStatusType(),rgvProtocol);
|
boolean rgvComplete = rgvComplete(rgvProtocol.getRgvNo());
|
if (!rgvComplete) {
|
log.error("小车取货越位,任务取消,复位失败,小车号{}!", rgvProtocol.getRgvNo());
|
break;
|
}
|
wrkMast.setWrkSts(9L);
|
wrkMast.setRgvNo(0);
|
wrkMast.setRgvCreateTime(new Date());
|
wrkMastService.updateById(wrkMast);
|
}
|
}
|
} catch (Exception e) {
|
log.error("小车复位线程报错!" + e);
|
}
|
}
|
|
/*
|
* 小车复位
|
* */
|
public synchronized boolean rgvComplete(Integer rgvNo) {
|
try {
|
// 命令下发区 --------------------------------------------------------------------------
|
if (!MessageQueue.offer(SlaveType.Rgv, rgvNo, new Task(3, new RgvCommand()))) {
|
log.error("小车复位RGV命令下发失败,RGV号={}", rgvNo);
|
return false;
|
} else {
|
log.info("小车复位RGV命令下发成功,RGV号={}", rgvNo);
|
return true;
|
}
|
} catch (Exception e) {
|
log.error("RGV命令下发失败,RGV号={}。异常:" + e, rgvNo);
|
return false;
|
}
|
}
|
}
|