自动化立体仓库 - WMS系统
chen.llin
17 小时以前 7692db6072ef569b5734d218cb11fa82e80171d1
src/main/java/com/zy/asrs/task/handler/AgvHandler.java
@@ -189,7 +189,7 @@
                    .in("wrk_sts", 7L, 8L)
                    .in("io_type", ioTypes)
                    .ne("id", task.getId()) // 排除当前任务本身
                    .andNew("(is_deleted = 0)")
                    .eq("is_deleted", 0) // 排除已删除的任务
            );
            
            int taskCount = allTasks != null ? allTasks.size() : 0;
@@ -267,7 +267,7 @@
                    .isNotNull("plc_str_time") // 只检查已收到AGV确认的任务(plc_str_time不为空)
                    .in("io_type", ioTypes)
                    .ne("id", task.getId()) // 排除当前任务本身
                    .andNew("(is_deleted = 0)")
                    .eq("is_deleted", 0) // 排除已删除的任务
            );
            
            // 检查并自动结束已完成工作档的AGV任务
@@ -368,7 +368,7 @@
                    .build()
                    .doPost();
            // 打印返回参数
            // log.info("{}呼叫agv搬运 - 返回参数:{}", namespace, response);
             log.info("{}呼叫agv搬运,请求参数「{}」 - 返回参数:{}", namespace,body, response);
            
            // 检查响应是否为空
            if (response == null || response.trim().isEmpty()) {
@@ -575,7 +575,8 @@
     * @param taskTypeName 任务类型名称(用于日志)
     * @return 仍然有效的正在搬运的任务列表(已完成的已被移除)
     */
    private List<Task> checkAndCompleteFinishedTasks(List<Task> transportingTasks, String taskTypeName) {
    @Transactional(rollbackFor = Exception.class)
    public List<Task> checkAndCompleteFinishedTasks(List<Task> transportingTasks, String taskTypeName) {
        if (transportingTasks == null || transportingTasks.isEmpty()) {
            return transportingTasks;
        }
@@ -676,6 +677,8 @@
        return validTasks;
    }
    /**
     * 从memo字段中获取重试次数
     * memo格式:如果包含"retryCount:数字",则返回该数字,否则返回0
@@ -745,7 +748,7 @@
    /**
     * 构造请求内容(仙工M4格式)
     */
    private String getRequest(Task task, String nameSpace) {
    public String getRequest(Task task, String nameSpace) {
        JSONObject object = new JSONObject();
        // taskId使用工作号(wrk_no),格式:T + 工作号
        // 如果工作号为空,则使用任务ID作为备选
@@ -792,6 +795,7 @@
        object.put("kind", kind);
        return object.toJSONString();
    }
    /**
     * 为任务分配站点(定时任务中调用)
@@ -884,75 +888,18 @@
                .in("dev_no", sites)
                .eq("in_enable", "Y")
                .eq("canining", "Y")
                .eq("loading", "N")
                .ne("dev_no", 0) // 排除dev_no=0的无效站点
        );
        
        if (devListWithConfig.isEmpty()) {
            // 站点配置不允许入库(canining != "Y"),暂不分配,等待配置开通(只在定时任务中记录日志)
            // 记录每个站点的canining状态
            StringBuilder caniningStatusInfo = new StringBuilder();
            for (Integer siteNo : sites) {
                BasDevp dev = allDevList.stream()
                        .filter(d -> d.getDevNo().equals(siteNo))
                        .findFirst()
                        .orElse(null);
                if (dev != null) {
                    if (caniningStatusInfo.length() > 0) {
                        caniningStatusInfo.append("; ");
        if (devListWithConfig==null || devListWithConfig.isEmpty()) {
            log.warn("任务ID:{}没有可入站点(站点未开通可入允许:canining='Y'),暂不分配站点,等待配置开通。能入站点列表:{}",
                    displayTaskId, sites);
            return null;
                    }
                    caniningStatusInfo.append("站点").append(siteNo)
                            .append("(canining=").append(dev.getCanining()).append(")");
                }
            }
            log.warn("任务ID:{}没有可入站点(站点未开通可入允许:canining='Y'),暂不分配站点,等待配置开通。能入站点列表:{},canining状态:{}",
                    displayTaskId, sites, caniningStatusInfo.toString());
            return null; // 返回null,表示暂不分配,等待配置开通
        }
        // 获取没有出库任务的站点(从已配置可入的站点中筛选)
        List<Integer> configuredSites = devListWithConfig.stream()
                .map(BasDevp::getDevNo)
                .collect(Collectors.toList());
        log.info("任务ID:{},已配置可入站点列表:{}", displayTaskId, configuredSites);
        List<Integer> canInSites = basDevpMapper.getCanInSites(configuredSites);
        if (canInSites.isEmpty()) {
            // 所有已配置可入的站点都有出库任务,暂不分配,等待下次定时任务再尝试(只在定时任务中记录日志)
            log.warn("任务ID:{}没有可入站点(请等待出库完成),暂不分配站点,等待下次定时任务再尝试。已配置可入站点列表:{}", displayTaskId, configuredSites);
            return null; // 返回null,表示暂不分配,等待下次定时任务再尝试
        }
        log.info("任务ID:{},没有出库任务的站点列表:{}", displayTaskId, canInSites);
        // 寻找入库任务最少的站点(且必须in_enable="Y"能入 和 canining="Y"可入),排除dev_no=0的无效站点
        List<BasDevp> devList = basDevpMapper.selectList(new EntityWrapper<BasDevp>()
                .in("dev_no", canInSites)
                .eq("in_enable", "Y")
                .eq("canining", "Y")
                .ne("dev_no", 0) // 排除dev_no=0的无效站点
        ).stream()
                .filter(dev -> dev.getDevNo() != null && dev.getDevNo() != 0) // 再次过滤,确保不为null或0
                .collect(Collectors.toList());
        if (devList.isEmpty()) {
            // 理论上不应该到这里,因为前面已经检查过了,但为了安全起见还是保留
            String errorMsg = "没有可入站点(in_enable='Y'且canining='Y')";
            log.warn("任务ID:{},{},可入站点列表:{}", displayTaskId, errorMsg, canInSites);
            return errorMsg;
        }
        // 记录每个站点的入库任务数
        StringBuilder siteInQtyInfo = new StringBuilder();
        for (BasDevp dev : devList) {
            if (siteInQtyInfo.length() > 0) {
                siteInQtyInfo.append("; ");
            }
            siteInQtyInfo.append("站点").append(dev.getDevNo())
                    .append("(入库任务数=").append(dev.getInQty()).append(")");
        }
        log.info("任务ID:{},可入站点及其入库任务数:{}", displayTaskId, siteInQtyInfo.toString());
        
        // 先按规则排序(入库任务数排序)
        devList.sort(Comparator.comparing(BasDevp::getInQty));
            devListWithConfig.sort(Comparator.comparing(BasDevp::getInQty));
        // 根据任务类型确定要检查的io_type列表
        Integer taskIoType = task.getIoType();
        List<Integer> checkIoTypes = null;
@@ -994,13 +941,20 @@
        }
        
        // 从可用站点中筛选出未被分配的站点
        List<BasDevp> unallocatedSites = devList.stream()
        List<BasDevp> unallocatedSites = devListWithConfig.stream()
                .filter(dev -> {
                    String staNo = String.valueOf(dev.getDevNo());
                    return !allocatedSiteNos.contains(staNo);
                })
                .collect(Collectors.toList());
        List<BasDevp> unallocatedSites2= new ArrayList<>();
        for(int i=0;devListWithConfig.size()>i;i++){
            unallocatedSites2.add(devListWithConfig.get(i));
        }
//        if(unallocatedSites==null || unallocatedSites.isEmpty()){
//            unallocatedSites=unallocatedSites2;
//
//        }
        // 只使用未分配站点
        if (unallocatedSites.isEmpty()) {
            // 未分配站点为空:不分配站点
@@ -1088,7 +1042,6 @@
        log.info("任务ID:{}已分配站点:{},机器人组:{},任务类型:{}", displayTaskId, endSite, robotGroup, taskTypeName);
        return null; // 分配成功,返回null
    }
    /**
     * 根据站点编号判断机器人组
     * @param staNo 站点编号
@@ -1113,6 +1066,7 @@
            return agvProperties.getRobotGroupEast(); // 默认使用东侧机器人组
        }
    }
    /**
     * 任务完成转历史 释放暂存点
@@ -1180,7 +1134,11 @@
        log.info("agv任务档转历史成功:{}", taskIds);
    }
    @Transactional(rollbackFor = Exception.class)
    public void moveTaskToHistory(Task agvTask) {
        moveTaskToHistory(Collections.singletonList(agvTask));
    }
    /**
     * 货物到达出库口,生成agv任务
     */