#
vincentlu
2025-12-30 b781dc511b21b80b14befe87d42eced1cce59d1f
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
package com.zy.acs.manager.core.service;
 
import com.zy.acs.manager.core.domain.TaskPosDto;
import com.zy.acs.manager.manager.entity.Code;
import com.zy.acs.manager.manager.entity.Segment;
import com.zy.acs.manager.manager.entity.Sta;
import com.zy.acs.manager.manager.enums.StaTypeType;
import com.zy.acs.manager.manager.service.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
 
import java.util.Objects;
 
// man_segment: start_time, end_time
/**
 * alter table man_sta
 *     add capacity int null comment '槽位数' after angle;
 *
 * alter table man_sta
 *     add occ_cnt int null comment '占用数' after capacity;
 *
 * alter table man_sta
 *     add rsv_in_cnt int null comment '预约放货量' after occ_cnt;
 *
 * alter table man_sta
 *     add rsv_out_cnt int null comment '预约取货量' after rsv_in_cnt;
 */
@Slf4j
@Service
public class TransferStationHandler {
 
    private static final long LOAD_DELAY_MS  = 15000L; // load ( inbound ) delay timeout
    private static final long PLACE_DELAY_MS  = 15000L; // place ( outbound ) delay timeout
 
    @Autowired
    private SegmentService segmentService;
    @Autowired
    private AgvService agvService;
    @Autowired
    private AgvDetailService agvDetailService;
    @Autowired
    private CodeService codeService;
    @Autowired
    private StaService staService;
 
    /**
     * 取货(入库):在取完第一个货的时候,担心滚筒输送线会有下一个货物,所以建议AGV在原地等待一段时间
     * 放货(出库):可能此时AGV上面其他背篓的料箱也是出库到这个滚筒输送线,所以等输送线把第一个料箱运走之后,再放第二个
     * 要做 ready-for-next
     */
    public boolean hasDelayAtSta(Segment currSeg) {
        if (currSeg == null) {
            throw new NullPointerException("segment is null in hasDelayAtSta.");
        }
        // 判断AGV是否在滚动输送线前
        Code currentCode = agvDetailService.getCurrentCode(currSeg.getAgvId());
        if (null == currentCode) {
            return false;
        }
        Sta rollerSta = staService.selectByCode(currentCode.getId(), StaTypeType.ROLLER);
        if (null == rollerSta) {
            return false;
        }
        // 如果为第一个segment(没有previous segment),则不需要等待
        Segment preSeg = segmentService.getPreviousStepOfFinish(currSeg.getTravelId(), currSeg.getSerial());
        if (preSeg == null || null == preSeg.getEndTime()) {
            return false;
        }
 
        TaskPosDto.PosType currPosType = TaskPosDto.PosType.of(currSeg.getPosType());
        TaskPosDto.PosType prePosType = TaskPosDto.PosType.of(preSeg.getPosType());
        if (prePosType == null || currPosType == null) {
            return false;
        }
        long preEndTime = preSeg.getEndTime().getTime();
        long now = System.currentTimeMillis();
        Long agvId = currSeg.getAgvId();
 
        // inbound
        if (prePosType.equals(TaskPosDto.PosType.ORI_STA)) {
 
            // 背篓未满才等
            Integer backpack = agvService.getBackpack(agvId);
            int countRemainingBackpack = segmentService.countRemainingBackpack(currSeg.getTravelId(), agvId);
            if (countRemainingBackpack >= backpack) {
                return false;
            }
 
            // timeout
            return (now - preEndTime) < LOAD_DELAY_MS;
        }
 
        // outbound
        if (prePosType == TaskPosDto.PosType.DEST_STA) {
 
            // 连续同口才等
            if (currPosType != TaskPosDto.PosType.DEST_STA) {
                return false;
            }
            if (!Objects.equals(preSeg.getEndNode(), currSeg.getEndNode())) {
                return false;
            }
 
            // timeout
            return (now - preEndTime) < PLACE_DELAY_MS;
        }
 
        return false;
    }
 
}