From eb8cf7ca0b55a8c4a0543e188b86d099dfc80dfb Mon Sep 17 00:00:00 2001 From: "HUOJIN\\92525" Date: Fri, 7 Nov 2025 17:55:05 +0800 Subject: [PATCH] =?UTF-8?q?Agv=E4=BB=BB=E5=8A=A1=E4=B8=8A=E6=8A=A5?= =?UTF-8?q?=E3=80=81=E8=BE=93=E9=80=81=E7=BA=BF=E6=89=AB=E6=8F=8F=E6=89=98?= =?UTF-8?q?=E7=9B=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../jeecg/common/aspect/AutoLogAspect.java | 4 +- .../org/jeecg/common/aspect/DictAspect.java | 12 +- cpte-boot-module/cpte-module-wms/pom.xml | 4 + .../cpte/modules/agvTask/entity/AgvTask.java | 25 +- .../modules/agvTask/mapper/AgvTaskMapper.java | 6 +- .../agvTask/service/IAgvTaskService.java | 8 + .../service/impl/AgvTaskServiceImpl.java | 10 + .../controller/ConveyorLineController.java | 42 +++ .../conveyorLine/request/ScanTrayRequest.java | 13 + .../service/IConveyorLineService.java | 13 + .../impl/IConveyorLineServiceImpl.java | 27 ++ .../hikAgv/controller/HikAgvController.java | 60 +++++ .../hikAgv/request/submit/AngleInfo.java | 28 ++ .../hikAgv/request/submit/CarrierInfo.java | 34 +++ .../modules/hikAgv/request/submit/Extra.java | 30 +++ .../hikAgv/request/submit/SubmitRequest.java | 104 ++++++++ .../hikAgv/request/submit/TargetRoute.java | 70 +++++ .../hikAgv/request/taskReporter/Extra.java | 15 ++ .../taskReporter/TaskReporterRequest.java | 36 +++ .../hikAgv/request/taskReporter/Values.java | 124 +++++++++ .../modules/hikAgv/response/HikResult.java | 46 ++++ .../modules/hikAgv/response/ResponesData.java | 10 + .../hikAgv/service/IHikAgvService.java | 30 +++ .../service/impl/IHikAgvServiceImpl.java | 251 ++++++++++++++++++ .../cpte/modules/quartz/job/AgvTaskJob.java | 38 +++ .../receive/mapper/AsnDetailMapper.java | 47 ++-- .../modules/receive/mapper/AsnMapper.java | 2 + .../org/cpte/modules/utils/HttpPostUtil.java | 75 ++++++ cpte-module-system/cpte-system-biz/pom.xml | 2 +- .../jeecg/modules/quartz/job/AgvTaskJob.java | 25 -- .../modules/system/mapper/SysDictMapper.java | 3 + 31 files changed, 1145 insertions(+), 49 deletions(-) create mode 100644 cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/conveyorLine/controller/ConveyorLineController.java create mode 100644 cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/conveyorLine/request/ScanTrayRequest.java create mode 100644 cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/conveyorLine/service/IConveyorLineService.java create mode 100644 cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/conveyorLine/service/impl/IConveyorLineServiceImpl.java create mode 100644 cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/hikAgv/controller/HikAgvController.java create mode 100644 cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/hikAgv/request/submit/AngleInfo.java create mode 100644 cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/hikAgv/request/submit/CarrierInfo.java create mode 100644 cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/hikAgv/request/submit/Extra.java create mode 100644 cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/hikAgv/request/submit/SubmitRequest.java create mode 100644 cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/hikAgv/request/submit/TargetRoute.java create mode 100644 cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/hikAgv/request/taskReporter/Extra.java create mode 100644 cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/hikAgv/request/taskReporter/TaskReporterRequest.java create mode 100644 cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/hikAgv/request/taskReporter/Values.java create mode 100644 cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/hikAgv/response/HikResult.java create mode 100644 cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/hikAgv/response/ResponesData.java create mode 100644 cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/hikAgv/service/IHikAgvService.java create mode 100644 cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/hikAgv/service/impl/IHikAgvServiceImpl.java create mode 100644 cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/quartz/job/AgvTaskJob.java create mode 100644 cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/utils/HttpPostUtil.java delete mode 100644 cpte-module-system/cpte-system-biz/src/main/java/org/jeecg/modules/quartz/job/AgvTaskJob.java diff --git a/cpte-boot-base-core/src/main/java/org/jeecg/common/aspect/AutoLogAspect.java b/cpte-boot-base-core/src/main/java/org/jeecg/common/aspect/AutoLogAspect.java index ef21a9f..1ee2801 100644 --- a/cpte-boot-base-core/src/main/java/org/jeecg/common/aspect/AutoLogAspect.java +++ b/cpte-boot-base-core/src/main/java/org/jeecg/common/aspect/AutoLogAspect.java @@ -104,7 +104,9 @@ public class AutoLogAspect { if(sysUser!=null){ dto.setUserid(sysUser.getUsername()); dto.setUsername(sysUser.getRealname()); - + }else { + dto.setUserid("赛意"); + dto.setUsername("赛意"); } //耗时 dto.setCostTime(time); diff --git a/cpte-boot-base-core/src/main/java/org/jeecg/common/aspect/DictAspect.java b/cpte-boot-base-core/src/main/java/org/jeecg/common/aspect/DictAspect.java index 9f9de8e..20cebdd 100644 --- a/cpte-boot-base-core/src/main/java/org/jeecg/common/aspect/DictAspect.java +++ b/cpte-boot-base-core/src/main/java/org/jeecg/common/aspect/DictAspect.java @@ -52,10 +52,20 @@ public class DictAspect { /** * 定义切点Pointcut */ - @Pointcut("(@within(org.springframework.web.bind.annotation.RestController) || " + +/* @Pointcut("(@within(org.springframework.web.bind.annotation.RestController) || " + "@within(org.springframework.stereotype.Controller) || @annotation(org.jeecg.common.aspect.annotation.AutoDict)) " + "&& execution(public org.jeecg.common.api.vo.Result org.jeecg..*.*(..)) || execution(public * org.cpte..*.*Controller.*(..))") public void excudeService() { + }*/ + + /** + * 定义切点Pointcut + */ + @Pointcut("(@within(org.springframework.web.bind.annotation.RestController) || " + + "@within(org.springframework.stereotype.Controller) || @annotation(org.jeecg.common.aspect.annotation.AutoDict)) " + + "&& (execution(public org.jeecg.common.api.vo.Result org.jeecg..*.*(..)) || " + + "(execution(public * org.cpte..*.*Controller.*(..)) && !execution(public org.cpte.modules.hikAgv.response.* org.cpte.modules.hikAgv.controller.*.*(..))))") + public void excudeService() { } @Around("excudeService()") diff --git a/cpte-boot-module/cpte-module-wms/pom.xml b/cpte-boot-module/cpte-module-wms/pom.xml index ecc0e2f..8866293 100644 --- a/cpte-boot-module/cpte-module-wms/pom.xml +++ b/cpte-boot-module/cpte-module-wms/pom.xml @@ -14,5 +14,9 @@ org.jeecgframework.boot3 cpte-boot-base-core + + org.jeecgframework.boot3 + cpte-system-biz + diff --git a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/agvTask/entity/AgvTask.java b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/agvTask/entity/AgvTask.java index 188a4a2..9c20e17 100644 --- a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/agvTask/entity/AgvTask.java +++ b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/agvTask/entity/AgvTask.java @@ -1,6 +1,7 @@ package org.cpte.modules.agvTask.entity; import java.io.Serializable; +import java.sql.Timestamp; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableId; @@ -13,6 +14,8 @@ import org.jeecgframework.poi.excel.annotation.Excel; import io.swagger.v3.oas.annotations.media.Schema; import lombok.experimental.Accessors; +import javax.persistence.Column; + /** * @Description: AGV任务表 * @author: cpte @@ -99,13 +102,27 @@ public class AgvTask implements Serializable { @Schema(description = "返回报文") private java.lang.String resMessage; /** - * 返回时间 + *走出储位时间 */ - @Excel(name = "返回时间", width = 20, format = "yyyy-MM-dd HH:mm:ss") @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss") @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") - @Schema(description = "返回时间") - private java.util.Date resMessageTime; + @Schema(description = "走出储位时间") + private java.util.Date outBinTime; + + /** + * 开始时间 + */ + @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @Schema(description = "开始时间") + private java.util.Date startTime; + /** + * 完成时间 + */ + @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @Schema(description = "完成时间") + private java.util.Date endTime; /** * 所属部门 */ diff --git a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/agvTask/mapper/AgvTaskMapper.java b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/agvTask/mapper/AgvTaskMapper.java index e11090e..4d1112b 100644 --- a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/agvTask/mapper/AgvTaskMapper.java +++ b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/agvTask/mapper/AgvTaskMapper.java @@ -3,15 +3,17 @@ package org.cpte.modules.agvTask.mapper; import java.util.List; import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; import org.cpte.modules.agvTask.entity.AgvTask; import com.baomidou.mybatisplus.core.mapper.BaseMapper; /** * @Description: AGV任务表 * @author: cpte - * @Date: 2025-11-06 + * @Date: 2025-11-06 * @Version: V1.0 */ public interface AgvTaskMapper extends BaseMapper { - + @Select(value = "select count(agv.id) from data_agv_task where carrier_code = #{carrierCode} and start_code = #{startCode} and end_code= #{endCode} and status in ('CREATED','ARRIVED','EXECUTING') ") + Long isAGVTaskDuplicate(String carrierCode, String startCode, String endCode); } diff --git a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/agvTask/service/IAgvTaskService.java b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/agvTask/service/IAgvTaskService.java index 502c622..577af48 100644 --- a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/agvTask/service/IAgvTaskService.java +++ b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/agvTask/service/IAgvTaskService.java @@ -3,6 +3,8 @@ package org.cpte.modules.agvTask.service; import org.cpte.modules.agvTask.entity.AgvTask; import com.baomidou.mybatisplus.extension.service.IService; +import java.util.List; + /** * @Description: AGV任务表 * @author: cpte @@ -22,4 +24,10 @@ public interface IAgvTaskService extends IService { */ AgvTask createAgvTask(String status, String carrierCode, String startCode, String endCode, String taskType,String type); + /** + * 查询agvTask任务列表 + * + * @param status 状态 + */ + List queryAgvTaskList(String status); } diff --git a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/agvTask/service/impl/AgvTaskServiceImpl.java b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/agvTask/service/impl/AgvTaskServiceImpl.java index a99f442..6fe2be5 100644 --- a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/agvTask/service/impl/AgvTaskServiceImpl.java +++ b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/agvTask/service/impl/AgvTaskServiceImpl.java @@ -1,5 +1,6 @@ package org.cpte.modules.agvTask.service.impl; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import org.cpte.modules.agvTask.entity.AgvTask; import org.cpte.modules.agvTask.mapper.AgvTaskMapper; import org.cpte.modules.agvTask.service.IAgvTaskService; @@ -9,6 +10,8 @@ import org.springframework.stereotype.Service; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import org.springframework.transaction.annotation.Transactional; +import java.util.List; + /** * @Description: AGV任务表 * @author: cpte @@ -33,4 +36,11 @@ public class AgvTaskServiceImpl extends ServiceImpl impl .build(); return this.save(agvTask) ? agvTask : null; } + + @Override + public List queryAgvTaskList(String status) { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(AgvTask::getStatus, status); + return this.list(queryWrapper); + } } diff --git a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/conveyorLine/controller/ConveyorLineController.java b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/conveyorLine/controller/ConveyorLineController.java new file mode 100644 index 0000000..f9b4807 --- /dev/null +++ b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/conveyorLine/controller/ConveyorLineController.java @@ -0,0 +1,42 @@ +package org.cpte.modules.conveyorLine.controller; + +import com.alibaba.fastjson.JSON; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import lombok.extern.slf4j.Slf4j; +import org.cpte.modules.conveyorLine.request.ScanTrayRequest; +import org.cpte.modules.conveyorLine.service.IConveyorLineService; +import org.jeecg.common.api.vo.Result; +import org.jeecg.common.aspect.annotation.AutoLog; +import org.jeecg.config.shiro.IgnoreAuth; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@Tag(name = "输送线") +@RestController +@RequestMapping("/api/conveyorLine") +@Slf4j +public class ConveyorLineController { + + @Autowired + private IConveyorLineService iConveyorLineService; + + /** + * 输送线扫描 + * + * @param scanTrayRequest 请求参数 + */ + @AutoLog(value = "输送线扫描") + @Operation(summary = "输送线-扫描托盘") + @PostMapping(value = "/scanTray") + @IgnoreAuth + public Result scanTray(@RequestBody @Valid ScanTrayRequest scanTrayRequest) { + iConveyorLineService.scanTray(scanTrayRequest); + return Result.OK("扫描成功"); + } + +} diff --git a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/conveyorLine/request/ScanTrayRequest.java b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/conveyorLine/request/ScanTrayRequest.java new file mode 100644 index 0000000..403a02e --- /dev/null +++ b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/conveyorLine/request/ScanTrayRequest.java @@ -0,0 +1,13 @@ +package org.cpte.modules.conveyorLine.request; + +import com.fasterxml.jackson.annotation.JsonProperty; +import jakarta.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class ScanTrayRequest { + //托盘码 + @NotBlank(message = "托盘码不能为空") + @JsonProperty("stockCode") + private String stockCode; +} diff --git a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/conveyorLine/service/IConveyorLineService.java b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/conveyorLine/service/IConveyorLineService.java new file mode 100644 index 0000000..67c9af0 --- /dev/null +++ b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/conveyorLine/service/IConveyorLineService.java @@ -0,0 +1,13 @@ +package org.cpte.modules.conveyorLine.service; + +import org.cpte.modules.conveyorLine.request.ScanTrayRequest; + +public interface IConveyorLineService { + + /** + * 扫描托盘 + * + * @param scanTrayRequest 扫描托盘请求参数 + */ + void scanTray(ScanTrayRequest scanTrayRequest); +} diff --git a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/conveyorLine/service/impl/IConveyorLineServiceImpl.java b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/conveyorLine/service/impl/IConveyorLineServiceImpl.java new file mode 100644 index 0000000..55e9d12 --- /dev/null +++ b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/conveyorLine/service/impl/IConveyorLineServiceImpl.java @@ -0,0 +1,27 @@ +package org.cpte.modules.conveyorLine.service.impl; + +import lombok.extern.slf4j.Slf4j; +import org.cpte.modules.conveyorLine.request.ScanTrayRequest; +import org.cpte.modules.conveyorLine.service.IConveyorLineService; +import org.cpte.modules.receive.entity.AsnDetail; +import org.cpte.modules.receive.mapper.AsnDetailMapper; +import org.cpte.modules.receive.service.IAsnService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +@Slf4j +public class IConveyorLineServiceImpl implements IConveyorLineService { + @Autowired + private AsnDetailMapper asnDetailMapper; + + @Override + public void scanTray(ScanTrayRequest scanTrayRequest) { + AsnDetail asnDetail=asnDetailMapper.queryByStockCode(scanTrayRequest.getStockCode()); + if(asnDetail==null){ + throw new RuntimeException("【"+scanTrayRequest.getStockCode()+"】托盘,无入库信息"); + } + } +} + + diff --git a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/hikAgv/controller/HikAgvController.java b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/hikAgv/controller/HikAgvController.java new file mode 100644 index 0000000..2bee872 --- /dev/null +++ b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/hikAgv/controller/HikAgvController.java @@ -0,0 +1,60 @@ +package org.cpte.modules.hikAgv.controller; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.extern.slf4j.Slf4j; +import org.cpte.modules.hikAgv.request.submit.SubmitRequest; +import org.cpte.modules.hikAgv.request.taskReporter.TaskReporterRequest; +import org.cpte.modules.hikAgv.response.ResponesData; +import org.cpte.modules.hikAgv.service.IHikAgvService; +import org.jeecg.common.api.vo.Result; +import org.cpte.modules.hikAgv.response.HikResult; +import org.jeecg.common.aspect.annotation.AutoLog; +import org.jeecg.config.shiro.IgnoreAuth; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@Tag(name = "海康AGV") +@RestController +@RequestMapping("/api/robot") +@Slf4j +public class HikAgvController { + + @Autowired + private IHikAgvService hikAgvService; + + /** + * 任务下发 + * + * @param submitRequest 请求参数 + */ + @AutoLog(value = "任务下发") + @Operation(summary = "海康AGV-任务下发") + @PostMapping(value = "/controller/task/submit") + @IgnoreAuth + public Result submit(@RequestBody SubmitRequest submitRequest) { + hikAgvService.sendAgvTask("http://localhost:8000/cpte-wms/rcs/rtas/api/robot/controller/task/submit", JSON.toJSONString(submitRequest), null); + return Result.OK("下发成功!"); + } + + @AutoLog(value = "任务上报") + @Operation(summary = "海康AGV-任务上报") + @PostMapping(value = "/reporter/task") + @IgnoreAuth + public HikResult taskReporter(@RequestBody TaskReporterRequest taskReporterRequest) { + try { + hikAgvService.taskReporter(taskReporterRequest); + ResponesData data = new ResponesData(); + data.setRobotTaskCode(taskReporterRequest.getRobotTaskCode()); + return HikResult.success(data); + } catch (Exception e) { + return HikResult.error("上报失败: " + e.getMessage()); + } + } +} diff --git a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/hikAgv/request/submit/AngleInfo.java b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/hikAgv/request/submit/AngleInfo.java new file mode 100644 index 0000000..4046270 --- /dev/null +++ b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/hikAgv/request/submit/AngleInfo.java @@ -0,0 +1,28 @@ +package org.cpte.modules.hikAgv.request.submit; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; + +/** + * 角度信息类 + * + * 用于描述AGV在工作站的角度信息配置,包括角度类型和具体角度值。 + */ +@Data +public class AngleInfo { + /** + * 角度类型 + * 可扩展枚举值,预制枚举值: + * ABSOLUTE: 绝对角度(与工作站的方向有关) + */ + @JsonProperty("type") + private String type; + + /** + * 角度值 + * 与 type 对应的具体角度值 + * 支持的角度值:[0, 90, 180, -90, 360] + */ + @JsonProperty("code") + private String code; +} diff --git a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/hikAgv/request/submit/CarrierInfo.java b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/hikAgv/request/submit/CarrierInfo.java new file mode 100644 index 0000000..696870f --- /dev/null +++ b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/hikAgv/request/submit/CarrierInfo.java @@ -0,0 +1,34 @@ +package org.cpte.modules.hikAgv.request.submit; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; + +/** + * 载具信息类 + * + * 用于描述AGV运输过程中承载货物的载具信息,包括载具类型、编码和层号等属性。 + */ +@Data +public class CarrierInfo { + + /** + * 载具类型 + * 描述载具的类型信息 + */ + @JsonProperty("carrierType") + private String carrierType; + + /** + * 载具编码 + * 载具的唯一标识编码 + */ + @JsonProperty("carrierCode") + private String carrierCode; + + /** + * 层号 + * 货物所在的层数,从0开始计数,从下往上编号 + */ + @JsonProperty("layer") + private String layer; +} diff --git a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/hikAgv/request/submit/Extra.java b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/hikAgv/request/submit/Extra.java new file mode 100644 index 0000000..01af057 --- /dev/null +++ b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/hikAgv/request/submit/Extra.java @@ -0,0 +1,30 @@ +package org.cpte.modules.hikAgv.request.submit; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; + +import java.util.List; + +/** + * 扩展信息类 + * + * 用于承载AGV任务的扩展配置信息,包括角度信息和载具信息等可选配置。 + */ +@Data +public class Extra { + + /** + * 角度信息 + * 包含角度类型与角度值,用于指定AGV在工作站的角度配置 + */ + @JsonProperty("angleInfo") + private AngleInfo angleInfo; + + /** + * 载具信息集合 + * 包含载具编号、层号等信息,用于描述运输过程中的载具配置 + * 支持多个载具信息的配置 + */ + @JsonProperty("carrierInfo") + private List carrierInfo; +} diff --git a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/hikAgv/request/submit/SubmitRequest.java b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/hikAgv/request/submit/SubmitRequest.java new file mode 100644 index 0000000..2dfe910 --- /dev/null +++ b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/hikAgv/request/submit/SubmitRequest.java @@ -0,0 +1,104 @@ +package org.cpte.modules.hikAgv.request.submit; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import lombok.Data; + +import java.util.List; + +/** + * AGV任务提交请求类 + *

+ * 用于向AGV系统提交任务请求的DTO对象,包含任务执行所需的所有参数配置。 + * 支持配置任务类型、执行路径、优先级、截止时间、机器人资源等核心属性。 + */ + +@JsonPropertyOrder({ + "taskType", + "targetRoute", + "initPriority", + "deadline", + "robotType", + "robotCode", + "interrupt", + "robotTaskCode", + "groupCode", + "extra" +}) +@Data +public class SubmitRequest { + /** + * 任务类型 + * 指定AGV需要执行的任务类型 + */ + @JsonProperty("taskType") + private String taskType; + + /** + * 执行步骤集合 + * 任务执行的路径规划和步骤集合 + */ + @JsonProperty("targetRoute") + private List targetRoute; + + /** + * 优先级 + * 任务的初始优先级设置 + */ + @JsonProperty("initPriority") + private Integer initPriority; + + /** + * 截止时间 + * 任务的截止时间,采用ISO 8601格式(如:2021-04-04T12:23:55Z) + */ + @JsonProperty("deadline") + private String deadline; + + /** + * 机器人类型 + * 指定机器人的资源类型,固定枚举值 + * GROUPS: 机器人资源组编号 + * ROBOTS: 机器人编号 + */ + @JsonProperty("robotType") + private String robotType; + + /** + * 机器人编码 + * 与 robotType 匹配的资源类型唯一标识,支持单个和多个编号 + */ + @JsonProperty("robotCode") + private List robotCode; + + /** + * 能否打断 + * 任务执行过程中是否允许被打断 + * 1: 可打断 - 该货架中途有其他任务时,打断当前任务 + * 0: 不可打断 - 该货架中途有其他任务时,不能打断当前任务,默认不可打断 + */ + @JsonProperty("interrupt") + private Integer interrupt; + + /** + * 机器人任务编码 + * 外部任务唯一编号,如果为空则由系统生成并返回 + */ + @JsonProperty("robotTaskCode") + private String robotTaskCode; + + /** + * 任务组编码 + * 任务组编号,全局唯一标识 + */ + @JsonProperty("groupCode") + private String groupCode; + + /** + * 扩展字段 + * 自定义扩展字段,支持不同业务场景的扩展内容, + * 可用于业务流程执行或透传上报 + */ + @JsonProperty("extra") + private Extra extra; +} diff --git a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/hikAgv/request/submit/TargetRoute.java b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/hikAgv/request/submit/TargetRoute.java new file mode 100644 index 0000000..3751db2 --- /dev/null +++ b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/hikAgv/request/submit/TargetRoute.java @@ -0,0 +1,70 @@ +package org.cpte.modules.hikAgv.request.submit; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; + +import java.util.List; + +/** + * 目标路径类 + * + * 用于描述AGV任务执行过程中的目标路径信息,包含目标位置、操作类型、资源配置等详细信息。 + */ +@Data +public class TargetRoute { + + /** + * 目标路径序列 + * 路径执行顺序编号,从0开始计数 + */ + @JsonProperty("seq") + private Integer seq; + + /** + * 目标类型 + * 指定目标位置的类型 + */ + @JsonProperty("type") + private String type; + + /** + * 目标编号 + * 目标位置的唯一标识编码 + */ + @JsonProperty("code") + private String code; + + /** + * 到达目标位置后的操作 + * 国标要求,非必要字段,对AMR动作无影响,支持可扩展枚举值 + * 预制枚举值: + * COLLECT: 取货 + * DELIVERY: 送货 + * ROTATE: 旋转 + */ + @JsonProperty("operation") + private String operation; + + /** + * 机器人类型 + * 指定机器人的资源类型,固定枚举值: + * GROUPS: 机器人资源组编号 + * ROBOTS: 机器人编号 + */ + @JsonProperty("robotType") + private String robotType; + + /** + * 机器人编码 + * 与 [robotType] 匹配的资源类型唯一标识 + */ + @JsonProperty("robotCode") + private List robotCode; + + /** + * 扩展字段 + * 自定义扩展字段,可随业务的差异而传入不同的扩展内容,在业务流程的执行中使用 + */ + @JsonProperty("extra") + private Extra extra; +} diff --git a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/hikAgv/request/taskReporter/Extra.java b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/hikAgv/request/taskReporter/Extra.java new file mode 100644 index 0000000..d1685d0 --- /dev/null +++ b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/hikAgv/request/taskReporter/Extra.java @@ -0,0 +1,15 @@ +package org.cpte.modules.hikAgv.request.taskReporter; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; + +@Data +public class Extra { + + @JsonProperty("async") + private String async; + + //节点信息 + @JsonProperty("values") + private Values values; +} diff --git a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/hikAgv/request/taskReporter/TaskReporterRequest.java b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/hikAgv/request/taskReporter/TaskReporterRequest.java new file mode 100644 index 0000000..33a7f3e --- /dev/null +++ b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/hikAgv/request/taskReporter/TaskReporterRequest.java @@ -0,0 +1,36 @@ +package org.cpte.modules.hikAgv.request.taskReporter; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; + +/** + * AGV任务状态上报请求类 + *

+ * 用于AGV任务执行过程中向系统上报任务状态信息的DTO对象, + * 包含任务执行的关键节点信息和当前位置信息。 + */ +@Data +public class TaskReporterRequest { + + /** + * 机器人任务编码 + * 外部任务唯一编号,用于关联具体任务实例 + */ + @JsonProperty("robotTaskCode") + private String robotTaskCode; + + /** + * 当前执行任务的机器人唯一标识 + * 用于标识执行当前任务的具体AGV设备 + */ + @JsonProperty("singleRobotCode") + private String singleRobotCode; + + /** + * 自定义扩展字段 + * 包含任务执行过程中的详细状态信息和其他扩展数据 + */ + @JsonProperty("extra") + private Extra extra; + +} diff --git a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/hikAgv/request/taskReporter/Values.java b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/hikAgv/request/taskReporter/Values.java new file mode 100644 index 0000000..d46841a --- /dev/null +++ b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/hikAgv/request/taskReporter/Values.java @@ -0,0 +1,124 @@ +package org.cpte.modules.hikAgv.request.taskReporter; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; + +/** + * AGV任务状态上报值对象 + *

+ * 包含AGV任务执行过程中的详细状态信息,如位置坐标、载具信息、机器人信息等 + */ +@Data +public class Values { + + /** + * 地图编号 + * 标识当前AGV所在地图的唯一编码 + */ + @JsonProperty("mapCode") + private String mapCode; + + /** + * 存储类型 + * 枚举值: + * BIN - 仓位 + * SITE - 站点 + */ + @JsonProperty("slotCategory") + private String slotCategory; + + /** + * 当前站点编号 + * AGV当前所在的站点位置编码 + */ + @JsonProperty("slotCode") + private String slotCode; + + /** + * 站点别名 + * 1.走出储位:起点 + * 2.任务完成:目标点 + */ + @JsonProperty("slotName") + private String slotName; + + /** + * 机器人当前位置 x 坐标 + * AGV在地图中的X轴坐标值 + */ + @JsonProperty("x") + private Integer x; + + /** + * 机器人当前位置 y 坐标 + * AGV在地图中的Y轴坐标值 + */ + @JsonProperty("y") + private Integer y; + + /** + * 任务执行过程中消息上报的方法名 + * 默认使用方式: + * start : 任务开始 + * outbin : 走出储位 + * end : 任务完成 + */ + @JsonProperty("method") + private String method; + + /** + * 载具种类 + * 标识载具的分类信息 + */ + @JsonProperty("carrierCategory") + private String carrierCategory; + + /** + * 载具类型 + * 标识载具的具体型号或类型 + */ + @JsonProperty("carrierType") + private String carrierType; + + /** + * 载具编号 + * 当前任务关联的载具唯一标识 + */ + @JsonProperty("carrierCode") + private String carrierCode; + + /** + * 机器人种类 + * 标识机器人的分类信息 + */ + @JsonProperty("amrCategory") + private String amrCategory; + + /** + * 机器人类型 + * 标识机器人的具体型号或类型 + */ + @JsonProperty("amrType") + private String amrType; + + /** + * 机器人编号 + * 机器人的唯一标识编码 + */ + @JsonProperty("amrCode") + private String amrCode; + + /** + * 载具名称 + * 载具的显示名称或描述信息 + */ + @JsonProperty("carrierName") + private String carrierName; + + /** + * 载具角度 + * 载具当前的方向角度值 + */ + @JsonProperty("carrierDir") + private String carrierDir; +} diff --git a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/hikAgv/response/HikResult.java b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/hikAgv/response/HikResult.java new file mode 100644 index 0000000..57b81fc --- /dev/null +++ b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/hikAgv/response/HikResult.java @@ -0,0 +1,46 @@ +package org.cpte.modules.hikAgv.response; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import java.io.Serializable; + +/** + * 接口返回数据格式 + * + * @author scott + * @email cpteos@163.com + * @date 2019年1月19日 + */ +@Data +public class HikResult implements Serializable { + + /** + * 返回代码 + */ + private String code = ""; + + /** + * 返回处理消息 + */ + private String message = ""; + + /** + * 返回数据对象 data + */ + private ResponesData data; + + public static HikResult success(ResponesData data) { + HikResult response = new HikResult(); + response.code = "SUCCESS"; + response.message = "成功"; + response.data = data; + return response; + } + + public static HikResult error(String message) { + HikResult response = new HikResult(); + response.code = "FAIL"; + response.message = message; + return response; + } +} diff --git a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/hikAgv/response/ResponesData.java b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/hikAgv/response/ResponesData.java new file mode 100644 index 0000000..5b86466 --- /dev/null +++ b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/hikAgv/response/ResponesData.java @@ -0,0 +1,10 @@ +package org.cpte.modules.hikAgv.response; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; + +@Data +public class ResponesData { + @JsonProperty("robotTaskCode") + private String robotTaskCode; +} diff --git a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/hikAgv/service/IHikAgvService.java b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/hikAgv/service/IHikAgvService.java new file mode 100644 index 0000000..725868d --- /dev/null +++ b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/hikAgv/service/IHikAgvService.java @@ -0,0 +1,30 @@ +package org.cpte.modules.hikAgv.service; + +import org.cpte.modules.agvTask.entity.AgvTask; +import org.cpte.modules.hikAgv.request.submit.SubmitRequest; +import org.cpte.modules.hikAgv.request.taskReporter.TaskReporterRequest; + +public interface IHikAgvService { + /** + * 生成任务下发JSON + * + * @param agvTask 任务 + */ + SubmitRequest generateAgvTaskJson(AgvTask agvTask); + + /** + * 下发任务 + * + * @param url 接口地址 + * @param json 接口json + * @param agvTask 任务 + */ + void sendAgvTask(String url, String json, AgvTask agvTask); + + /** + * 任务上报 + * + * @param taskReporterRequest 任务上报参数 + */ + void taskReporter(TaskReporterRequest taskReporterRequest); +} diff --git a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/hikAgv/service/impl/IHikAgvServiceImpl.java b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/hikAgv/service/impl/IHikAgvServiceImpl.java new file mode 100644 index 0000000..722d66d --- /dev/null +++ b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/hikAgv/service/impl/IHikAgvServiceImpl.java @@ -0,0 +1,251 @@ +package org.cpte.modules.hikAgv.service.impl; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.cpte.modules.agvTask.entity.AgvTask; +import org.cpte.modules.agvTask.mapper.AgvTaskMapper; +import org.cpte.modules.agvTask.service.IAgvTaskService; +import org.cpte.modules.constant.enums.*; +import org.cpte.modules.hikAgv.request.submit.*; +import org.cpte.modules.hikAgv.request.taskReporter.TaskReporterRequest; +import org.cpte.modules.hikAgv.service.IHikAgvService; +import org.jeecg.modules.system.mapper.SysDictMapper; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.time.LocalDateTime; +import java.time.ZoneOffset; +import java.time.format.DateTimeFormatter; +import java.util.*; + +@Service +@Slf4j +public class IHikAgvServiceImpl implements IHikAgvService { + + // 接口开关 + final String open_flag = "OPEN"; + + // 成功码 + final String success_code = "SUCCESS"; + + @Autowired + private SysDictMapper sysDictMapper; + + @Autowired + private AgvTaskMapper agvTaskMapper; + + @Autowired + private IAgvTaskService iAgvTaskService; + + @Override + public SubmitRequest generateAgvTaskJson(AgvTask agvTask) { + SubmitRequest submitRequest = new SubmitRequest(); + submitRequest.setTaskType("PF-LMR-COMMON"); + + // 设置起点路径 + TargetRoute srcTargetRoute = createSrcTargetRoute(agvTask); + + // 设置终点路径 + TargetRoute dstTargetRoute = createDstTargetRoute(agvTask); + + submitRequest.setTargetRoute(Arrays.asList(srcTargetRoute, dstTargetRoute)); + submitRequest.setInitPriority(agvTask == null ? 99 : agvTask.getPriority()); + + LocalDateTime now = LocalDateTime.now(ZoneOffset.UTC); + String deadline = now.format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss'Z'")); + submitRequest.setDeadline(deadline); + + submitRequest.setRobotType("GROUPS"); + submitRequest.setRobotCode(Collections.singletonList("c3a1e7bb")); + + Extra extra1 = new Extra(); + extra1.setCarrierInfo(createCarrierInfoList(agvTask == null ? "" : agvTask.getCarrierCode())); + + submitRequest.setExtra(extra1); + submitRequest.setInterrupt(0); + submitRequest.setRobotTaskCode(agvTask == null ? "" : agvTask.getId()); + submitRequest.setGroupCode(agvTask == null ? "" : agvTask.getId()); + + return submitRequest; + } + + @Override + public void sendAgvTask(String url, String json, AgvTask agvTask) { + log.info("请求报文:{}", json); + // 检查接口开关, 未开启则返回 + if (sysDictMapper.queryByDictCode(open_flag) == null) { + updateAgvTaskResponse(agvTask, "接口未开启", "FAILED"); + return; + } + + String code = null; + String message = null; + try { + //String result = HttpPostUtil.sendPostReq(url, json); + String result = "{\n" + + " \"message\": \"成功\",\n" + + " \"code\":\"SUCCESS\",\n" + + "}"; + if (StringUtils.isEmpty(result)) { + message = "AGV返回信息:下发任务接口调用失败"; + throw new RuntimeException(message); + } + + JSONObject resulObject = JSON.parseObject(result); + if (resulObject == null) { + message = "AGV返回信息:下发任务接口返回为空"; + throw new RuntimeException(message); + } + + code = resulObject.getString("code"); + message = resulObject.getString("message"); + + if (!success_code.equals(code)) { + throw new RuntimeException("AGV返回消息:" + message); + } + + // 更新任务状态 + updateAgvTaskResponse(agvTask, message, code); + } catch (Exception e) { + // 记录异常到 AgvTask + updateAgvTaskResponse(agvTask, e.getMessage(), "FAILED"); + throw e; // 继续向上抛出异常供 Controller 层处理 + } + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void taskReporter(TaskReporterRequest taskReporterRequest) { + AgvTask agvTask = agvTaskMapper.selectById(taskReporterRequest.getRobotTaskCode()); + String status = taskReporterRequest.getExtra().getValues().getMethod(); + switch (status) { + case "outbin": + //走出储位 + handleOutBin(agvTask); + break; + case "end": + //任务完成 + handleEnd(agvTask); + break; + case "resend": + //重新发送 + handleResend(agvTask); + break; + } + } + + + /** + * 走出储位 + * + * @param agvTask 任务 + */ + private void handleOutBin(AgvTask agvTask) { + + } + + /** + * 任务完成 + * + * @param agvTask 任务 + */ + private void handleEnd(AgvTask agvTask) { + agvTask.setStatus(AgvStatusEnum.COMPLETED.getValue()); + agvTask.setEndTime(new Date()); + agvTaskMapper.updateById(agvTask); + } + + /** + * 重新发送 + * + * @param agvTask + */ + private void handleResend(AgvTask agvTask) { + Long count = agvTaskMapper.isAGVTaskDuplicate(agvTask.getCarrierCode(), agvTask.getStartCode(), agvTask.getEndCode()); + if (count > 0) { + throw new RuntimeException("任务已重新生成,请勿重复操作! "); + } + AgvTask newAgvTask = iAgvTaskService.createAgvTask(AgvStatusEnum.CREATED.getValue(), agvTask.getCarrierCode(), agvTask.getStartCode(), agvTask.getEndCode(), agvTask.getTaskType(), agvTask.getType()); + switch (agvTask.getType()) { + case "INBOUND": + case "OUTBOUND": + //下发任务 + sendAgvTask("", "", newAgvTask); + break; + default: + throw new RuntimeException("任务类型不支持: " + agvTask.getType()); + } + } + + + private void updateAgvTaskResponse(AgvTask agvTask, String message, String code) { + if (agvTask != null) { + if (success_code.equals(code)) { + agvTask.setStatus(AgvStatusEnum.EXECUTING.getValue()); + } + agvTask.setResMessage(message); + agvTask.setStartTime(new Date()); + agvTaskMapper.updateById(agvTask); + } + } + + /** + * 创建起点路径 + * + * @param agvTask 任务 + * @return TargetRoute + */ + private TargetRoute createSrcTargetRoute(AgvTask agvTask) { + TargetRoute srcTargetRoute = new TargetRoute(); + srcTargetRoute.setSeq(0); + srcTargetRoute.setType("ZONE"); + srcTargetRoute.setCode(agvTask == null ? "" : agvTask.getStartCode()); + srcTargetRoute.setOperation("COLLECT"); + srcTargetRoute.setExtra(null); + srcTargetRoute.setRobotType("GROUPS"); + srcTargetRoute.setRobotCode(Collections.singletonList("a361flb8")); + return srcTargetRoute; + } + + /** + * 创建终点路径 + * + * @param agvTask 任务 + * @return TargetRoute + */ + private TargetRoute createDstTargetRoute(AgvTask agvTask) { + TargetRoute dstTargetRoute = new TargetRoute(); + dstTargetRoute.setSeq(1); + dstTargetRoute.setType("SITE"); + dstTargetRoute.setCode(agvTask == null ? "" : agvTask.getEndCode()); + dstTargetRoute.setOperation("DELIVERY"); + + Extra extra = new Extra(); + + AngleInfo angleInfo = new AngleInfo(); + angleInfo.setType("RELATIVE"); + angleInfo.setCode("90"); + + extra.setAngleInfo(angleInfo); + extra.setCarrierInfo(createCarrierInfoList(agvTask == null ? "" : agvTask.getCarrierCode())); + + dstTargetRoute.setExtra(extra); + return dstTargetRoute; + } + + private List createCarrierInfoList(String carrierCode) { + List carrierInfoList = new ArrayList<>(); + CarrierInfo cif = new CarrierInfo(); + cif.setCarrierType("1"); // 建议替换为常量 + cif.setCarrierCode(carrierCode); + cif.setLayer("0"); + carrierInfoList.add(cif); + return carrierInfoList; + } + +} + + diff --git a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/quartz/job/AgvTaskJob.java b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/quartz/job/AgvTaskJob.java new file mode 100644 index 0000000..ec58100 --- /dev/null +++ b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/quartz/job/AgvTaskJob.java @@ -0,0 +1,38 @@ +package org.cpte.modules.quartz.job; + +import com.alibaba.fastjson.JSON; +import lombok.extern.slf4j.Slf4j; +import org.cpte.modules.agvTask.entity.AgvTask; +import org.cpte.modules.agvTask.service.IAgvTaskService; +import org.cpte.modules.constant.enums.AgvStatusEnum; +import org.cpte.modules.hikAgv.service.IHikAgvService; +import org.jeecg.common.util.DateUtils; +import org.quartz.Job; +import org.quartz.JobExecutionContext; +import org.quartz.JobExecutionException; +import org.springframework.beans.factory.annotation.Autowired; + +import java.util.List; + +@Slf4j +public class AgvTaskJob implements Job { + @Autowired + private IAgvTaskService agvTaskService; + + @Autowired + private IHikAgvService hikAgvService; + + @Override + public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException { + // 查询待执行任务 + List agvTaskList = agvTaskService.queryAgvTaskList(AgvStatusEnum.CREATED.getValue()); + String taskSubmitUrl = "http://localhost:8000/cpte-wms/rcs/rtas/api/robot/controller/task/submit"; + for (AgvTask agvTask : agvTaskList) { + try { + hikAgvService.sendAgvTask(taskSubmitUrl, JSON.toJSONString(hikAgvService.generateAgvTaskJson(agvTask)), agvTask); + } catch (Exception e) { + log.error("发送AGV任务失败,任务ID: {}", agvTask.getId(), e); + } + } + } +} diff --git a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/receive/mapper/AsnDetailMapper.java b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/receive/mapper/AsnDetailMapper.java index 12856a7..ed94818 100644 --- a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/receive/mapper/AsnDetailMapper.java +++ b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/receive/mapper/AsnDetailMapper.java @@ -1,6 +1,9 @@ package org.cpte.modules.receive.mapper; import java.util.List; + +import org.apache.ibatis.annotations.Select; +import org.cpte.modules.receive.entity.Asn; import org.cpte.modules.receive.entity.AsnDetail; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import org.apache.ibatis.annotations.Param; @@ -8,24 +11,38 @@ import org.apache.ibatis.annotations.Param; /** * @Description: 入库明细 * @author: cpte - * @Date: 2025-11-03 + * @Date: 2025-11-03 * @Version: V1.0 */ public interface AsnDetailMapper extends BaseMapper { - /** - * 通过主表id删除子表数据 - * - * @param mainId 主表id - * @return boolean - */ - public boolean deleteByMainId(@Param("mainId") String mainId); + /** + * 通过主表id删除子表数据 + * + * @param mainId 主表id + * @return boolean + */ + public boolean deleteByMainId(@Param("mainId") String mainId); - /** - * 通过主表id查询子表数据 - * - * @param mainId 主表id - * @return List - */ - public List selectByMainId(@Param("mainId") String mainId); + /** + * 通过主表id查询子表数据 + * + * @param mainId 主表id + * @return List + */ + public List selectByMainId(@Param("mainId") String mainId); + + + /** + * 根据容器查询入库信息 + * + * @param stockCode 容器编号 + * @return AsnDetail + */ + @Select("select * from data_asn_detail " + + "join data_asn on data_asn.id=data_asn_detail.asn_id " + + "join base_stock on data_asn_detail.stock_id=base_stock.id " + + "where base_stock.stock_code = #{stockCode} " + + "and data_asn.status='CREATED' ") + AsnDetail queryByStockCode(@Param("stockCode") String stockCode); } diff --git a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/receive/mapper/AsnMapper.java b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/receive/mapper/AsnMapper.java index c0e414c..5af8b53 100644 --- a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/receive/mapper/AsnMapper.java +++ b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/receive/mapper/AsnMapper.java @@ -22,4 +22,6 @@ public interface AsnMapper extends BaseMapper { */ @Select("select * from data_asn where no = #{no}") Asn queryByNo(@Param("no") String no); + + } diff --git a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/utils/HttpPostUtil.java b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/utils/HttpPostUtil.java new file mode 100644 index 0000000..125d1ee --- /dev/null +++ b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/utils/HttpPostUtil.java @@ -0,0 +1,75 @@ +package org.cpte.modules.utils; + +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.io.IOUtils; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.HttpURLConnection; +import java.net.URL; +import java.nio.charset.StandardCharsets; + +@Slf4j +public class HttpPostUtil { + public static String sendPostReq(String apiUrl, String jsonRequest) { + HttpURLConnection connection = null; + try { + // 创建URL对象并建立连接 + URL url = new URL(apiUrl); + connection = (HttpURLConnection) url.openConnection(); + + // 配置连接参数 + connection.setConnectTimeout(5000); + connection.setReadTimeout(10000); + connection.setDoOutput(true); + connection.setDoInput(true); + connection.setUseCaches(false); + connection.setRequestMethod("POST"); + + // 设置HTTP头 + connection.setRequestProperty("Content-Type", "application/json; charset=UTF-8"); + connection.setRequestProperty("Accept", "application/json"); + + // 写入请求体 + byte[] requestData = jsonRequest.getBytes(StandardCharsets.UTF_8); + connection.setRequestProperty("Content-Length", String.valueOf(requestData.length)); + + try (OutputStream os = connection.getOutputStream()) { + os.write(requestData); + } + + // 处理响应 + int responseCode = connection.getResponseCode(); + if (responseCode >= HttpURLConnection.HTTP_BAD_REQUEST) { + // 错误处理 + try (InputStream errorStream = connection.getErrorStream()) { + String errorResponse = ""; + if (errorStream != null) { + errorResponse = new String(IOUtils.toByteArray(errorStream), StandardCharsets.UTF_8); + } + log.error("HTTP请求失败: 状态码={}, 错误响应={}", responseCode, errorResponse); + return null; + } + } + + // 读取正常响应 + try (InputStream inputStream = connection.getInputStream()) { + String response = new String(IOUtils.toByteArray(inputStream), StandardCharsets.UTF_8); + if (response.trim().isEmpty()) { + log.warn("HTTP请求返回空响应"); + } + return response; + } + + } catch (IOException e) { + log.error("HTTP请求异常: {}", e.getMessage(), e); + return null; + } finally { + // 确保连接断开 + if (connection != null) { + connection.disconnect(); + } + } + } +} diff --git a/cpte-module-system/cpte-system-biz/pom.xml b/cpte-module-system/cpte-system-biz/pom.xml index 92d71bf..1b46d75 100644 --- a/cpte-module-system/cpte-system-biz/pom.xml +++ b/cpte-module-system/cpte-system-biz/pom.xml @@ -73,6 +73,6 @@ cpte-boot-module-airag ${cpte.version} - + diff --git a/cpte-module-system/cpte-system-biz/src/main/java/org/jeecg/modules/quartz/job/AgvTaskJob.java b/cpte-module-system/cpte-system-biz/src/main/java/org/jeecg/modules/quartz/job/AgvTaskJob.java deleted file mode 100644 index 3e9a9c9..0000000 --- a/cpte-module-system/cpte-system-biz/src/main/java/org/jeecg/modules/quartz/job/AgvTaskJob.java +++ /dev/null @@ -1,25 +0,0 @@ -package org.jeecg.modules.quartz.job; - -import lombok.extern.slf4j.Slf4j; -import org.jeecg.common.util.DateUtils; -import org.quartz.Job; -import org.quartz.JobExecutionContext; -import org.quartz.JobExecutionException; - -@Slf4j -public class AgvTaskJob implements Job { - /** - * 若参数变量名修改 QuartzJobController中也需对应修改 - */ - private String parameter; - - public void setParameter(String parameter) { - this.parameter = parameter; - } - - @Override - public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException { - log.info(" Job Execution key:" + jobExecutionContext.getJobDetail().getKey()); - log.info(String.format("welcome %s! Jeecg-Boot 带参数定时任务 SampleParamJob ! 时间:" + DateUtils.now(), this.parameter)); - } -} diff --git a/cpte-module-system/cpte-system-biz/src/main/java/org/jeecg/modules/system/mapper/SysDictMapper.java b/cpte-module-system/cpte-system-biz/src/main/java/org/jeecg/modules/system/mapper/SysDictMapper.java index 770c261..7e5d8ef 100644 --- a/cpte-module-system/cpte-system-biz/src/main/java/org/jeecg/modules/system/mapper/SysDictMapper.java +++ b/cpte-module-system/cpte-system-biz/src/main/java/org/jeecg/modules/system/mapper/SysDictMapper.java @@ -214,4 +214,7 @@ public interface SysDictMapper extends BaseMapper { * @return */ int removeLogicDeleted(@Param("ids")List ids); + + @Select("select * from sys_dict where description = #{description}") + SysDict queryByDictCode(String description); }