现场调度修改

This commit is contained in:
liuhanqing
2026-02-26 09:46:54 +08:00
parent cbc76be62f
commit 9c6c32b7ed
15 changed files with 888 additions and 23 deletions

View File

@@ -16,5 +16,6 @@ public class ReceiveJob {
private String inOrOut;
private String jobId;
private String roadwayId;
private String classId;
}

View File

@@ -360,6 +360,7 @@ public class ApiServiceImpl implements IApiService {
mydoJob.setRoadwayId(receiveOutJob.getRoadwayId());
mydoJob.setCreateTime(DateUtils.getNowDate());
mydoJob.setExecutionPhase("0");
mydoJob.setTheFloor(receiveOutJob.getClassId());
int i = mydoJobService.insertMydoJob(mydoJob);
if (i > 0) {
return AjaxResult.success();

View File

@@ -143,7 +143,17 @@ public class RoadCacheServiceImpl implements RoadCacheService {
HashSet<String> otherCarSiteList = new HashSet<>();
for (WcsSrgvQueue wcsSrgvQueue : otherCarQueue) {
if (wcsSrgvQueue.getPathInfo()!=null) {
otherCarSiteList.addAll(Arrays.asList(wcsSrgvQueue.getPathInfo().split(",")));
//根据小车当前点位去除已走路径
DeviceSrgv otherCarCurrStatus = deviceSrgvService.selectDeviceSrgvByGuid(wcsSrgvQueue.getAgvId());
String currSite = otherCarCurrStatus.getCurrSite();
List<String> allSiteList = Arrays.asList(wcsSrgvQueue.getPathInfo().split(","));
int i = allSiteList.indexOf(currSite);
if (i==-1){
i=0;
}
List<String> resultSiteList = allSiteList.subList(i, allSiteList.size());
otherCarSiteList.addAll(resultSiteList);
//otherCarSiteList.addAll(Arrays.asList(wcsSrgvQueue.getPathInfo().split(",")));
}
}
//锁定其他小车路径

View File

@@ -94,4 +94,5 @@ public class MydoJob extends BaseEntity
private String productId;
private String productName;
private String classId;
}

View File

@@ -2,6 +2,7 @@ package com.ruoyi.queue.srgv.mapper;
import java.util.List;
import com.ruoyi.queue.srgv.domain.WcsSrgvQueue;
import org.apache.ibatis.annotations.Param;
/**
* 四向小车任务队列Mapper接口
@@ -70,4 +71,6 @@ public interface WcsSrgvQueueMapper
* @return 结果
*/
public int deleteWcsSrgvQueueByGuids(String[] guids);
String selectMinCountJob(@Param("list") List<String> outModelSSJ);
}

View File

@@ -77,4 +77,6 @@ public interface IWcsSrgvQueueService
* @param taskNo
*/
public WcsSrgvQueue insertHistory(String taskNo);
String selectMinCountJob(List<String> outModelSSJ);
}

View File

@@ -115,6 +115,11 @@ public class WcsSrgvQueueServiceImpl implements IWcsSrgvQueueService
return wcsSrgvQueueMapper.deleteWcsSrgvQueueByGuid(guid);
}
@Override
public String selectMinCountJob( List<String> outModelSSJ) {
return wcsSrgvQueueMapper.selectMinCountJob(outModelSSJ) ;
}
@Override
public WcsSrgvQueue insertHistory(String taskNo) {
WcsSrgvQueue wcsSrgvQueue = wcsSrgvQueueMapper.selectWcsSrgvQueueByTaskNo(taskNo);

View File

@@ -90,6 +90,12 @@ public class PlcSrgvRead implements Runnable {
if (read2.IsSuccess) {
setValueByByte2(read2.Content, deviceSrgv);
}
// //读取双字,路径
OperateResultExOne<byte[]> read4 = modbusTcpNet.Read("6000", (short) 800);// 5000-5799 路径 400个
if (read4.IsSuccess) {
setValueByByte4(read4.Content, deviceSrgv);
}
}
//单字
@@ -150,6 +156,29 @@ public class PlcSrgvRead implements Runnable {
agvData.setCurrFloor(floor);
}
private void setValueByByte4(byte[] content, DeviceSrgv agvData) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < content.length; i += 4) {
// 检查剩余字节是否足够4个
if (i + 4 > content.length) break;
// TODO 注意双字反转
int value = byteTransform.TransInt32(content, i);
// 如果值为0,终止循环
if (value == 0) {
break;
}
sb.append(String.format("%06d", value)).append(","); // 用逗号分隔每个int值
}
// 移除最后多余的 ","
if (sb.length() > 0) {
sb.setLength(sb.length() - 1);
}
agvData.setPath(sb.toString());
}
public void ConnectServer() {
modbusTcpNet = new ModbusTcpNet();//创建一个Modbus对象
log.info("创建连接对象,IP{}", this.ip);

View File

@@ -99,6 +99,7 @@ public class PlcSsjRead implements Runnable {
ssjDevice.setKx(ParseUtil.optInt(4, ddsx1));
ssjDevice.setDw(ParseUtil.optInt(6, ddsx1));
ssjDevice.setTaskNo(ParseUtil.optDInt(0, ddsx1));
ssjDevice.setModel(ParseUtil.optInt(8, ddsx1));//出入库模式 1入 2出
}
}

View File

@@ -51,7 +51,9 @@ public class MonitoringThread implements Runnable {
}
for (String srgvCode : PlcSrgvRead.deviceSrgvMap.keySet()) {
DeviceSrgv deviceSrgv = PlcSrgvRead.deviceSrgvMap.get(srgvCode);
deviceSrgvService.updateDeviceSrgv(deviceSrgv);
if (!deviceSrgv.getCurrSite().equals("000000")){
deviceSrgvService.updateDeviceSrgv(deviceSrgv);
}
}
for (String tsjCode : PlcTsjRead.deviceTsjMap.keySet()) {
DeviceTsj deviceTsj = PlcTsjRead.deviceTsjMap.get(tsjCode);

View File

@@ -18,6 +18,7 @@ import com.ruoyi.common.domain.SendData2;
import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.device.srgv.domain.DeviceSrgv;
import com.ruoyi.device.srgv.service.IDeviceSrgvService;
import com.ruoyi.device.ssj.domain.DeviceSsj;
import com.ruoyi.job.charg.domain.SrgvChargingJob;
import com.ruoyi.job.charg.service.ISrgvChargingJobService;
import com.ruoyi.job.domain.JobCallBack;
@@ -30,6 +31,7 @@ import com.ruoyi.queue.srgv.service.IWcsSrgvQueueService;
import com.ruoyi.schedule.ScheduleThread;
import com.ruoyi.schedule.plcRead.srgv.PlcSrgvRead;
import com.ruoyi.schedule.plcRead.srgv.roadUtil.PathFinder;
import com.ruoyi.schedule.plcRead.ssj.PlcSsjRead;
import lombok.extern.slf4j.Slf4j;
import java.text.SimpleDateFormat;
@@ -65,7 +67,7 @@ public class BaseSRgvThread implements Runnable, SRgvThreadInterface {
private IBasCargoSpaceService basCargoSpaceService;
public IDeviceSrgvService deviceSrgvService;
private int taskCache = 450001;
private int taskCache = 30001;
public void init() {
sRgvCodeList = new HashMap<>();
@@ -280,14 +282,35 @@ public class BaseSRgvThread implements Runnable, SRgvThreadInterface {
endSite = "tsj";
}
WcsSrgvMap wcsSrgvMap1 = new WcsSrgvMap();
String cargoPlaceSite ="";
ConcurrentHashMap<String, DeviceSsj> deviceSsjMap = PlcSsjRead.deviceSsjMap;
List<String> outModelSSJ=new ArrayList<>();
for (String deviceSsj : deviceSsjMap.keySet()) {
if (deviceSsj.equals("TD1001")||deviceSsj.equals("TD1008")) {
DeviceSsj deviceSsj1=deviceSsjMap.get(deviceSsj);
if (deviceSsj1.getModel()==2){
String s="";
if (deviceSsj1.equals("TD1001")){
s="050101";
}else {
s="070101";
}
outModelSSJ.add(s);
}
}
}
cargoPlaceSite= wcsSagvQueueMapper.selectMinCountJob(outModelSSJ);
if (Objects.equals(cargoPlaceSite, "")){
return;
}
wcsSrgvMap1.setRemark(mydoJob1.getExitId());
//TODO 读取输送机入出库模式分配出口
List<WcsSrgvMap> wcsSrgvMaps1 = wcsSrgvMapService.selectWcsSrgvMapList(wcsSrgvMap1);
String cargoPlaceSite = wcsSrgvMaps1.get(0).getSiteId();
String cargoPlaceSite1 =cargoPlaceSite;
List<DeviceSrgv> sameSiteDevices = deviceSrgvMap.values().stream()
.filter(d -> d.getWorkMode() == 5
&& d.getStatus() == 1
&& d.getCurrSite().equals(cargoPlaceSite))
&& d.getCurrSite().equals(cargoPlaceSite1))
.collect(Collectors.toList());
if (!sameSiteDevices.isEmpty() && !Objects.equals(sameSiteDevices.get(0).getDeviceId(), deviceSrgv.getDeviceId())) {
WcsSrgvMap wcsSrgvMap3 = new WcsSrgvMap();
@@ -458,7 +481,7 @@ public class BaseSRgvThread implements Runnable, SRgvThreadInterface {
//生成占位小车到缓存点队列
WcsSrgvQueue wcsSrgvQueue3 = new WcsSrgvQueue();
wcsSrgvQueue3.setGuid(UUID.randomUUID().toString());
wcsSrgvQueue3.setTaskNo(mydoJob1.getTaskNo());
wcsSrgvQueue3.setTaskNo(String.valueOf(taskCache));
wcsSrgvQueue3.setTaskType("1");
wcsSrgvQueue3.setPriority(Long.parseLong("2"));
wcsSrgvQueue3.setCargo("1");
@@ -474,6 +497,7 @@ public class BaseSRgvThread implements Runnable, SRgvThreadInterface {
wcsSrgvQueue3.setDefault02("4");
wcsSrgvQueue3.setDefault07(sameSiteDevices.get(0).getCurrFloor().toString());
wcsSagvQueueMapper.insertWcsSrgvQueue(wcsSrgvQueue3);
taskCache++;
return;
}
}
@@ -578,11 +602,12 @@ public class BaseSRgvThread implements Runnable, SRgvThreadInterface {
//计算最短路径
List<int[]> shortestPath = PathFinder.findShortestPath(emptyMap, arrByRoadSite.get(startSite).getX(), arrByRoadSite.get(startSite).getY(), arrByRoadSite.get(endSite).getX(), arrByRoadSite.get(endSite).getY());
// TODO 小车避让 目前只针对同层最多两台车 并且点位设置到了050201 判断地图中取的路径 不能直达说明有车阻挡 直接返回-1 用-1判断小车阻挡调离小车
if (shortestPath.size() == 1 && shortestPath.get(0)[0] == -1 && shortestPath.get(0)[1] == -1) {
shortestPath = null;
String endBlockAgv = null;
DeviceSrgv endBlockDevice = null;
// TODO 通过arrByRoadSite 中的站点 查询是否存在其他车的站点,如果存在则生成其他车到避让点的队列
if (arrByRoadSite != null && !arrByRoadSite.isEmpty()) {
// 将arrByRoadSite转为String类型的Set(统一类型,方便匹配)
Set<String> roadSiteSet = arrByRoadSite.keySet().stream()
@@ -621,19 +646,19 @@ public class BaseSRgvThread implements Runnable, SRgvThreadInterface {
// 生成纯数字任务号(PLC要求),9 + HHmmss
taskB.setTaskNo(String.valueOf(taskCache));
taskB.setAgvId(endBlockAgv);
taskB.setTaskType("1"); // 点到点移动
taskB.setTaskType("4"); // 避让任务
taskB.setDefault02("4"); // 业务类型标识为点到点
taskB.setPriority(9L); // 高优先级,尽快避让
taskB.setIssued("0"); // 未下发
taskB.setExecutionStatus("1");// 初始状态
taskB.setStartSite(endBlockDevice.getCurrSite());
taskB.setCargoPickSite(endBlockDevice.getCurrSite());
taskB.setCargoPlaceSite("05020" + endBlockDevice.getCurrFloor());
taskB.setEndSite("05020" + endBlockDevice.getCurrFloor());
taskB.setCargoPlaceSite(cacheMaps.get(0).getSiteId());
taskB.setEndSite(cacheMaps.get(0).getSiteId());
taskB.setTheFloor(floor.toString());
taskB.setDefault03(endBlockDevice.getCurrSite());
// taskB.setDefault03(endBlockDevice.getCurrSite());
taskB.setDefault07(floor.toString());
taskB.setDefault08("1");//避让任务,直接完成
// taskB.setDefault08("1");//避让任务,直接完成
taskB.setCreateDate(DateUtil.now());
wcsSagvQueueMapper.insertWcsSrgvQueue(taskB);
taskCache++;
@@ -901,7 +926,7 @@ public class BaseSRgvThread implements Runnable, SRgvThreadInterface {
wcsSagvQueueMapper.updateWcsSrgvQueue(wcsSrgvQueue);
MydoJob mydoJob = mydoJobService.selectMydoJobByTaskNo(Long.valueOf(wcsSrgvQueue.getTaskNo()));
//换层任务不修改执行阶段
if (!wcsSrgvQueue.getDefault02().equals("8") && !wcsSrgvQueue.getDefault02().equals("3")) {
if (mydoJob!=null && !wcsSrgvQueue.getDefault02().equals("8") && !wcsSrgvQueue.getDefault02().equals("3")) {
mydoJob.setExecutionPhase("3");
mydoJob.setStatus("3");
mydoJobService.updateMydoJob(mydoJob);
@@ -1176,6 +1201,7 @@ public class BaseSRgvThread implements Runnable, SRgvThreadInterface {
jobCallBack.setTaskNo(Convert.toLong(mydoJob.getTaskNo()));
jobCallBack.setCreateTime(new Date());
jobCallBackService.insertJobCallBack(jobCallBack);
mydoJobService.insertHistory(mydoJob.getJobId());
mydoJobService.deleteMydoJobByJobId(mydoJob.getJobId());
}
break;
@@ -1183,6 +1209,13 @@ public class BaseSRgvThread implements Runnable, SRgvThreadInterface {
case "2":
MydoJob mydoJobOut = mydoJobService.selectMydoJobByTaskNo(Long.valueOf(wcsSrgvQueue.getTaskNo()));
if (mydoJobOut != null) {
JobCallBack jobCallBack = new JobCallBack();
jobCallBack.setType(wcsSrgvQueue.getDefault02());
jobCallBack.setMydojobId(mydoJobOut.getJobId());
jobCallBack.setStatus("0");
jobCallBack.setTaskNo(Convert.toLong(mydoJobOut.getTaskNo()));
jobCallBack.setCreateTime(new Date());
jobCallBackService.insertJobCallBack(jobCallBack);
mydoJobService.insertHistory(mydoJobOut.getJobId());
mydoJobService.deleteMydoJobByJobId(mydoJobOut.getJobId());
}
@@ -1207,9 +1240,15 @@ public class BaseSRgvThread implements Runnable, SRgvThreadInterface {
//充电之类的,不知道用不用
} else if ("4".equals(taskType)) {
{
wcsSagvQueueMapper.deleteWcsSrgvQueueByGuid(wcsSrgvQueue.getGuid());
}
}
//更新小车待机时间
deviceSrgvService.updateLastTimeByAgvId(wcsSrgvQueue.getAgvId());
// deviceSrgvService.updateLastTimeByAgvId(wcsSrgvQueue.getAgvId());
}
}

View File

@@ -0,0 +1,754 @@
package com.ruoyi.schedule.scheduleTask.srgv;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import com.ruoyi.bas.port.service.IWcsPortService;
import com.ruoyi.bas.srgvmap.domain.WcsSrgvMap;
import com.ruoyi.bas.srgvmap.service.IWcsSrgvMapService;
import com.ruoyi.bas.srgvmap.service.RoadCacheService;
import com.ruoyi.common.TaskStage;
import com.ruoyi.common.domain.SendData2;
import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.device.srgv.domain.DeviceSrgv;
import com.ruoyi.job.charg.service.ISrgvChargingJobService;
import com.ruoyi.job.domain.JobCallBack;
import com.ruoyi.job.domain.MydoJob;
import com.ruoyi.job.service.IJobCallBackService;
import com.ruoyi.job.service.IMydoJobService;
import com.ruoyi.queue.srgv.domain.WcsSrgvQueue;
import com.ruoyi.queue.srgv.service.IWcsSrgvQueueFinishService;
import com.ruoyi.queue.srgv.service.IWcsSrgvQueueService;
import com.ruoyi.queue.tsj.domain.TsjDeviceExecutionQueue;
import com.ruoyi.queue.tsj.service.ITsjDeviceExecutionQueueService;
import com.ruoyi.schedule.plcRead.srgv.PlcSrgvRead;
import com.ruoyi.schedule.plcRead.srgv.roadUtil.PathFinder;
import lombok.extern.slf4j.Slf4j;
import java.util.*;
import java.util.stream.Collectors;
import static com.ruoyi.common.TaskStage.FINISHED;
import static com.ruoyi.common.TaskStage.STAGE7;
@Slf4j
public class BaseSRgvThread1 implements Runnable, SRgvThreadInterface {
private IWcsSrgvMapService wcsSrgvMapService;
private IWcsSrgvQueueService wcsSrgvQueueService;
private ITsjDeviceExecutionQueueService tsjDeviceExecutionQueueService;
private IMydoJobService mydoJobService;
private RoadCacheService roadCacheService;
private IJobCallBackService jobCallBackService;
public IWcsSrgvQueueFinishService wcsSagvQueueFinishMapper;
public IWcsPortService wcsPortService;
public ISrgvChargingJobService srgvChargingJobMapper;
public boolean isRun = true;
public HashMap<String, List<String>> sRgvCodeList;
public void init() {
sRgvCodeList = new HashMap<>();
ArrayList<String> sRgvCodes = new ArrayList<>();
sRgvCodes.add("1");
/*sRgvCodes.add("2");
sRgvCodes.add("3");*/
sRgvCodeList.put("srgv", sRgvCodes);
wcsSagvQueueFinishMapper = SpringUtils.getBean(IWcsSrgvQueueFinishService.class);
wcsPortService = SpringUtils.getBean(IWcsPortService.class);
srgvChargingJobMapper = SpringUtils.getBean(ISrgvChargingJobService.class);
mydoJobService = SpringUtils.getBean(IMydoJobService.class);
wcsSrgvMapService = SpringUtils.getBean(IWcsSrgvMapService.class);
roadCacheService = SpringUtils.getBean(RoadCacheService.class);
wcsSrgvQueueService = SpringUtils.getBean(IWcsSrgvQueueService.class);
tsjDeviceExecutionQueueService = SpringUtils.getBean(ITsjDeviceExecutionQueueService.class);
}
@Override
public void run() {
init();
while (isRun) {
for (String code : sRgvCodeList.get("srgv")) {
try {
if (PlcSrgvRead.deviceSrgvMap.containsKey(code)) {
if (ObjUtil.isNotNull(PlcSrgvRead.deviceSrgvMap.get(code))) {
DeviceSrgv deviceSrgv = PlcSrgvRead.deviceSrgvMap.get(code);
//selectCarForTask();
createSrgvInOutQueue();
srgvTask(deviceSrgv);
} else {
log.error("小车设备为空");
}
}
} catch (RuntimeException e) {
log.error(e.getMessage(), e);
}
}
try {
Thread.sleep(1500);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
public void selectCarForTask() {
MydoJob mydoJob = mydoJobService.selectNoAllocatCar();
/*
选择执行任务的小车
优先级 目标层已有小车 > 1 层空闲小车 > 其他无任务层空闲小车
*/
if (ObjUtil.isNotNull(mydoJob)) {
for (String srgvId : PlcSrgvRead.deviceSrgvMap.keySet()) {
DeviceSrgv deviceSrgv = PlcSrgvRead.deviceSrgvMap.get(srgvId);
//如果小车空闲,选择小车
if (deviceSrgv.getStatus() == 0) {
mydoJob.setCarId(srgvId);
mydoJob.setStatus("3");
mydoJob.setStartTime(DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
/*
根据选择的小车当前位置 确定mydojob的任务阶段
*/
Integer floor = deviceSrgv.getCurrFloor();
String currSite = deviceSrgv.getCurrSite();
if (floor.equals(Convert.toInt(mydoJob.getRoadwayId()))) {
//小车所在楼层和任务开始楼层一致 3 5
if (!currSite.equals(mydoJob.getCargoSpaceId())) {
mydoJob.setExecutionPhase("3");
} else {
//判断目标楼层是不是1层
if (!"1".equals(mydoJob.getTargetRoadwayId())) {
mydoJob.setExecutionPhase("5");
} else {
mydoJob.setExecutionPhase("7");
}
}
} else {
mydoJob.setExecutionPhase("1");
}
mydoJobService.updateMydoJob(mydoJob);
}
}
}
}
/* 出库
1-2-3-5-6-7 车在其它层 && 取货目标在其它层
1-2-3-7 车在其它层 && 取货目标在1层
3-5-6-7 车在取货层 && 取货目标在其它层
3-7 车在取货层 && 层数为1 && 放货目标在1层
*/
public void outQueue() {
}
/* 入库
1-2-3-5-6-7 车在其它层 && 放货目标在其它层
1-2-3-7 车在其它层 && 放货目标在1层
3-5-6-7 车在1层 && 放货目标在其它层
3-7 车在1层 && 放货目标在1层
任务类型 方式
1 srgv 点对点 当前位置→本层电梯口
2 tsj 换层 取放 当前层→起点层
3 srgv 点对点 取货 当前位置->取货点
5 srgv 点对点 取货点->本层电梯口
6 tsj 换层 取放 取货层->放货层
7 srgv 点对点 放货 本层电梯口->放货点
*/
public void createSrgvInOutQueue() {
MydoJob param = new MydoJob();
param.setStatus("3");
List<MydoJob> mydoJobs = mydoJobService.selectMydoJobList(param);
if (CollUtil.isNotEmpty(mydoJobs)) {
for (MydoJob mydoJob : mydoJobs) {
if (StrUtil.isNotEmpty(mydoJob.getCarId())) {
//绑定任务小车
DeviceSrgv deviceSrgv = PlcSrgvRead.deviceSrgvMap.get(mydoJob.getCarId());
//开始小车任务阶段
if (mydoJob.getExecutionPhase().equals(TaskStage.STAGE1.getCode())) {
/*
当前位置→本层电梯口 srgv
1. 调用 A * 算法规划层内最优路径(避开墙 0/4,走通道 2)
2. 实时检测通道冲突(与其他小车路径不重叠)
3. 移动到本层电梯口
*/
String startSite = deviceSrgv.getCurrSite();
Integer floor = deviceSrgv.getCurrFloor();
String endSite = getTsjSiteIdByFloor(floor);
if (StrUtil.isEmpty(endSite)) {
log.info("生成tsj队列失败,未找到层数为{}电梯口", floor);
} else {
String rwlx = "4";
int srgvQueue = createSrgvQueue(mydoJob, startSite, endSite, rwlx);
if (srgvQueue > 0) {
log.info("生成srgv队列成功 rwh:{},startSite:{},endSite:{}", mydoJob.getTaskNo(), startSite, endSite);
}
}
}
if (mydoJob.getExecutionPhase().equals(TaskStage.STAGE2.getCode())) {
/*
本层电梯口→起点层电梯口 tsj
1. 加入电梯排队队列(按任务优先级 + 到电梯口距离排序)
2. 等待电梯空闲后占用电梯,跨层到 1 层
3. 电梯到达后,更新小车位置为(1,8,8)
*/
//生成tsj队列
//根据位置判断列数
String srcColumn = "";
String tarColumn = "";
Integer srcFloor = deviceSrgv.getCurrFloor();
Integer tarFloor = Convert.toInt(mydoJob.getRoadwayId());
String rwlx = "";
int tsjQueue = createTsjQueue(Convert.toLong(mydoJob.getTaskNo()), srcFloor, srcColumn, tarFloor, tarColumn, mydoJob.getCarId(), rwlx);
if (tsjQueue > 0) {
log.info("生成tsj队列成功 rwh:{},srcC:{},srcF:{},tarC:{},tarF:{},rwlx:{}", mydoJob.getTaskNo(), srcColumn, srcFloor, tarColumn, tarFloor, rwlx);
}
}
if (mydoJob.getExecutionPhase().equals(TaskStage.STAGE3.getCode())) {
/*
起点层电梯口(小车当前位置)→起点层作业点 srgv
1. 规划 1 层电梯口到作业点的路径(1 层通道拥堵高发,优先走预设单向通道)
2. 检查作业点占用状态(同一时间仅 1 台小车作业)
3. 移动到作业点并锁定作业点
*/
//生成srgv队列
String startSite = getTsjSiteIdByFloor(Convert.toInt(mydoJob.getRoadwayId()));
String endSite = mydoJob.getCargoSpaceId();
String rwlx = "4";
int srgvQueue = createSrgvQueue(mydoJob, startSite, endSite, rwlx);
if (srgvQueue > 0) {
log.info("生成srgv队列成功 rwh:{},startSite:{},endSite:{}", mydoJob.getTaskNo(), startSite, endSite);
}
}
/*if (mydoJob.getExecutionPhase().equals(TaskStage.STAGE4.getCode())) {
*//*
作业点执行取/放货-> srgv
1. 触发取货传感器,确认货物已装载
2. 更新任务状态为取货完成
3. 释放作业点(供其他小车使用)
*//*
String startSite = "";
String endSite = "";
String rwlx = "4";
int srgvQueue = createSrgvQueue(mydoJob, startSite, endSite, rwlx);
if (srgvQueue > 0) {
log.info("生成srgv队列成功 rwh:{},startSite:{},endSite:{}", mydoJob.getTaskNo(), startSite, endSite);
}
}*/
if (mydoJob.getExecutionPhase().equals(TaskStage.STAGE5.getCode())) {
/*
作业点->起点层电梯口 srgv
1. 规划作业点到电梯口的返程路径
2. 再次检测 1 层通道冲突(避免与新任务小车对向拥堵)
3. 移动到 1 层电梯口
*/
String startSite = "";
String endSite = "";
String rwlx = "4";
int srgvQueue = createSrgvQueue(mydoJob, startSite, endSite, rwlx);
if (srgvQueue > 0) {
log.info("生成srgv队列成功 rwh:{},startSite:{},endSite:{}", mydoJob.getTaskNo(), startSite, endSite);
}
}
if (mydoJob.getExecutionPhase().equals(TaskStage.STAGE6.getCode())) {
/*
起点层电梯口→目标层电梯口 tsj
1. 加入电梯队列(按任务优先级排序,优先高优先级任务)
2. 占用电梯跨层到目标层
3. 电梯到达后,更新小车位置为(目标层,8,8)
*/
//生成tsj队列
String srcColumn = "";
String tarColumn = "";
Integer srcFloor = 0;
Integer tarFloor = 0;
String rwlx = "";
int tsjQueue = createTsjQueue(Convert.toLong(mydoJob.getTaskNo()), srcFloor, srcColumn, tarFloor, tarColumn, mydoJob.getCarId(), rwlx);
if (tsjQueue > 0) {
log.info("生成tsj队列成功 rwh:{},srcC:{},srcF:{},tarC:{},tarF:{},rwlx:{}", mydoJob.getTaskNo(), srcColumn, srcFloor, tarColumn, tarFloor, rwlx);
}
}
if (mydoJob.getExecutionPhase().equals(STAGE7.getCode())) {
/*
当前位置→目标货位 srgv
1. 规划目标层电梯口到目标货位的路径
2. 检查目标货位状态(是否空闲,避免重复放货)
3. 移动到目标货位,触发放货传感器
*/
//生成srgv队列
String startSite = deviceSrgv.getCurrSite();
String endSite = mydoJob.getTargetCargoSpaceId();
String rwlx = "4";
int srgvQueue = createSrgvQueue(mydoJob, startSite, endSite, rwlx);
if (srgvQueue > 0) {
log.info("生成srgv队列成功 rwh:{},startSite:{},endSite:{}", mydoJob.getTaskNo(), startSite, endSite);
}
}
if (mydoJob.getExecutionPhase().equals(TaskStage.STAGE8.getCode())) {
/*
. 可选两种待命策略:
- 策略 1(优先高效):回到目标层电梯口(就近待命,减少下一次任务跨层成本)
- 策略 2(优先均衡):回到1 层作业点附近(适配高频 1 层出发任务)
2. 更新小车状态为idle,清空当前任务
*/
//生成srgv队列
String startSite = "";
String endSite = "";
String rwlx = "4";
int srgvQueue = createSrgvQueue(mydoJob, startSite, endSite, rwlx);
if (srgvQueue > 0) {
log.info("生成srgv队列成功 rwh:{},startSite:{},endSite:{}", mydoJob.getTaskNo(), startSite, endSite);
}
}
if (mydoJob.getExecutionPhase().equals(FINISHED.getCode())) {
//完成任务
mydoJob.setFinishTime(DateUtil.formatDateTime(new Date()));
mydoJob.setStatus("4");
mydoJobService.updateMydoJob(mydoJob);
mydoJobService.insertHistory(mydoJob.getJobId());
JobCallBack jobCallBack = new JobCallBack();
jobCallBack.setMydojobId(mydoJob.getJobId());
jobCallBack.setStatus("0");
if (Convert.toInt(mydoJob.getInOrOut()) < 20) {
jobCallBack.setType("1");
} else {
jobCallBack.setType("2");
}
jobCallBack.setTaskNo(Convert.toLong(mydoJob.getTaskNo()));
jobCallBack.setCreateTime(new Date());
jobCallBackService.insertJobCallBack(jobCallBack);
}
}
}
}
}
/**
* 创建srgv队列
*
* @param mydoJob 任务
* @param startSite 源站
* @param endSite 目的站
* @param rwlx 任务类型 1-入库 2-出库 3-充电 4-点对点
*/
private int createSrgvQueue(MydoJob mydoJob, String startSite, String endSite, String rwlx) {
WcsSrgvQueue queue = wcsSrgvQueueService.selectWcsSrgvQueueByTaskNo(mydoJob.getTaskNo());
if (queue != null) {
return 0;
}
//生成srgv队列
WcsSrgvQueue wcsSrgvQueue = new WcsSrgvQueue();
wcsSrgvQueue.setGuid(IdUtil.simpleUUID());
wcsSrgvQueue.setTaskType("1");
wcsSrgvQueue.setTaskNo(mydoJob.getTaskNo());
wcsSrgvQueue.setPriority(2L);
wcsSrgvQueue.setCargo("0");
wcsSrgvQueue.setIssued("0");
wcsSrgvQueue.setExecutionStatus("0");
wcsSrgvQueue.setCargoPickSite(mydoJob.getCargoSpaceId());
wcsSrgvQueue.setCargoPlaceSite(mydoJob.getTargetCargoSpaceId());
wcsSrgvQueue.setStartSite(startSite);
wcsSrgvQueue.setEndSite(endSite);
wcsSrgvQueue.setCreateDate(DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
wcsSrgvQueue.setAgvId(mydoJob.getCarId());
wcsSrgvQueue.setDefault02(rwlx);
return wcsSrgvQueueService.insertWcsSrgvQueue(wcsSrgvQueue);
}
//出库 1-2-3-4-5-6-7-4-9
/**
* 创建提升机队列
*
* @param taskNo 任务编号
* @param srcColumn 源列
* @param srcFloor 源层
* @param tarColumn 目标列
* @param tarFloor 目标层
* @param carId 小车id
* @param rwlx 任务类型
*/
private int createTsjQueue(Long taskNo, Integer srcFloor, String srcColumn, Integer tarFloor, String tarColumn, String carId, String rwlx) {
TsjDeviceExecutionQueue queue = tsjDeviceExecutionQueueService.selectTsjDeviceExecutionQueueByRwh(taskNo);
if (ObjUtil.isNull(queue)) {
TsjDeviceExecutionQueue tsjDeviceExecutionQueue = new TsjDeviceExecutionQueue();
tsjDeviceExecutionQueue.setGuid(IdUtil.simpleUUID());
tsjDeviceExecutionQueue.setDeviceId(1L);
tsjDeviceExecutionQueue.setDeviceName("提升机");
tsjDeviceExecutionQueue.setTaskNo(taskNo);
tsjDeviceExecutionQueue.setSrcColumn(srcColumn);
tsjDeviceExecutionQueue.setSrcLayer(Convert.toStr(srcFloor));
tsjDeviceExecutionQueue.setTarColumn(tarColumn);
tsjDeviceExecutionQueue.setTarLayer(Convert.toStr(tarFloor));
tsjDeviceExecutionQueue.setSendType("1");
tsjDeviceExecutionQueue.setCreateDate(DateUtil.formatDateTime(new Date()));
tsjDeviceExecutionQueue.setSpare1(carId);
tsjDeviceExecutionQueue.setTaskType("1");
tsjDeviceExecutionQueue.setRwlx(rwlx);
return tsjDeviceExecutionQueueService.insertTsjDeviceExecutionQueue(tsjDeviceExecutionQueue);
}
return 0;
}
private String getTsjSiteIdByFloor(int floor) {
String siteId = null;
switch (floor) {
case 1:
siteId = "040801";
break;
case 2:
siteId = "040802";
break;
case 3:
siteId = "040803";
break;
case 4:
siteId = "040804";
break;
case 5:
siteId = "040805";
break;
case 6:
siteId = "040806";
break;
case 7:
siteId = "040807";
break;
case 8:
siteId = "040808";
break;
default:
return null;
}
return siteId;
}
/**
* 小车任务处理
*/
private void srgvTask(DeviceSrgv deviceSrgv) {
//队列下发成功处理
resQueue(deviceSrgv);
//小车完成队列
completeCarTask(deviceSrgv);
//小车发送任务
sendTask(deviceSrgv);
}
/**
* 队列下发成功处理
*/
private void resQueue(DeviceSrgv deviceSrgv) {
int taskNo = deviceSrgv.getTaskNo();
String currSite = deviceSrgv.getCurrSite();
Integer deviceId = deviceSrgv.getDeviceId();
if (taskNo > 999 && !"000000".equals(currSite)) {
WcsSrgvQueue param = new WcsSrgvQueue();
param.setTaskNo(Convert.toStr(taskNo));
param.setIssued("0");
param.setAgvId(String.valueOf(deviceId));
List<WcsSrgvQueue> wcsSrgvQueues = wcsSrgvQueueService.selectWcsSrgvQueueList(param);
if (CollUtil.isNotEmpty(wcsSrgvQueues)) {
WcsSrgvQueue wcsSrgvQueue = wcsSrgvQueues.get(0);
wcsSrgvQueue.setIssued("1");
wcsSrgvQueue.setStartDate(DateUtil.now());
wcsSrgvQueueService.updateWcsSrgvQueue(wcsSrgvQueue);
}
}
}
/**
* 小车完成队列
*/
private void completeCarTask(DeviceSrgv deviceSrgv) {
//联机自动
if (deviceSrgv.getWorkMode() == 4) {
WcsSrgvQueue param = new WcsSrgvQueue();
param.setAgvId(Convert.toStr(deviceSrgv.getDeviceId()));
param.setEndSite(deviceSrgv.getCurrSite());//目标点
param.setIssued("1");
param.setTaskNo(deviceSrgv.getTaskNo().toString());
List<WcsSrgvQueue> wcsSagvQueues = wcsSrgvQueueService.selectWcsSrgvQueueList(param);//查询到达目标的
if (CollUtil.isNotEmpty(wcsSagvQueues)) {
WcsSrgvQueue wcsSrgvQueue = wcsSagvQueues.get(0);
MydoJob mydoJob = mydoJobService.selectMydoJobByTaskNo(Convert.toLong(wcsSrgvQueue.getTaskNo()));
if (mydoJob != null) {
Integer floor = deviceSrgv.getCurrFloor();
Integer startFloor = Convert.toInt(mydoJob.getRoadwayId());
Integer endFloor = Convert.toInt(mydoJob.getTargetRoadwayId());
if (Convert.toInt(mydoJob.getInOrOut()) < 20) {
//入库
if ("1".equals(mydoJob.getExecutionPhase())) {
mydoJob.setExecutionPhase("2");
mydoJobService.updateMydoJob(mydoJob);
} else if ("3".equals(mydoJob.getExecutionPhase())) {
if (floor.equals(endFloor)) {
mydoJob.setExecutionPhase("7");
mydoJobService.updateMydoJob(mydoJob);
} else {
mydoJob.setExecutionPhase("5");
mydoJobService.updateMydoJob(mydoJob);
}
} else if ("5".equals(mydoJob.getExecutionPhase())) {
mydoJob.setExecutionPhase("6");
mydoJobService.updateMydoJob(mydoJob);
} else if ("7".equals(mydoJob.getExecutionPhase())) {
mydoJob.setExecutionPhase("8");
mydoJobService.updateMydoJob(mydoJob);
}
} else {
//出库
if ("1".equals(mydoJob.getExecutionPhase())) {
mydoJob.setExecutionPhase("2");
mydoJobService.updateMydoJob(mydoJob);
} else if ("3".equals(mydoJob.getExecutionPhase())) {
if (floor.equals(1)) {
mydoJob.setExecutionPhase("7");
mydoJobService.updateMydoJob(mydoJob);
} else {
mydoJob.setExecutionPhase("5");
mydoJobService.updateMydoJob(mydoJob);
}
} else if ("5".equals(mydoJob.getExecutionPhase())) {
mydoJob.setExecutionPhase("6");
mydoJobService.updateMydoJob(mydoJob);
} else if ("7".equals(mydoJob.getExecutionPhase())) {
mydoJob.setExecutionPhase("8");
mydoJobService.updateMydoJob(mydoJob);
}
}
wcsSrgvQueue.setExecutionStatus("4");
wcsSrgvQueue.setUpdateTime(DateUtil.date());
wcsSrgvQueueService.updateWcsSrgvQueue(wcsSrgvQueue);
wcsSrgvQueueService.insertHistory(wcsSrgvQueue.getTaskNo());
wcsSrgvQueueService.deleteWcsSrgvQueueByGuid(wcsSrgvQueue.getGuid());
}
}
}
}
/**
* 小车发送任务
*/
private void sendTask(DeviceSrgv deviceSrgv) {
WcsSrgvQueue param = new WcsSrgvQueue();
param.setIssued("0");
param.setAgvId(deviceSrgv.getDeviceId().toString());
List<WcsSrgvQueue> wcsSrgvQueues = wcsSrgvQueueService.selectWcsSrgvQueueList(param);
if (CollUtil.isEmpty(wcsSrgvQueues)) {
return;
}
for (WcsSrgvQueue wcsSrgvQueue : wcsSrgvQueues) {
String agvId = wcsSrgvQueue.getAgvId();
if (agvId.equals(Convert.toStr(deviceSrgv.getDeviceId())) && deviceSrgv.getWorkMode() == 4 && deviceSrgv.getAllowSend() == 1) {
String endSite = wcsSrgvQueue.getEndSite();
String currSite = deviceSrgv.getCurrSite();
//判断是否可以下发任务
if ("0".equals(wcsSrgvQueue.getIssued())) {
sendPointToPointTask(deviceSrgv, wcsSrgvQueue, currSite, endSite);
}
}
}
}
/**
* 小车发送点对点任务
*/
private void sendPointToPointTask(DeviceSrgv deviceSrgv, WcsSrgvQueue wcsSrgvQueue, String startSite, String endSite) {
Integer floor = deviceSrgv.getCurrFloor();
//获取当前地图
Map<String, WcsSrgvMap> arrByRoadSite = roadCacheService.getArrByRoadSite(floor);
//处理地图
int[][] emptyMap = roadCacheService.handleMap(arrByRoadSite, deviceSrgv);
//计算最短路径
List<int[]> shortestPath = PathFinder.findShortestPath(emptyMap, arrByRoadSite.get(startSite).getX(), arrByRoadSite.get(startSite).getY(), arrByRoadSite.get(endSite).getX(), arrByRoadSite.get(endSite).getY());
//判断是否能规划出最短路径
if (shortestPath == null || shortestPath.isEmpty()) {
log.error("无法到达指定位置");
return;
}
//获取拐点路径
List<int[]> trun = PathFinder.extractInflectionPoints2(shortestPath);
// 路径点拼接
StringBuilder pathBuilder = new StringBuilder();
if (!shortestPath.isEmpty()) {
for (int[] ints : shortestPath) {
WcsSrgvMap roadSiteByArr = roadCacheService.selectRoadSiteByArr(ints[0], ints[1], floor);
if (roadSiteByArr == null) {
log.error("无此站点 x y z :{},{},{}", ints[0], ints[1], floor);
throw new RuntimeException("点位信息错误");
}
String site = roadSiteByArr.getSiteId();
pathBuilder.append(site).append(",");
}
}
// 拐点拼接
StringBuilder turnBuilder = new StringBuilder();
if (!trun.isEmpty()) {
for (int[] ints : trun) {
WcsSrgvMap roadSiteByArr = roadCacheService.selectRoadSiteByArr(ints[0], ints[1], floor);
if (roadSiteByArr == null) {
log.error("无此站点 x y z :{},{},{}", ints[0], ints[1], floor);
throw new RuntimeException("点位信息错误");
}
String site = roadSiteByArr.getSiteId();
turnBuilder.append(site).append(",");
}
if (turnBuilder.length() > 0) {
turnBuilder.setLength(turnBuilder.length() - 1);
}
// 当trun长度小于6时,后面用0拼接
if (trun.size() < 6) {
for (int i = trun.size(); i < 6; i++) {
turnBuilder.append(",0");
}
}
}
List<SendData2> sendDataList = new ArrayList<>();
if (!trun.isEmpty()) {
SendData2 path = new SendData2();
path.setAddress("4000");//地址
path.setData(startSite + "," + endSite + "," + turnBuilder);
path.setType(2);
sendDataList.add(path);
} else {
SendData2 path = new SendData2();
path.setAddress("4000");//地址
path.setData(startSite + "," + endSite);
path.setType(2);
sendDataList.add(path);
}
//任务号、原、目标数据转换
String siteId = wcsSrgvQueue.getTaskNo() + "1";//+ "," + startSite + "," + endSite;
SendData2 site = new SendData2();
site.setAddress("4400");
site.setData(siteId);
site.setType(2);
sendDataList.add(site);
//任务类型转换
SendData2 taskType = new SendData2();
taskType.setAddress("2200");
taskType.setData(wcsSrgvQueue.getTaskType());
taskType.setType(1);
sendDataList.add(taskType);
//下发标志转换
SendData2 flag = new SendData2();
flag.setAddress("2202");
flag.setData("1");
flag.setType(1);
sendDataList.add(flag);
//下发数据
boolean b = sendCarTask(sendDataList, deviceSrgv);
if (b) {
wcsSrgvQueue.setPathInfo(pathBuilder.toString());
wcsSrgvQueue.setTrunPath(turnBuilder.toString());
wcsSrgvQueueService.updateWcsSrgvQueue(wcsSrgvQueue);
} else {
log.error("小车下发失败 taskNo:{}", wcsSrgvQueue.getTaskNo());
}
}
/**
* 小车发送任务
*/
private boolean sendCarTask(List<SendData2> sendDataList, DeviceSrgv deviceSrgv) {
boolean b = true;
for (SendData2 sendData : sendDataList) {
String address = sendData.getAddress();
String data = sendData.getData();//
String[] split = data.split(",");
int type = sendData.getType();//1单字 2双字 3字符串
//双字
if (type == 2) {
int[] intData = Arrays.stream(split).map(String::trim).mapToInt(Integer::parseInt).toArray();
boolean write = true;//PlcSrgvRead.Write(address, intData);
if (!write) {
b = false;
break;
}
}
//单字
if (type == 1) {
//String[]转为 short[]
short[] shortData = new short[split.length];
for (int i = 0; i < split.length; i++) {
try {
shortData[i] = Short.parseShort(split[i].trim());
} catch (NumberFormatException e) {
// 记录日志并设置默认值
shortData[i] = 0;
}
}
boolean write = true;//PlcSrgvRead.Write(address, shortData);
if (!write) {
b = false;
break;
}
}
}
String collect = sendDataList.stream().map(li -> "{" + li.getAddress() + ":" + li.getData() + "}").collect(Collectors.joining(","));
log.info("小车:" + deviceSrgv.getDeviceId() + ",下发值:" + collect + ",,结果:" + b);
return b;
}
}

View File

@@ -124,7 +124,7 @@ public class SsjThread implements Runnable {
}
void inDispatch1(DeviceSsj deviceSsj) {
if (deviceSsj.getRkqq() == 1 && StrUtil.isNotBlank(deviceSsj.getTrayCode())) {
if (deviceSsj.getRkqq() == 1 && StrUtil.isNotBlank(deviceSsj.getTrayCode().trim())) {
//todo 查是否为入库模式,不是退回,是否超重
HashMap<String, Object> map = new HashMap<>();
map.put("trayCode", deviceSsj.getTrayCode());
@@ -136,6 +136,7 @@ public class SsjThread implements Runnable {
mydoJob.setStatus("1");
mydoJob.setExecutionPhase("1");
mydoJob.setCreateTime(new Date());
mydoJob.setTheFloor(mydoJob.getClassId());
if ("GS1002".equals(deviceSsj.getDeviceCode())) {
mydoJob.setEntranceId("L1004");
} else {
@@ -158,12 +159,9 @@ public class SsjThread implements Runnable {
} else {
int i = writeToSsj(deviceSsj.getPlcDbWriteAddress(), "0", 2, 2);
if (i == 1) {
log.info(deviceSsj.getDeviceCode() + "未查到该托盘码作业,下发退回,去向2");
log.info(deviceSsj.getDeviceCode() + "未查到该托盘码作业,下发退回,去向2 条码"+deviceSsj.getTrayCode());
}
}
}
}

View File

@@ -117,8 +117,7 @@ public class TsjThread implements Runnable {
private void createSRgvQueueTsjQd(Long rwh, DeviceTsj tsj) {
for (String sRgv : PlcSrgvRead.deviceSrgvMap.keySet()) {
DeviceSrgv deviceSrgv = PlcSrgvRead.deviceSrgvMap.get(sRgv);
if (deviceSrgv.getCurrSite().equals("09050" + deviceSrgv.getCurrFloor()) && deviceSrgv.getWorkMode() == 5 && deviceSrgv.getStatus() == 2 && tsj.getHczt() == 1) {
if ((deviceSrgv.getCurrSite().equals("09050" + deviceSrgv.getCurrFloor()) ||deviceSrgv.getCurrSite().equals("10050" + deviceSrgv.getCurrFloor()))&& deviceSrgv.getWorkMode() == 5 && deviceSrgv.getStatus() == 2 && tsj.getHczt() == 1) {
SendData rwlxSendData = new SendData(Tools.INT, 1);
DeviceTsj deviceTsj = PlcTsjRead.deviceTsjMap.get(Convert.toStr(1));
byte[] bytes = Tools.sendData(rwlxSendData);

View File

@@ -85,7 +85,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<select id="selectWcsSrgvQueueByFloor" parameterType="String" resultMap="WcsSrgvQueueResult">
<include refid="selectWcsSrgvQueueVo"/>
where default07 =#{theFloor}
where default07 =#{theFloor} and default07 !='1'
</select>
<insert id="insertWcsSrgvQueue" parameterType="WcsSrgvQueue">
@@ -192,4 +192,24 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</foreach>
</delete>
<select id="selectMinCountJob" parameterType="list" resultType="string">
<choose>
<when test="list == null or list.size() == 0">
SELECT '' AS result_site
</when>
<otherwise>
select top(1) site_id from
(select '050101' as site_id,isnull(count(1),0) as num from wcs_srgv_queue where cargo_place_site ='050101'
union
select '070101' as site_id,isnull(count(1),0) as num from wcs_srgv_queue where cargo_place_site ='070101')r
where r.site_id in
<foreach collection="list" item="site" open="(" separator="," close=")">
#{site}
</foreach>
order by num
</otherwise>
</choose>
</select>
</mapper>