package com.zy.acs.manager.manager.service.impl; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.zy.acs.common.constant.RedisConstant; import com.zy.acs.common.enums.AgvStatusType; import com.zy.acs.common.utils.RedisSupport; import com.zy.acs.framework.common.Cools; import com.zy.acs.framework.exception.CoolException; import com.zy.acs.manager.common.domain.BaseParam; import com.zy.acs.manager.common.domain.PageParam; import com.zy.acs.manager.common.domain.PageResult; import com.zy.acs.manager.core.cache.CoreCache; import com.zy.acs.manager.core.domain.VehicleDto; import com.zy.acs.manager.core.service.astart.MapDataDispatcher; import com.zy.acs.manager.manager.controller.result.AgvResult; import com.zy.acs.manager.manager.entity.Agv; import com.zy.acs.manager.manager.entity.AgvDetail; import com.zy.acs.manager.manager.entity.AgvModel; import com.zy.acs.manager.manager.entity.Segment; import com.zy.acs.manager.manager.enums.SegmentStateType; import com.zy.acs.manager.manager.mapper.AgvMapper; import com.zy.acs.manager.manager.service.*; import com.zy.acs.manager.system.service.ConfigService; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import javax.annotation.PostConstruct; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; /** * 字典数据Service实现 * * @author vincent * @since 2020-03-14 11:29:04 */ @Slf4j @Service public class AgvServiceImpl extends ServiceImpl implements AgvService { private final RedisSupport redis = RedisSupport.defaultRedisSupport; public static final Map AGV_ID_MAP = new ConcurrentHashMap<>(); public static final Map AGV_NO_MAP = new ConcurrentHashMap<>(); @Autowired private AgvDetailService agvDetailService; @Autowired private AgvModelService agvModelService; @Autowired private ConfigService configService; @Autowired private CodeService codeService; @Autowired private SegmentService segmentService; @Autowired private TaskService taskService; @Autowired private AreaAgvService areaAgvService; @Autowired private MapDataDispatcher mapDataDispatcher; @PostConstruct public void init() { for (Agv agv : this.list()) { AGV_ID_MAP.put(agv.getUuid(), agv.getId()); AGV_NO_MAP.put(agv.getId(), agv.getUuid()); } } @Override public PageResult pageRel(PageParam pageParam) { return new PageResult<>(this.baseMapper.selectPageRel(pageParam, pageParam.checkoutMap()), pageParam.getTotal()); } @Override public Agv selectByUuid(String uuid) { return this.getOne(new LambdaQueryWrapper().eq(Agv::getUuid, uuid)); } @Override public Long getAgvId(String uuid) { if (Cools.isEmpty(uuid)) { return null; } Long agvId = AGV_ID_MAP.get(uuid); if (agvId != null) { return agvId; } Agv agv = this.selectByUuid(uuid); if (agv == null) { return null; } AGV_ID_MAP.put(uuid, agv.getId()); return agv.getId(); } @Override public String getAgvNo(Long agvId) { if (Cools.isEmpty(agvId)) { return null; } String agvNo = AGV_NO_MAP.get(agvId); if (!Cools.isEmpty(agvNo)) { return agvNo; } Agv agv = this.getById(agvId); if (null == agv) { return null; } AGV_NO_MAP.put(agvId, agv.getUuid()); return agv.getUuid(); } @Override public Agv modify(Agv agv, Long userId) { if (agv == null || agv.getId() == null) { throw new CoolException("Update Fail"); } Date now = new Date(); // 唯一性校验:只有当 uuid 非空时才校验(避免空值误判) if (!Cools.isEmpty(agv.getUuid())) { boolean exists = this.count(new LambdaQueryWrapper() .eq(Agv::getUuid, agv.getUuid()) .ne(Agv::getId, agv.getId())) > 0; if (exists) { throw new CoolException("Update Fail"); } } Agv oldAgv = this.getById(agv.getId()); String oldAgvNo = oldAgv.getUuid(); agv.setUpdateBy(userId); agv.setUpdateTime(now); if (!this.updateById(agv)) { throw new CoolException("Update Fail"); } // 以 DB 最终值为准刷新缓存(防止请求体缺字段/为空) Agv newAgv = this.getById(agv.getId()); String newAgvNo = newAgv.getUuid(); if (!oldAgvNo.equals(newAgvNo)) { AGV_ID_MAP.remove(oldAgvNo); AGV_ID_MAP.put(newAgvNo, newAgv.getId()); AGV_NO_MAP.remove(newAgv.getId()); AGV_NO_MAP.put(newAgv.getId(), newAgvNo); } return newAgv; } @Override @Transactional(rollbackFor = Exception.class) public Long delete(Long agvId, Long userId) { if (Cools.isEmpty(agvId)) { return null; } Agv agv = this.getById(agvId); AGV_NO_MAP.remove(agvId); AGV_ID_MAP.remove(agv.getUuid()); mapDataDispatcher.modifyDynamicMatrix(MapDataDispatcher.MAP_DEFAULT_LEV, null, agv.getUuid(), true); areaAgvService.removeByAgvId(agvId); this.removeById(agvId); agvDetailService.removeByAgvId(agvId); return agvId; } @Override public Boolean judgeEnable(Long agvId) { return this.judgeEnable(agvId, false); } @Override public Boolean judgeEnable(Long agvId, Boolean isLowBattery) { String agvNo = this.getAgvNo(agvId); AgvModel agvModel = agvModelService.getByAgvId(agvId); if (0 < segmentService.count(new LambdaQueryWrapper() .eq(Segment::getAgvId, agvId) .eq(Segment::getState, SegmentStateType.RUNNING.toString()) )) { // log.warn("[{}]号Agv正在忙碌 - segment......", agvNo); return false; } if (!this.judgeOnline(agvId)) { // log.warn("[{}]号Agv不是在线状态......", agvNo); return false; } AgvDetail agvDetail = agvDetailService.selectMajorByAgvId(agvId); if (null == agvDetail) { log.warn("[{}]号Agv未收到状态包......", agvNo); return false; } if (null == agvDetail.getSoc() || agvDetail.getSoc() == 0) { return false; } if (!agvDetail.getAgvStatus().equals(AgvStatusType.IDLE) && !agvDetail.getAgvStatus().equals(AgvStatusType.CHARGE)) { log.warn("[{}]号Agv不是空闲状态......", agvNo); return false; } if (agvDetail.getAgvStatus().equals(AgvStatusType.CHARGE)) { if (agvDetail.getSoc() < agvModel.getQuaBattery()) { return false; } } if (!agvDetail.getAgvStatus().equals(AgvStatusType.CHARGE)) { if (agvDetail.getPos() != 1) { log.warn("[{}]号Agv当前不在定位......", agvNo); return false; } if (null == agvDetail.getRecentCode()) { log.warn("[{}]号Agv当前不在定位......", agvNo); return false; } } // with battery if (isLowBattery) { Agv agv = this.getById(agvId); if (agvDetailService.isPowerLoss(agv, agvDetail, agvModel)) { log.warn("[{}]号Agv电量不足......", agvNo); return false; } } return true; } @Override public Boolean judgeOnline(Long agvId) { Agv agv = this.getById(agvId); return redis.getObject(RedisConstant.AGV_ONLINE_FLAG, agv.getUuid()) != null; } @Override public List getVehicleDtoList(List noIncluded) { List res = new ArrayList<>(); List list = this.list(new LambdaQueryWrapper()); for (Agv agv : list) { if (!Cools.isEmpty(noIncluded)) { if (noIncluded.contains(agv.getUuid())) { continue; } } AgvDetail detail = agvDetailService.selectByAgvId(agv.getId()); VehicleDto dto = new VehicleDto(); dto.setVehicle(agv.getUuid()); dto.setPosCode(codeService.getCacheById(detail.getRecentCode()).getData()); res.add(dto); } return res; } @Override public Integer getBackpack(Agv agv) { // if (null != agv.getStage()) { // return agv.getStage(); // } AgvModel agvModel = agvModelService.getByAgvId(agv.getId()); assert null != agvModel; return agvModel.getBackpack(); } @Override public Agv findByPosition(Long codeId) { List agvList = this.list(new LambdaQueryWrapper() // .eq(Agv::getStatus, StatusType.ENABLE.val) ); for (Agv agv : agvList) { AgvDetail agvDetail = agvDetailService.selectByAgvId(agv.getId()); if (null == agvDetail) { continue; } if (null == agvDetail.getRecentCode()) { continue; } if (agvDetail.getRecentCode().equals(codeId)) { return agv; } } return null; } @Override public int getBackpackRemainingCapacity(Long agvId) { Integer usedSlots = CoreCache.AGV_BACKPACK_USED_CACHE.get(agvId); if (null == usedSlots) { usedSlots = taskService.findTransportTasksCountByAgv(agvId); } AgvModel agvModel = agvModelService.getByAgvId(agvId); return Math.max(agvModel.getBackpack() - usedSlots, 0); // if less than zero, then return zero } }