pang.jiabao
昨天 15161de49e7f35e2fc926a20577905621f30554c
输送线和CTU安全交互
3个文件已添加
6个文件已修改
379 ■■■■■ 已修改文件
src/main/java/com/zy/controller/RcsController.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/entity/EqptNotify.java 49 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/entity/RcsTaskContinue.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/entity/ReporterEqpt.java 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/enums/RcsRetMethodEnum.java 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/service/RcsService.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/service/impl/MainServiceImpl.java 23 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/service/impl/RcsServiceImpl.java 232 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/application.yml 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/controller/RcsController.java
@@ -4,6 +4,7 @@
import com.zy.common.web.BaseController;
import com.zy.entity.RcsReporterTask;
import com.zy.entity.RcsReturn;
import com.zy.entity.ReporterEqpt;
import com.zy.service.RcsService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PostMapping;
@@ -27,4 +28,11 @@
        return rcsService.reporterTask(param);
    }
    // 请求外设接口-WCS 放货请求
    @PostMapping("/api/robot/reporter/eqpt")
    public RcsReturn reporterEqpt(@RequestBody ReporterEqpt param){
        log.info("agv放货请求:{}",JSONObject.toJSONString(param));
        return rcsService.reporterEqpt(param);
    }
}
src/main/java/com/zy/entity/EqptNotify.java
New file
@@ -0,0 +1,49 @@
package com.zy.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
 * @author pang.jiabao
 * @description 2.1.15 外设执行通知接口WCS
 * @createDate 2025/12/28 10:32
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class EqptNotify {
    /**
     * 设备编号/设备名称
     */
    private String eqptCode;
    /**
     * 任务号为唯一编号,可使用UUID
     */
    private String taskCode;
    /**
     * 任务执行状态:可扩展枚举值。
     * 预制枚举值:
     * 1. 自动门,风淋门
     * "1"-开门到位
     * "2"-关门到位
     * 2. 电梯
     * "3"-开门到位
     * "4"-物料到达目标楼层
     * 3. 装卸机、输送线
     * "5"-取货
     * "6"-放货
     * "7"-到达
     */
    private String actionStatus;
    /**
     * 分配的站点编号,电梯多拖场景使用。
     */
    private String siteCode;
}
src/main/java/com/zy/entity/RcsTaskContinue.java
New file
@@ -0,0 +1,20 @@
package com.zy.entity;
import lombok.Data;
// 继续执行任务
@Data
public class RcsTaskContinue {
    // 任务链编号
    private String robotTaskCode;
    // 触发类型:
    //SITE 站点编号触发
    //CARRIER 载具编号触发
    //ROBOT 车号触发
    //TASK 任务链编号触发
    private String triggerType;
    // 与 triggerType 对应的触发编号
    private String triggerCode;
}
src/main/java/com/zy/entity/ReporterEqpt.java
New file
@@ -0,0 +1,29 @@
package com.zy.entity;
import lombok.Data;
/**
 * @author pang.jiabao
 * @description 请求外设接口-WCS
 * @createDate 2025/12/26 10:42
 */
@Data
public class ReporterEqpt {
    /**
     * 设备编号
     */
    private String eqptCode;
    /**
     * 任务号为唯一编号
     */
    private String taskCode;
    /**
     * 任务执行方法
     * APPLY_FROM_AGV AGV申请送料
     */
    private String method;
}
src/main/java/com/zy/enums/RcsRetMethodEnum.java
@@ -5,7 +5,8 @@
    TASK_START("start", "任务开始"),
    TASK_END("end", "任务完成"),
    TASK_OUT_BIN("outbin", "走出储位"),
    APPLY_FROM_AGV("APPLY_FROM_AGV", "放货申请"),
    PICK_COMPLETE("pickComplete", "取货完成"),
    APPLY_IN_STATION("applyInStation", "入站请求"),
    APPLY_OFF_STATION("applyOutStation", "离站请求"),
    ARRIVE_ON_STATION("arriveOnStation", "到站完成"),
src/main/java/com/zy/service/RcsService.java
@@ -2,6 +2,7 @@
import com.zy.entity.RcsReporterTask;
import com.zy.entity.RcsReturn;
import com.zy.entity.ReporterEqpt;
public interface RcsService {
@@ -13,4 +14,8 @@
     */
    RcsReturn reporterTask(RcsReporterTask rcsReporterTask);
    /**
     * 请求外设接口-WCS 放货请求
     */
    RcsReturn reporterEqpt(ReporterEqpt param);
}
src/main/java/com/zy/service/impl/MainServiceImpl.java
@@ -130,7 +130,7 @@
        } else {
            staProtocol = staProtocol.clone();
        }
        if(staProtocol.isAutoing() && staProtocol.isLoading() && staProtocol.getWorkNo() != 0) {
        if(staProtocol.isAutoing() && staProtocol.isLoading() && staProtocol.getWorkNo() != 0 && staProtocol.isInEnable()) {
            WrkMast wrkMast = wrkMastService.selectOne(new EntityWrapper<WrkMast>().eq("wrk_no", staProtocol.getWorkNo()));
            if(wrkMast != null && Cools.isEmpty(wrkMast.getMk())) {
//              log.info("货物流动到位106:"+wrkMast.getWrkNo());
@@ -329,7 +329,7 @@
                    // 获取目标站
                    Wrapper<StaDesc> wrapper = new EntityWrapper<StaDesc>()
                            .eq("type_no", wrkMast.getIoType() - 50)
                            .eq("stn_no", pickSta.getStaNo() + 1) // 作业站点 = 拣料出库的目标站
                            .eq("stn_no", pickSta.getStaNo()) // 作业站点 = 拣料出库的目标站
                            .eq("crn_no", wrkMast.getCrnNo()); // 堆垛机号
                    StaDesc staDesc = staDescService.selectOne(wrapper);
                    if (Cools.isEmpty(staDesc)) {
@@ -391,7 +391,7 @@
                    // 更新站点信息 且 下发plc命令
                    staProtocol.setWorkNo(wrkMast.getWrkNo());
                    staProtocol.setStaNo(staProtocol.getSiteId().shortValue());
                    staProtocol.setStaNo(wrkMast.getStaNo().shortValue());
                    devpThread.setPakMk(staProtocol.getSiteId(), false);
                    boolean result = MessageQueue.offer(SlaveType.Devp, devp.getId(), new Task(2, staProtocol));
                    log.error("输送线下发5:"+wrkMast.getWrkNo()+","+wrkMast.getStaNo());
@@ -1083,13 +1083,6 @@
                    continue;
                }
                String barcode = barcodeThread.getBarcode();
                if(!Cools.isEmpty(barcode)) {
                    if("NG".endsWith(barcode) || "NoRead".equals(barcode)) {
                        continue;
                    }
                } else {
                    continue;
                }
                LedThread ledThread = null;
                if (!Cools.isEmpty(emptyInSta.getLed()))  {
@@ -1108,6 +1101,14 @@
                        && staProtocol.isPakMk()
                        && staProtocol.getWorkNo() == 9997
                        ) {
                    if (staProtocol.isBarcodeErr() || Cools.isEmpty(barcode) || barcode.startsWith("ERROR") || "NG".endsWith(barcode) || "00000000".equals(barcode)) {
                        staProtocol.setWorkNo(wrkNo);
                        staProtocol.setStaNo(emptyInSta.getBackSta().shortValue());
                        devpThread.setPakMk(staProtocol.getSiteId(), false);
                        MessageQueue.offer(SlaveType.Devp, devp.getId(), new Task(2, staProtocol));
                        MessageQueue.offer(SlaveType.Led, emptyInSta.getLed(), new Task(3, "条码扫描错误:" + barcode));
                        continue;
                    }
                    News.warnNoLog(""+mark+" - 0"+" - 开始执行:空栈板初始化入库,叉车入库站放货");
                    try {
@@ -1407,7 +1408,7 @@
                        ledCommand.setEmptyMk(true);
                        break;
                    default:
                        News.error("任务入出库类型错误!!![工作号:{}] [入出库类型:{}]", wrkMast.getWrkNo(), wrkMast.getIoType());
//                        News.error("任务入出库类型错误!!![工作号:{}] [入出库类型:{}]", wrkMast.getWrkNo(), wrkMast.getIoType());
                        break;
                }
                ledCommand.setLocNo(wrkMast.getLocNo());
src/main/java/com/zy/service/impl/RcsServiceImpl.java
@@ -1,5 +1,6 @@
package com.zy.service.impl;
import com.alibaba.excel.util.StringUtils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
@@ -13,10 +14,8 @@
import com.zy.core.model.Task;
import com.zy.core.model.protocol.StaProtocol;
import com.zy.core.properties.SlaveProperties;
import com.zy.entity.RcsReporterTask;
import com.zy.entity.RcsReturn;
import com.zy.entity.WrkDetl;
import com.zy.entity.WrkMast;
import com.zy.core.thread.SiemensDevpThread;
import com.zy.entity.*;
import com.zy.enums.RcsRetMethodEnum;
import com.zy.service.ApiLogService;
import com.zy.service.RcsService;
@@ -29,11 +28,21 @@
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
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.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import static com.zy.enums.RcsRetMethodEnum.APPLY_FROM_AGV;
@Slf4j
@Service
@@ -41,6 +50,9 @@
    @Value("${dj.url}")
    public String DJ_URL;
    @Value("${hik.url}")
    private String HIK_URL;
    @Resource
    private WrkMastService wrkMastService;
@@ -74,19 +86,86 @@
            if (singleRobotCode.equals("14") || singleRobotCode.equals("15")) { // 两台CTU库机器人编号
                WrkMast wrkMast = wrkMastService.selectOne(new EntityWrapper<WrkMast>().eq("task_no", robotTaskCode));
                if (wrkMast != null) {
                    Integer ioType = wrkMast.getIoType();
                    if (Objects.requireNonNull(RcsRetMethodEnum.getEnum(method)) == RcsRetMethodEnum.TASK_END) {
                        if ((ioType == 101 || ioType == 110 || ioType == 103) && wrkMast.getWrkSts() == 12) {
                    if (Objects.requireNonNull(RcsRetMethodEnum.getEnum(method)) == RcsRetMethodEnum.TASK_START) {
                        // 开始
                        wrkMast.setModiTime(now);
                        wrkMastService.updateById(wrkMast);
                    } else if (Objects.requireNonNull(RcsRetMethodEnum.getEnum(method)) == RcsRetMethodEnum.PICK_COMPLETE) {
                        // 取货完成,清除输送线任务号
                        SiemensDevpThread siemensDevpThread = (SiemensDevpThread) SlaveConnection.get(SlaveType.Devp, 1);
                        StaProtocol staProtocol = siemensDevpThread.getStation().get(106).clone();
                        // 取货完成清除输送线任务号
                        if (Objects.equals(staProtocol.getWorkNo(), wrkMast.getWrkNo())) {
                            staProtocol.setWorkNo(0);
                            staProtocol.setStaNo((short) 0);
                            boolean result = MessageQueue.offer(SlaveType.Devp, 1, new Task(2, staProtocol));
                            News.info("CTU取货完成,给站点写0工作号,下发任务:{},站点:{},agv任务号:{}", result, 106, robotTaskCode);
                            if (!result) {
                                rcsReturn.setCode("Err_Internal");
                                rcsReturn.setMessage("清除输送线任务号命令下发失败");
                                JSONObject data = new JSONObject();
                                data.put("robotTaskCode", robotTaskCode);
                                rcsReturn.setData(data);
                                return rcsReturn;
                            }
                        } else {
                            News.warn("CTU取货完成任务号{},清除输送线任务号:{},任务号不同", wrkMast.getWrkNo(), staProtocol.getWorkNo());
                        }
                    } else if (method.equals(APPLY_FROM_AGV.getCode())) {
                        // 放货申请
                        SiemensDevpThread siemensDevpThread = (SiemensDevpThread) SlaveConnection.get(SlaveType.Devp, 1);
                        StaProtocol staProtocol = siemensDevpThread.getStation().get(101).clone();
                        if (staProtocol == null) {
                            rcsReturn.setCode("Err_Internal");
                            rcsReturn.setMessage("101站点线程为空");
                            JSONObject data = new JSONObject();
                            data.put("robotTaskCode", robotTaskCode);
                            rcsReturn.setData(data);
                            return rcsReturn;
                        }
                        if (staProtocol.isOutEnable() && staProtocol.isAutoing() && !staProtocol.isLoading() && staProtocol.getWorkNo() == 0) { // 可出
                            RcsTaskContinue rcsTaskContinue = new RcsTaskContinue();
                            rcsTaskContinue.setRobotTaskCode(robotTaskCode);
                            rcsTaskContinue.setTriggerType("TASK");
                            rcsTaskContinue.setTriggerCode(robotTaskCode);
                            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 (!"SUCCESS".equals(rcsReturn1.getCode())) {
                                    // 返回RCS
                                    rcsReturn.setCode("Err_Internal");
                                    rcsReturn.setMessage("返回继续执行失败");
                                    JSONObject data = new JSONObject();
                                    data.put("robotTaskCode", robotTaskCode);
                                    rcsReturn.setData(data);
                                    return rcsReturn;
                                }
                            }
                        } else {
                            News.warn("站点{}不满足放货条件,自动:{},无物:{},可出:{},任务号:{}",
                                    101, staProtocol.isAutoing(), staProtocol.isLoading(), staProtocol.isOutEnable(), staProtocol.getWorkNo());
                            rcsReturn.setCode("Err_Internal");
                            rcsReturn.setMessage("站点不满足放货条件");
                            JSONObject data = new JSONObject();
                            data.put("robotTaskCode", robotTaskCode);
                            rcsReturn.setData(data);
                            return rcsReturn;
                        }
                    } else if (Objects.requireNonNull(RcsRetMethodEnum.getEnum(method)) == RcsRetMethodEnum.TASK_END) {
                        // 任务完成
                        Integer ioType = wrkMast.getIoType();
                        if (ioType == 1 || ioType == 10 || ioType == 53 || ioType == 57) {
                            wrkMast.setWrkSts(4L);
                            wrkMast.setCrnEndTime(now);
                            wrkMast.setModiTime(now);
                            wrkMastService.updateById(wrkMast);
                        } else if ((ioType == 101 || ioType == 110 || ioType == 103 || ioType == 107) && wrkMast.getWrkSts() == 12) {
                            // 给输送线下发命令
                            for (DevpSlave devp : slaveProperties.getDevp()) {
                                DevpThread devpThread = (DevpThread) SlaveConnection.get(SlaveType.Devp, devp.getId());
                                Map<Integer, StaProtocol> station = devpThread.getStation();
                                StaProtocol staProtocol = station.get(wrkMast.getSourceStaNo());
                                if (staProtocol == null) {
                                    continue;
                                } else {
                                    staProtocol = staProtocol.clone();
                                }
                                StaProtocol staProtocol = devpThread.getStation().get(wrkMast.getSourceStaNo()).clone();
                                staProtocol.setWorkNo(wrkMast.getWrkNo());
                                staProtocol.setStaNo(wrkMast.getStaNo().shortValue());
                                boolean result = MessageQueue.offer(SlaveType.Devp, devp.getId(), new Task(2, staProtocol));
@@ -113,7 +192,7 @@
                                if (!Cools.isEmpty(orderNo)) {
                                    // 构造请求参数
                                    JSONObject jsonObject = new JSONObject();
                                    jsonObject.put("billType",wrkDetl.getThreeCode());
                                    jsonObject.put("billType", wrkDetl.getThreeCode());
                                    jsonObject.put("orderNo", wrkDetl.getOrderNo());
                                    jsonObject.put("createTime", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(now));
                                    JSONArray jsonArray = new JSONArray();
@@ -144,7 +223,7 @@
                                            log.error("出库完成上报TMS失败!url:{};request:{};response:{}", url, request, response);
                                        }
                                    } catch (Exception e) {
                                        log.error("出库完成上报TMS异常,request:{}",request);
                                        log.error("出库完成上报TMS异常,request:{}", request);
                                        e.printStackTrace();
                                    } finally {
                                        try {
@@ -188,4 +267,123 @@
        return rcsReturn;
    }
    @Override
    public RcsReturn reporterEqpt(ReporterEqpt param) {
        String robotTaskCode = param.getTaskCode();
        String method = param.getMethod();
        RcsReturn rcsReturn = new RcsReturn();
        if (method.equals(APPLY_FROM_AGV.getCode())) {
            SiemensDevpThread siemensDevpThread = (SiemensDevpThread) SlaveConnection.get(SlaveType.Devp, 1);
            StaProtocol staProtocol = siemensDevpThread.getStation().get(101).clone();
            if (staProtocol == null) {
                rcsReturn.setCode("Err_Internal");
                rcsReturn.setMessage("101站点线程为空");
                JSONObject data = new JSONObject();
                data.put("robotTaskCode", robotTaskCode);
                rcsReturn.setData(data);
                return rcsReturn;
            }
            if (staProtocol.isOutEnable() && staProtocol.isAutoing() && !staProtocol.isLoading() && staProtocol.getWorkNo() == 0) { // 可出
                EqptNotify eqptNotify = new EqptNotify(param.getEqptCode(), robotTaskCode, "6", "101");
                String url = HIK_URL + "spi/wcs/robot/eqpt/notify";
                String response = sendPost(url, JSONObject.toJSONString(eqptNotify));
                if (!StringUtils.isEmpty(response) && response.contains("code")) {
                    RcsReturn rcsReturn1 = JSONObject.parseObject(response, RcsReturn.class);
                    if (!"0".equals(rcsReturn1.getCode())) {
                        // 返回RCS
                        rcsReturn.setCode("Err_Internal");
                        rcsReturn.setMessage("通知RCS继续放货失败");
                        JSONObject data = new JSONObject();
                        data.put("robotTaskCode", robotTaskCode);
                        rcsReturn.setData(data);
                        return rcsReturn;
                    }
                } else {
                    rcsReturn.setCode("Err_Internal");
                    rcsReturn.setMessage("请求url" + url + "失败");
                    JSONObject data = new JSONObject();
                    data.put("robotTaskCode", robotTaskCode);
                    rcsReturn.setData(data);
                    return rcsReturn;
                }
            } else {
                News.warn("站点{}不满足放货条件,自动:{},无物:{},可出:{},任务号:{}",
                        101, staProtocol.isAutoing(), staProtocol.isLoading(), staProtocol.isOutEnable(), staProtocol.getWorkNo());
                rcsReturn.setCode("Err_Internal");
                rcsReturn.setMessage("站点不满足放货条件");
                JSONObject data = new JSONObject();
                data.put("robotTaskCode", robotTaskCode);
                rcsReturn.setData(data);
                return rcsReturn;
            }
        }
        rcsReturn.setCode("SUCCESS");
        rcsReturn.setMessage("成功!");
        JSONObject data = new JSONObject();
        data.put("extra", "null");
        rcsReturn.setData(data);
        log.info("agv放货请求返回:{}", JSONObject.toJSONString(rcsReturn));
        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();
    }
}
src/main/resources/application.yml
@@ -1,5 +1,5 @@
server:
  port: 9090
  port: 9091
  servlet:
    context-path: /@pom.build.finalName@
@@ -130,10 +130,14 @@
  # LED1
  led[0]:
    id: 1
    ip: 127.0.0.1
    ip: 172.26.11.82
    port: 5005
    devpPlcId: ${wcs-slave.devp[0].id}
    staArr: 103,104
    crnId: 1
# TMS
dj:
  url: http://172.26.11.2/
  url: http://172.26.11.2/
#海康对接
hik:
  url: http://172.26.11.98:80/rcs/rtas/