package com.zy.asrs.service.impl;
|
|
import com.alibaba.excel.util.StringUtils;
|
import com.alibaba.fastjson.JSONObject;
|
import com.baomidou.mybatisplus.mapper.EntityWrapper;
|
import com.core.common.Cools;
|
import com.zy.asrs.entity.*;
|
import com.zy.asrs.enums.RcsRetMethodEnum;
|
import com.zy.asrs.service.AgvTaskService;
|
import com.zy.asrs.service.RcsService;
|
import com.zy.core.cache.MessageQueue;
|
import com.zy.core.cache.SlaveConnection;
|
import com.zy.core.enums.SlaveType;
|
import com.zy.core.model.protocol.StaProtocol;
|
import com.zy.core.thread.SiemensDevpThread;
|
import lombok.extern.slf4j.Slf4j;
|
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.stereotype.Service;
|
|
import java.io.BufferedReader;
|
import java.io.IOException;
|
import java.io.InputStreamReader;
|
import java.io.PrintWriter;
|
import java.net.ConnectException;
|
import java.net.SocketTimeoutException;
|
import java.net.URL;
|
import java.net.URLConnection;
|
import java.nio.charset.StandardCharsets;
|
import java.util.Date;
|
import java.util.Objects;
|
|
@Slf4j
|
@Service
|
public class RcsServiceImpl implements RcsService {
|
// 海康RCS地址
|
@Value("${hik.url}")
|
private String HIK_URL;
|
|
@Value("${mes.url}")
|
public String MES_URL;
|
|
@Autowired
|
private AgvTaskService agvTaskService;
|
|
|
/**
|
* 2.2.1任务执行回馈
|
* 厂家:海量、华晓
|
*
|
* @param rcsReporterTask
|
* @return
|
*/
|
@Override
|
public RcsReturn reporterTask(RcsReporterTask rcsReporterTask) {
|
log.info("海康AGV站点任务请求={}", JSONObject.toJSONString(rcsReporterTask));
|
|
RcsReturn rcsReturn = new RcsReturn();
|
|
String robotTaskCode = rcsReporterTask.getRobotTaskCode();
|
String singleRobotCode = rcsReporterTask.getSingleRobotCode();
|
String[] split = robotTaskCode.split("-");
|
robotTaskCode = split[0];
|
JSONObject values = rcsReporterTask.getExtra().getJSONObject("values");
|
// start : 任务开始;outbin : 走出储位;end : 任务完成
|
String method = values.getString("method");
|
String carrierType = values.getString("carrierType");
|
String slotCategory = values.getString("slotCategory");
|
String slotCode = values.getString("slotCode");
|
EntityWrapper<AgvTask> wrapper = new EntityWrapper<>();
|
wrapper.eq("task_no", robotTaskCode);
|
AgvTask task = agvTaskService.selectOne(wrapper);
|
if (!Cools.isEmpty(task)) {
|
try {
|
switch (Objects.requireNonNull(RcsRetMethodEnum.getEnum(method))) {
|
//放货申请
|
case APPLY_PUT: {
|
if(task.getStaNo().equals("401")||task.getStaNo().equals("402")||task.getStaNo().equals("307")) {
|
Integer sourceStaNo = Integer.valueOf(task.getStaNo());
|
SiemensDevpThread siemensDevpThread = (SiemensDevpThread) SlaveConnection.get(SlaveType.Devp, 1);
|
StaProtocol staProtocol = siemensDevpThread.getStation().get(sourceStaNo).clone();
|
//wcs反馈rcs继续执行
|
if (staProtocol != null && !staProtocol.isLoading() && !staProtocol.isEmptyOutType()) {
|
if(task.getTaskType().equals("AGV补空料架")){
|
RcsTaskContinue rcsTaskContinue = new RcsTaskContinue();
|
rcsTaskContinue.setRobotTaskCode(task.getTaskNo()+"-"+(task.getCtnType()-1));
|
rcsTaskContinue.setTriggerType("TASK");
|
rcsTaskContinue.setTriggerCode(task.getTaskNo()+"-"+(task.getCtnType()-1));
|
|
String url = HIK_URL + "api/robot/controller/task/extend/continue";
|
String response = sendPost(url, JSONObject.toJSONString(rcsTaskContinue));
|
if (!StringUtils.isEmpty(response) && response.contains("code")) {
|
log.info("允许AGV放货成功");
|
}
|
// 返回RCS
|
rcsReturn.setCode("SUCCESS");
|
rcsReturn.setMessage("");
|
JSONObject data = new JSONObject();
|
data.put("robotTaskCode", robotTaskCode);
|
rcsReturn.setData(data);
|
}else {
|
//出发PLC站点的扫码器扫码
|
boolean result = MessageQueue.offer(SlaveType.Devp, 1, new com.zy.core.model.Task(3, staProtocol));
|
if (result) {
|
log.info("入库站点={}触发扫码成功", staProtocol.getSiteId());
|
// 返回RCS
|
rcsReturn.setCode("SUCCESS");
|
rcsReturn.setMessage("");
|
JSONObject data = new JSONObject();
|
data.put("robotTaskCode", robotTaskCode);
|
rcsReturn.setData(data);
|
RcsTaskContinue rcsTaskContinue = new RcsTaskContinue();
|
rcsTaskContinue.setRobotTaskCode(task.getTaskNo()+"-"+(task.getCtnType()-1));
|
rcsTaskContinue.setTriggerType("TASK");
|
rcsTaskContinue.setTriggerCode(task.getTaskNo()+"-"+(task.getCtnType()-1));
|
|
String url = HIK_URL + "api/robot/controller/task/extend/continue";
|
String response = sendPost(url, JSONObject.toJSONString(rcsTaskContinue));
|
if (!StringUtils.isEmpty(response) && response.contains("code")) {
|
log.info("允许AGV放货成功");
|
}
|
} else {
|
// 返回RCS
|
rcsReturn.setCode("Err_Internal");
|
rcsReturn.setMessage("");
|
JSONObject data = new JSONObject();
|
data.put("robotTaskCode", robotTaskCode);
|
rcsReturn.setData(data);
|
}
|
}
|
}
|
}else {
|
TransParent transParent = new TransParent();
|
transParent.setTaskno(task.getTaskNo()+"-"+(task.getCtnType()-1));
|
transParent.setTaskname(task.getTaskNo()+"-"+(task.getCtnType()-1));
|
transParent.setStationId(task.getStaNo());
|
transParent.setAgvCode("2");//连接器库
|
int i = applyInStation(transParent);
|
if (i == 1) {
|
rcsReturn.setCode("SUCCESS");
|
rcsReturn.setMessage("");
|
JSONObject data = new JSONObject();
|
data.put("robotTaskCode", robotTaskCode);
|
rcsReturn.setData(data);
|
}else {
|
// 返回RCS
|
rcsReturn.setCode("Err_Internal");
|
rcsReturn.setMessage("");
|
JSONObject data = new JSONObject();
|
data.put("robotTaskCode", robotTaskCode);
|
rcsReturn.setData(data);
|
}
|
}
|
|
}
|
break;
|
|
//放货完成 --》agv已经离开
|
case TASK_END: {
|
if(task.getStaNo().equals("401")||task.getStaNo().equals("402")||task.getStaNo().equals("307")) {
|
Integer sourceStaNo = Integer.valueOf(task.getStaNo());
|
SiemensDevpThread siemensDevpThread = (SiemensDevpThread) SlaveConnection.get(SlaveType.Devp, 1);
|
StaProtocol staProtocol = siemensDevpThread.getStation().get(sourceStaNo).clone();
|
Boolean boo = false;
|
Short wrkNo = 9991;
|
//放货完成 --》agv已经离开 --》给PLC站点写9991工作号
|
//补空料架 --》agv已经立库 --》给PLC站点写9995工作号
|
if (task.getTaskType().equals("AGV补空料架") && staProtocol != null && !staProtocol.isLoading() && staProtocol.isEmptyOutType() && staProtocol.getWorkNo() == 0) {
|
boo = true;
|
wrkNo = 9995;
|
} else if (!task.getTaskType().equals("AGV补空料架") && staProtocol != null && staProtocol.isLoading() && staProtocol.isEmptyOutType() && staProtocol.getWorkNo() == 0) {
|
boo = true;
|
}
|
if (boo) {
|
staProtocol.setWorkNo(wrkNo);//空料架到位信号点
|
staProtocol.setStaNo(Short.valueOf("0"));
|
boolean result = MessageQueue.offer(SlaveType.Devp, 1, new com.zy.core.model.Task(2, staProtocol));
|
log.info("AGV放货完成,给站点写9991工作号,下发任务:{},站点:{},agv任务号:{}", result, task.getStaNo(), task.getTaskNo());
|
if (result) {
|
// 更新任务状态等内部逻辑
|
task.setWrkSts(304L); // 301 任务下发、302 任务执行、303 任务中断、304 任务结束
|
task.setModiTime(new Date());
|
agvTaskService.updateById(task);
|
// 返回RCS
|
rcsReturn.setCode("SUCCESS");
|
rcsReturn.setMessage("");
|
JSONObject data = new JSONObject();
|
data.put("robotTaskCode", robotTaskCode);
|
rcsReturn.setData(data);
|
} else {
|
// 返回RCS
|
rcsReturn.setCode("Err_Internal");
|
rcsReturn.setMessage("");
|
JSONObject data = new JSONObject();
|
data.put("robotTaskCode", robotTaskCode);
|
rcsReturn.setData(data);
|
}
|
} else {
|
// 返回RCS
|
rcsReturn.setCode("Err_Internal");
|
rcsReturn.setMessage("");
|
JSONObject data = new JSONObject();
|
data.put("robotTaskCode", robotTaskCode);
|
rcsReturn.setData(data);
|
}
|
}else {
|
// 更新任务状态等内部逻辑
|
task.setWrkSts(304L); // 301 任务下发、302 任务执行、303 任务中断、304 任务结束
|
task.setModiTime(new Date());
|
agvTaskService.updateById(task);
|
// 返回RCS
|
rcsReturn.setCode("SUCCESS");
|
rcsReturn.setMessage("");
|
JSONObject data = new JSONObject();
|
data.put("robotTaskCode", robotTaskCode);
|
rcsReturn.setData(data);
|
}
|
}
|
break;
|
//rcs请求wms取货申请
|
case APPLY_PICK: {
|
if(task.getSourceStaNo().equals("401")||task.getSourceStaNo().equals("402")||task.getSourceStaNo().equals("307")) {
|
Integer sourceStaNo = Integer.valueOf(task.getSourceStaNo());
|
SiemensDevpThread siemensDevpThread = (SiemensDevpThread) SlaveConnection.get(SlaveType.Devp, 1);
|
StaProtocol staProtocol = siemensDevpThread.getStation().get(sourceStaNo).clone();
|
//判断站点是否有料架和托盘
|
if (staProtocol != null && (staProtocol.isLoading() || task.getTaskType().equals("AGV空料架回缓存区"))
|
&& staProtocol.isEmptyOutType()) {
|
RcsTaskContinue rcsTaskContinue = new RcsTaskContinue();
|
rcsTaskContinue.setRobotTaskCode(task.getTaskNo() + "-" + (task.getCtnType() - 1));
|
rcsTaskContinue.setTriggerType("TASK");
|
rcsTaskContinue.setTriggerCode(task.getTaskNo() + "-" + (task.getCtnType() - 1));
|
|
String url = HIK_URL + "api/robot/controller/task/extend/continue";
|
String response = sendPost(url, JSONObject.toJSONString(rcsTaskContinue));
|
if (!StringUtils.isEmpty(response) && response.contains("code")) {
|
RcsReturn rcsReturn1 = JSONObject.parseObject(response, RcsReturn.class);
|
if ("200".equals(rcsReturn1.getCode())) {
|
// 返回RCS
|
rcsReturn.setCode("SUCCESS");
|
rcsReturn.setMessage("");
|
JSONObject data = new JSONObject();
|
data.put("robotTaskCode", robotTaskCode);
|
rcsReturn.setData(data);
|
} else {
|
// 返回RCS
|
rcsReturn.setCode("Err_Internal");
|
rcsReturn.setMessage("");
|
JSONObject data = new JSONObject();
|
data.put("robotTaskCode", robotTaskCode);
|
rcsReturn.setData(data);
|
}
|
}
|
}
|
}else {
|
TransParent transParent = new TransParent();
|
transParent.setTaskno(task.getTaskNo()+"-"+(task.getCtnType()-1));
|
transParent.setTaskname(task.getTaskNo()+"-"+(task.getCtnType()-1));
|
transParent.setStationId(task.getStaNo());
|
transParent.setAgvCode("2");//连接器库
|
int i = applyInStation(transParent);
|
if (i == 1) {
|
rcsReturn.setCode("SUCCESS");
|
rcsReturn.setMessage("");
|
JSONObject data = new JSONObject();
|
data.put("robotTaskCode", robotTaskCode);
|
rcsReturn.setData(data);
|
}else {
|
// 返回RCS
|
rcsReturn.setCode("Err_Internal");
|
rcsReturn.setMessage("");
|
JSONObject data = new JSONObject();
|
data.put("robotTaskCode", robotTaskCode);
|
rcsReturn.setData(data);
|
}
|
}
|
}
|
break;
|
//rcs取货完成,已退出输送线
|
case PICK_COMPLETE: {
|
Integer sourceStaNo = Integer.valueOf(task.getSourceStaNo());
|
SiemensDevpThread siemensDevpThread = (SiemensDevpThread) SlaveConnection.get(SlaveType.Devp, 1);
|
StaProtocol staProtocol = siemensDevpThread.getStation().get(sourceStaNo).clone();
|
//放货完成 --》agv已经离开 --》给PLC站点写9991工作号
|
if (staProtocol != null && !staProtocol.isLoading() && !staProtocol.isEmptyOutType()) {
|
staProtocol.setWorkNo((short) 0);
|
staProtocol.setStaNo((short) 0);
|
boolean result = MessageQueue.offer(SlaveType.Devp, 1, new com.zy.core.model.Task(2, staProtocol));
|
log.info("AGV取货完成,给站点写0工作号,下发任务:{},站点:{},agv任务号:{}", result, task.getStaNo(), task.getTaskNo());
|
if (result) {
|
// 返回RCS
|
rcsReturn.setCode("SUCCESS");
|
rcsReturn.setMessage("");
|
JSONObject data = new JSONObject();
|
data.put("robotTaskCode", robotTaskCode);
|
rcsReturn.setData(data);
|
} else {
|
// 返回RCS
|
rcsReturn.setCode("Err_Internal");
|
rcsReturn.setMessage("");
|
JSONObject data = new JSONObject();
|
data.put("robotTaskCode", robotTaskCode);
|
rcsReturn.setData(data);
|
}
|
|
}
|
}
|
break;
|
//AGV取货离站请求
|
case APPLY_IN_OFF_STATION:{
|
//如果是立库站点直接允许离站
|
if(task.getSourceStaNo().equals("401")||task.getSourceStaNo().equals("402")||task.getSourceStaNo().equals("307")) {
|
RcsTaskContinue rcsTaskContinue = new RcsTaskContinue();
|
rcsTaskContinue.setRobotTaskCode(task.getTaskNo() + "-" + (task.getCtnType() - 1));
|
rcsTaskContinue.setTriggerType("TASK");
|
rcsTaskContinue.setTriggerCode(task.getTaskNo() + "-" + (task.getCtnType() - 1));
|
|
String url = HIK_URL + "api/robot/controller/task/extend/continue";
|
String response = sendPost(url, JSONObject.toJSONString(rcsTaskContinue));
|
if (!StringUtils.isEmpty(response) && response.contains("code")) {
|
RcsReturn rcsReturn1 = JSONObject.parseObject(response, RcsReturn.class);
|
if ("200".equals(rcsReturn1.getCode())) {
|
// 返回RCS
|
rcsReturn.setCode("SUCCESS");
|
rcsReturn.setMessage("");
|
JSONObject data = new JSONObject();
|
data.put("robotTaskCode", robotTaskCode);
|
rcsReturn.setData(data);
|
} else {
|
// 返回RCS
|
rcsReturn.setCode("Err_Internal");
|
rcsReturn.setMessage("");
|
JSONObject data = new JSONObject();
|
data.put("robotTaskCode", robotTaskCode);
|
rcsReturn.setData(data);
|
}
|
}
|
}else{
|
//如果是工位需要像mes请求离站
|
TransParent transParent = new TransParent();
|
transParent.setTaskno(task.getTaskNo()+"-"+(task.getCtnType()-1));
|
transParent.setTaskname(task.getTaskNo()+"-"+(task.getCtnType()-1));
|
transParent.setStationId(task.getStaNo());
|
transParent.setAgvCode("2");//连接器库
|
int i = applyOutStation(transParent);
|
if (i == 1) {
|
rcsReturn.setCode("SUCCESS");
|
rcsReturn.setMessage("");
|
JSONObject data = new JSONObject();
|
data.put("robotTaskCode", robotTaskCode);
|
rcsReturn.setData(data);
|
}else {
|
// 返回RCS
|
rcsReturn.setCode("Err_Internal");
|
rcsReturn.setMessage("");
|
JSONObject data = new JSONObject();
|
data.put("robotTaskCode", robotTaskCode);
|
rcsReturn.setData(data);
|
}
|
}
|
break;
|
}
|
//AGV放货离站请求
|
case APPLY_OFF_STATION:{
|
//如果是立库站点直接允许离站
|
if(task.getStaNo().equals("401")||task.getStaNo().equals("402")||task.getStaNo().equals("307")) {
|
RcsTaskContinue rcsTaskContinue = new RcsTaskContinue();
|
rcsTaskContinue.setRobotTaskCode(task.getTaskNo() + "-" + (task.getCtnType() - 1));
|
rcsTaskContinue.setTriggerType("TASK");
|
rcsTaskContinue.setTriggerCode(task.getTaskNo() + "-" + (task.getCtnType() - 1));
|
|
String url = HIK_URL + "api/robot/controller/task/extend/continue";
|
String response = sendPost(url, JSONObject.toJSONString(rcsTaskContinue));
|
if (!StringUtils.isEmpty(response) && response.contains("code")) {
|
RcsReturn rcsReturn1 = JSONObject.parseObject(response, RcsReturn.class);
|
if ("200".equals(rcsReturn1.getCode())) {
|
// 返回RCS
|
rcsReturn.setCode("SUCCESS");
|
rcsReturn.setMessage("");
|
JSONObject data = new JSONObject();
|
data.put("robotTaskCode", robotTaskCode);
|
rcsReturn.setData(data);
|
} else {
|
// 返回RCS
|
rcsReturn.setCode("Err_Internal");
|
rcsReturn.setMessage("");
|
JSONObject data = new JSONObject();
|
data.put("robotTaskCode", robotTaskCode);
|
rcsReturn.setData(data);
|
}
|
}
|
}else{
|
//如果是工位需要像mes请求离站
|
TransParent transParent = new TransParent();
|
transParent.setTaskno(task.getTaskNo()+"-"+(task.getCtnType()-1));
|
transParent.setTaskname(task.getTaskNo()+"-"+(task.getCtnType()-1));
|
transParent.setStationId(task.getStaNo());
|
transParent.setAgvCode("2");//连接器库
|
int i = applyOutStation(transParent);
|
if (i == 1) {
|
rcsReturn.setCode("SUCCESS");
|
rcsReturn.setMessage("");
|
JSONObject data = new JSONObject();
|
data.put("robotTaskCode", robotTaskCode);
|
rcsReturn.setData(data);
|
}else {
|
// 返回RCS
|
rcsReturn.setCode("Err_Internal");
|
rcsReturn.setMessage("");
|
JSONObject data = new JSONObject();
|
data.put("robotTaskCode", robotTaskCode);
|
rcsReturn.setData(data);
|
}
|
}
|
|
break;
|
}
|
|
default: {
|
}
|
break;
|
}
|
|
|
} catch (Exception e) {
|
log.error("RCS反馈任务进度处理异常 - {}", rcsReporterTask, e);
|
rcsReturn.setCode("Err_Internal");
|
rcsReturn.setMessage("内部处理异常");
|
JSONObject data = new JSONObject();
|
data.put("robotTaskCode", robotTaskCode);
|
rcsReturn.setData(data);
|
}
|
}
|
return rcsReturn;
|
}
|
|
/**
|
* 向指定 URL 发送POST方法的请求
|
*
|
* @param url 发送请求的 URL
|
* @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
|
* @return 所代表远程资源的响应结果
|
*/
|
public static String sendPost(String url, String param) {
|
PrintWriter out = null;
|
BufferedReader in = null;
|
StringBuilder result = new StringBuilder();
|
try {
|
log.info("sendPost - {} - {}", url, param);
|
URL realUrl = new URL(url);
|
URLConnection conn = realUrl.openConnection();
|
conn.setRequestProperty("Content-Type", "application/json");
|
conn.setRequestProperty("Content-Length", "<calculated when request is sent>");
|
conn.setRequestProperty("Host", "<calculated when request is sent>");
|
conn.setRequestProperty("Accept", "*/*");
|
conn.setRequestProperty("Accept-Encoding", "gzip, deflate, br");
|
conn.setRequestProperty("Connection", "keep-alive");
|
|
conn.setRequestProperty("X-lr-request-id", String.valueOf(new Date().getTime()));
|
conn.setRequestProperty("X-lr-version", "4.3");
|
|
conn.setConnectTimeout(5000);
|
conn.setReadTimeout(5000);
|
conn.setDoOutput(true);
|
conn.setDoInput(true);
|
out = new PrintWriter(conn.getOutputStream());
|
out.print(param);
|
out.flush();
|
in = new BufferedReader(new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8));
|
String line;
|
while ((line = in.readLine()) != null) {
|
result.append(line);
|
}
|
log.info("recv - {}", result);
|
} catch (ConnectException e) {
|
log.error("调用HttpUtils.sendPost ConnectException, url=" + url + ",param=" + param, e);
|
} catch (SocketTimeoutException e) {
|
log.error("调用HttpUtils.sendPost SocketTimeoutException, url=" + url + ",param=" + param, e);
|
} catch (IOException e) {
|
log.error("调用HttpUtils.sendPost IOException, url=" + url + ",param=" + param, e);
|
} catch (Exception e) {
|
log.error("调用HttpsUtil.sendPost Exception, url=" + url + ",param=" + param, e);
|
} finally {
|
try {
|
if (out != null) {
|
out.close();
|
}
|
if (in != null) {
|
in.close();
|
}
|
} catch (IOException ex) {
|
log.error("调用in.close Exception, url=" + url + ",param=" + param, ex);
|
}
|
}
|
return result.toString();
|
}
|
|
/**
|
* 入站请求:转发AGV->入站请求->给MES
|
*
|
* @param apply
|
* @return
|
*/
|
public int applyInStation(TransParent apply) {
|
String path = "AGVTransportPalletNotice";
|
String url = MES_URL + path;
|
String response = RcsServiceImpl.sendPost(url, JSONObject.toJSONString(apply));
|
if (!StringUtils.isEmpty(response) && response.contains("Success")) {
|
MesReturn mesReturn = JSONObject.parseObject(response, MesReturn.class);
|
if ("1".equals(mesReturn.getSuccess())) {
|
return 1;
|
}
|
}
|
|
return 0;
|
}
|
|
/**
|
* 离站请求:转发AGV->离站请求->给MES
|
*
|
* @param apply
|
* @return
|
*/
|
public int applyOutStation(TransParent apply) {
|
|
String url = MES_URL + "AGVDepartureRequest";
|
String response = RcsServiceImpl.sendPost(url, JSONObject.toJSONString(apply));
|
if (!StringUtils.isEmpty(response) && response.contains("Success")) {
|
MesReturn mesReturn = JSONObject.parseObject(response, MesReturn.class);
|
if ("1".equals(mesReturn.getSuccess())) {
|
return 1;
|
}
|
}
|
|
return 0;
|
}
|
}
|