#
vincentlu
2025-01-21 d5c06a9e5bc44564cc1d31cb82ec29640c4f2cbb
#
8个文件已修改
217 ■■■■ 已修改文件
zy-acs-flow/src/map/tool.js 75 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-manager/src/main/java/com/zy/acs/manager/core/cache/CoreCache.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-manager/src/main/java/com/zy/acs/manager/core/domain/MapWsAgvVo.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-manager/src/main/java/com/zy/acs/manager/core/domain/type/JobType.java 17 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-manager/src/main/java/com/zy/acs/manager/core/scheduler/MapDataWsScheduler.java 26 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-manager/src/main/java/com/zy/acs/manager/core/service/PatrolService.java 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-manager/src/main/java/com/zy/acs/manager/fake/AgvSimulatorTask.java 47 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-manager/src/main/java/com/zy/acs/manager/fake/FakeProcessor.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-flow/src/map/tool.js
@@ -652,6 +652,55 @@
    }
}
export function createAgvJobPanel(parentContainer, text) {
    const panel = new PIXI.Container();
    const sideLen = 50;
    const halfCircle = new PIXI.Graphics();
    halfCircle.beginFill(themeMode === 'light' ? '#5c5a5a' : '#eee');
    halfCircle.lineStyle(2, themeMode === 'light' ? '#5c5a5a' : '#eee');
    halfCircle.arc(0, 0, sideLen, 0, Math.PI);
    halfCircle.endFill();
    const rectangle = new PIXI.Graphics();
    rectangle.lineStyle(2, themeMode === 'light' ? '#5c5a5a' : '#eee', 1);
    rectangle.drawRoundedRect(
        -sideLen / 2,   // 左上角 x
        -sideLen / 2,   // 左上角 y
        sideLen,       // 宽
        sideLen - 20,  // 高 (留一点空间,看起来更像半圆容器)
        16             // 圆角
    );
    rectangle.endFill();
    rectangle.mask = halfCircle;
    panel.addChild(rectangle, halfCircle);
    const msg = new PIXI.Text(text, {
        fill: themeMode === 'light' ? '#2b2b2b' : '#eee',
        fontSize: 12,
        fontFamily: 'MicrosoftYaHei',
        fontWeight: 'bold',
        align: 'center',
    });
    msg.anchor.set(0.5);
    msg.position.set(0, -10);
    panel.addChild(msg);
    panel.scale.set(3);
    parentContainer.addChild(panel);
    let phase = 0;
    function onTick(delta) {
        phase += delta / 8;  // 旋转速度可调
        phase %= (Math.PI * 2);
        halfCircle.rotation = phase;
    }
    app.ticker.add(onTick);
    panel._onTick = onTick;
    return panel;
}
// dynamic graphic ----------------
@@ -666,13 +715,16 @@
const agvRotationOffset = rotationParseNum(agvRotationOffsetDegrees);
const showAgvSprite = (curZone, agvVo, setCurSprite) => {
    const { agvNo, code, direction, battery, backpack, error } = agvVo;
    const { agvNo, code, direction, battery, jobType, backpack: backpackCount, error } = agvVo;
    if (!code) { return; }
    const codeSprite = querySprite(DEVICE_TYPE.POINT, code);
    if (!codeSprite) { return; }
    if (agvNo === '12') {
        console.log(backpackCount);
    }
    const targetRotation = rotationParseNum(direction);
    const backpackCount = backpack?.filter(item => item.loaded === true).length || 0;
    // const backpackCount = backpack?.filter(item => item.loaded === true).length || 0;
    let agvSprite = querySprite(DEVICE_TYPE.AGV, agvNo);
    if (!agvSprite) {
@@ -722,6 +774,25 @@
        animateRotation(agvSprite, targetRotation + agvRotationOffset, agvRotationOffset);
    }
    // job effect
    if (jobType) {
        if (!agvSprite.data.jobEffect) {
            agvSprite.data.jobEffect = createAgvJobPanel(agvSprite, jobType);
            agvSprite.data.jobEffect.x = -80;
            agvSprite.data.jobEffect.y = 0;
        }
        if (agvSprite.data.jobEffect) {
            agvSprite.data.jobEffect.rotation = -agvSprite.rotation - rotationParseNum(MAP_DEFAULT_ROTATION);
        }
    } else {
        if (agvSprite.data.jobEffect) {
            app.ticker.remove(agvSprite.data.jobEffect._onTick);
            agvSprite.removeChild(agvSprite.data.jobEffect);
            agvSprite.data.jobEffect.destroy(true);
            agvSprite.data.jobEffect = null;
        }
    }
    if (error) {
        agvSprite.tint = 0xff3f34;
    } else {
zy-acs-manager/src/main/java/com/zy/acs/manager/core/cache/CoreCache.java
@@ -1,6 +1,7 @@
package com.zy.acs.manager.core.cache;
import com.zy.acs.manager.core.domain.CodeStepDto;
import com.zy.acs.manager.core.domain.type.JobType;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@@ -9,6 +10,8 @@
    public static final Map<Long, Integer> AGV_BACKPACK_USED_CACHE = new ConcurrentHashMap<>();
    public static final Map<String, JobType> AGV_MOCK_JOB_CACHE = new ConcurrentHashMap<>();
    public static final Map<Long, CodeStepDto> AGV_MOCK_STEP_CACHE = new ConcurrentHashMap<>();
}
zy-acs-manager/src/main/java/com/zy/acs/manager/core/domain/MapWsAgvVo.java
@@ -19,7 +19,7 @@
    private Double direction = 0.0;
    private List<BackpackDto> backpack = new ArrayList<>();
    private int backpack = 0;
    private List<String> dynamicRoute = new ArrayList<>();
zy-acs-manager/src/main/java/com/zy/acs/manager/core/domain/type/JobType.java
@@ -3,19 +3,18 @@
@SuppressWarnings("all")
public enum JobType {
    CONVEYOR_PICK(2000),
    CONVEYOR_DROP(2000),
    LOC_PICK(500),
    LOCK_DROP(500),
    CONVEYOR_PICK(2000, "取料箱"),
    CONVEYOR_DROP(2000, "放料箱"),
    LOC_PICK(1000, "取料箱"),
    LOCK_DROP(1000, "放料箱"),
    ;
    public static void main(String[] args) {
        System.out.println();
    }
    public long waitTime;
    public String breif;
    JobType(long waitTime) {
    JobType(long waitTime, String breif) {
        this.waitTime = waitTime;
        this.breif = breif;
    }
}
zy-acs-manager/src/main/java/com/zy/acs/manager/core/scheduler/MapDataWsScheduler.java
@@ -1,5 +1,6 @@
package com.zy.acs.manager.core.scheduler;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.zy.acs.common.utils.GsonUtils;
import com.zy.acs.framework.common.Cools;
@@ -8,6 +9,7 @@
import com.zy.acs.manager.core.domain.CodeStepDto;
import com.zy.acs.manager.core.domain.MapWsAgvVo;
import com.zy.acs.manager.core.domain.MapWsVo;
import com.zy.acs.manager.core.domain.type.JobType;
import com.zy.acs.manager.core.service.MapService;
import com.zy.acs.manager.manager.entity.Agv;
import com.zy.acs.manager.manager.entity.AgvDetail;
@@ -87,14 +89,16 @@
            Code code = codeService.getCacheById(recentCode);
            if (null == code) { continue; }
            JobType jobType = this.getJobType(agv.getId(), code.getData());
            MapWsAgvVo vo = new MapWsAgvVo();
            vo.setAgvModel(agvModel.getType());
            vo.setAgvNo(agv.getUuid());
            vo.setCode(code.getData());
            vo.setDirection(agvDetail.getAgvAngle());
            vo.setBackpack(GsonUtils.fromJsonToList(agvDetail.getBackpack(), BackpackDto.class));
            vo.setBackpack(this.getBackpack(agv.getId(), agvDetail.getBackpack()));
            vo.setBattery(agvDetail.getSoc());
            vo.setJobType(this.getJobType(agv.getId(), code.getData()));
            vo.setJobType(null == jobType ? null : jobType.breif);
            vo.setError(agvDetail.realError());
            vo.setDynamicRoute(codeDataListMap.get(agv.getUuid()));
@@ -105,7 +109,7 @@
        return agvVos;
    }
    private String getJobType(Long agvId, String currCodeData) {
    private JobType getJobType(Long agvId, String currCodeData) {
        if (null == agvId || Cools.isEmpty(currCodeData)) {
            return null;
        }
@@ -116,7 +120,7 @@
        if (!codeStepDto.getCodeData().equals(currCodeData)) {
            return null;
        }
        return codeStepDto.getJobType().toString();
        return codeStepDto.getJobType();
    }
    @PreDestroy
@@ -124,4 +128,18 @@
        this.singleThreadExecutor.shutdownNow();
    }
    private Integer getBackpack(Long agvId, String backpackJson) {
        if (null == agvId || Cools.isEmpty(backpackJson)) {
            return null;
        }
        List<BackpackDto> backpackDtoList = JSON.parseArray(backpackJson, BackpackDto.class);
        int jsonCount = (int) backpackDtoList.stream().filter(BackpackDto::getLoaded).count();
        Integer cacheCount = CoreCache.AGV_BACKPACK_USED_CACHE.get(agvId);
        if (null == cacheCount) {
            return jsonCount;
        }
        return Math.max(jsonCount, cacheCount);
    }
}
zy-acs-manager/src/main/java/com/zy/acs/manager/core/service/PatrolService.java
@@ -53,8 +53,6 @@
        add("00000246");
    }};
    private Map<String, JobType> agvJobMap = new ConcurrentHashMap<>();
    @Autowired
    private AgvService agvService;
    @Autowired
@@ -89,9 +87,9 @@
            return;
        }
        JobType jobType = this.agvJobMap.get(agvNo);
        JobType jobType = CoreCache.AGV_MOCK_JOB_CACHE.get(agvNo);
        if (null == jobType) {
            this.agvJobMap.put(agvNo, JobType.LOC_PICK);
            CoreCache.AGV_MOCK_JOB_CACHE.put(agvNo, JobType.LOC_PICK);
            CoreCache.AGV_BACKPACK_USED_CACHE.put(agvId, 0);
            jobType = JobType.LOC_PICK;
        }
@@ -130,40 +128,6 @@
            log.info( "{}开始作业演示...", agvNo);
            CoreCache.AGV_MOCK_STEP_CACHE.put(agvId, CodeStepDto.build(destinationCodeData, jobType));
            switch (jobType) {
                case LOC_PICK:
                    Integer usedSlotsByLocPick = CoreCache.AGV_BACKPACK_USED_CACHE.get(agvId);
                    usedSlotsByLocPick++;
                    if (Objects.equals(agvModelService.getByAgvId(agvId).getBackpack(), usedSlotsByLocPick)) {
                        this.agvJobMap.put(agvNo, JobType.CONVEYOR_DROP);
                    } else {
                        CoreCache.AGV_BACKPACK_USED_CACHE.put(agvId, usedSlotsByLocPick);
                    }
                    break;
                case CONVEYOR_DROP:
                    CoreCache.AGV_BACKPACK_USED_CACHE.put(agvId, 0);
                    this.agvJobMap.put(agvNo, JobType.CONVEYOR_PICK);
                    break;
                case CONVEYOR_PICK:
                    CoreCache.AGV_BACKPACK_USED_CACHE.put(agvId, agvModelService.getByAgvId(agvId).getBackpack());
                    this.agvJobMap.put(agvNo, JobType.LOCK_DROP);
                    break;
                case LOCK_DROP:
                    Integer usedSlotsByLocDrop = CoreCache.AGV_BACKPACK_USED_CACHE.get(agvId);
                    usedSlotsByLocDrop--;
                    if (usedSlotsByLocDrop == 0) {
                        this.agvJobMap.put(agvNo, JobType.LOC_PICK);
                    } else {
                        CoreCache.AGV_BACKPACK_USED_CACHE.put(agvId, usedSlotsByLocDrop);
                    }
                    break;
                default:
                    break;
            }
        }
    }
@@ -320,8 +284,8 @@
            AGV_PATROL_MAP.remove(agvNo);
            CoreCache.AGV_BACKPACK_USED_CACHE.remove(agvId);
            CoreCache.AGV_MOCK_STEP_CACHE.remove(agvId);
            this.agvJobMap.remove(agvNo);
            log.info("已停止AGV " + agvNo + " 的跑库任务。");
            CoreCache.AGV_MOCK_JOB_CACHE.remove(agvNo);
            log.info("已停止AGV {} 的跑库任务。", agvNo);
            return R.ok("已停止AGV " + agvNo + " 的跑库任务。");
        } else {
            log.error("未能成功停止AGV " + agvNo + " 的跑库任务。");
zy-acs-manager/src/main/java/com/zy/acs/manager/fake/AgvSimulatorTask.java
@@ -6,6 +6,7 @@
import com.zy.acs.common.utils.RedisSupport;
import com.zy.acs.manager.core.cache.CoreCache;
import com.zy.acs.manager.core.domain.CodeStepDto;
import com.zy.acs.manager.core.domain.type.JobType;
import com.zy.acs.manager.core.scheduler.MapDataWsScheduler;
import com.zy.acs.manager.core.service.MainService;
import com.zy.acs.manager.core.service.MapService;
@@ -14,10 +15,7 @@
import com.zy.acs.manager.manager.entity.Code;
import com.zy.acs.manager.manager.enums.ActionStsType;
import com.zy.acs.manager.manager.enums.ActionTypeType;
import com.zy.acs.manager.manager.service.ActionService;
import com.zy.acs.manager.manager.service.AgvDetailService;
import com.zy.acs.manager.manager.service.CodeService;
import com.zy.acs.manager.manager.service.JamService;
import com.zy.acs.manager.manager.service.*;
import lombok.extern.slf4j.Slf4j;
import java.util.List;
@@ -31,6 +29,7 @@
    private final Agv agv;
    private final AgvDetailService agvDetailService;
    private final AgvModelService agvModelService;
    private final ActionService actionService;
    private final CodeService codeService;
    private final MapService mapService;
@@ -46,6 +45,7 @@
            Agv agv
            , RedisSupport redis
            , AgvDetailService agvDetailService
            , AgvModelService agvModelService
            , ActionService actionService
            , CodeService codeService
            , MapService mapService
@@ -56,6 +56,7 @@
        this.agv = agv;
        this.redis = redis;
        this.agvDetailService = agvDetailService;
        this.agvModelService = agvModelService;
        this.actionService = actionService;
        this.codeService = codeService;
        this.mapService = mapService;
@@ -145,12 +146,48 @@
    }
    private void finishActionList(String qrCode) {
        Long agvId = this.agv.getId();
        String agvNo = this.agv.getUuid();
        // 1.show effect
        CodeStepDto codeStepDto = CoreCache.AGV_MOCK_STEP_CACHE.get(this.agv.getId());
        CodeStepDto codeStepDto = CoreCache.AGV_MOCK_STEP_CACHE.get(agvId);
        if (null != codeStepDto && qrCode.equals(codeStepDto.getCodeData())) {
//            Code currentCode = agvDetailService.getCurrentCode(this.agv.getId());
            try { Thread.sleep(codeStepDto.getJobType().waitTime); } catch (InterruptedException ignore) {}
            CoreCache.AGV_MOCK_STEP_CACHE.remove(this.agv.getId());
            JobType jobType = CoreCache.AGV_MOCK_JOB_CACHE.get(this.agv.getUuid());
            switch (jobType) {
                case LOC_PICK:
                    Integer usedSlotsByLocPick = CoreCache.AGV_BACKPACK_USED_CACHE.get(agvId);
                    usedSlotsByLocPick++;
                    CoreCache.AGV_BACKPACK_USED_CACHE.put(agvId, usedSlotsByLocPick);
                    if (Objects.equals(agvModelService.getByAgvId(agvId).getBackpack(), usedSlotsByLocPick)) {
                        CoreCache.AGV_MOCK_JOB_CACHE.put(agvNo, JobType.CONVEYOR_DROP);
                    }
                    break;
                case CONVEYOR_DROP:
                    CoreCache.AGV_BACKPACK_USED_CACHE.put(agvId, 0);
                    CoreCache.AGV_MOCK_JOB_CACHE.put(agvNo, JobType.CONVEYOR_PICK);
                    break;
                case CONVEYOR_PICK:
                    CoreCache.AGV_BACKPACK_USED_CACHE.put(agvId, agvModelService.getByAgvId(agvId).getBackpack());
                    CoreCache.AGV_MOCK_JOB_CACHE.put(agvNo, JobType.LOCK_DROP);
                    break;
                case LOCK_DROP:
                    Integer usedSlotsByLocDrop = CoreCache.AGV_BACKPACK_USED_CACHE.get(agvId);
                    usedSlotsByLocDrop--;
                    CoreCache.AGV_BACKPACK_USED_CACHE.put(agvId, usedSlotsByLocDrop);
                    if (usedSlotsByLocDrop == 0) {
                        CoreCache.AGV_MOCK_JOB_CACHE.put(agvNo, JobType.LOC_PICK);
                    }
                    break;
                default:
                    break;
            }
        }
        // 2.complete data
zy-acs-manager/src/main/java/com/zy/acs/manager/fake/FakeProcessor.java
@@ -55,6 +55,8 @@
    @Autowired
    private AgvDetailService agvDetailService;
    @Autowired
    private AgvModelService agvModelService;
    @Autowired
    private ActionService actionService;
    @Autowired
    private ConfigService configService;
@@ -133,6 +135,7 @@
                                            agv
                                            , redis
                                            , agvDetailService
                                            , agvModelService
                                            , actionService
                                            , codeService
                                            , mapService