From 65e1e401ae5ec302ad045e2eb1b0706cc9a0d1d1 Mon Sep 17 00:00:00 2001 From: lsymicc Date: Tue, 24 Jun 2025 18:02:25 +0800 Subject: [PATCH] =?UTF-8?q?agv=E8=AF=B7=E6=B1=82=E5=AE=9E=E4=BD=93?= =?UTF-8?q?=E7=B1=BB=E5=92=8Cplc=E5=88=9D=E5=A7=8B=E5=8C=96=E8=BF=9E?= =?UTF-8?q?=E6=8E=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ruoyi-admin/pom.xml | 13 ++ .../ruoyi/device/agv/domain/ResponseBase.java | 26 +++ .../domain/cancelTask/CancelTaskRequest.java | 65 ++++++++ .../domain/cancelTask/CancelTaskResponse.java | 6 + .../continueTask/ContinueTaskRequest.java | 67 ++++++++ .../continueTask/ContinueTaskResponse.java | 6 + .../domain/continueTask/NextPositionCode.java | 17 ++ .../GenAgvSchedulingTaskRequest.java | 150 ++++++++++++++++++ .../GenAgvSchedulingTaskResponse.java | 13 ++ .../genAgvSchedulingTask/PositionCode.java | 31 ++++ .../ruoyi/schedule/data/ConvConnection.java | 95 +++++++++++ .../schedule/plc/domain/ConvBaseRead.java | 46 ++++++ 12 files changed, 535 insertions(+) create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/device/agv/domain/ResponseBase.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/device/agv/domain/cancelTask/CancelTaskRequest.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/device/agv/domain/cancelTask/CancelTaskResponse.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/device/agv/domain/continueTask/ContinueTaskRequest.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/device/agv/domain/continueTask/ContinueTaskResponse.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/device/agv/domain/continueTask/NextPositionCode.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/device/agv/domain/genAgvSchedulingTask/GenAgvSchedulingTaskRequest.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/device/agv/domain/genAgvSchedulingTask/GenAgvSchedulingTaskResponse.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/device/agv/domain/genAgvSchedulingTask/PositionCode.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/schedule/data/ConvConnection.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/schedule/plc/domain/ConvBaseRead.java diff --git a/ruoyi-admin/pom.xml b/ruoyi-admin/pom.xml index 93bf94c..9efcb4e 100644 --- a/ruoyi-admin/pom.xml +++ b/ruoyi-admin/pom.xml @@ -83,6 +83,19 @@ slf4j-api + + + org.apache.plc4x + plc4j-api + 0.9.0 + + + + org.apache.plc4x + plc4j-driver-s7 + 0.9.0 + + diff --git a/ruoyi-admin/src/main/java/com/ruoyi/device/agv/domain/ResponseBase.java b/ruoyi-admin/src/main/java/com/ruoyi/device/agv/domain/ResponseBase.java new file mode 100644 index 0000000..3ad1468 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/device/agv/domain/ResponseBase.java @@ -0,0 +1,26 @@ +package com.ruoyi.device.agv.domain; + +import lombok.Data; + +import javax.validation.constraints.NotNull; + +@Data +public class ResponseBase { + /** + * 返回码 + */ + private Integer code; + /** + * 返回消息 + */ + private String message; + /** + * 请求编号 + */ + @NotNull + public String reqCode; + /** + * 自定义返回 + */ + private Object data; +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/device/agv/domain/cancelTask/CancelTaskRequest.java b/ruoyi-admin/src/main/java/com/ruoyi/device/agv/domain/cancelTask/CancelTaskRequest.java new file mode 100644 index 0000000..1fa386c --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/device/agv/domain/cancelTask/CancelTaskRequest.java @@ -0,0 +1,65 @@ +package com.ruoyi.device.agv.domain.cancelTask; + +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Size; + +@Data +public class CancelTaskRequest { + + /** + * 请求编号 + */ + @NotBlank(message = "请求编号不能为空") + @Size(max = 32, message = "请求编号不能超过32位") + private String reqCode; + + /** + * 请求时间戳 + * 格式: “yyyy-MM-dd HH:mm:ss” + */ + @Size(max = 20, message = "请求时间格式应为 yyyy-MM-dd HH:mm:ss") + private String reqTime; + + /** + * 客户端编号 + */ + @Size(max = 16, message = "客户端编号不能超过16位") + private String clientCode; + + /** + * 令牌号, 由调度系统颁发,由RCS-2000告知上层系统 + */ + @Size(max = 64, message = "令牌号不能超过64位") + private String tokenCode; + + /** + * 取消类型 + * 0表示:取消后货架直接放地上 + * 1表示:AGV仍然背着货架, 根据回库区域执行回库指令, 只有潜伏车和CTU车支持。 + * 若不传值,默认的取消模式为0 + */ + @Size(max = 16, message = "取消类型不能超过16位") + private String forceCancel; + + /** + * forcecancel=1时有意义, + * 回库区域编号, + * 如果为空,采用货架配置的库区 + */ + @Size(max = 16, message = "回库区域编号不能超过16位") + private String matterArea; + + /** + * 取消该AGV正在执行的任务单 + */ + @Size(max = 5, message = "AGV编号不能超过5位") + private String agvCode; + + /** + * 任务单编号, 取消该任务单 + */ + @Size(max = 64, message = "任务单编号不能超过64位") + private String taskCode; +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/device/agv/domain/cancelTask/CancelTaskResponse.java b/ruoyi-admin/src/main/java/com/ruoyi/device/agv/domain/cancelTask/CancelTaskResponse.java new file mode 100644 index 0000000..305f365 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/device/agv/domain/cancelTask/CancelTaskResponse.java @@ -0,0 +1,6 @@ +package com.ruoyi.device.agv.domain.cancelTask; + +import com.ruoyi.device.agv.domain.ResponseBase; + +public class CancelTaskResponse extends ResponseBase { +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/device/agv/domain/continueTask/ContinueTaskRequest.java b/ruoyi-admin/src/main/java/com/ruoyi/device/agv/domain/continueTask/ContinueTaskRequest.java new file mode 100644 index 0000000..9770c00 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/device/agv/domain/continueTask/ContinueTaskRequest.java @@ -0,0 +1,67 @@ +package com.ruoyi.device.agv.domain.continueTask; + +import lombok.Data; + +@Data +public class ContinueTaskRequest { + + /** + * 请求编号 + * 每个请求都要一个唯一编号,同一个请求重复提交,使用同一编号。 + */ + private String reqCode; + + /** + * 请求时间截 + * 格式:"yyyy-MM-dd HH:mm:ss" + */ + private String reqTime; + + /** + * 客户端编号 + * 如PDA,HCWMS等。 + */ + private String clientCode; + + /** + * 令牌号 + * 由调度系统颁发。 + */ + private String tokenCode; + + /** + * 工作位 + * 与RCS-2000端配置的位置名称一致。 + */ + private String wbCode; + + /** + * 货架号 + * 采用货架号触发的方式。 + */ + private String podCode; + + /** + * AGV编号 + * 采用AGV编号触发的方式。 + */ + private String agvCode; + + /** + * 任务单号 + * 选填,不填系统自动生成,必须为64位UUID。 + */ + private String taskCode; + + /** + * 下一个子任务的序列 + * 指定第几个子任务开始执行,校验子任务执行是否正确。不填默认执行下一个子任务。 + */ + private String taskSeq; + + /** + * 下一个位置信息 + * 在任务类型中配置外部设置时需要传入,否则不需要设置。待现场地图部署、配置完成后可获取。 + */ + private NextPositionCode nextPositionCode; +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/device/agv/domain/continueTask/ContinueTaskResponse.java b/ruoyi-admin/src/main/java/com/ruoyi/device/agv/domain/continueTask/ContinueTaskResponse.java new file mode 100644 index 0000000..095de32 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/device/agv/domain/continueTask/ContinueTaskResponse.java @@ -0,0 +1,6 @@ +package com.ruoyi.device.agv.domain.continueTask; + +import com.ruoyi.device.agv.domain.ResponseBase; + +public class ContinueTaskResponse extends ResponseBase { +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/device/agv/domain/continueTask/NextPositionCode.java b/ruoyi-admin/src/main/java/com/ruoyi/device/agv/domain/continueTask/NextPositionCode.java new file mode 100644 index 0000000..203bf24 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/device/agv/domain/continueTask/NextPositionCode.java @@ -0,0 +1,17 @@ +package com.ruoyi.device.agv.domain.continueTask; + +public class NextPositionCode { + + /** + * 位置编号 + */ + private String positionCode; + + /** + * 对象类型定义 + * 00:代表nextPositionCode是一个位置 + * 02:代表nextPositionCode是一个策略 + */ + private String type; + +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/device/agv/domain/genAgvSchedulingTask/GenAgvSchedulingTaskRequest.java b/ruoyi-admin/src/main/java/com/ruoyi/device/agv/domain/genAgvSchedulingTask/GenAgvSchedulingTaskRequest.java new file mode 100644 index 0000000..856d19c --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/device/agv/domain/genAgvSchedulingTask/GenAgvSchedulingTaskRequest.java @@ -0,0 +1,150 @@ +package com.ruoyi.device.agv.domain.genAgvSchedulingTask; + +import lombok.Data; + +import javax.validation.constraints.NotNull; +import java.util.List; + +@Data +public class GenAgvSchedulingTaskRequest { + /** + * 请求编号 + * 同一个请求重复提交, 使用同一编号 + */ + @NotNull + private String reqCode; + /** + * 请求时间 + * 格式: “yyyy-MM-dd HH:mm:ss” + */ + private String reqTime; + /** + * 客户端编号 + * 客户端编号,如PDA,HCWMS等 + */ + private String clientCode; + /** + * 令牌号 + * 由调度系统颁发 + */ + private String tokenCode; + /** + * 任务类型 + * 内置任务类型: + * 厂内货架搬运: F01 + * 厂内货架空满交换: F02 + * 辊筒搬运接驳:F03 + * 厂内货架出库AGV待命:F04 + * 旋转货架: F05 + * 厂内电梯任务: F06 + * 以下为叉车专用任务类型 + * 高位货架到工作台: F11 + * 工作台到高位货架: F12 + * 巷道到工作台: F13 + * 工作台到巷道: F14 + * 高位货架到工作台(接驳) : F15 + * 工作台到高位货架 (接驳) : F16 + * 巷道到工作台(接驳) : F17 + * 工作台到巷道(接驳) : F18 + * 叉车电梯主任务: F20 + */ + @NotNull + private String taskTyp; + /** + * 容器类型(叉车/CTU专用) 叉车项目必传 + */ + private String ctnrTyp; + /** + * 容器编号 (叉车/CTU专用) + */ + private String ctnrCode; // + /** + * 容器数量(叉车堆叠专用),默认值1,仅记录堆叠的数量不记录堆叠的每个容器号 + */ + private String ctnrNum; + /** + * 任务模式 + * 0-普通move 1-出库move 2-入库move 3-移库move + */ + private String taskMode; + /** + * 工作位 + * 与RCS-2000端配置的位置名称一致, 工作位名称为字母\数字\或组合 + */ + private String wbCode; + /** + * 位置路径 + * AGV关键路径位置集合,与任务类型中模板配置的位置路径一一对应。待现场地图部署、配置完成后可获取 + */ + private List positionCodePath; + /** + * 货架编号 + * 不指定货架可以为空 + */ + private String podCode; + /** + * 货架方向 + * “180”,”0”,”90”,”-90” 分别对应地图的”左”,”右”,”上”,”下” + * 不指定方向可以为空 + * 如果终点不是工作台或工作台未配置操作方向则货架拣货方向podDir作为终点方向 + * 如果工作台配有操作方向,则系统会根据货架拣货方向podDir和工作台操作方向计算货架终点方向 + */ + private String podDir; + /** + * 货架类型, 传空时表示随机找个货架 + * 找空货架传参方式如下: + * -1: 代表不关心货架类型, 找到空货架即可. + * -2: 代表从工作位获取关联货架类型, 如果未配置, 只找空货架. + * 货架类型编号: 只找该货架类型的空货架 + */ + private String podTyp; + /** + * 物料批次 + * 物料批次或货架上的物料唯一编码,生成任务单时,货架与物料直接绑定时使用. (通过同时传podCode和materialLot来绑定或通过 wbCode 找到位置上的货架和materialLot来绑定) + * 如果是区域/策略内查找货架,可以匹配对应物料批次的货架,支持以下值: + * 0:区域/策略内查找空货架 + * 1:区域/策略内查找满货架 + * 其他值:查找指定物料批次对应的货架 + * 巷道任务通过该字段传入特征值 + */ + private String materialLot; + /** + * 优先级 + * 从(1~127)级,最大优先级最高。为空时,采用任务模板的优先级 + */ + private String priority; + /** + * AGV编号 + * 填写表示指定某一编号的AGV执行该任务 + */ + private String agvCode; + /** + * 任务单号 + * 选填, 不填系统自动生成 + */ + private String taskCode; + /** + * 组编号 + * CTU场景下用于按组出库,同组任务优先拼车。 如业务需要任务组间或组内按顺序出库,则需调用料箱顺序出库(CTU)接口。 + * 潜伏式场景下,通过组号来管理顺序出库的顺序,组号小的优先出库。 + */ + private String groupId; + /** + * 设备类型 + */ + private String agvTyp; + /** + * 选择策略 + * 区域/策略中挑选货架以及根据物料批次挑选货架时的先进先出规则,支持以下4个值: + * 1:按照货架到达储位的时间顺序,先进先出 + * 2:按照货架到达储位的时间顺序,先进后出 + * 9:按照货架绑定物料批次的时间顺序,先进先出 + * 10:按照货架绑定物料批次的时间顺序,先进后出 + */ + private String positionSelStrategy; + /** + * 自定义数据 + */ + private String data; + +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/device/agv/domain/genAgvSchedulingTask/GenAgvSchedulingTaskResponse.java b/ruoyi-admin/src/main/java/com/ruoyi/device/agv/domain/genAgvSchedulingTask/GenAgvSchedulingTaskResponse.java new file mode 100644 index 0000000..073c8f9 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/device/agv/domain/genAgvSchedulingTask/GenAgvSchedulingTaskResponse.java @@ -0,0 +1,13 @@ +package com.ruoyi.device.agv.domain.genAgvSchedulingTask; + +import com.ruoyi.device.agv.domain.ResponseBase; +import lombok.Data; + +import javax.validation.constraints.NotNull; + +@Data +public class GenAgvSchedulingTaskResponse extends ResponseBase { + + + +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/device/agv/domain/genAgvSchedulingTask/PositionCode.java b/ruoyi-admin/src/main/java/com/ruoyi/device/agv/domain/genAgvSchedulingTask/PositionCode.java new file mode 100644 index 0000000..83aeac7 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/device/agv/domain/genAgvSchedulingTask/PositionCode.java @@ -0,0 +1,31 @@ +package com.ruoyi.device.agv.domain.genAgvSchedulingTask; + +import lombok.Data; + +@Data +public class PositionCode { + /** + * 位置编号 - 单个编号不超过64位 + */ + private String positionCode; + /** + * 类型 + * + * 位置类型说明: + * 00表示:位置编号 + * 01表示:物料批次号 + * 02表示:策略编号(含多个区域) 如:第一个区域放不下, 可以放第二个区域 + * 03表示:货架编号,通过货架编号找到货架所在位置 + * 04表示:区域编号,在区域中查找可用位置 + * 05表示:仓位编号(叉车/CTU专用) + * 06表示:巷道编号 + * 07表示:容器编号 + * 08表示:巷道策略 + * 09表示:巷道区域 + * 10表示:巷道仓位 + * 11表示:输送线(机台)编号 + * 12表示:CTU工作台(梳齿工作站)编号 + * 13表示:搬运巷道指定货架出库 + */ + private String type; +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/schedule/data/ConvConnection.java b/ruoyi-admin/src/main/java/com/ruoyi/schedule/data/ConvConnection.java new file mode 100644 index 0000000..d8599a2 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/schedule/data/ConvConnection.java @@ -0,0 +1,95 @@ +package com.ruoyi.schedule.data; + + +import com.ruoyi.schedule.plc.domain.ConvPortRead; +import lombok.extern.slf4j.Slf4j; +import org.apache.plc4x.java.PlcDriverManager; +import org.apache.plc4x.java.api.PlcConnection; +import org.apache.plc4x.java.api.messages.PlcReadRequest; +import org.apache.plc4x.java.api.messages.PlcReadResponse; +import org.apache.plc4x.java.api.types.PlcResponseCode; +import org.springframework.stereotype.Service; + +import javax.annotation.PostConstruct; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.TimeUnit; + +/** + * 获取输送机plc连接 + */ +@Slf4j +@Service +public class ConvConnection { + + Integer convPortCount = 10; + + String ipConv = "127.0.0.1"; + + PlcConnection convConnection; + + /** + * 初始化输送机plc连接 + */ + @PostConstruct + public void initializeConvConnection() { + try { + convConnection = new PlcDriverManager().getConnection("s7://" + ipConv); + log.info("【输送机连接初始化】输送机连接成功!"); + }catch (Exception e){ + log.warn("【输送机连接初始化】输送机连接失败:" + e.getMessage()); + } + } + + + /** + * 获取所有输送机状态参数 + * @return + */ + public List getConvPortStatus() { + + List convPorts = new ArrayList<>(); + + for (int i = 0; i < convPortCount; i++) { + try { + PlcReadRequest.Builder builder = convConnection.readRequestBuilder(); + + builder.addItem("value-test","%M0.0:BOOL"); + builder.addItem("conv-inPostion","%DB501.DBW" + (0 + i * 30) + ":INT"); + builder.addItem("conv-height","%DB501.DBW" + (2 + i * 30) + ":INT"); + builder.addItem("conv-isException","%DB501.DBD" + (4 + i * 30) + ":DINT"); + builder.addItem("conv-free","%DB501.DBW" + (6 + i * 30) + ":INT"); + builder.addItem("conv-taskId","%DB501.DBD" + (8 + i * 30) + ":INT"); + builder.addItem("conv-palletId","%DB501.DBD" + (16 + i * 30) + ":STRING"); + + PlcReadRequest readRequest = builder.build(); + + PlcReadResponse response=readRequest.execute().get(2000, TimeUnit.MILLISECONDS); + + if (response.getResponseCode("value-test") == PlcResponseCode.OK) { + convPorts.get(i).setInPostion(response.getInteger("conv-inPostion")); + convPorts.get(i).setHeight(response.getInteger("conv-height")); + convPorts.get(i).setIsException(response.getInteger("conv-isException")); + convPorts.get(i).setFree(response.getInteger("conv-free")); + convPorts.get(i).setTaskId(response.getString("conv-taskId")); + convPorts.get(i).setPalletId(response.getString("conv-palletId")); + + }else{ + log.warn("【获取出入口输送机状态】获取状态参数失败:" + response.getResponseCode("value-test")); + return null; + } + + } catch (Exception e) { + log.warn("【获取出入口输送机状态】获取状态参数失败:" + e.getMessage()); + return null; + } + } + + return convPorts; + + } + + + + +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/schedule/plc/domain/ConvBaseRead.java b/ruoyi-admin/src/main/java/com/ruoyi/schedule/plc/domain/ConvBaseRead.java new file mode 100644 index 0000000..145d750 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/schedule/plc/domain/ConvBaseRead.java @@ -0,0 +1,46 @@ +package com.ruoyi.schedule.plc.domain; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class ConvBaseRead { + + /** + * 输送机编号 + */ + private String convName; + + /** + * 任务号 + */ + private String taskId; + + /** + * 是否空闲 + * 1-空闲 0-占用 + */ + private Integer free; + + /** + * 输送到位 + * 0-未到位 1-到位 + */ + private Integer inPostion; + + /** + * 入库到位 + * 0-未到位 1-到位 + */ + private Integer inPostionForStockIn; + + /** + * 出库到位 + * 0-未到位 1-到位 + */ + private Integer inPostionForStockOut; + +}