本地生成、下发、更新、完成任务的基本调度方法

This commit is contained in:
lsymicc
2025-06-30 15:59:31 +08:00
parent a768bc2e94
commit eef6f9fe06
12 changed files with 329 additions and 24 deletions

View File

@@ -6,7 +6,7 @@ public class Constant {
/**
* REST协议接口基础地址
*/
public static final String BASEURL = "http://127.0.0.1:8080";
public static final String BASEURL = "http://127.0.0.1:8081";
/**
* REST协议接口基础地址

View File

@@ -6,9 +6,19 @@ package com.ruoyi.common;
public class TaskStatusCode {
/**
* 任务状态-待执行
* 任务状态-待请求下发
*/
public static final String TASK_READY = "100";
public static final String TASK_READY = "0";
/**
* 任务状态-(向设备)请求下发任务成功
*/
public static final String TASK_SEND_SUCCESS = "1";
/**
* 任务状态-已创建(设备请求成功)
*/
public static final String TASK_CREATED = "100";
/**
* 任务状态-执行中
@@ -26,8 +36,18 @@ public class TaskStatusCode {
public static final String TASK_FINISH_MANUAL = "103";
/**
* 任务状态-手动取消
* 任务状态-已取消
*/
public static final String TASK_CANCEL = "104";
/**
* 任务状态-手动取消
*/
public static final String TASK_CANCEL_MANUAL = "105";
/**
* 任务状态-手动取消
*/
public static final String TASK_INTERUPTED = "109";
}

View File

@@ -5,7 +5,7 @@ import lombok.Data;
/**
* 通过请求参数, 查询 AGV 状态信息,包括电池电量。
* 调用频次: 100车以下:5秒, 100~200车:10秒, 200 ~300车:15秒
* 调用路径: http://IP:8182/rcms-dps/rest/queryAgvStatus
* 调用路径示例: http://IP:8182/rcms-dps/rest/queryAgvStatus
*/
@Data
public class QueryAgvStatusRequest {

View File

@@ -1,16 +1,28 @@
package com.ruoyi.schedule.scheduleTask;
import cn.hutool.Hutool;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ruoyi.common.Constant;
import com.ruoyi.common.TaskStatusCode;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.uuid.UUID;
import com.ruoyi.device.agv.domain.ResponseBase;
import com.ruoyi.device.agv.domain.genAgvSchedulingTask.GenAgvSchedulingTaskRequest;
import com.ruoyi.device.agv.domain.genAgvSchedulingTask.GenAgvSchedulingTaskResponse;
import com.ruoyi.device.agv.domain.genAgvSchedulingTask.PositionCodeData;
import com.ruoyi.device.agv.domain.queryTaskStatus.TaskStatusData;
import com.ruoyi.schedule.job.mydojob.domain.MydoJob;
import com.ruoyi.schedule.task.domain.WcsTask;
import com.ruoyi.schedule.task.mapper.WcsTaskMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.List;
/**
@@ -20,6 +32,8 @@ import java.util.List;
@Slf4j
public class Execution {
@Autowired
WcsTaskMapper wcsTaskMapper;
/**
* 查询是否有wcs任务
@@ -37,6 +51,57 @@ public class Execution {
}
/**
* 获取所有wcs任务
*/
public void getAllTask(){
//查询实时任务表获取所有【待执行】任务
LambdaQueryWrapper<WcsTask> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(WcsTask::getTaskStatus, TaskStatusCode.TASK_READY);
List<WcsTask> tasks = wcsTaskMapper.selectList(queryWrapper);
//无【待执行】任务
if (tasks.size() == 0) return;
for (int i = 0; i < tasks.size(); i++) {
//请求agv/ctu下发指令
GenAgvSchedulingTaskRequest request = new GenAgvSchedulingTaskRequest();
request.setReqCode(UUID.randomUUID().toString().replace("-", ""));
//入库类型
switch (tasks.get(i).getTaskType()) {
case "1":
request.setTaskTyp("F12");
break;
case "2":
request.setTaskTyp("F11");
break;
default:
log.warn("【向设备下发任务请求】TaskTyp:{},生成任务的请求参数错误,异常的任务类型!", request.getTaskTyp());
return;
}
//添加路径(未测试)
List<PositionCodeData> path = new ArrayList<>();
path.add(new PositionCodeData(tasks.get(i).getSourceLocation(),"05"));
path.add(new PositionCodeData(tasks.get(i).getTargetLocation(),"05"));
request.setPositionCodePath(path);
//wcs任务号---设备任务编号
request.setTaskCode(tasks.get(i).getTaskId());
//下发成功---更新【任务状态】为下发成功
if (sendCommand(request)){
tasks.get(i).setTaskStatus(TaskStatusCode.TASK_SEND_SUCCESS);
wcsTaskMapper.updateWcsTask(tasks.get(i));
}
}
}
/**
* 向AGV/CTU请求下发指令
@@ -68,14 +133,18 @@ public class Execution {
return false;
}
//返回码
if (genAgvSchedulingTaskResponse.getCode() == 0 ) {
return true;
}else {
log.error("【下发设备任务】下发任务失败," + genAgvSchedulingTaskResponse.getMessage() + "!");
//返回码错误
if (genAgvSchedulingTaskResponse.getCode() != 0 ) {
if (genAgvSchedulingTaskResponse.getMessage() == ""){
log.error("【下发设备任务】下发任务失败,发生了未知错误");
}else{
log.error("【下发设备任务】下发任务失败,{}", genAgvSchedulingTaskResponse.getMessage());
}
return false;
}
return true;
}
@@ -105,8 +174,6 @@ public class Execution {
return false;
}
//4.请求编号一致时避免重复下发
return true;

View File

@@ -0,0 +1,62 @@
package com.ruoyi.schedule.scheduleTask;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ruoyi.common.TaskStatusCode;
import com.ruoyi.schedule.task.domain.WcsTask;
import com.ruoyi.schedule.task.mapper.WcsTaskMapper;
import com.ruoyi.schedule.taskHistory.domain.WcsTaskHistory;
import com.ruoyi.schedule.taskHistory.mapper.WcsTaskHistoryMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
import java.util.List;
@Component
@Slf4j
public class Finish {
@Autowired
WcsTaskMapper wcsTaskMapper;
@Autowired
WcsTaskHistoryMapper wcsTaskHistoryMapper;
public void taskFinish() {
//查询实时任务表获取所有【已结束】,【已取消】和手动处理的任务任务
LambdaQueryWrapper<WcsTask> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(WcsTask::getTaskStatus, TaskStatusCode.TASK_FINISH)
.or()
.eq(WcsTask::getTaskStatus, TaskStatusCode.TASK_CANCEL)
.or()
.eq(WcsTask::getTaskStatus, TaskStatusCode.TASK_FINISH_MANUAL)
.or()
.eq(WcsTask::getTaskStatus, TaskStatusCode.TASK_CANCEL_MANUAL);;
List<WcsTask> tasks = wcsTaskMapper.selectList(queryWrapper);
for (int i = 0; i < tasks.size(); i++) {
//todo 任务完成/取消请求wms
WcsTaskHistory wcsTaskHistory = new WcsTaskHistory();
BeanUtils.copyProperties(tasks.get(i), wcsTaskHistory);
wcsTaskHistory.setFinishTime(LocalDateTime.now());
//向历史记录添加任务数据
wcsTaskHistoryMapper.insertWcsTaskHistory(wcsTaskHistory);
log.info("【添加到历任务记录】{}", JSON.toJSONString(wcsTaskHistory));
//移除实时任务表数据
wcsTaskMapper.deleteWcsTaskByTaskId(tasks.get(i).getTaskId());
log.info("【实时任务已完成】{}", JSON.toJSONString(tasks.get(i)));
}
}
}

View File

@@ -0,0 +1,94 @@
package com.ruoyi.schedule.scheduleTask;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ruoyi.common.Constant;
import com.ruoyi.common.TaskStatusCode;
import com.ruoyi.device.agv.domain.queryTaskStatus.TaskStatusData;
import com.ruoyi.schedule.task.domain.WcsTask;
import com.ruoyi.schedule.task.mapper.WcsTaskMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
import java.util.List;
/**
* 通过【查询任务状态】接口获取当前任务的任务状态(待执行/执行中/结束...)
*/
@Component
@Slf4j
public class StatusUpdate {
@Autowired
WcsTaskMapper wcsTaskMapper;
public void statusUpdate() {
//查询实时任务表获取所有【下发成功】任务
LambdaQueryWrapper<WcsTask> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(WcsTask::getTaskStatus, TaskStatusCode.TASK_SEND_SUCCESS);
List<WcsTask> tasks = wcsTaskMapper.selectList(queryWrapper);
//wcs本地任务轮询
for (int i = 0; i < tasks.size(); i++) {
//查询【设备任务状态】接口是否有该任务号已
HttpResponse response = HttpRequest.post(Constant.BASEURL + "/queryTaskStatus").execute();
List<TaskStatusData> deviceTasks = JSON.parseArray(response.body(), TaskStatusData.class);
//接口查询的AGV/CTU设备任务轮询
for (int j = 0; j < deviceTasks.size(); j++) {
//wcs任务记录的任务号与接口查询的任务号匹配
if (tasks.get(i).getTaskId() != deviceTasks.get(j).getTaskCode()) continue;
switch (deviceTasks.get(j).getTaskStatus()) {
case "1":
//【任务状态】更新为已创建
if (tasks.get(j).getTaskStatus() == TaskStatusCode.TASK_SEND_SUCCESS && tasks.get(j).getTaskStatus() != TaskStatusCode.TASK_CREATED) {
tasks.get(j).setTaskStatus(TaskStatusCode.TASK_CREATED);
wcsTaskMapper.updateWcsTask(tasks.get(i));
}
break;
case "2"://【任务状态】更新为执行中
if (tasks.get(j).getTaskStatus() == TaskStatusCode.TASK_CREATED && tasks.get(j).getTaskStatus() != TaskStatusCode.TASK_RUNNING) {
tasks.get(j).setTaskStatus(TaskStatusCode.TASK_RUNNING);
//更新【调度时间】
tasks.get(j).setScheduleTime(LocalDateTime.now());
wcsTaskMapper.updateWcsTask(tasks.get(i));
}
break;
case "5"://【任务状态】更新为已取消
if ((tasks.get(j).getTaskStatus() == TaskStatusCode.TASK_CREATED ||
tasks.get(j).getTaskStatus() == TaskStatusCode.TASK_RUNNING) &&
tasks.get(j).getTaskStatus() != TaskStatusCode.TASK_CANCEL) {
tasks.get(j).setTaskStatus(TaskStatusCode.TASK_CANCEL);
wcsTaskMapper.updateWcsTask(tasks.get(i));
}
break;
case "9"://【任务状态】更新为已结束
if (tasks.get(j).getTaskStatus() != TaskStatusCode.TASK_FINISH) {
tasks.get(j).setTaskStatus(TaskStatusCode.TASK_FINISH);
wcsTaskMapper.updateWcsTask(tasks.get(j));
}
break;
case "10"://【任务状态】更新为被中断
if (tasks.get(j).getTaskStatus() != TaskStatusCode.TASK_FINISH) {
tasks.get(j).setTaskStatus(TaskStatusCode.TASK_INTERUPTED);
wcsTaskMapper.updateWcsTask(tasks.get(j));
}
break;
}
}
}
}
}

View File

@@ -0,0 +1,16 @@
package com.ruoyi.schedule.scheduleTask;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
/**
* 用于处理没有正常执行或完成/取消的任务
*/
@Component
@Slf4j
public class TaskHandler {
}

View File

@@ -118,7 +118,7 @@ public class WcsTaskController extends BaseController
/**
* PTL拣选入口空---wms请求出库任务---生成wcs本地任务
* PTL拣选入口空---wms推送请求出库---生成wcs本地任务
* @param task
* @return
*/
@@ -137,14 +137,51 @@ public class WcsTaskController extends BaseController
LambdaQueryWrapper<WcsTask> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(WcsTask::getJobId, task.getJobId());
Long count= wcsTaskMapper.selectCount(wrapper);
//任务已存在---返回失败
if (count > 0) {
response.setCode(1);
response.setMessage("failed");
return response;
}
//初始化任务状态---待执行
task.setTaskStatus(TaskStatusCode.TASK_READY);
task.setCreateTime(LocalDateTime.now().toLocalTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
wcsTaskService.insertWcsTask(task);
return response;
}
/**
* PTL拣选出口扫描到到位料箱---wms推送请求入库---生成wcs本地任务
* @param task
* @return
*/
@PostMapping("/stockIn")
public ResponseBase stockIn(@RequestBody WcsTask task) {
log.info("【获取入库请求】" + JSON.toJSONString(task));
ResponseBase response = new ResponseBase();
response.setCode(0);
response.setMessage("success");
response.setData(JSON.toJSONString(task));
//todo 有无信息校验
//查询是否已经有该作业号的任务
LambdaQueryWrapper<WcsTask> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(WcsTask::getJobId, task.getJobId());
Long count= wcsTaskMapper.selectCount(wrapper);
//任务已存在---返回失败
if (count > 0) {
response.setCode(1);
response.setMessage("failed");
return response;
}
//初始化任务状态---待执行
task.setTaskStatus(TaskStatusCode.TASK_READY);
wcsTaskService.insertWcsTask(task);
return response;

View File

@@ -1,10 +1,11 @@
package com.ruoyi.schedule.task.domain;
import lombok.Data;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.core.domain.BaseEntity;
import org.springframework.data.annotation.Id;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
/**
* 实时任务对象 wcs_task
@@ -22,6 +23,7 @@ public class WcsTask
private String jobId;
/** wcs任务号 */
@Excel(name = "任务号")
private String taskId;
/** 任务类型 */
@@ -42,11 +44,15 @@ public class WcsTask
/** 生成时间 */
@Excel(name = "生成时间")
private String createTime;
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime createTime = LocalDateTime.now();
/** 调度时间 */
/**
* 调度时间
* 设备开始运行的时间
*/
@Excel(name = "调度时间")
private String scheduleTime;
private LocalDateTime scheduleTime;
/** 设备编号 */
@Excel(name = "设备编号")

View File

@@ -1,5 +1,6 @@
package com.ruoyi.schedule.task.service.impl;
import java.time.LocalDateTime;
import java.util.List;
import com.ruoyi.common.utils.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
@@ -65,7 +66,7 @@ public class WcsTaskServiceImpl implements IWcsTaskService
@Override
public int insertWcsTask(WcsTask wcsTask)
{
wcsTask.setCreateTime(DateUtils.getNowDate().toString());
wcsTask.setCreateTime(LocalDateTime.now());
return wcsTaskMapper.insertWcsTask(wcsTask);
}

View File

@@ -6,6 +6,8 @@ import org.apache.commons.lang3.builder.ToStringStyle;
import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.core.domain.BaseEntity;
import java.time.LocalDateTime;
/**
* 任务历史记录对象 wcs_task_history
*
@@ -43,11 +45,11 @@ public class WcsTaskHistory extends BaseEntity
/** 调度时间 */
@Excel(name = "调度时间")
private String scheduleTime;
private LocalDateTime scheduleTime;
/** 结束时间 */
@Excel(name = "结束时间")
private String finishTime;
private LocalDateTime finishTime;
/** 设备编号 */
@Excel(name = "设备编号")

View File

@@ -72,7 +72,7 @@ spring:
# 端口,默认为6379
port: 6379
# 数据库索引
database: 0
database: 1
# 密码
password: 123456
# 连接超时时间