package com.zy.asrs.task.handler;
|
|
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSONObject;
|
import com.baomidou.mybatisplus.mapper.EntityWrapper;
|
import com.zy.asrs.entity.Task;
|
import com.zy.asrs.entity.TaskLog;
|
import com.zy.asrs.entity.WrkMast;
|
import com.zy.asrs.mapper.BasStationMapper;
|
import com.zy.asrs.mapper.WrkMastMapper;
|
import com.zy.asrs.service.ApiLogService;
|
import com.zy.asrs.service.TaskLogService;
|
import com.zy.asrs.service.TaskService;
|
import com.zy.common.constant.ApiInterfaceConstant;
|
import com.zy.common.utils.HttpHandler;
|
import lombok.extern.slf4j.Slf4j;
|
import org.springframework.beans.BeanUtils;
|
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.stereotype.Service;
|
import org.springframework.transaction.annotation.Transactional;
|
|
import javax.annotation.Resource;
|
import java.util.ArrayList;
|
import java.util.Collections;
|
import java.util.List;
|
import java.util.stream.Collectors;
|
|
/**
|
* @author pang.jiabao
|
* @description AGV交互相关定时任务处理类
|
* @createDate 2025/11/18 14:42
|
*/
|
@Slf4j
|
@Service
|
public class AgvHandler {
|
|
@Resource
|
private WrkMastMapper wrkMastMapper;
|
|
@Resource
|
private ApiLogService apiLogService;
|
|
@Resource
|
private TaskService taskService;
|
|
@Resource
|
private TaskLogService taskLogService;
|
|
@Resource
|
private BasStationMapper basStationMapper;
|
|
@Value("${Agv.sendTask}")
|
private boolean agvSendTask;
|
|
/**
|
* 呼叫agv搬运
|
*/
|
public void callAgv(List<Task> taskList) {
|
|
if (!agvSendTask) {
|
return;
|
}
|
|
for (Task task : taskList) {
|
// 呼叫agv
|
String response = "";
|
boolean success = false;
|
String url = ApiInterfaceConstant.AGV_IP + ApiInterfaceConstant.AGV_CREATE_TASK_PATH;
|
String namespace = "";
|
switch (task.getIoType()) {
|
case 1:
|
case 10:
|
case 53:
|
case 57:
|
namespace = "入库";
|
break;
|
case 3:
|
namespace = "转移";
|
break;
|
case 101:
|
case 110:
|
case 103:
|
case 107:
|
namespace = "出库";
|
break;
|
default:
|
}
|
String body = getRequest(task,namespace);
|
try {
|
// 使用仙工M4接口
|
response = new HttpHandler.Builder()
|
.setUri(ApiInterfaceConstant.AGV_IP)
|
.setPath(ApiInterfaceConstant.AGV_CREATE_TASK_PATH)
|
.setJson(body)
|
.build()
|
.doPost();
|
JSONObject jsonObject = JSON.parseObject(response);
|
if (jsonObject.getInteger("code").equals(200)) {
|
success = true;
|
task.setWrkSts(8L);
|
taskService.updateById(task);
|
log.info(namespace + "呼叫agv搬运成功:{}", task.getId());
|
} else {
|
log.error(namespace + "呼叫agv搬运失败!!!url:{};request:{};response:{}", url, body, response);
|
}
|
} catch (Exception e) {
|
log.error(namespace + "呼叫agv搬运异常", e);
|
} finally {
|
try {
|
// 保存接口日志
|
apiLogService.save(
|
namespace + "呼叫agv搬运",
|
url,
|
null,
|
"127.0.0.1",
|
body,
|
response,
|
success
|
);
|
} catch (Exception e) {
|
log.error(namespace + "呼叫agv保存接口日志异常:", e);
|
}
|
}
|
}
|
}
|
|
/**
|
* 构造请求内容(仙工M4格式)
|
*/
|
private String getRequest(Task task, String nameSpace) {
|
JSONObject object = new JSONObject();
|
// taskId使用任务ID,格式:T + 任务ID
|
object.put("taskId", "T" + task.getId());
|
object.put("fromBin", task.getSourceStaNo());
|
object.put("toBin", task.getStaNo());
|
// robotGroup从invWh字段获取,如果没有则使用默认值
|
String robotGroup = task.getInvWh();
|
if (robotGroup == null || robotGroup.isEmpty()) {
|
robotGroup = "Group-001"; // 默认机器人组
|
}
|
object.put("robotGroup", robotGroup);
|
// kind根据任务类型映射
|
String kind = "";
|
switch (nameSpace) {
|
case "入库":
|
kind = "实托入库";
|
break;
|
case "出库":
|
kind = "实托出库";
|
break;
|
case "转移":
|
kind = "货物转运";
|
break;
|
default:
|
kind = "货物转运";
|
}
|
object.put("kind", kind);
|
return object.toJSONString();
|
}
|
|
/**
|
* 任务完成转历史 释放暂存点
|
*/
|
@Transactional(rollbackFor = Exception.class)
|
public void moveTaskToHistory(List<Task> taskList) {
|
|
// 写入历史表
|
for (Task task : taskList) {
|
TaskLog log = new TaskLog();
|
BeanUtils.copyProperties(task, log);
|
taskLogService.insert(log);
|
}
|
|
// 批量删除原任务
|
List<Long> taskIds = taskList.stream().map(Task::getId).collect(Collectors.toList());
|
taskService.delete(new EntityWrapper<Task>().in("id",taskIds));
|
|
// 批量更新暂存点状态
|
List<String> locOList = new ArrayList<>();
|
List<String> locFList = new ArrayList<>();
|
for (Task task : taskList) {
|
String sourceStaNo = task.getSourceStaNo();
|
String staNo = task.getStaNo();
|
if (task.getIoType() == 3) {
|
locOList.add(sourceStaNo);
|
locFList.add(staNo);
|
} else if (task.getIoType() < 100) {
|
locOList.add(sourceStaNo);
|
} else {
|
locFList.add(staNo);
|
}
|
}
|
|
if (!locOList.isEmpty()) {
|
basStationMapper.updateLocStsBatch(locOList, "O");
|
}
|
if (!locFList.isEmpty()) {
|
basStationMapper.updateLocStsBatch(locFList, "F");
|
}
|
|
log.info("agv任务档转历史成功:{}", taskIds);
|
}
|
|
/**
|
* 货物到达出库口,生成agv任务
|
*/
|
public void createAgvOutTasks(List<String> sites) {
|
|
// 获取到可用出库站点的任务
|
List<WrkMast> wrkMastList = wrkMastMapper.selectList(new EntityWrapper<WrkMast>().eq("call_agv", 1).in("sta_no",sites));
|
|
for(WrkMast wrkMast:wrkMastList) {
|
// todo 计算agv目标暂存位
|
int endSite = 2004;
|
|
// 插入agv任务
|
Task task = new Task(wrkMast.getWrkNo(), 7L, wrkMast.getIoType(), String.valueOf(wrkMast.getStaNo()), String.valueOf(endSite), null, wrkMast.getBarcode());
|
taskService.insert(task);
|
// 更新任务档agv搬运标识
|
wrkMast.setCallAgv(2);
|
wrkMastMapper.updateById(wrkMast);
|
|
// 更新暂存位状态 S.入库预约
|
basStationMapper.updateLocStsBatch( Collections.singletonList(String.valueOf(endSite)), "S");
|
}
|
}
|
|
/**
|
* 取消AGV任务(仙工M4接口)
|
* @param task 任务对象
|
* @return 是否成功
|
*/
|
public boolean cancelAgvTask(Task task) {
|
if (!agvSendTask) {
|
return false;
|
}
|
|
if (task == null || task.getId() == null) {
|
log.error("取消AGV任务失败:任务或任务ID为空");
|
return false;
|
}
|
|
String response = "";
|
boolean success = false;
|
String url = ApiInterfaceConstant.AGV_IP + ApiInterfaceConstant.AGV_CANCEL_TASK_PATH;
|
String namespace = "";
|
String kind = "";
|
|
// 根据任务类型确定kind和namespace
|
switch (task.getIoType()) {
|
case 1:
|
case 10:
|
case 53:
|
case 57:
|
namespace = "入库";
|
kind = "实托入库";
|
break;
|
case 3:
|
namespace = "转移";
|
kind = "货物转运";
|
break;
|
case 101:
|
case 110:
|
case 103:
|
case 107:
|
namespace = "出库";
|
kind = "实托出库";
|
break;
|
default:
|
kind = "货物转运";
|
}
|
|
// 构造取消任务请求
|
JSONObject cancelRequest = new JSONObject();
|
cancelRequest.put("taskId", "T" + task.getId());
|
cancelRequest.put("kind", kind);
|
String body = cancelRequest.toJSONString();
|
|
try {
|
response = new HttpHandler.Builder()
|
.setUri(ApiInterfaceConstant.AGV_IP)
|
.setPath(ApiInterfaceConstant.AGV_CANCEL_TASK_PATH)
|
.setJson(body)
|
.build()
|
.doPost();
|
|
JSONObject jsonObject = JSON.parseObject(response);
|
if (jsonObject.getInteger("code") != null && jsonObject.getInteger("code").equals(200)) {
|
success = true;
|
log.info(namespace + "取消AGV任务成功:{}", task.getId());
|
} else {
|
log.error(namespace + "取消AGV任务失败!!!url:{};request:{};response:{}", url, body, response);
|
}
|
} catch (Exception e) {
|
log.error(namespace + "取消AGV任务异常", e);
|
} finally {
|
try {
|
// 保存接口日志
|
apiLogService.save(
|
namespace + "取消AGV任务",
|
url,
|
null,
|
"127.0.0.1",
|
body,
|
response,
|
success
|
);
|
} catch (Exception e) {
|
log.error(namespace + "取消AGV任务保存接口日志异常:", e);
|
}
|
}
|
|
return success;
|
}
|
}
|