no message
parent
c1a20e1e2a
commit
3b2fbf9385
|
|
@ -4,7 +4,6 @@ import com.youchain.appupdate.request.*;
|
||||||
import com.youchain.appupdate.service.NioF3AppService;
|
import com.youchain.appupdate.service.NioF3AppService;
|
||||||
import com.youchain.basicdata.domain.Item;
|
import com.youchain.basicdata.domain.Item;
|
||||||
import com.youchain.basicdata.domain.Point;
|
import com.youchain.basicdata.domain.Point;
|
||||||
import com.youchain.basicdata.repository.ItemRepository;
|
|
||||||
import com.youchain.basicdata.service.ItemService;
|
import com.youchain.basicdata.service.ItemService;
|
||||||
import com.youchain.basicdata.service.PointService;
|
import com.youchain.basicdata.service.PointService;
|
||||||
import com.youchain.businessdata.domain.AgvTask;
|
import com.youchain.businessdata.domain.AgvTask;
|
||||||
|
|
@ -49,7 +48,7 @@ public class NioF3AppServiceImpl implements NioF3AppService {
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public void bindSmallItemPicking(BindSmall bindSmall) {
|
public void bindSmallItemPicking(BindSmall bindSmall) {
|
||||||
// 验证参数
|
// 验证参数
|
||||||
validateParams(bindSmall);
|
validateBindSmallParams(bindSmall);
|
||||||
|
|
||||||
// 验证Les任务
|
// 验证Les任务
|
||||||
List<Les> lesList = validateLes(bindSmall.getSrcPositionCode(), bindSmall.getOnlineNo());
|
List<Les> lesList = validateLes(bindSmall.getSrcPositionCode(), bindSmall.getOnlineNo());
|
||||||
|
|
@ -62,27 +61,28 @@ public class NioF3AppServiceImpl implements NioF3AppService {
|
||||||
AgvTask agvTask = createAgvTask(bindSmall.getSrcPositionCode(), lesIds, beatCode);
|
AgvTask agvTask = createAgvTask(bindSmall.getSrcPositionCode(), lesIds, beatCode);
|
||||||
|
|
||||||
// 下发任务
|
// 下发任务
|
||||||
kmReService.sendAgvTask(agvTask, kmReService.sendAgvTaskQYCJson(agvTask, bindSmall.getShooter(), null));
|
List<String> tugModels = Arrays.asList("modelA", "modelB");
|
||||||
|
kmReService.sendAgvTask(agvTask, kmReService.createTuggerJson(agvTask, tugModels));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 验证参数
|
* 验证参数
|
||||||
*
|
*
|
||||||
* @param smallRequest -> 参数
|
* @param bindSmall -> 参数
|
||||||
*/
|
*/
|
||||||
private void validateParams(BindSmall smallRequest) {
|
private void validateBindSmallParams(BindSmall bindSmall) {
|
||||||
if (StringUtils.isEmpty(smallRequest.getSrcPositionCode())) {
|
if (StringUtils.isEmpty(bindSmall.getSrcPositionCode())) {
|
||||||
throw new BadRequestException("起点必填");
|
throw new BadRequestException("起点必填");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (StringUtils.isEmpty(smallRequest.getOnlineNo())) {
|
if (StringUtils.isEmpty(bindSmall.getOnlineNo())) {
|
||||||
throw new BadRequestException("上线单号必填");
|
throw new BadRequestException("上线单号必填");
|
||||||
}
|
}
|
||||||
|
|
||||||
//验证起点
|
//验证起点
|
||||||
Point point = pointService.validatePoint(smallRequest.getSrcPositionCode());
|
Point point = pointService.validatePoint(bindSmall.getSrcPositionCode());
|
||||||
if (!BaseStatus.XJ_DFQ.equals(point.getType())) {
|
if (!BaseStatus.XJ_DFQ.equals(point.getType())) {
|
||||||
throw new BadRequestException(smallRequest.getSrcPositionCode() + "不属于小件待发区点位");
|
throw new BadRequestException(bindSmall.getSrcPositionCode() + "不属于小件待发区点位");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -101,7 +101,7 @@ public class NioF3AppServiceImpl implements NioF3AppService {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void validateAgvTask(String pointCode) {
|
private void validateAgvTask(String pointCode) {
|
||||||
Long taskCount = agvTaskService.findByStartSlotCode(pointCode, "MOVE", "TUGGER");
|
Long taskCount = agvTaskService.findByStartSlotCode(pointCode, "MOVE", "TUGGER_MOVE");
|
||||||
if (taskCount > 0) {
|
if (taskCount > 0) {
|
||||||
throw new BadRequestException(pointCode + "点位有任务,请勿重复下发");
|
throw new BadRequestException(pointCode + "点位有任务,请勿重复下发");
|
||||||
}
|
}
|
||||||
|
|
@ -124,7 +124,7 @@ public class NioF3AppServiceImpl implements NioF3AppService {
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public void bindLargeItemPicking(BindLarge bindLarge) {
|
public void bindLargeItemPicking(BindLarge bindLarge) {
|
||||||
//验证参数
|
//验证参数
|
||||||
validateParams(bindLarge);
|
validateBindLargeParams(bindLarge);
|
||||||
|
|
||||||
//获取所有扫描的料箱号
|
//获取所有扫描的料箱号
|
||||||
List<String> boxNos = bindLarge.getBoxAndDolly().stream().map(BoxAndDolly::getBoxNo).collect(Collectors.toList());
|
List<String> boxNos = bindLarge.getBoxAndDolly().stream().map(BoxAndDolly::getBoxNo).collect(Collectors.toList());
|
||||||
|
|
@ -146,14 +146,44 @@ public class NioF3AppServiceImpl implements NioF3AppService {
|
||||||
AgvTask agvTask = createAgvTask(bindLarge.getSrcPositionCode(), lesIds, beatCode);
|
AgvTask agvTask = createAgvTask(bindLarge.getSrcPositionCode(), lesIds, beatCode);
|
||||||
|
|
||||||
//下发任务
|
//下发任务
|
||||||
kmReService.sendAgvTask(agvTask, kmReService.sendAgvTaskQYCJson(agvTask, boxNos.size(), dollyList));
|
kmReService.sendAgvTask(agvTask, kmReService.createTuggerJson(agvTask, dollyList));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证参数
|
||||||
|
*
|
||||||
|
* @param bindLarge -> 参数
|
||||||
|
*/
|
||||||
|
private void validateBindLargeParams(BindLarge bindLarge) {
|
||||||
|
if (StringUtils.isEmpty(bindLarge.getSrcPositionCode())) {
|
||||||
|
throw new BadRequestException("起点必填");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bindLarge.getBoxAndDolly().isEmpty()) {
|
||||||
|
throw new BadRequestException("料箱和Dolly未扫描绑定");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (BoxAndDolly item : bindLarge.getBoxAndDolly()) {
|
||||||
|
if (StringUtils.isEmpty(item.getBoxNo())) {
|
||||||
|
throw new BadRequestException("料箱必填");
|
||||||
|
}
|
||||||
|
if (StringUtils.isEmpty(item.getDolly())) {
|
||||||
|
throw new BadRequestException("Dolly编号必填");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//验证起点
|
||||||
|
Point point = pointService.validatePoint(bindLarge.getSrcPositionCode());
|
||||||
|
if (!BaseStatus.DJ_DFQ.equals(point.getType())) {
|
||||||
|
throw new BadRequestException(bindLarge.getSrcPositionCode() + "不属于大件待发区点位");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public void bindLargeItemZyPicking(BindLargeZy bindLargeZy) {
|
public void bindLargeItemZyPicking(BindLargeZy bindLargeZy) {
|
||||||
//验证参数
|
//验证参数
|
||||||
validateParams(bindLargeZy);
|
validateBindLargeZyParams(bindLargeZy);
|
||||||
|
|
||||||
//获取所有扫描的料箱号;
|
//获取所有扫描的料箱号;
|
||||||
List<String> boxNos = bindLargeZy.getBoxAndDolly().stream().map(BoxAndDolly::getBoxNo).collect(Collectors.toList());
|
List<String> boxNos = bindLargeZy.getBoxAndDolly().stream().map(BoxAndDolly::getBoxNo).collect(Collectors.toList());
|
||||||
|
|
@ -169,6 +199,51 @@ public class NioF3AppServiceImpl implements NioF3AppService {
|
||||||
//获取目标点位
|
//获取目标点位
|
||||||
String beatCode = getBeatCode(lesList);
|
String beatCode = getBeatCode(lesList);
|
||||||
|
|
||||||
|
//获取专用dolly
|
||||||
|
List<String> dollyList = getDollyList(lesList);
|
||||||
|
|
||||||
|
//创建任务
|
||||||
|
AgvTask agvTask = createAgvTask(bindLargeZy.getSrcPositionCode(), lesIds, beatCode);
|
||||||
|
|
||||||
|
//下发任务
|
||||||
|
kmReService.sendAgvTask(agvTask, kmReService.createTuggerJson(agvTask, dollyList));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证参数
|
||||||
|
*
|
||||||
|
* @param bindLargeZy -> 参数
|
||||||
|
*/
|
||||||
|
private void validateBindLargeZyParams(BindLargeZy bindLargeZy) {
|
||||||
|
if (StringUtils.isEmpty(bindLargeZy.getSrcPositionCode())) {
|
||||||
|
throw new BadRequestException("起点必填");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bindLargeZy.getBoxAndDolly().isEmpty()) {
|
||||||
|
throw new BadRequestException("料箱未扫描绑定");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (BoxAndDolly item : bindLargeZy.getBoxAndDolly()) {
|
||||||
|
if (StringUtils.isEmpty(item.getBoxNo())) {
|
||||||
|
throw new BadRequestException("料箱必填");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//验证起点
|
||||||
|
Point point = pointService.validatePoint(bindLargeZy.getSrcPositionCode());
|
||||||
|
if (!BaseStatus.DJ_DFQ.equals(point.getType())) {
|
||||||
|
throw new BadRequestException(bindLargeZy.getSrcPositionCode() + "不属于大件待发区点位");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取专用dolly
|
||||||
|
*
|
||||||
|
* @param lesList -> 扫描的Les
|
||||||
|
* @return 专用dolly
|
||||||
|
*/
|
||||||
|
private List<String> getDollyList(List<Les> lesList) {
|
||||||
//获取物料
|
//获取物料
|
||||||
List<String> materialCodes = lesList.stream().map(Les::getMaterialCode).collect(Collectors.toList());
|
List<String> materialCodes = lesList.stream().map(Les::getMaterialCode).collect(Collectors.toList());
|
||||||
materialCodes = removeLastTwoCharsFromList(materialCodes);
|
materialCodes = removeLastTwoCharsFromList(materialCodes);
|
||||||
|
|
@ -186,14 +261,7 @@ public class NioF3AppServiceImpl implements NioF3AppService {
|
||||||
dollyList.add("00000");
|
dollyList.add("00000");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return dollyList;
|
||||||
//创建任务
|
|
||||||
AgvTask agvTask = createAgvTask(bindLargeZy.getSrcPositionCode(), lesIds, beatCode);
|
|
||||||
|
|
||||||
//下发任务
|
|
||||||
kmReService.sendAgvTask(agvTask, kmReService.sendAgvTaskQYCJson(agvTask, boxNos.size(), dollyList));
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -212,85 +280,27 @@ public class NioF3AppServiceImpl implements NioF3AppService {
|
||||||
* @param strings 零件号
|
* @param strings 零件号
|
||||||
* @return 零件号
|
* @return 零件号
|
||||||
*/
|
*/
|
||||||
public List<String> removeLastTwoCharsFromList(List<String> strings) {
|
private List<String> removeLastTwoCharsFromList(List<String> strings) {
|
||||||
return strings.stream()
|
return strings.stream()
|
||||||
.map(this::removeLastTwoChars)
|
.map(this::removeLastTwoChars)
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private AgvTask createAgvTask(String srcPositionCode, List<Long> lesIds, String beatCode) {
|
||||||
* 验证参数
|
|
||||||
*
|
|
||||||
* @param bindLargeZy -> 参数
|
|
||||||
*/
|
|
||||||
private void validateParams(BindLargeZy bindLargeZy) {
|
|
||||||
if (StringUtils.isEmpty(bindLargeZy.getSrcPositionCode())) {
|
|
||||||
throw new BadRequestException("起点必填");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bindLargeZy.getBoxAndDolly().isEmpty()) {
|
|
||||||
throw new BadRequestException("料箱未扫描绑定");
|
|
||||||
}
|
|
||||||
|
|
||||||
for (BoxAndDolly item : bindLargeZy.getBoxAndDolly()) {
|
|
||||||
if (item.getBoxNo() == null || item.getBoxNo().trim().isEmpty()) {
|
|
||||||
throw new BadRequestException("料箱必填");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//验证起点
|
|
||||||
Point point = pointService.validatePoint(bindLargeZy.getSrcPositionCode());
|
|
||||||
if (!BaseStatus.DJ_DFQ.equals(point.getType())) {
|
|
||||||
throw new BadRequestException(bindLargeZy.getSrcPositionCode() + "不属于大件待发区点位");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public AgvTask createAgvTask(String srcPositionCode, List<Long> lesIds, String beatCode) {
|
|
||||||
String lockKey = getLockKey(srcPositionCode);
|
String lockKey = getLockKey(srcPositionCode);
|
||||||
synchronized (lockKey) {
|
synchronized (lockKey) {
|
||||||
// 验证起点是否有Agv任务
|
// 验证起点是否有Agv任务
|
||||||
validateAgvTask(srcPositionCode);
|
validateAgvTask(srcPositionCode);
|
||||||
// 生成任务
|
// 生成任务
|
||||||
AgvTask agvTask = agvTaskService.createAgvTask(BizStatus.OPEN, null, srcPositionCode, beatCode, "TUGGER");
|
AgvTask agvTask = agvTaskService.createAgvTask(BizStatus.OPEN, null, srcPositionCode, beatCode, "TUGGER_MOVE");
|
||||||
// 绑定任务
|
// 绑定任务
|
||||||
bindLesAgvTask(agvTask.getId(), lesIds);
|
bindLesAgvTask(agvTask.getId(), lesIds);
|
||||||
return agvTask;
|
return agvTask;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 验证参数
|
|
||||||
*
|
|
||||||
* @param bindLarge -> 参数
|
|
||||||
*/
|
|
||||||
private void validateParams(BindLarge bindLarge) {
|
|
||||||
if (StringUtils.isEmpty(bindLarge.getSrcPositionCode())) {
|
|
||||||
throw new BadRequestException("起点必填");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bindLarge.getBoxAndDolly().isEmpty()) {
|
private void validateBoxNos(List<Les> lesList, List<String> boxNos) {
|
||||||
throw new BadRequestException("料箱和Dolly未扫描绑定");
|
|
||||||
}
|
|
||||||
|
|
||||||
for (BoxAndDolly item : bindLarge.getBoxAndDolly()) {
|
|
||||||
if (item.getBoxNo() == null || item.getBoxNo().trim().isEmpty()) {
|
|
||||||
throw new BadRequestException("料箱必填");
|
|
||||||
}
|
|
||||||
if (item.getDolly() == null || item.getDolly().trim().isEmpty()) {
|
|
||||||
throw new BadRequestException("Dolly编号必填");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//验证起点
|
|
||||||
Point point = pointService.validatePoint(bindLarge.getSrcPositionCode());
|
|
||||||
if (!BaseStatus.DJ_DFQ.equals(point.getType())) {
|
|
||||||
throw new BadRequestException(bindLarge.getSrcPositionCode() + "不属于大件待发区点位");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void validateBoxNos(List<Les> lesList, List<String> boxNos) {
|
|
||||||
// 1.检查料箱是否有重复
|
// 1.检查料箱是否有重复
|
||||||
Set<String> seen = new HashSet<>();
|
Set<String> seen = new HashSet<>();
|
||||||
Set<String> duplicates = new HashSet<>();
|
Set<String> duplicates = new HashSet<>();
|
||||||
|
|
|
||||||
|
|
@ -87,15 +87,12 @@ public class AgvTask extends BaseEntity implements Serializable {
|
||||||
|
|
||||||
@Column(name = "`job_type`",nullable = false)
|
@Column(name = "`job_type`",nullable = false)
|
||||||
@NotBlank
|
@NotBlank
|
||||||
@ApiModelProperty(value = "工作类型")
|
@ApiModelProperty(value = "工作类型;missionType")
|
||||||
/**
|
private String jobType;
|
||||||
* 01:料箱
|
|
||||||
*/
|
|
||||||
private String jobType="01";
|
|
||||||
|
|
||||||
@Column(name = "`job_priority`")
|
@Column(name = "`job_priority`")
|
||||||
@ApiModelProperty(value = "优先级")
|
@ApiModelProperty(value = "优先级")
|
||||||
private Integer jobPriority=1;
|
private Integer jobPriority;
|
||||||
|
|
||||||
@Column(name = "`job_priority_type`")
|
@Column(name = "`job_priority_type`")
|
||||||
@ApiModelProperty(value = "强制优先级")
|
@ApiModelProperty(value = "强制优先级")
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,243 @@
|
||||||
|
package com.youchain.businessdata.inputJson;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSONArray;
|
||||||
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
import com.youchain.basicdata.domain.Point;
|
||||||
|
import com.youchain.basicdata.service.PointService;
|
||||||
|
import com.youchain.businessdata.domain.AgvTask;
|
||||||
|
import com.youchain.utils.BizStatus;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class AgvTaskJsonBuilder {
|
||||||
|
// 常量定义
|
||||||
|
private static final String ORG_ID_WMS = "WMS";//组织
|
||||||
|
private static final String ORG_ID_WCS = "WCS";//组织
|
||||||
|
private static final String PRIORITY = "1";//优先级
|
||||||
|
private static final String NODE_POINT = "NODE_POINT";//节点类型
|
||||||
|
private static final String NODE_SLOT = "NODE_SLOT";//节点类型
|
||||||
|
private static final String PASS_STRATEGY_AUTO = "AUTO";//移动策略
|
||||||
|
private static final String PASS_STRATEGY_MANUAL = "MANUAL";//移动策略
|
||||||
|
|
||||||
|
private final PointService pointService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建基础AGV任务JSON对象
|
||||||
|
*/
|
||||||
|
private JSONObject createBaseAgvTaskJson(AgvTask agvTask, String orgId, String missionType, String robotType) {
|
||||||
|
JSONObject jsonObject = new JSONObject(true);
|
||||||
|
jsonObject.put("orgId", orgId);
|
||||||
|
jsonObject.put("requestId", String.valueOf(System.currentTimeMillis()));
|
||||||
|
jsonObject.put("missionCode", agvTask.getId());
|
||||||
|
jsonObject.put("missionType", missionType);
|
||||||
|
jsonObject.put("viewBoardType", "");
|
||||||
|
jsonObject.put("robotType", robotType);
|
||||||
|
jsonObject.put("priority", PRIORITY);
|
||||||
|
return jsonObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建叉车任务JSON
|
||||||
|
*/
|
||||||
|
public String createForkMissionJson(AgvTask agvTask) {
|
||||||
|
//基础对象
|
||||||
|
JSONObject jsonObject = createBaseAgvTaskJson(agvTask, ORG_ID_WMS, agvTask.getJobType(), "FORKLIFT");
|
||||||
|
jsonObject.put("containerCode", agvTask.getStockCode());
|
||||||
|
jsonObject.put("robotId", "");
|
||||||
|
|
||||||
|
//创建json数组
|
||||||
|
JSONArray missionDataArray = new JSONArray();
|
||||||
|
|
||||||
|
//根据任务类型取节点类型
|
||||||
|
boolean isPickTask = BizStatus.PICK.equals(agvTask.getType());
|
||||||
|
String startNodeType = isPickTask ? NODE_SLOT : NODE_POINT;
|
||||||
|
String endNodeType = isPickTask ? NODE_POINT : NODE_SLOT;
|
||||||
|
|
||||||
|
//起点
|
||||||
|
missionDataArray.add(createForkMissionNode(1, agvTask.getStartSlotCode(), startNodeType));
|
||||||
|
|
||||||
|
//终点
|
||||||
|
missionDataArray.add(createForkMissionNode(2, agvTask.getEndSlotCode(), endNodeType));
|
||||||
|
|
||||||
|
//添加任务数据
|
||||||
|
jsonObject.put("missionData", missionDataArray);
|
||||||
|
return jsonObject.toJSONString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建叉车任务数据节点
|
||||||
|
*/
|
||||||
|
private JSONObject createForkMissionNode(int sequence, String position, String nodeType) {
|
||||||
|
JSONObject node = new JSONObject(true);
|
||||||
|
node.put("sequence", sequence);
|
||||||
|
node.put("position", position);
|
||||||
|
node.put("nodeType", nodeType);
|
||||||
|
node.put("stackNumber", 0);
|
||||||
|
node.put("actionConfirm", false);
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建货架任务JSON
|
||||||
|
*/
|
||||||
|
public String createRackMissionJson(AgvTask agvTask) {
|
||||||
|
//基础对象
|
||||||
|
JSONObject jsonObject = createBaseAgvTaskJson(agvTask, ORG_ID_WMS, agvTask.getJobType(), "LIFT");
|
||||||
|
|
||||||
|
//创建json数组
|
||||||
|
JSONArray missionDataArray = new JSONArray();
|
||||||
|
|
||||||
|
//创建任务数据
|
||||||
|
missionDataArray.add(createRackMissionNode(agvTask));
|
||||||
|
|
||||||
|
//添加任务数据
|
||||||
|
jsonObject.put("missionData", missionDataArray);
|
||||||
|
return jsonObject.toJSONString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建货架任务数据节点
|
||||||
|
*/
|
||||||
|
private JSONObject createRackMissionNode(AgvTask agvTask) {
|
||||||
|
JSONObject node = new JSONObject(true);
|
||||||
|
node.put("sequence", 1);//序号
|
||||||
|
node.put("containerCode", agvTask.getStockCode());//容器
|
||||||
|
node.put("startPosition", agvTask.getStartSlotCode());//点位
|
||||||
|
node.put("startPositionType", "NODE_POINT");//
|
||||||
|
node.put("endPosition", agvTask.getEndSlotCode());//点位
|
||||||
|
node.put("endPositionType", "NODE_POINT");//
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建滚筒任务JSON
|
||||||
|
*/
|
||||||
|
public String createRollerJson(AgvTask agvTask) {
|
||||||
|
//基础对象
|
||||||
|
JSONObject jsonObject = createBaseAgvTaskJson(agvTask, ORG_ID_WMS, agvTask.getJobType(), "ROLLER");
|
||||||
|
jsonObject.put("lockRobotAfterFinish", false);
|
||||||
|
|
||||||
|
//创建json数组
|
||||||
|
JSONArray missionDataArray = new JSONArray();
|
||||||
|
|
||||||
|
//起点
|
||||||
|
missionDataArray.add(createRollerNode(1, agvTask.getStartSlotCode(), "ROLLER_RECEIVE", agvTask.getStartSlotCode(), true, "AUTO"));
|
||||||
|
|
||||||
|
//途径点
|
||||||
|
missionDataArray.add(createRollerNode(2, "FX001", "", "", false, "MANUAL"));
|
||||||
|
|
||||||
|
//终点
|
||||||
|
missionDataArray.add(createRollerNode(3, agvTask.getEndSlotCode(), "ROLLER_SEND", agvTask.getEndSlotCode(), true, "AUTO"));
|
||||||
|
|
||||||
|
//添加任务数据
|
||||||
|
jsonObject.put("missionData", missionDataArray);
|
||||||
|
return jsonObject.toJSONString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建滚筒任务数据节点
|
||||||
|
*/
|
||||||
|
private JSONObject createRollerNode(int sequence, String position, String actionType, String deviceCode, boolean actionConfirm, String passStrategy) {
|
||||||
|
JSONObject node = new JSONObject(true);
|
||||||
|
node.put("sequence", sequence);
|
||||||
|
node.put("position", position);
|
||||||
|
node.put("type", NODE_POINT);
|
||||||
|
node.put("actionType", actionType);
|
||||||
|
node.put("binCode", "");
|
||||||
|
node.put("rollerLevel", 1);
|
||||||
|
node.put("deviceCode", deviceCode);
|
||||||
|
node.put("actionConfirm", actionConfirm);
|
||||||
|
node.put("passStrategy", passStrategy);
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建牵引车任务JSON
|
||||||
|
*/
|
||||||
|
public String createTuggerJson(AgvTask agvTask, List<String> tugModels) {
|
||||||
|
JSONObject jsonObject = createBaseAgvTaskJson(agvTask, ORG_ID_WCS, agvTask.getJobType(), "TUGGER");
|
||||||
|
jsonObject.put("templateCode", "");
|
||||||
|
jsonObject.put("lockRobotAfterFinish", false);
|
||||||
|
jsonObject.put("unlockRobotId", "");
|
||||||
|
jsonObject.put("unlockMissionCode", "");
|
||||||
|
|
||||||
|
// 根据区域调整参数
|
||||||
|
Point point = pointService.validatePoint(agvTask.getStartSlotCode());
|
||||||
|
|
||||||
|
//创建json数组
|
||||||
|
JSONArray missionDataArray = new JSONArray();
|
||||||
|
|
||||||
|
// 起点
|
||||||
|
missionDataArray.add(createTuggerStartNode(agvTask.getStartSlotCode(), tugModels));
|
||||||
|
|
||||||
|
//途径点
|
||||||
|
List<String> stations = parseStations(agvTask.getEndSlotCode());
|
||||||
|
for (int i = 0; i < stations.size(); i++) {
|
||||||
|
missionDataArray.add(createTuggerWayNode(i + 2, stations.get(i)));
|
||||||
|
}
|
||||||
|
|
||||||
|
//终点
|
||||||
|
missionDataArray.add(createTuggerEndNode(stations.size() + 2, point.getBeatCode()));
|
||||||
|
|
||||||
|
jsonObject.put("missionData", missionDataArray);
|
||||||
|
return jsonObject.toJSONString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建牵引车任务起点数据节点
|
||||||
|
*/
|
||||||
|
private JSONObject createTuggerStartNode(String position, List<String> tugModels) {
|
||||||
|
JSONObject node = new JSONObject(true);
|
||||||
|
node.put("sequence", 1);
|
||||||
|
node.put("type", NODE_POINT);
|
||||||
|
node.put("position", position);
|
||||||
|
node.put("actionType", "TUGGER_ATTACH");
|
||||||
|
node.put("tugCount", tugModels.size());
|
||||||
|
node.put("passStrategy", PASS_STRATEGY_AUTO);
|
||||||
|
node.put("tugModels", tugModels);
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建牵引车任务途径点节点
|
||||||
|
*/
|
||||||
|
private JSONObject createTuggerWayNode(int sequence, String position) {
|
||||||
|
JSONObject node = new JSONObject(true);
|
||||||
|
node.put("sequence", sequence);
|
||||||
|
node.put("type", NODE_POINT);
|
||||||
|
node.put("position", position);
|
||||||
|
node.put("passStrategy", PASS_STRATEGY_MANUAL);
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建牵引车任务终点节点
|
||||||
|
*/
|
||||||
|
private JSONObject createTuggerEndNode(int sequence, String position) {
|
||||||
|
JSONObject node = new JSONObject(true);
|
||||||
|
node.put("sequence", sequence);
|
||||||
|
node.put("type", NODE_POINT);
|
||||||
|
node.put("position", position);
|
||||||
|
node.put("actionType", "TUGGER_DETACH");
|
||||||
|
node.put("passStrategy", PASS_STRATEGY_AUTO);
|
||||||
|
node.put("waitingMillis", 0);
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解析站点字符串
|
||||||
|
*/
|
||||||
|
private List<String> parseStations(String stationString) {
|
||||||
|
return Arrays.stream(stationString.split(","))
|
||||||
|
.map(String::trim)
|
||||||
|
.filter(s -> !s.isEmpty())
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -40,10 +40,6 @@ public interface AgvTaskRepository extends JpaRepository<AgvTask, Long>, JpaSpec
|
||||||
@Lock(LockModeType.PESSIMISTIC_WRITE)
|
@Lock(LockModeType.PESSIMISTIC_WRITE)
|
||||||
Long findByStartSlotCode(String startSlotCode, String type, String jobType);
|
Long findByStartSlotCode(String startSlotCode, String type, String jobType);
|
||||||
|
|
||||||
|
@Query(value = "from AgvTask agv where agv.slotCode=:slotCode and agv.type=:type and agv.jobType=:jobType and agv.status='ARRIVED' ")
|
||||||
@Query(value = "select count(agv.id) from AgvTask agv where agv.endSlotCode=:endSlotCode and agv.type=:type and agv.jobType=:jobType and agv.status in ('OPEN','ATCALL','UP_CONTAINER') ")
|
AgvTask findBySlotCode(String slotCode,String type, String jobType);
|
||||||
Long findByEndSlotCode(String endSlotCode, String type, String jobType);
|
|
||||||
|
|
||||||
@Query(value = "from AgvTask agv where agv.slotCode=:slotCode and agv.type='MOVE' and agv.jobType='TUGGER' and agv.status='ARRIVED' ")
|
|
||||||
AgvTask findBySlotCode(String slotCode);
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,6 @@
|
||||||
*/
|
*/
|
||||||
package com.youchain.businessdata.service;
|
package com.youchain.businessdata.service;
|
||||||
|
|
||||||
import com.youchain.basicdata.domain.Point;
|
|
||||||
import com.youchain.basicdata.domain.Stock;
|
import com.youchain.basicdata.domain.Stock;
|
||||||
import com.youchain.businessdata.domain.AgvTask;
|
import com.youchain.businessdata.domain.AgvTask;
|
||||||
import com.youchain.businessdata.service.dto.AgvTaskDto;
|
import com.youchain.businessdata.service.dto.AgvTaskDto;
|
||||||
|
|
@ -93,13 +92,14 @@ public interface AgvTaskService {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建agvTask任务
|
* 创建agvTask任务
|
||||||
* @param bizStatus 状态
|
*
|
||||||
* @param stock 容器
|
* @param bizStatus 状态
|
||||||
|
* @param stock 容器
|
||||||
* @param srcPointCode 起点
|
* @param srcPointCode 起点
|
||||||
* @param endPointCode 终点
|
* @param endPointCode 终点
|
||||||
* @param jobType 任务类型
|
* @param jobType 任务类型
|
||||||
*/
|
*/
|
||||||
AgvTask createAgvTask(String bizStatus, Stock stock, String srcPointCode, String endPointCode,String jobType);
|
AgvTask createAgvTask(String bizStatus, Stock stock, String srcPointCode, String endPointCode, String jobType);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据容器查询任务
|
* 根据容器查询任务
|
||||||
|
|
@ -117,20 +117,14 @@ public interface AgvTaskService {
|
||||||
*/
|
*/
|
||||||
Long findByStartSlotCode(String startSlotCode, String type, String jobType);
|
Long findByStartSlotCode(String startSlotCode, String type, String jobType);
|
||||||
|
|
||||||
/**
|
|
||||||
* 根据终点查询是否有重复任务
|
|
||||||
*
|
|
||||||
* @param endSlotCode 点位
|
|
||||||
* @param type 任务类型
|
|
||||||
* @param jobType 作业类型
|
|
||||||
*/
|
|
||||||
Boolean findByEndSlotCode(String endSlotCode, String type, String jobType);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据途径点找到对应任务
|
* 根据途径点找到对应任务
|
||||||
|
*
|
||||||
* @param slotCode 途径点
|
* @param slotCode 途径点
|
||||||
* @return
|
* @param type 任务类型
|
||||||
|
* @param jobType 作业类型
|
||||||
|
* @return AgvTask
|
||||||
*/
|
*/
|
||||||
AgvTask findBySlotCode(String slotCode);
|
AgvTask findBySlotCode(String slotCode, String type, String jobType);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,7 @@ public interface KMReService {
|
||||||
*
|
*
|
||||||
* @param agvTask 任务
|
* @param agvTask 任务
|
||||||
*/
|
*/
|
||||||
String sendAgvTaskCcJson(AgvTask agvTask);
|
String createForkMissionJson(AgvTask agvTask);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -58,23 +58,22 @@ public interface KMReService {
|
||||||
*
|
*
|
||||||
* @param agvTask 任务
|
* @param agvTask 任务
|
||||||
*/
|
*/
|
||||||
String sendAgvTaskHjJson(AgvTask agvTask);
|
String createRackMissionJson(AgvTask agvTask);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 下发agv滚筒任务JSON
|
* 下发agv滚筒任务JSON
|
||||||
*
|
*
|
||||||
* @param agvTask 任务
|
* @param agvTask 任务
|
||||||
*/
|
*/
|
||||||
String sendAgvTaskGtJson(AgvTask agvTask);
|
String createRollerJson(AgvTask agvTask);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 下发agv牵引车任务JSON
|
* 下发agv牵引车任务JSON
|
||||||
*
|
*
|
||||||
* @param agvTask 任务
|
* @param agvTask 任务
|
||||||
* @param tugCount 牵引车数量
|
|
||||||
* @param tugModels 牵引车型号
|
* @param tugModels 牵引车型号
|
||||||
*/
|
*/
|
||||||
String sendAgvTaskQYCJson(AgvTask agvTask, int tugCount, List<String> tugModels);
|
String createTuggerJson(AgvTask agvTask, List<String> tugModels);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 下发agv任务
|
* 下发agv任务
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,9 @@ public class LesDto {
|
||||||
//终点类型
|
//终点类型
|
||||||
private String dstType;
|
private String dstType;
|
||||||
|
|
||||||
|
//响应报文
|
||||||
|
private String repMessage;
|
||||||
|
|
||||||
/** 创建时间 */
|
/** 创建时间 */
|
||||||
private Timestamp createTime;
|
private Timestamp createTime;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,6 @@ package com.youchain.businessdata.service.impl;
|
||||||
import com.youchain.basicdata.domain.Stock;
|
import com.youchain.basicdata.domain.Stock;
|
||||||
import com.youchain.businessdata.domain.*;
|
import com.youchain.businessdata.domain.*;
|
||||||
import com.youchain.businessdata.service.*;
|
import com.youchain.businessdata.service.*;
|
||||||
import com.youchain.exception.BadRequestException;
|
|
||||||
import com.youchain.utils.*;
|
import com.youchain.utils.*;
|
||||||
import com.youchain.businessdata.repository.AgvTaskRepository;
|
import com.youchain.businessdata.repository.AgvTaskRepository;
|
||||||
import com.youchain.businessdata.service.dto.AgvTaskDto;
|
import com.youchain.businessdata.service.dto.AgvTaskDto;
|
||||||
|
|
@ -149,13 +148,8 @@ public class AgvTaskServiceImpl implements AgvTaskService {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Boolean findByEndSlotCode(String endSlotCode, String type, String jobType) {
|
public AgvTask findBySlotCode(String slotCode, String type, String jobType) {
|
||||||
return agvTaskRepository.findByEndSlotCode(endSlotCode, type, jobType)>0;
|
return agvTaskRepository.findBySlotCode(slotCode, type, jobType);
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public AgvTask findBySlotCode(String slotCode) {
|
|
||||||
return agvTaskRepository.findBySlotCode(slotCode);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,24 +1,17 @@
|
||||||
package com.youchain.businessdata.service.impl;
|
package com.youchain.businessdata.service.impl;
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSON;
|
||||||
import com.alibaba.fastjson.JSONArray;
|
|
||||||
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson.JSONObject;
|
||||||
import com.youchain.appupdate.request.BoxAndDolly;
|
|
||||||
import com.youchain.basicdata.domain.Point;
|
import com.youchain.basicdata.domain.Point;
|
||||||
import com.youchain.basicdata.domain.Stock;
|
import com.youchain.basicdata.domain.Stock;
|
||||||
import com.youchain.basicdata.service.PointService;
|
import com.youchain.basicdata.service.PointService;
|
||||||
import com.youchain.basicdata.service.StockService;
|
import com.youchain.basicdata.service.StockService;
|
||||||
import com.youchain.businessdata.domain.AgvTask;
|
import com.youchain.businessdata.domain.AgvTask;
|
||||||
import com.youchain.businessdata.domain.Les;
|
import com.youchain.businessdata.inputJson.AgvTaskJsonBuilder;
|
||||||
import com.youchain.businessdata.domain.Task;
|
|
||||||
import com.youchain.businessdata.inputJson.Dolly;
|
import com.youchain.businessdata.inputJson.Dolly;
|
||||||
import com.youchain.businessdata.inputJson.UpdateTuggerTrailerInfo;
|
import com.youchain.businessdata.inputJson.UpdateTuggerTrailerInfo;
|
||||||
import com.youchain.businessdata.service.*;
|
import com.youchain.businessdata.service.*;
|
||||||
import com.youchain.config.SignConfig;
|
|
||||||
import com.youchain.exception.BadRequestException;
|
import com.youchain.exception.BadRequestException;
|
||||||
import com.youchain.modules.quartz.utils.TimeNumberUtils;
|
|
||||||
import com.youchain.modules.system.domain.Dict;
|
|
||||||
import com.youchain.modules.system.repository.DictRepository;
|
|
||||||
import com.youchain.modules.system.service.DictService;
|
import com.youchain.modules.system.service.DictService;
|
||||||
import com.youchain.utils.*;
|
import com.youchain.utils.*;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
@ -27,7 +20,6 @@ import org.apache.commons.collections4.CollectionUtils;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
import java.sql.Array;
|
|
||||||
import java.sql.Timestamp;
|
import java.sql.Timestamp;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
@ -41,6 +33,7 @@ public class KMReServiceImpl implements KMReService {
|
||||||
private final PointService pointService;
|
private final PointService pointService;
|
||||||
private final AgvTaskService agvTaskService;
|
private final AgvTaskService agvTaskService;
|
||||||
private final LesService lesService;
|
private final LesService lesService;
|
||||||
|
private final AgvTaskJsonBuilder agvTaskJsonBuilder;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -169,242 +162,51 @@ public class KMReServiceImpl implements KMReService {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 叉车任务Json
|
* 叉车任务Json
|
||||||
*
|
*
|
||||||
* @param agvTasks 任务
|
* @param agvTask 任务
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public String sendAgvTaskCcJson(AgvTask agvTasks) {
|
public String createForkMissionJson(AgvTask agvTask) {
|
||||||
|
return agvTaskJsonBuilder.createForkMissionJson(agvTask);
|
||||||
JSONObject jsonObject = new JSONObject(true);
|
|
||||||
String requestId = TimeNumberUtils.getCcCode();
|
|
||||||
Map<String, Object> objMap = new LinkedHashMap<>();
|
|
||||||
objMap.put("orgId", "KUKA");//库存组织 ID
|
|
||||||
objMap.put("requestId", requestId);//请求 id
|
|
||||||
objMap.put("missionCode", agvTasks.getId());//任务编号
|
|
||||||
objMap.put("missionType", agvTasks.getJobType());//货 架 ( 托 盘 ) 移动 RACK_MOVE
|
|
||||||
objMap.put("viewBoardType", "");//
|
|
||||||
objMap.put("containerCode", agvTasks.getStockCode());//
|
|
||||||
objMap.put("robotType", "FORKLIFT");//机器人功能类型
|
|
||||||
objMap.put("robotId", "");//机器人编号
|
|
||||||
objMap.put("priority", "1");//数值越小,优先级越高,默认是 1
|
|
||||||
JSONArray missionDataArray = new JSONArray();
|
|
||||||
JSONObject missionDataObj = new JSONObject(true);
|
|
||||||
Map<String, Object> missionDataMap = new LinkedHashMap<>();
|
|
||||||
missionDataMap.put("sequence", 1);//序号
|
|
||||||
missionDataMap.put("position", agvTasks.getStartSlotCode());//点位
|
|
||||||
String nodeType = "NODE_POINT";
|
|
||||||
if (BizStatus.PICK.equals(agvTasks.getType())) {
|
|
||||||
nodeType = "NODE_SLOT";
|
|
||||||
}
|
|
||||||
missionDataMap.put("nodeType", nodeType);//
|
|
||||||
missionDataMap.put("stackNumber", 0);
|
|
||||||
missionDataMap.put("actionConfirm", false);
|
|
||||||
missionDataObj.putAll(missionDataMap);
|
|
||||||
missionDataArray.add(missionDataObj);
|
|
||||||
|
|
||||||
JSONObject missionDataObj2 = new JSONObject(new LinkedHashMap<>());
|
|
||||||
Map<String, Object> missionDataMap2 = new LinkedHashMap<>();
|
|
||||||
missionDataMap2.put("sequence", 2);//序号
|
|
||||||
missionDataMap2.put("position", agvTasks.getEndSlotCode());//目标点
|
|
||||||
String nodeType2 = "NODE_SLOT";
|
|
||||||
if (BizStatus.PICK.equals(agvTasks.getType())) {
|
|
||||||
nodeType2 = "NODE_POINT";
|
|
||||||
}
|
|
||||||
missionDataMap2.put("nodeType", nodeType2);//
|
|
||||||
missionDataMap2.put("stackNumber", 0);
|
|
||||||
missionDataMap2.put("actionConfirm", false);
|
|
||||||
missionDataObj2.putAll(missionDataMap2);
|
|
||||||
missionDataArray.add(missionDataObj2);
|
|
||||||
|
|
||||||
objMap.put("missionData", missionDataArray);
|
|
||||||
jsonObject.putAll(objMap);
|
|
||||||
return jsonObject.toJSONString();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 货架任务Json
|
* 货架任务Json
|
||||||
*
|
*
|
||||||
* @param agvTasks 任务
|
* @param agvTask 任务
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public String sendAgvTaskHjJson(AgvTask agvTasks) {
|
public String createRackMissionJson(AgvTask agvTask) {
|
||||||
JSONObject jsonObject = new JSONObject(true);
|
return agvTaskJsonBuilder.createRackMissionJson(agvTask);
|
||||||
String requestId = TimeNumberUtils.getHjCode();
|
|
||||||
Map<String, Object> objMap = new LinkedHashMap<>();
|
|
||||||
objMap.put("orgId", "KUKA");//库存组织 ID
|
|
||||||
objMap.put("requestId", requestId);//请求 id
|
|
||||||
objMap.put("missionCode", agvTasks.getId());//任务编号
|
|
||||||
objMap.put("missionType", agvTasks.getJobType());//货 架 ( 托 盘 ) 移动 RACK_MOVE
|
|
||||||
objMap.put("viewBoardType", "");//IDENTIFY_REQUIRE
|
|
||||||
objMap.put("robotType", "LIFT");//机器人功能类型
|
|
||||||
objMap.put("priority", "1");//数值越小,优先级越高,默认是 1
|
|
||||||
JSONArray missionDataArray = new JSONArray();
|
|
||||||
JSONObject missionDataObj = new JSONObject(true);
|
|
||||||
Map<String, Object> missionDataMap = new LinkedHashMap<>();
|
|
||||||
missionDataMap.put("sequence", 1);//序号
|
|
||||||
missionDataMap.put("containerCode", agvTasks.getStockCode());//容器
|
|
||||||
missionDataMap.put("startPosition", agvTasks.getStartSlotCode());//点位
|
|
||||||
missionDataMap.put("startPositionType", "NODE_POINT");//
|
|
||||||
missionDataMap.put("endPosition", agvTasks.getEndSlotCode());//点位
|
|
||||||
missionDataMap.put("endPositionType", "NODE_POINT");//
|
|
||||||
missionDataObj.putAll(missionDataMap);
|
|
||||||
missionDataArray.add(missionDataObj);
|
|
||||||
|
|
||||||
objMap.put("missionData", missionDataArray);
|
|
||||||
jsonObject.putAll(objMap);
|
|
||||||
return jsonObject.toJSONString();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String sendAgvTaskGtJson(AgvTask agvTask) {
|
public String createRollerJson(AgvTask agvTask) {
|
||||||
JSONObject jsonObject = new JSONObject(true);
|
return agvTaskJsonBuilder.createRollerJson(agvTask);
|
||||||
String requestId = TimeNumberUtils.getGTTaskCode();
|
|
||||||
Map<String, Object> objMap = new LinkedHashMap<>();
|
|
||||||
objMap.put("orgId", "KUKA");//库存组织 ID(或工厂代码,供应商代码)
|
|
||||||
objMap.put("requestId", requestId);//请求 id
|
|
||||||
objMap.put("missionCode", agvTask.getId());//任务编号
|
|
||||||
objMap.put("missionType", "ROLLER_MOVE");//任务类型 :滚筒
|
|
||||||
objMap.put("viewBoardType", "");//上视识别类型:
|
|
||||||
objMap.put("robotType", "ROLLER");
|
|
||||||
objMap.put("priority", "1");
|
|
||||||
objMap.put("lockRobotAfterFinish", false);
|
|
||||||
JSONArray missionDataArray = new JSONArray();
|
|
||||||
|
|
||||||
JSONObject missionDataObj = new JSONObject(true);
|
|
||||||
Map<String, Object> missionDataMap = new LinkedHashMap<>();
|
|
||||||
missionDataMap.put("sequence", 1);//序号
|
|
||||||
missionDataMap.put("position", agvTask.getStartSlotCode());//起点
|
|
||||||
missionDataMap.put("type", "NODE_POINT");//
|
|
||||||
missionDataMap.put("actionType", "ROLLER_RECEIVE");//
|
|
||||||
missionDataMap.put("binCode", "");//容器
|
|
||||||
missionDataMap.put("rollerLevel", 1);//
|
|
||||||
missionDataMap.put("deviceCode", agvTask.getStartSlotCode());//设备编号
|
|
||||||
missionDataMap.put("actionConfirm", true);//
|
|
||||||
missionDataMap.put("passStrategy", "AUTO");//
|
|
||||||
missionDataObj.putAll(missionDataMap);
|
|
||||||
missionDataArray.add(missionDataObj);
|
|
||||||
|
|
||||||
JSONObject missionDataObj2 = new JSONObject(true);
|
|
||||||
Map<String, Object> missionDataMap2 = new LinkedHashMap<>();
|
|
||||||
missionDataMap2.put("sequence", 2);//序号
|
|
||||||
missionDataMap2.put("position", "FX001");//中转点
|
|
||||||
missionDataMap2.put("type", "NODE_POINT");//
|
|
||||||
missionDataMap2.put("actionType", "");//
|
|
||||||
missionDataMap2.put("binCode", "");//容器
|
|
||||||
missionDataMap2.put("rollerLevel", 1);//
|
|
||||||
missionDataMap2.put("deviceCode", "");//
|
|
||||||
missionDataMap2.put("actionConfirm", false);//
|
|
||||||
missionDataMap2.put("passStrategy", "MANUAL");//
|
|
||||||
missionDataObj2.putAll(missionDataMap2);
|
|
||||||
missionDataArray.add(missionDataObj2);
|
|
||||||
|
|
||||||
JSONObject missionDataObj3 = new JSONObject(true);
|
|
||||||
Map<String, Object> missionDataMap3 = new LinkedHashMap<>();
|
|
||||||
missionDataMap3.put("sequence", 3);//序号
|
|
||||||
missionDataMap3.put("position", agvTask.getEndSlotCode());//终点
|
|
||||||
missionDataMap3.put("type", "NODE_POINT");//
|
|
||||||
missionDataMap3.put("actionType", "ROLLER_SEND");//
|
|
||||||
missionDataMap3.put("binCode", "");//容器
|
|
||||||
missionDataMap3.put("rollerLevel", 1);//
|
|
||||||
missionDataMap3.put("deviceCode", agvTask.getEndSlotCode());//终点
|
|
||||||
missionDataMap3.put("actionConfirm", true);//
|
|
||||||
missionDataMap3.put("passStrategy", "AUTO");//
|
|
||||||
missionDataObj3.putAll(missionDataMap3);
|
|
||||||
missionDataArray.add(missionDataObj3);
|
|
||||||
|
|
||||||
objMap.put("missionData", missionDataArray);
|
|
||||||
jsonObject.putAll(objMap);
|
|
||||||
return jsonObject.toJSONString();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String sendAgvTaskQYCJson(AgvTask agvTask, int tugCount, List<String> tugModels) {
|
public String createTuggerJson(AgvTask agvTask, List<String> tugModels) {
|
||||||
JSONObject jsonObject = new JSONObject(true);
|
return agvTaskJsonBuilder.createTuggerJson(agvTask, tugModels);
|
||||||
String requestId = TimeNumberUtils.getQYTaskCode();
|
|
||||||
Map<String, Object> objMap = new LinkedHashMap<>();
|
|
||||||
objMap.put("orgId", "WCS");//库存组织 ID(或工厂代码,供应商代码)
|
|
||||||
objMap.put("requestId", requestId);//请求 id
|
|
||||||
objMap.put("missionCode", agvTask.getId());//任务编号
|
|
||||||
objMap.put("missionType", "TUGGER_MOVE");//任务类型 :滚筒
|
|
||||||
objMap.put("viewBoardType", "");//上视识别类型:
|
|
||||||
objMap.put("robotType", "TUGGER");
|
|
||||||
objMap.put("priority", "1");
|
|
||||||
objMap.put("templateCode", "");
|
|
||||||
objMap.put("lockRobotAfterFinish", false);
|
|
||||||
objMap.put("unlockRobotId", "");
|
|
||||||
objMap.put("unlockMissionCode", "");
|
|
||||||
|
|
||||||
JSONArray missionDataArray = new JSONArray();
|
|
||||||
|
|
||||||
JSONObject missionDataObj = new JSONObject(true);
|
|
||||||
Map<String, Object> missionDataMap = new LinkedHashMap<>();
|
|
||||||
Point point = pointService.validatePoint(agvTask.getStartSlotCode());
|
|
||||||
String areaCode = point.getArea().getCode();
|
|
||||||
if ("XJQ".equals(areaCode)) {
|
|
||||||
tugModels = Arrays.asList("modelA", "modelB");
|
|
||||||
} else {
|
|
||||||
tugCount = tugModels.size();
|
|
||||||
}
|
|
||||||
missionDataMap.put("sequence", 1);//序号
|
|
||||||
missionDataMap.put("type", "NODE_POINT");//作业类型:点位:NODE_POINT;区域:NODE_AREA
|
|
||||||
missionDataMap.put("position", agvTask.getStartSlotCode());//起点
|
|
||||||
missionDataMap.put("actionType", "TUGGER_ATTACH");//动作:TUGGER_ATTACH:挂钩;TUGGER_DETACH:脱钩
|
|
||||||
missionDataMap.put("tugCount", tugCount);//牵引车后方的拖挂车数量
|
|
||||||
missionDataMap.put("passStrategy", "AUTO");//当前任务点结束后放行策略:自动:AUTO;手动:MANUAL
|
|
||||||
missionDataMap.put("tugModels", tugModels);//牵引车后方的拖挂车规格【模型名字】需要和tugCount一致
|
|
||||||
missionDataObj.putAll(missionDataMap);
|
|
||||||
missionDataArray.add(missionDataObj);
|
|
||||||
|
|
||||||
List<String> stations = Arrays.stream(agvTask.getEndSlotCode().split(","))
|
|
||||||
.map(String::trim)
|
|
||||||
.filter(s -> !s.isEmpty())
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
|
|
||||||
//途径点
|
|
||||||
for (int i = 0; i < stations.size(); i++) {
|
|
||||||
JSONObject missionDataObj2 = new JSONObject(true);
|
|
||||||
Map<String, Object> missionDataMap2 = new LinkedHashMap<>();
|
|
||||||
int sequence = (1 + (i + 1));
|
|
||||||
missionDataMap2.put("sequence", sequence);//序号
|
|
||||||
missionDataMap2.put("type", "NODE_POINT");//作业类型:点位:NODE_POINT;区域:NODE_AREA
|
|
||||||
missionDataMap2.put("position", stations.get(i));//途径点
|
|
||||||
missionDataMap2.put("passStrategy", "MANUAL");//当前任务点结束后放行策略:自动:AUTO;手动:MANUAL
|
|
||||||
missionDataObj2.putAll(missionDataMap2);
|
|
||||||
missionDataArray.add(missionDataObj2);
|
|
||||||
}
|
|
||||||
|
|
||||||
JSONObject missionDataObj3 = new JSONObject(true);
|
|
||||||
Map<String, Object> missionDataMap3 = new LinkedHashMap<>();
|
|
||||||
missionDataMap3.put("sequence", stations.size() + 2);//序号
|
|
||||||
missionDataMap3.put("type", "NODE_POINT");//作业类型:点位:NODE_POINT;区域:NODE_AREA
|
|
||||||
missionDataMap3.put("position", point.getBeatCode());//终点
|
|
||||||
missionDataMap3.put("actionType", "TUGGER_DETACH");//动作:TUGGER_ATTACH:挂钩;TUGGER_DETACH:脱钩
|
|
||||||
missionDataMap3.put("passStrategy", "AUTO");//当前任务点结束后放行策略:自动:AUTO;手动:MANUAL
|
|
||||||
missionDataMap3.put("waitingMillis", 0);//自动触发离开当前任务节点的时间,默认单位:毫秒
|
|
||||||
missionDataObj3.putAll(missionDataMap3);
|
|
||||||
missionDataArray.add(missionDataMap3);
|
|
||||||
|
|
||||||
objMap.put("missionData", missionDataArray);
|
|
||||||
jsonObject.putAll(objMap);
|
|
||||||
return jsonObject.toJSONString();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void sendAgvTask(AgvTask agvTask, String json) {
|
public void sendAgvTask(AgvTask agvTask, String json) {
|
||||||
try {
|
try {
|
||||||
// 请求
|
|
||||||
String result = HttpPostUtil.sendPostReq(UrlApi.submitMission(), json);
|
|
||||||
log.info("LES回传参数: {}", json);
|
|
||||||
|
|
||||||
// 检查接口开关
|
// 检查接口开关
|
||||||
if (!dictService.isInterfaceEnabled()) {
|
if (!dictService.isInterfaceEnabled()) {
|
||||||
// 更新LES状态
|
// 更新AGV状态
|
||||||
updateAgvTaskStatus(agvTask, null, json);
|
updateAgvTaskStatus(agvTask, null, json);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 请求
|
||||||
|
String result = HttpPostUtil.sendPostReq(UrlApi.submitMission(), json);
|
||||||
|
log.info("AGV请求参数: {}", json);
|
||||||
|
|
||||||
//验证响应
|
//验证响应
|
||||||
validateAgvTaskResponse(result);
|
validateAgvTaskResponse(result);
|
||||||
|
|
||||||
|
|
@ -412,8 +214,7 @@ public class KMReServiceImpl implements KMReService {
|
||||||
updateAgvTaskStatus(agvTask, result, json);
|
updateAgvTaskStatus(agvTask, result, json);
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("AGV下发失败", e);
|
throw new BadRequestException(e.getMessage());
|
||||||
throw new BadRequestException("AGV下发失败:" + e.getMessage());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -423,11 +224,11 @@ public class KMReServiceImpl implements KMReService {
|
||||||
*/
|
*/
|
||||||
private void validateAgvTaskResponse(String result) {
|
private void validateAgvTaskResponse(String result) {
|
||||||
if (StringUtils.isEmpty(result)) {
|
if (StringUtils.isEmpty(result)) {
|
||||||
throw new BadRequestException("AGV返回信息:下发任务接口调用失败!");
|
throw new BadRequestException("AGV返回信息:下发任务接口调用失败");
|
||||||
}
|
}
|
||||||
JSONObject resulObject = JSON.parseObject(result);
|
JSONObject resulObject = JSON.parseObject(result);
|
||||||
if (resulObject == null) {
|
if (resulObject == null) {
|
||||||
throw new BadRequestException("AGV返回信息:下发任务接口返回为空!");
|
throw new BadRequestException("AGV返回信息:下发任务接口返回为空");
|
||||||
}
|
}
|
||||||
|
|
||||||
String code = resulObject.getString("code");
|
String code = resulObject.getString("code");
|
||||||
|
|
@ -502,7 +303,7 @@ public class KMReServiceImpl implements KMReService {
|
||||||
throw new BadRequestException("器具必填");
|
throw new BadRequestException("器具必填");
|
||||||
}
|
}
|
||||||
//根据点位找到当前到站的AGV任务;
|
//根据点位找到当前到站的AGV任务;
|
||||||
AgvTask agvTask = agvTaskService.findBySlotCode(updateTuggerTrailerInfo.getSrcPositionCode());
|
AgvTask agvTask = agvTaskService.findBySlotCode(updateTuggerTrailerInfo.getSrcPositionCode(), BizStatus.MOVE, "TUGGER_MOVE");
|
||||||
if (agvTask == null) {
|
if (agvTask == null) {
|
||||||
throw new BadRequestException(updateTuggerTrailerInfo.getSrcPositionCode() + "点未匹配到任务");
|
throw new BadRequestException(updateTuggerTrailerInfo.getSrcPositionCode() + "点未匹配到任务");
|
||||||
}
|
}
|
||||||
|
|
@ -597,13 +398,13 @@ public class KMReServiceImpl implements KMReService {
|
||||||
// 根据任务类型发送不同的实现
|
// 根据任务类型发送不同的实现
|
||||||
switch (agvTask.getJobType()) {
|
switch (agvTask.getJobType()) {
|
||||||
case "FORKLIFT_MOVE":
|
case "FORKLIFT_MOVE":
|
||||||
sendAgvTask(newAgvTask, sendAgvTaskCcJson(newAgvTask));
|
sendAgvTask(newAgvTask, createForkMissionJson(newAgvTask));
|
||||||
break;
|
break;
|
||||||
case "RACK_MOVE":
|
case "RACK_MOVE":
|
||||||
sendAgvTask(newAgvTask, sendAgvTaskHjJson(newAgvTask));
|
sendAgvTask(newAgvTask, createRackMissionJson(newAgvTask));
|
||||||
break;
|
break;
|
||||||
case "ROLLER_MOVE":
|
case "ROLLER_MOVE":
|
||||||
sendAgvTask(newAgvTask, sendAgvTaskGtJson(newAgvTask));
|
sendAgvTask(newAgvTask, createRollerJson(newAgvTask));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new BadRequestException("任务类型不支持: " + agvTask.getJobType());
|
throw new BadRequestException("任务类型不支持: " + agvTask.getJobType());
|
||||||
|
|
|
||||||
|
|
@ -8,8 +8,6 @@ import com.youchain.businessdata.domain.Les;
|
||||||
import com.youchain.businessdata.inputJson.LesRequest;
|
import com.youchain.businessdata.inputJson.LesRequest;
|
||||||
import com.youchain.businessdata.inputJson.PositionCodeRequest;
|
import com.youchain.businessdata.inputJson.PositionCodeRequest;
|
||||||
import com.youchain.businessdata.repository.LesRepository;
|
import com.youchain.businessdata.repository.LesRepository;
|
||||||
import com.youchain.businessdata.service.AgvTaskService;
|
|
||||||
import com.youchain.businessdata.service.KMReService;
|
|
||||||
import com.youchain.businessdata.service.LesService;
|
import com.youchain.businessdata.service.LesService;
|
||||||
import com.youchain.businessdata.service.dto.LesDto;
|
import com.youchain.businessdata.service.dto.LesDto;
|
||||||
import com.youchain.businessdata.service.dto.LesQueryCriteria;
|
import com.youchain.businessdata.service.dto.LesQueryCriteria;
|
||||||
|
|
@ -54,8 +52,6 @@ public class LesServiceImpl implements LesService {
|
||||||
|
|
||||||
private final DictService dictService;
|
private final DictService dictService;
|
||||||
|
|
||||||
private final KMReService kmReService;
|
|
||||||
|
|
||||||
private final LesMapper lesMapper;
|
private final LesMapper lesMapper;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -130,21 +126,13 @@ public class LesServiceImpl implements LesService {
|
||||||
String taskCode = lesRequest.getTaskCode();
|
String taskCode = lesRequest.getTaskCode();
|
||||||
validateLes(taskCode);
|
validateLes(taskCode);
|
||||||
|
|
||||||
String materialCode = lesRequest.getMaterialCode();//物料代码
|
try {
|
||||||
|
createLes(lesRequest, dstPoint);
|
||||||
//有物料走料箱上线场景;无物料走其余场景
|
} catch (DataIntegrityViolationException e) {
|
||||||
if (StringUtils.isNotEmpty(materialCode)) {
|
// 数据库唯一约束冲突
|
||||||
try {
|
throw new BadRequestException(taskCode + "任务号系统已接收,请勿重复操作");
|
||||||
createLes(lesRequest, dstPoint);
|
} catch (Exception e) {
|
||||||
} catch (DataIntegrityViolationException e) {
|
throw new BadRequestException("创建任务失败:" + e.getMessage());
|
||||||
// 数据库唯一约束冲突
|
|
||||||
throw new BadRequestException(taskCode + "任务号系统已接收,请勿重复操作");
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new BadRequestException("创建任务失败:" + e.getMessage());
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
//直接转发给AGV
|
|
||||||
sendLesTask(JSON.toJSONString(lesRequest));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -183,12 +171,12 @@ public class LesServiceImpl implements LesService {
|
||||||
try {
|
try {
|
||||||
// 生成请求参数
|
// 生成请求参数
|
||||||
String json = this.lesCallBackJson(les.getDstPositionCode(), les.getTaskCode());
|
String json = this.lesCallBackJson(les.getDstPositionCode(), les.getTaskCode());
|
||||||
log.info("LES回传参数: {}", json);
|
log.info("LES请求参数: {}", json);
|
||||||
|
|
||||||
// 检查接口开关
|
// 检查接口开关
|
||||||
if (!dictService.isInterfaceEnabled()) {
|
if (!dictService.isInterfaceEnabled()) {
|
||||||
// 更新LES状态
|
// 更新LES状态
|
||||||
updateLesStatus(les, null, json);
|
updateLesStatus(les, "success", json);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -205,8 +193,7 @@ public class LesServiceImpl implements LesService {
|
||||||
updateLesStatus(les, result, json);
|
updateLesStatus(les, result, json);
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("LES回传失败", e);
|
throw new BadRequestException(e.getMessage());
|
||||||
throw new BadRequestException("LES回传失败:" + e.getMessage());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -266,7 +253,7 @@ public class LesServiceImpl implements LesService {
|
||||||
*/
|
*/
|
||||||
private void validateLesResponse(String result) {
|
private void validateLesResponse(String result) {
|
||||||
if (StringUtils.isEmpty(result)) {
|
if (StringUtils.isEmpty(result)) {
|
||||||
throw new BadRequestException("LES返回信息:LES回传接口调用失败!");
|
throw new BadRequestException("LES返回信息:LES回传接口调用失败");
|
||||||
}
|
}
|
||||||
|
|
||||||
//解析XML格式
|
//解析XML格式
|
||||||
|
|
@ -275,7 +262,7 @@ public class LesServiceImpl implements LesService {
|
||||||
//解析JSON格式
|
//解析JSON格式
|
||||||
JSONObject resulObject = JSON.parseObject(result);
|
JSONObject resulObject = JSON.parseObject(result);
|
||||||
if (resulObject == null) {
|
if (resulObject == null) {
|
||||||
throw new BadRequestException("LES返回信息:LES回传接口返回为空!");
|
throw new BadRequestException("LES返回信息:LES回传接口返回为空");
|
||||||
}
|
}
|
||||||
|
|
||||||
String resultCode = resulObject.getString("resultCode");
|
String resultCode = resulObject.getString("resultCode");
|
||||||
|
|
@ -343,23 +330,20 @@ public class LesServiceImpl implements LesService {
|
||||||
if (StringUtils.isEmpty(lesRequest.getTaskCode())) {
|
if (StringUtils.isEmpty(lesRequest.getTaskCode())) {
|
||||||
throw new BadRequestException("任务号必填");
|
throw new BadRequestException("任务号必填");
|
||||||
}
|
}
|
||||||
//物料有值;说明是料箱上线场景
|
if (StringUtils.isEmpty(lesRequest.getRouteCode())) {
|
||||||
if (StringUtils.isNotEmpty(lesRequest.getMaterialCode())) {
|
throw new BadRequestException("编组/线路必填");
|
||||||
if (StringUtils.isEmpty(lesRequest.getRouteCode())) {
|
}
|
||||||
throw new BadRequestException("编组/线路必填");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (StringUtils.isEmpty(lesRequest.getBoxNo())) {
|
if (StringUtils.isEmpty(lesRequest.getBoxNo())) {
|
||||||
throw new BadRequestException("料箱号必填");
|
throw new BadRequestException("料箱号必填");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (StringUtils.isEmpty(lesRequest.getOnlineNo())) {
|
if (StringUtils.isEmpty(lesRequest.getOnlineNo())) {
|
||||||
throw new BadRequestException("上线单号必填");
|
throw new BadRequestException("上线单号必填");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lesRequest.getPositionCodePath() == null || lesRequest.getPositionCodePath().isEmpty() || lesRequest.getPositionCodePath().size() < 2) {
|
if (lesRequest.getPositionCodePath() == null || lesRequest.getPositionCodePath().isEmpty() || lesRequest.getPositionCodePath().size() < 2) {
|
||||||
throw new BadRequestException("节点不能为空且长度至少为2");
|
throw new BadRequestException("节点不能为空且长度至少为2");
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -414,9 +398,4 @@ public class LesServiceImpl implements LesService {
|
||||||
.build();
|
.build();
|
||||||
lesRepository.save(les);
|
lesRepository.save(les);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sendLesTask(String json) {
|
|
||||||
kmReService.sendAgvTaskToContainer(UrlApi.submitMission(), json);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue