|  |  |  | 
|---|
|  |  |  | package com.zy.asrs.wcs.core.service.impl; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | import com.zy.asrs.wcs.core.entity.Task; | 
|---|
|  |  |  | import com.alibaba.fastjson.JSON; | 
|---|
|  |  |  | import com.alibaba.fastjson.JSONArray; | 
|---|
|  |  |  | import com.alibaba.fastjson.JSONObject; | 
|---|
|  |  |  | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; | 
|---|
|  |  |  | import com.zy.asrs.framework.common.Cools; | 
|---|
|  |  |  | import com.zy.asrs.framework.common.SnowflakeIdWorker; | 
|---|
|  |  |  | import com.zy.asrs.wcs.core.domain.dto.RedisMapDto; | 
|---|
|  |  |  | import com.zy.asrs.wcs.core.entity.*; | 
|---|
|  |  |  | import com.zy.asrs.wcs.core.kernel.AnalyzeService; | 
|---|
|  |  |  | import com.zy.asrs.wcs.core.model.MapNode; | 
|---|
|  |  |  | import com.zy.asrs.wcs.core.model.enums.DeviceCtgType; | 
|---|
|  |  |  | import com.zy.asrs.wcs.core.model.enums.MotionStsType; | 
|---|
|  |  |  | import com.zy.asrs.wcs.core.model.enums.TaskStsType; | 
|---|
|  |  |  | import com.zy.asrs.wcs.core.service.TaskService; | 
|---|
|  |  |  | import com.zy.asrs.wcs.core.service.*; | 
|---|
|  |  |  | import com.zy.asrs.wcs.core.utils.RedisUtil; | 
|---|
|  |  |  | import com.zy.asrs.wcs.core.utils.ShuttleDispatcher; | 
|---|
|  |  |  | import com.zy.asrs.wcs.core.utils.Utils; | 
|---|
|  |  |  | import com.zy.asrs.wcs.rcs.News; | 
|---|
|  |  |  | import com.zy.asrs.wcs.core.entity.Motion; | 
|---|
|  |  |  | import com.zy.asrs.wcs.core.service.MotionService; | 
|---|
|  |  |  | import com.zy.asrs.wcs.rcs.cache.SlaveConnection; | 
|---|
|  |  |  | import com.zy.asrs.wcs.rcs.constant.DeviceRedisConstant; | 
|---|
|  |  |  | import com.zy.asrs.wcs.rcs.entity.Device; | 
|---|
|  |  |  | import com.zy.asrs.wcs.rcs.model.enums.ShuttleProtocolStatusType; | 
|---|
|  |  |  | import com.zy.asrs.wcs.rcs.model.enums.SlaveType; | 
|---|
|  |  |  | import com.zy.asrs.wcs.rcs.model.protocol.ShuttleProtocol; | 
|---|
|  |  |  | import com.zy.asrs.wcs.rcs.model.protocol.StaProtocol; | 
|---|
|  |  |  | import com.zy.asrs.wcs.rcs.service.DeviceService; | 
|---|
|  |  |  | import com.zy.asrs.wcs.rcs.thread.DevpThread; | 
|---|
|  |  |  | import com.zy.asrs.wcs.rcs.thread.ShuttleThread; | 
|---|
|  |  |  | import com.zy.asrs.wcs.system.entity.Dict; | 
|---|
|  |  |  | import com.zy.asrs.wcs.system.service.DictService; | 
|---|
|  |  |  | import lombok.extern.slf4j.Slf4j; | 
|---|
|  |  |  | import org.springframework.beans.factory.annotation.Autowired; | 
|---|
|  |  |  | import org.springframework.stereotype.Service; | 
|---|
|  |  |  | import org.springframework.transaction.annotation.Transactional; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | import java.util.Date; | 
|---|
|  |  |  | import java.util.List; | 
|---|
|  |  |  | import java.util.*; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | /** | 
|---|
|  |  |  | * 立体仓库WCS系统主流程业务 | 
|---|
|  |  |  | 
|---|
|  |  |  | private AnalyzeService analyzeService; | 
|---|
|  |  |  | @Autowired | 
|---|
|  |  |  | private MotionService motionService; | 
|---|
|  |  |  | @Autowired | 
|---|
|  |  |  | private DeviceService deviceService; | 
|---|
|  |  |  | @Autowired | 
|---|
|  |  |  | private LocCtgService locCtgService; | 
|---|
|  |  |  | @Autowired | 
|---|
|  |  |  | private LocService locService; | 
|---|
|  |  |  | @Autowired | 
|---|
|  |  |  | private SnowflakeIdWorker snowflakeIdWorker; | 
|---|
|  |  |  | @Autowired | 
|---|
|  |  |  | private TaskCtgService taskCtgService; | 
|---|
|  |  |  | @Autowired | 
|---|
|  |  |  | private DictService dictService; | 
|---|
|  |  |  | @Autowired | 
|---|
|  |  |  | private ShuttleDispatcher shuttleDispatcher; | 
|---|
|  |  |  | @Autowired | 
|---|
|  |  |  | private RedisUtil redisUtil; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | /** | 
|---|
|  |  |  | * 组托 | 
|---|
|  |  |  | 
|---|
|  |  |  | */ | 
|---|
|  |  |  | public synchronized void generateInboundWrk() { | 
|---|
|  |  |  |  | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | /** | 
|---|
|  |  |  | * 初始化实时地图 | 
|---|
|  |  |  | */ | 
|---|
|  |  |  | public synchronized void initRealtimeBasMap() { | 
|---|
|  |  |  | try { | 
|---|
|  |  |  | List<Dict> dicts = dictService.list(new LambdaQueryWrapper<Dict>() | 
|---|
|  |  |  | .like(Dict::getFlag, "map") | 
|---|
|  |  |  | .eq(Dict::getStatus, 1)); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | TreeMap<Integer, ArrayList<ArrayList<MapNode>>> levData = new TreeMap<>(); | 
|---|
|  |  |  | for (Dict dict : dicts) { | 
|---|
|  |  |  | String[] split = dict.getFlag().split("-"); | 
|---|
|  |  |  | int lev = Integer.parseInt(split[1]); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | TreeMap<Integer, List<JSONObject>> rows = new TreeMap<>(); | 
|---|
|  |  |  | //排序Row | 
|---|
|  |  |  | JSONArray value = JSON.parseArray(dict.getValue()); | 
|---|
|  |  |  | for (Object o : value) { | 
|---|
|  |  |  | JSONObject item = JSON.parseObject(o.toString()); | 
|---|
|  |  |  | if (item.getString("type").equals("SHELF")) { | 
|---|
|  |  |  | JSONObject property = JSON.parseObject(item.getString("property")); | 
|---|
|  |  |  | Integer row1 = property.getInteger("row"); | 
|---|
|  |  |  | ArrayList<JSONObject> bays = new ArrayList<>(); | 
|---|
|  |  |  | if (rows.containsKey(row1)) { | 
|---|
|  |  |  | bays.addAll(rows.get(row1)); | 
|---|
|  |  |  | } | 
|---|
|  |  |  | bays.add(property); | 
|---|
|  |  |  | rows.put(row1, bays); | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | ArrayList<ArrayList<MapNode>> list = new ArrayList<>(); | 
|---|
|  |  |  | //排序Bay | 
|---|
|  |  |  | for (Map.Entry<Integer, List<JSONObject>> entry : rows.entrySet()) { | 
|---|
|  |  |  | ArrayList<MapNode> nodes = new ArrayList<>(); | 
|---|
|  |  |  | for (JSONObject object : entry.getValue()) { | 
|---|
|  |  |  | MapNode mapNode = new MapNode(); | 
|---|
|  |  |  | mapNode.setValue(object.getInteger("shelfType")); | 
|---|
|  |  |  | mapNode.setTop(object.getInteger("top")); | 
|---|
|  |  |  | mapNode.setBottom(object.getInteger("bottom")); | 
|---|
|  |  |  | mapNode.setLeft(object.getInteger("left")); | 
|---|
|  |  |  | mapNode.setRight(object.getInteger("right")); | 
|---|
|  |  |  | mapNode.setRow(object.getInteger("row")); | 
|---|
|  |  |  | mapNode.setBay(object.getInteger("bay")); | 
|---|
|  |  |  | mapNode.setNo(object.getString("row") + "-" + object.getString("bay")); | 
|---|
|  |  |  | nodes.add(mapNode); | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | Collections.sort(nodes, new Comparator<MapNode>() { | 
|---|
|  |  |  | @Override | 
|---|
|  |  |  | public int compare(MapNode o1, MapNode o2) { | 
|---|
|  |  |  | return Integer.compare(o1.getBay(), o2.getBay()); | 
|---|
|  |  |  | } | 
|---|
|  |  |  | }); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | list.add(nodes); | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | levData.put(lev, list); | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | for (Map.Entry<Integer, ArrayList<ArrayList<MapNode>>> entry : levData.entrySet()) { | 
|---|
|  |  |  | ArrayList<ArrayList<MapNode>> lists = entry.getValue();//获取地图 | 
|---|
|  |  |  |  | 
|---|
|  |  |  | MapNode mapNode = new MapNode(); | 
|---|
|  |  |  | mapNode.setValue(-1); | 
|---|
|  |  |  | mapNode.setTop(1000); | 
|---|
|  |  |  | mapNode.setBottom(1000); | 
|---|
|  |  |  | mapNode.setLeft(1000); | 
|---|
|  |  |  | mapNode.setRight(1000); | 
|---|
|  |  |  | mapNode.setRow(0); | 
|---|
|  |  |  | mapNode.setBay(0); | 
|---|
|  |  |  | mapNode.setNo("0-0"); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | //获取最长row | 
|---|
|  |  |  | int row = 0; | 
|---|
|  |  |  | //给每个row首尾增加-1节点 | 
|---|
|  |  |  | for (ArrayList<MapNode> list : lists) { | 
|---|
|  |  |  | if (list.size() > row) { | 
|---|
|  |  |  | row = list.size(); | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | list.add(0, mapNode.clone()); | 
|---|
|  |  |  | list.add(mapNode.clone()); | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | ArrayList<MapNode> headNodes = new ArrayList<>(); | 
|---|
|  |  |  | ArrayList<MapNode> footerNodes = new ArrayList<>(); | 
|---|
|  |  |  | for (int i = 0; i < row+2; i++) { | 
|---|
|  |  |  | headNodes.add(mapNode.clone()); | 
|---|
|  |  |  | footerNodes.add(mapNode.clone()); | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | lists.add(0, headNodes); | 
|---|
|  |  |  | lists.add(footerNodes); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | Integer lev = entry.getKey(); | 
|---|
|  |  |  | Date now = new Date(); | 
|---|
|  |  |  | RedisMapDto map = new RedisMapDto(); | 
|---|
|  |  |  | map.setData(JSON.toJSONString(lists)); | 
|---|
|  |  |  | map.setCreateTime(now); | 
|---|
|  |  |  | map.setUpdateTime(now); | 
|---|
|  |  |  | map.setLev(lev); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | //将地图数据存入redis | 
|---|
|  |  |  | redisUtil.set(DeviceRedisConstant.MAP + lev, JSON.toJSONString(map)); | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } catch (Exception e) { | 
|---|
|  |  |  | e.printStackTrace(); | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | // 解析入库工作档 | 
|---|
|  |  |  | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | /** | 
|---|
|  |  |  | * 出库 ====>> 同一时间一台穿梭车只能有一个出库任务 | 
|---|
|  |  |  | */ | 
|---|
|  |  |  | public synchronized void generateOutboundWrkMast() { | 
|---|
|  |  |  | List<Task> tasks = taskService.selectPakOut(); | 
|---|
|  |  |  | if (tasks.isEmpty()) { | 
|---|
|  |  |  | return; | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | for (Task task : tasks) { | 
|---|
|  |  |  | DevpThread devpThread = (DevpThread) SlaveConnection.get(SlaveType.Devp, 1); | 
|---|
|  |  |  | StaProtocol staProtocol = devpThread.getStation().get(Integer.parseInt(task.getOriginSite()));//源站 | 
|---|
|  |  |  | StaProtocol staProtocol1 = devpThread.getStation().get(Integer.parseInt(task.getDestSite()));//目标站 | 
|---|
|  |  |  | if (staProtocol == null || staProtocol1 == null) { | 
|---|
|  |  |  | continue; | 
|---|
|  |  |  | } else { | 
|---|
|  |  |  | staProtocol = staProtocol.clone(); | 
|---|
|  |  |  | staProtocol1 = staProtocol1.clone(); | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | //            // 查询站点详细信息 | 
|---|
|  |  |  | //            BasDevp staDetl = basDevpService.selectById(outSta.getStaNo()); | 
|---|
|  |  |  | //            if (staDetl == null) { | 
|---|
|  |  |  | //                log.error("出库 ===>> 站点在数据库不存在, 站点编号={}", outSta.getStaNo()); | 
|---|
|  |  |  | //                continue; | 
|---|
|  |  |  | //            } | 
|---|
|  |  |  | // 判断堆垛机出库站状态 | 
|---|
|  |  |  | if (staProtocol.isAutoing() && !staProtocol.isLoading() && staProtocol.getWorkNo() == 0 && staProtocol.isOutEnable()) { | 
|---|
|  |  |  |  | 
|---|
|  |  |  | if (!(staProtocol1.isAutoing() && !staProtocol1.isLoading() && staProtocol1.getWorkNo() == 0 && staProtocol1.isOutEnable())) { | 
|---|
|  |  |  | continue; | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | //                //同库位组校验 | 
|---|
|  |  |  | //                List<String> outerLoc = Utils.getGroupOuterLoc(wrkMast.getSourceLocNo()); | 
|---|
|  |  |  | //                List<LocMast> outerLocMasts = locMastService.selectNotEmptyLocNos(outerLoc); | 
|---|
|  |  |  | //                if (!outerLocMasts.isEmpty()) { | 
|---|
|  |  |  | //                    News.info("{}任务,浅库位存在货物,系统等待中", wrkMast.getWrkNo()); | 
|---|
|  |  |  | //                    continue;//浅库位存在未执行任务 | 
|---|
|  |  |  | //                } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | // generate motion list | 
|---|
|  |  |  | List<Motion> motionList = analyzeService.generateMotion(task); | 
|---|
|  |  |  | if (Cools.isEmpty(motionList)) { | 
|---|
|  |  |  | log.error("出库 ===>> 暂时没有空闲小车, 任务号={}", task.getTaskNo()); | 
|---|
|  |  |  | continue; | 
|---|
|  |  |  | } | 
|---|
|  |  |  | motionService.batchInsert(motionList, task.getUuid(), Integer.valueOf(task.getTaskNo())); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | // 更新工作主档 | 
|---|
|  |  |  | task.setTaskSts(TaskStsType.ANALYZE_OUTBOUND.sts); // 工作状态 | 
|---|
|  |  |  | task.setUpdateTime(new Date()); | 
|---|
|  |  |  | if (!taskService.updateById(task)) { | 
|---|
|  |  |  | News.error("更新工作档失败!!! [工作号:{}]", task.getTaskNo()); | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | /** | 
|---|
|  |  |  | * 四向穿梭车电量检测 ===>> 发起充电 | 
|---|
|  |  |  | */ | 
|---|
|  |  |  | public synchronized void loopShuttleCharge() { | 
|---|
|  |  |  | // 获取充电桩库位类型 | 
|---|
|  |  |  | LocCtg locCtg = locCtgService.getOne(new LambdaQueryWrapper<LocCtg>() | 
|---|
|  |  |  | .eq(LocCtg::getFlag, "CHARGE") | 
|---|
|  |  |  | .eq(LocCtg::getStatus, 1)); | 
|---|
|  |  |  | if (locCtg == null) { | 
|---|
|  |  |  | return; | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | //获取充电任务类型 | 
|---|
|  |  |  | TaskCtg taskCtg = taskCtgService.getOne(new LambdaQueryWrapper<TaskCtg>() | 
|---|
|  |  |  | .eq(TaskCtg::getFlag, "CHARGE") | 
|---|
|  |  |  | .eq(TaskCtg::getStatus, 1)); | 
|---|
|  |  |  | if (taskCtg == null) { | 
|---|
|  |  |  | return; | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | List<Device> list = deviceService.list(new LambdaQueryWrapper<Device>() | 
|---|
|  |  |  | .eq(Device::getDeviceType, DeviceCtgType.SHUTTLE.val()) | 
|---|
|  |  |  | .eq(Device::getStatus, 1)); | 
|---|
|  |  |  | for (Device device : list) { | 
|---|
|  |  |  | //获取四向穿梭车线程 | 
|---|
|  |  |  | ShuttleThread shuttleThread = (ShuttleThread) SlaveConnection.get(SlaveType.Shuttle, device.getId().intValue()); | 
|---|
|  |  |  | if (shuttleThread == null) { | 
|---|
|  |  |  | continue; | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | ShuttleProtocol shuttleProtocol = shuttleThread.getStatus(); | 
|---|
|  |  |  | if (shuttleProtocol == null) { | 
|---|
|  |  |  | continue; | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | if (!shuttleProtocol.getProtocolStatusType().equals(ShuttleProtocolStatusType.IDLE)) { | 
|---|
|  |  |  | continue; | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | if (!shuttleThread.isRequireCharge()) { | 
|---|
|  |  |  | continue; | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | String currentLocNo = shuttleProtocol.getCurrentLocNo(); | 
|---|
|  |  |  | int lev = Utils.getLev(currentLocNo);//获取小车楼层 | 
|---|
|  |  |  | //搜索小车当前楼层充电桩 | 
|---|
|  |  |  | ArrayList<Loc> allChargeLoc = new ArrayList<>(); | 
|---|
|  |  |  | List<Loc> list1 = locService.list(new LambdaQueryWrapper<Loc>() | 
|---|
|  |  |  | .eq(Loc::getLocCtg, locCtg.getId()) | 
|---|
|  |  |  | .eq(Loc::getStatus, 1) | 
|---|
|  |  |  | .eq(Loc::getLev, lev)); | 
|---|
|  |  |  | if (!list1.isEmpty()) { | 
|---|
|  |  |  | allChargeLoc.addAll(list1); | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | //搜索其他楼层充电桩 | 
|---|
|  |  |  | List<Loc> list2 = locService.list(new LambdaQueryWrapper<Loc>() | 
|---|
|  |  |  | .eq(Loc::getLocCtg, locCtg.getId()) | 
|---|
|  |  |  | .eq(Loc::getStatus, 1) | 
|---|
|  |  |  | .notIn(Loc::getLev, lev)); | 
|---|
|  |  |  | if (!list2.isEmpty()) { | 
|---|
|  |  |  | allChargeLoc.addAll(list2); | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | //没有找到充电桩 | 
|---|
|  |  |  | if (allChargeLoc.isEmpty()) { | 
|---|
|  |  |  | continue; | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | //选择空闲充电桩 | 
|---|
|  |  |  | Loc chargeLoc = null; | 
|---|
|  |  |  | for (Loc loc : allChargeLoc) { | 
|---|
|  |  |  | // 判断充电位是否被占用(车辆位置) | 
|---|
|  |  |  | if (Utils.hasShuttleInLoc(loc.getLocNo(), device.getId())) { | 
|---|
|  |  |  | continue; | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | // 盘点充电位是否存在任务档 | 
|---|
|  |  |  | List<Task> tasks = taskService.hasChargeInLoc(loc.getLocNo()); | 
|---|
|  |  |  | if (!tasks.isEmpty()) { | 
|---|
|  |  |  | continue; | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | chargeLoc = loc; | 
|---|
|  |  |  | break; | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | if (chargeLoc == null) { | 
|---|
|  |  |  | continue;//未找到充电桩 | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | if (motionService.count(new LambdaQueryWrapper<Motion>() | 
|---|
|  |  |  | .eq(Motion::getDeviceCtg, DeviceCtgType.SHUTTLE.val()) | 
|---|
|  |  |  | .eq(Motion::getDevice, device.getDeviceNo()) | 
|---|
|  |  |  | .eq(Motion::getMotionSts, MotionStsType.EXECUTING.val())) > 0) { | 
|---|
|  |  |  | continue; | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | //判断当前小车是否满足需要充电要求 | 
|---|
|  |  |  | if (!shuttleThread.isRequireCharge()) { | 
|---|
|  |  |  | continue; | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | Task taskCharge = taskService.selectChargeWorking(Integer.valueOf(device.getDeviceNo())); | 
|---|
|  |  |  | if (taskCharge != null) {//已有充电任务 | 
|---|
|  |  |  | continue; | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | String chargeLocNo = chargeLoc.getLocNo(); | 
|---|
|  |  |  | Task task = new Task(); | 
|---|
|  |  |  | task.setUuid(String.valueOf(snowflakeIdWorker.nextId())); | 
|---|
|  |  |  | task.setTaskNo(String.valueOf(Utils.getTaskNo("CHARGE"))); | 
|---|
|  |  |  | task.setTaskSts(TaskStsType.NEW_CHARGE.sts); | 
|---|
|  |  |  | task.setTaskCtg(taskCtg.getId()); | 
|---|
|  |  |  | task.setPriority(10); | 
|---|
|  |  |  | task.setOriginSite(null); | 
|---|
|  |  |  | task.setOriginLoc(null); | 
|---|
|  |  |  | task.setDestSite(null); | 
|---|
|  |  |  | task.setDestLoc(chargeLocNo); | 
|---|
|  |  |  | task.setIoTime(new Date()); | 
|---|
|  |  |  | task.setStartTime(new Date()); | 
|---|
|  |  |  | task.setHostId(device.getHostId()); | 
|---|
|  |  |  | task.setStatus(1); | 
|---|
|  |  |  | task.setMemo("charge"); | 
|---|
|  |  |  | task.setShuttleNo(Integer.valueOf(device.getDeviceNo())); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | // generate motion list | 
|---|
|  |  |  | List<Motion> motionList = analyzeService.generateChargeMotion(task); | 
|---|
|  |  |  | if (Cools.isEmpty(motionList)) { | 
|---|
|  |  |  | News.error("保存{}号四向穿梭车充电任务失败!!!", device.getDeviceNo()); | 
|---|
|  |  |  | continue; | 
|---|
|  |  |  | } | 
|---|
|  |  |  | motionService.batchInsert(motionList, task.getUuid(), Integer.valueOf(task.getTaskNo())); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | task.setTaskSts(TaskStsType.ANALYZE_CHARGE.sts); | 
|---|
|  |  |  | if (!taskService.save(task)) { | 
|---|
|  |  |  | News.error("保存{}号四向穿梭车充电任务失败!!!", device.getDeviceNo()); | 
|---|
|  |  |  | continue; | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | News.info("保存{}号四向穿梭车充电任务成功!!!", device.getDeviceNo()); | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | /** | 
|---|
|  |  |  | * 四向穿梭车电量检测 ===>> 满电后回到待机位 | 
|---|
|  |  |  | */ | 
|---|
|  |  |  | public synchronized void loopShuttleToStandbyCauseCharge() { | 
|---|
|  |  |  | Integer enoughPower = 90; | 
|---|
|  |  |  | Dict dict = dictService.getOne(new LambdaQueryWrapper<Dict>() | 
|---|
|  |  |  | .eq(Dict::getFlag, "chargeMaxValue") | 
|---|
|  |  |  | .eq(Dict::getStatus, 1)); | 
|---|
|  |  |  | if (dict != null) { | 
|---|
|  |  |  | enoughPower = Integer.parseInt(dict.getValue()); | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | //获取迁移任务类型 | 
|---|
|  |  |  | TaskCtg taskCtg = taskCtgService.getOne(new LambdaQueryWrapper<TaskCtg>() | 
|---|
|  |  |  | .eq(TaskCtg::getFlag, "MOVE") | 
|---|
|  |  |  | .eq(TaskCtg::getStatus, 1)); | 
|---|
|  |  |  | if (taskCtg == null) { | 
|---|
|  |  |  | return; | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | List<Device> list = deviceService.list(new LambdaQueryWrapper<Device>() | 
|---|
|  |  |  | .eq(Device::getDeviceType, DeviceCtgType.SHUTTLE.val()) | 
|---|
|  |  |  | .eq(Device::getStatus, 1)); | 
|---|
|  |  |  | for (Device device : list) { | 
|---|
|  |  |  | //获取四向穿梭车线程 | 
|---|
|  |  |  | ShuttleThread shuttleThread = (ShuttleThread) SlaveConnection.get(SlaveType.Shuttle, device.getId().intValue()); | 
|---|
|  |  |  | if (shuttleThread == null) { | 
|---|
|  |  |  | continue; | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | if (!shuttleThread.isCharging()) { | 
|---|
|  |  |  | continue; | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | if (!shuttleThread.isChargingCompleted()) { | 
|---|
|  |  |  | continue; | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | //查找充电任务 | 
|---|
|  |  |  | Task chargeTask = taskService.getOne(new LambdaQueryWrapper<Task>() | 
|---|
|  |  |  | .eq(Task::getTaskSts, TaskStsType.CHARGE_WORKING.sts) | 
|---|
|  |  |  | .eq(Task::getShuttleNo, device.getDeviceNo())); | 
|---|
|  |  |  | if (chargeTask == null) { | 
|---|
|  |  |  | continue; | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | //充电完成 | 
|---|
|  |  |  | // 已有迁移任务 | 
|---|
|  |  |  | if (taskService.selectMoveWorking(Integer.valueOf(device.getDeviceNo())) != null) { | 
|---|
|  |  |  | continue; | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | //获取避让位置 | 
|---|
|  |  |  | String standByLocNo = shuttleDispatcher.searchStandByLocNo(Integer.valueOf(device.getDeviceNo()), device.getHostId(), shuttleThread.getStatus().getCurrentLocNo()); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | Task task = new Task(); | 
|---|
|  |  |  | task.setUuid(String.valueOf(snowflakeIdWorker.nextId())); | 
|---|
|  |  |  | task.setTaskNo(String.valueOf(Utils.getTaskNo("MOVE"))); | 
|---|
|  |  |  | task.setTaskSts(TaskStsType.NEW_MOVE.sts); | 
|---|
|  |  |  | task.setTaskCtg(taskCtg.getId()); | 
|---|
|  |  |  | task.setPriority(10); | 
|---|
|  |  |  | task.setOriginSite(null); | 
|---|
|  |  |  | task.setOriginLoc(null); | 
|---|
|  |  |  | task.setDestSite(null); | 
|---|
|  |  |  | task.setDestLoc(standByLocNo); // 避让位置 | 
|---|
|  |  |  | task.setIoTime(new Date()); | 
|---|
|  |  |  | task.setStartTime(new Date()); | 
|---|
|  |  |  | task.setHostId(device.getHostId()); | 
|---|
|  |  |  | task.setStatus(1); | 
|---|
|  |  |  | task.setMemo("charge"); | 
|---|
|  |  |  | task.setShuttleNo(Integer.valueOf(device.getDeviceNo())); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | // generate motion list | 
|---|
|  |  |  | List<Motion> motionList = analyzeService.generateShuttleChargeWrkComplete(task); | 
|---|
|  |  |  | if (Cools.isEmpty(motionList)) { | 
|---|
|  |  |  | News.error("保存{}号四向穿梭车迁移任务失败!!!", device.getDeviceNo()); | 
|---|
|  |  |  | continue; | 
|---|
|  |  |  | } | 
|---|
|  |  |  | motionService.batchInsert(motionList, task.getUuid(), Integer.valueOf(task.getTaskNo())); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | task.setTaskSts(TaskStsType.ANALYZE_MOVE.sts); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | if (!taskService.save(task)) { | 
|---|
|  |  |  | News.error("保存{}号四向穿梭车迁移任务失败!!!", device.getDeviceNo()); | 
|---|
|  |  |  | continue; | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | chargeTask.setTaskSts(TaskStsType.COMPLETE_CHARGE.sts); | 
|---|
|  |  |  | chargeTask.setIoTime(new Date()); | 
|---|
|  |  |  | taskService.updateById(chargeTask); | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | } | 
|---|