package com.zy.asrs.wcs.core.service.impl;
|
|
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.common.domain.dto.StartupDto;
|
import com.zy.asrs.common.domain.param.SearchLocParam;
|
import com.zy.asrs.common.utils.HttpHandler;
|
import com.zy.asrs.framework.common.Cools;
|
import com.zy.asrs.framework.common.SnowflakeIdWorker;
|
import com.zy.asrs.wcs.core.domain.dto.MatDto;
|
import com.zy.asrs.wcs.core.domain.dto.RedisMapDto;
|
import com.zy.asrs.wcs.core.domain.dto.StaDto;
|
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.*;
|
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.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.command.LedCommand;
|
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.BarcodeThread;
|
import com.zy.asrs.wcs.rcs.thread.DevpThread;
|
import com.zy.asrs.wcs.rcs.thread.LedThread;
|
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 org.springframework.transaction.interceptor.TransactionAspectSupport;
|
import java.util.*;
|
|
/**
|
* 立体仓库WCS系统主流程业务
|
* Created by vincent on 2020/8/6
|
*/
|
@Slf4j
|
@Service("mainService")
|
@Transactional
|
public class MainServiceImpl {
|
|
@Autowired
|
private TaskService taskService;
|
@Autowired
|
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;
|
@Autowired
|
private BasConveyorService basConveyorService;
|
@Autowired
|
private BasConveyorStaService basConveyorStaService;
|
@Autowired
|
private BasConveyorPathService basConveyorPathService;
|
@Autowired
|
private BasLedService basLedService;
|
|
/**
|
* 组托
|
* 入库站,根据条码扫描生成入库工作档,工作状态 2
|
*/
|
public synchronized void generateInboundWrk() {
|
try {
|
// 根据输送线plc遍历
|
List<Device> list = deviceService.list(new LambdaQueryWrapper<Device>()
|
.eq(Device::getDeviceType, DeviceCtgType.CONVEYOR.val())
|
.eq(Device::getStatus, 1));
|
for (Device devp : list) {
|
BasConveyor basConveyor = basConveyorService.getOne(new LambdaQueryWrapper<BasConveyor>().eq(BasConveyor::getDeviceId, devp.getId()).eq(BasConveyor::getHostId, devp.getHostId()));
|
// 遍历入库口
|
for (StaDto inSta : JSON.parseArray(basConveyor.getInSta(), StaDto.class)) {
|
// 获取入库站信息
|
DevpThread devpThread = (DevpThread) SlaveConnection.get(SlaveType.Conveyor, devp.getId().intValue());
|
StaProtocol staProtocol = devpThread.getStation().get(inSta.getStaNo());
|
if (staProtocol == null) {
|
continue;
|
} else {
|
staProtocol = staProtocol.clone();
|
}
|
Short workNo = staProtocol.getWorkNo();
|
// 尺寸检测异常
|
boolean back = false;
|
String errMsg = "异常:";
|
if (staProtocol.isFrontErr()) {
|
errMsg = errMsg + "前超限;";
|
back = true;
|
}
|
if (staProtocol.isBackErr()) {
|
errMsg = errMsg + "后超限";
|
back = true;
|
}
|
if (staProtocol.isHighErr()) {
|
errMsg = errMsg + "高超限";
|
back = true;
|
}
|
if (staProtocol.isLeftErr()) {
|
errMsg = errMsg + "左超限";
|
back = true;
|
}
|
if (staProtocol.isRightErr()) {
|
errMsg = errMsg + "右超限";
|
back = true;
|
}
|
if (staProtocol.isWeightErr()) {
|
errMsg = errMsg + "超重";
|
back = true;
|
}
|
if (staProtocol.isBarcodeErr()) {
|
errMsg = errMsg + "扫码失败";
|
back = true;
|
}
|
// 退回
|
if (back) {
|
// led 异常显示
|
LedThread ledThread = (LedThread) SlaveConnection.get(SlaveType.Led, inSta.getLed());
|
if (ledThread != null) {
|
ledThread.error(errMsg);
|
}
|
continue;
|
}
|
|
// 判断是否满足入库条件
|
if (staProtocol.isAutoing() && staProtocol.isLoading()
|
&& staProtocol.isInEnable()
|
&& !staProtocol.isEmptyMk() && (workNo == 0 || (workNo >= 9990 && workNo <= 9999))
|
) {
|
|
// 获取条码扫描仪信息
|
BarcodeThread barcodeThread = (BarcodeThread) SlaveConnection.get(SlaveType.Barcode, inSta.getBarcode());
|
if (barcodeThread == null) {
|
continue;
|
}
|
String barcode = barcodeThread.getBarcode();
|
if (!Cools.isEmpty(barcode)) {
|
News.info("{}号条码扫描器检测条码信息:{}", inSta.getBarcode(), barcode);
|
if ("NG".endsWith(barcode) || "NoRead".equals(barcode) || "empty".equals(barcode) || "00000000".equals(barcode)) {
|
staProtocol.setWorkNo((short) 32002);
|
staProtocol.setStaNo(inSta.getBackSta().shortValue());
|
devpThread.setPakMk(staProtocol.getSiteId(), false);
|
devpThread.writeWorkSta(staProtocol.getSiteId(), (short) 32002, inSta.getBackSta().shortValue());
|
|
// led 异常显示
|
LedThread ledThread = (LedThread) SlaveConnection.get(SlaveType.Led, inSta.getLed());
|
if (ledThread != null) {
|
String errorMsg = "扫码失败,请重试";
|
ledThread.error(errorMsg);
|
}
|
continue;
|
}
|
}
|
|
//获取入库任务类型
|
TaskCtg taskCtg = taskCtgService.getOne(new LambdaQueryWrapper<TaskCtg>()
|
.eq(TaskCtg::getFlag, String.valueOf(TaskCtgType.IN))
|
.eq(TaskCtg::getStatus, 1));
|
|
// 判断重复工作档
|
Task task1 = taskService.getOne(new LambdaQueryWrapper<Task>()
|
.eq(Task::getOriginSite, inSta.getStaNo())
|
.eq(Task::getTaskCtg, taskCtg.getId())
|
.in(Task::getTaskSts, 1, 2, 3)
|
.eq(Task::getZpallet, barcode));
|
if (task1 != null) {
|
News.error("工作档已存在,工作号={}", task1.getTaskNo());
|
continue;
|
}
|
|
try {
|
//获取WMS地址
|
Dict dict = dictService.getOne(new LambdaQueryWrapper<Dict>().eq(Dict::getFlag, "WMS_URL").eq(Dict::getStatus, 1));
|
if (dict == null) {
|
News.error("WMS地址未配置");
|
continue;
|
}
|
String wmsUrl = dict.getValue();
|
|
SearchLocParam param = new SearchLocParam();
|
param.setBarcode(barcode);
|
param.setIoType(1);
|
param.setSourceStaNo(inSta.getStaNo());
|
param.setLocType1(staProtocol.getLocType1().shortValue());
|
String response = new HttpHandler.Builder()
|
.setUri(wmsUrl)
|
.setPath("/rpc/pakin/loc/v2")
|
.setJson(JSON.toJSONString(param))
|
.build()
|
.doPost();
|
JSONObject jsonObject = JSON.parseObject(response);
|
LedThread ledThread = (LedThread) SlaveConnection.get(SlaveType.Led, inSta.getLed());
|
Integer code = jsonObject.getInteger("code");
|
if (code.equals(200)) {
|
StartupDto dto = jsonObject.getObject("data", StartupDto.class);
|
|
//获取输送路径
|
BasConveyorPath conveyorPath = basConveyorPathService.getOne(new LambdaQueryWrapper<BasConveyorPath>()
|
.eq(BasConveyorPath::getTypeNo, TaskCtgType.IN.val())
|
.eq(BasConveyorPath::getDeviceId, devp.getId())
|
.eq(BasConveyorPath::getStnNo, staProtocol.getSiteId()));
|
if (conveyorPath == null) {
|
News.error("输送路径不存在");
|
}else {
|
devpThread.writeWorkSta(staProtocol.getSiteId(), dto.getWorkNo().shortValue(), conveyorPath.getDeviceStn().shortValue());
|
devpThread.setPakMk(staProtocol.getSiteId(), false);
|
}
|
}else {
|
if (ledThread != null) {
|
String errorMsg = jsonObject.getString("msg");
|
if (!Cools.isEmpty(errorMsg)) {
|
ledThread.error(errorMsg);
|
ledThread.setLedMk(false);
|
}
|
}
|
News.error("请求接口失败!!!url:{};request:{};response:{}", wmsUrl + "/rpc/pakin/loc/v2", JSON.toJSONString(param), response);
|
}
|
} catch (Exception e) {
|
e.printStackTrace();
|
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
|
}
|
}
|
}
|
}
|
} catch (Exception e) {
|
e.printStackTrace();
|
}
|
}
|
|
/**
|
* 初始化实时地图
|
*/
|
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]);
|
|
Object data = redisUtil.get(DeviceRedisConstant.MAP + lev);
|
if (data != null) {
|
continue;
|
}
|
|
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"));
|
mapNode.setXBase(object.getInteger("refx"));
|
mapNode.setYBase(object.getInteger("refy"));
|
nodes.add(mapNode);
|
}
|
|
Collections.sort(nodes, new Comparator<MapNode>() {
|
@Override
|
public int compare(MapNode o1, MapNode o2) {
|
return Integer.compare(o1.getBay(), o2.getBay());
|
}
|
});
|
|
ArrayList<MapNode> sortNodes = new ArrayList<>();
|
int defaultBay = 1;//默认从1列开始
|
for (MapNode node : nodes) {
|
if (node.getBay() == defaultBay) {
|
defaultBay++;
|
sortNodes.add(node);
|
continue;
|
}
|
|
//存在空缺节点,自动补足
|
for (int i = defaultBay; i < node.getBay(); i++) {
|
MapNode mapNode = new MapNode();
|
mapNode.setValue(-1);
|
mapNode.setTop(1000);
|
mapNode.setBottom(1000);
|
mapNode.setLeft(1000);
|
mapNode.setRight(1000);
|
mapNode.setRow(node.getRow());
|
mapNode.setBay(i);
|
mapNode.setNo(node.getRow() + "-" + i);
|
mapNode.setXBase(0);
|
mapNode.setYBase(0);
|
sortNodes.add(mapNode);
|
}
|
|
defaultBay = node.getBay() + 1;
|
sortNodes.add(node);
|
}
|
|
list.add(sortNodes);
|
}
|
|
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");
|
mapNode.setXBase(0);
|
mapNode.setYBase(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());
|
}
|
|
//最后一次检测地图节点是否完整,地图矩阵row均要达到最长row
|
for (ArrayList<MapNode> list : lists) {
|
int len = (row + 2);//row+2是因为头节点和尾节点存在人为添加的-1节点
|
if (list.size() == len) {
|
continue;
|
}
|
//节点长度不满足,进行补足
|
for (int i = list.size(); i < len; i++) {
|
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 analyzeInBoundTask() {
|
for (Task task : taskService.selectWaitAnalyzeInBoundTask()) {
|
if (Cools.isEmpty(task.getShuttleNo())) {
|
//分配小车
|
//搜索空闲车
|
ShuttleThread shuttleThread = shuttleDispatcher.searchIdleShuttle(task);
|
if (shuttleThread == null) {
|
News.info("{}任务未找到空闲穿梭车", task.getTaskNo());
|
continue;
|
}
|
|
task.setShuttleNo(Integer.valueOf(shuttleThread.getDevice().getDeviceNo()));//保存穿梭车号
|
task.setUpdateTime(new Date());
|
if (!taskService.updateById(task)) {
|
News.info("{}任务更新穿梭车号失败", task.getTaskNo());
|
}
|
continue;
|
}
|
|
// generate motion list
|
List<Motion> motionList = analyzeService.generateMotion(task);
|
if (motionList.isEmpty()) {
|
continue;
|
}
|
motionService.batchInsert(motionList, task.getUuid(), Integer.valueOf(task.getTaskNo()), task.getHostId());
|
|
// 更新工作主档
|
task.setTaskSts(TaskStsType.ANALYZE_INBOUND.sts); // 工作状态
|
task.setUpdateTime(new Date());
|
if (!taskService.updateById(task)) {
|
News.error("更新工作档失败!!! [工作号:{}]", task.getTaskNo());
|
}
|
}
|
}
|
|
/**
|
* 出库 ====>> 同一时间一台穿梭车只能有一个出库任务
|
*/
|
public synchronized void analyzeOutBoundTask() {
|
List<Task> tasks = taskService.selectPakOut();
|
if (tasks.isEmpty()) {
|
return;
|
}
|
|
for (Task task : tasks) {
|
BasConveyorSta originStaObj = basConveyorStaService.selectBySiteNo(task.getOriginSite());//获取源站
|
if (originStaObj == null) {
|
continue;
|
}
|
|
BasConveyor basConveyor = basConveyorService.getById(originStaObj.getConveyorId());
|
if(basConveyor == null) {
|
continue;
|
}
|
|
DevpThread devpThread = (DevpThread) SlaveConnection.get(SlaveType.Conveyor, basConveyor.getDeviceId().intValue());
|
StaProtocol staProtocol = devpThread.getStation().get(Integer.parseInt(task.getOriginSite()));//源站
|
// StaProtocol staProtocol1 = devpThread.getStation().get(Integer.parseInt(task.getDestSite()));//目标站
|
if (staProtocol == null) {
|
continue;
|
} else {
|
staProtocol = staProtocol.clone();
|
// staProtocol1 = staProtocol1.clone();
|
}
|
|
// 判断堆垛机出库站状态
|
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;//浅库位存在未执行任务
|
// }
|
|
if (Cools.isEmpty(task.getShuttleNo())) {
|
//分配小车
|
//搜索空闲车
|
ShuttleThread shuttleThread = shuttleDispatcher.searchIdleShuttle(task);
|
if (shuttleThread == null) {
|
News.info("{}任务未找到空闲穿梭车", task.getTaskNo());
|
continue;
|
}
|
|
task.setShuttleNo(Integer.valueOf(shuttleThread.getDevice().getDeviceNo()));//保存穿梭车号
|
task.setUpdateTime(new Date());
|
if (!taskService.updateById(task)) {
|
News.info("{}任务更新穿梭车号失败", task.getTaskNo());
|
}
|
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.getHostId());
|
|
// 更新工作主档
|
task.setTaskSts(TaskStsType.ANALYZE_OUTBOUND.sts); // 工作状态
|
task.setUpdateTime(new Date());
|
if (!taskService.updateById(task)) {
|
News.error("更新工作档失败!!! [工作号:{}]", task.getTaskNo());
|
}
|
|
}
|
}
|
}
|
|
// 解析小车移动工作档
|
public synchronized void analyzeMoveTask() {
|
for (Task task : taskService.selectWaitAnalyzeMoveTask()) {
|
if (Cools.isEmpty(task.getShuttleNo())) {
|
//分配小车
|
//搜索空闲车
|
ShuttleThread shuttleThread = shuttleDispatcher.searchIdleShuttle(task);
|
if (shuttleThread == null) {
|
News.info("{}任务未找到空闲穿梭车", task.getTaskNo());
|
continue;
|
}
|
|
task.setShuttleNo(Integer.valueOf(shuttleThread.getDevice().getDeviceNo()));//保存穿梭车号
|
task.setUpdateTime(new Date());
|
if (!taskService.updateById(task)) {
|
News.info("{}任务更新穿梭车号失败", task.getTaskNo());
|
}
|
continue;
|
}
|
|
// generate motion list
|
List<Motion> motionList = analyzeService.generateShuttleMoveMotion(task);
|
if (motionList.isEmpty()) {
|
continue;
|
}
|
motionService.batchInsert(motionList, task.getUuid(), Integer.valueOf(task.getTaskNo()), task.getHostId());
|
|
// 更新工作主档
|
task.setTaskSts(TaskStsType.ANALYZE_MOVE.sts); // 工作状态
|
task.setUpdateTime(new Date());
|
if (!taskService.updateById(task)) {
|
News.error("更新工作档失败!!! [工作号:{}]", task.getTaskNo());
|
}
|
}
|
}
|
|
/**
|
* 四向穿梭车电量检测 ===>> 发起充电
|
*/
|
public synchronized void loopShuttleCharge() {
|
//获取充电任务类型
|
TaskCtg taskCtg = taskCtgService.getOne(new LambdaQueryWrapper<TaskCtg>()
|
.eq(TaskCtg::getFlag, String.valueOf(TaskCtgType.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::getLocSts, LocStsType.C.val())
|
.eq(Loc::getStatus, 1)
|
.eq(Loc::getLev, lev));
|
if (!list1.isEmpty()) {
|
allChargeLoc.addAll(list1);
|
}
|
|
//搜索其他楼层充电桩
|
List<Loc> list2 = locService.list(new LambdaQueryWrapper<Loc>()
|
.eq(Loc::getLocSts, LocStsType.C.val())
|
.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.getHostId());
|
|
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, String.valueOf(TaskCtgType.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;
|
}
|
|
ShuttleProtocol shuttleProtocol = shuttleThread.getStatus();
|
if (shuttleProtocol == 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.getHostId());
|
|
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);
|
}
|
}
|
|
/**
|
* 出库 ===>> 工作档信息写入led显示器
|
*/
|
public void ledExecute() {
|
// 遍历LED
|
List<Device> list = deviceService.list(new LambdaQueryWrapper<Device>()
|
.eq(Device::getDeviceType, DeviceCtgType.LED.val())
|
.eq(Device::getStatus, 1));
|
for (Device ledDevice : list) {
|
//获取led数据
|
BasLed led = basLedService.getOne(new LambdaQueryWrapper<BasLed>()
|
.eq(BasLed::getDeviceId, ledDevice.getId()));
|
List<Integer> staArr = JSON.parseArray(led.getSta(), Integer.class);
|
|
BasConveyor basConveyor = basConveyorService.getById(led.getConveyorId().intValue());
|
if (basConveyor == null) {
|
continue;
|
}
|
|
// 获取输送线plc线程
|
DevpThread devpThread = (DevpThread) SlaveConnection.get(SlaveType.Conveyor, basConveyor.getDeviceId().intValue());
|
// 命令集合
|
List<LedCommand> commands = new ArrayList<>();
|
// 工作档集合
|
List<Task> tasks = new ArrayList<>();
|
for (Integer staNo : staArr) {
|
// 获取叉车站点
|
StaProtocol staProtocol = devpThread.getStation().get(staNo);
|
if (null == staProtocol || null == staProtocol.getWorkNo() || 0 == staProtocol.getWorkNo() || !staProtocol.isLoading()) {
|
continue;
|
} else {
|
staProtocol = staProtocol.clone();
|
}
|
// 获取工作档数据
|
Task task = taskService.getOne(new LambdaQueryWrapper<Task>().eq(Task::getTaskNo, staProtocol.getWorkNo()));
|
if (null == task) {
|
continue;
|
}
|
|
tasks.add(task);
|
// 组装命令
|
LedCommand ledCommand = new LedCommand();
|
ledCommand.setWorkNo(task.getTaskNo());
|
ledCommand.setIoType(task.getTaskCtg().intValue());
|
ledCommand.setTitle(task.getTaskCtg$());
|
ledCommand.setSourceLocNo(task.getOriginLoc());
|
ledCommand.setLocNo(task.getDestLoc());
|
ledCommand.setStaNo(Integer.parseInt(task.getDestSite()));
|
|
try {
|
//获取WMS地址
|
Dict dict = dictService.getOne(new LambdaQueryWrapper<Dict>().eq(Dict::getFlag, "WMS_URL").eq(Dict::getStatus, 1));
|
if (dict != null) {
|
String wmsUrl = dict.getValue();
|
|
HashMap<String, Object> param = new HashMap<>();
|
param.put("taskNo", task.getTaskNo());
|
String response = new HttpHandler.Builder()
|
.setUri(wmsUrl)
|
.setPath("/queryTask")
|
.setJson(JSON.toJSONString(param))
|
.build()
|
.doPost();
|
JSONObject jsonObject = JSON.parseObject(response);
|
Integer code = jsonObject.getInteger("code");
|
if (code.equals(200)) {
|
List<MatDto> matDtos = JSON.parseArray(jsonObject.getString("data"), MatDto.class);
|
ledCommand.setMatDtos(matDtos);
|
}
|
}
|
} catch (Exception e) {
|
e.printStackTrace();
|
}
|
|
commands.add(ledCommand);
|
}
|
// 获取LED线程
|
LedThread ledThread = (LedThread) SlaveConnection.get(SlaveType.Led, ledDevice.getId().intValue());
|
// 命令下发 -------------------------------------------------------------------------------
|
if (!commands.isEmpty()) {
|
ledThread.write(commands);
|
ledThread.setLedMk(false);
|
}
|
}
|
}
|
|
/**
|
* 其他 ===>> LED显示器复位,显示默认信息
|
*/
|
public void ledReset() {
|
// 根据输送线plc遍历
|
List<Device> list = deviceService.list(new LambdaQueryWrapper<Device>()
|
.eq(Device::getDeviceType, DeviceCtgType.LED.val())
|
.eq(Device::getStatus, 1));
|
for (Device ledDevice : list) {
|
//获取led数据
|
BasLed led = basLedService.getOne(new LambdaQueryWrapper<BasLed>()
|
.eq(BasLed::getDeviceId, ledDevice.getId()));
|
List<Integer> staArr = JSON.parseArray(led.getSta(), Integer.class);
|
|
BasConveyor basConveyor = basConveyorService.getById(led.getConveyorId().intValue());
|
if (basConveyor == null) {
|
continue;
|
}
|
|
// 获取输送线plc线程
|
DevpThread devpThread = (DevpThread) SlaveConnection.get(SlaveType.Conveyor, basConveyor.getDeviceId().intValue());
|
// 命令集合
|
boolean reset = true;
|
for (Integer staNo : staArr) {
|
// 获取叉车站点
|
StaProtocol staProtocol = devpThread.getStation().get(staNo);
|
if (staProtocol == null) {
|
continue;
|
}
|
if (staProtocol.getWorkNo() != 0 && staProtocol.isLoading()) {
|
reset = false;
|
break;
|
}
|
}
|
// 获取led线程
|
LedThread ledThread = (LedThread) SlaveConnection.get(SlaveType.Led, ledDevice.getId().intValue());
|
// led显示默认内容
|
if (reset && !ledThread.isLedMk()) {
|
ledThread.errorReset();
|
ledThread.setLedMk(true);
|
}
|
}
|
|
for (Device ledDevice : list) {
|
//获取led数据
|
BasLed led = basLedService.getOne(new LambdaQueryWrapper<BasLed>()
|
.eq(BasLed::getDeviceId, ledDevice.getId()));
|
List<Integer> staArr = JSON.parseArray(led.getSta(), Integer.class);
|
|
BasConveyor basConveyor = basConveyorService.getById(led.getConveyorId());
|
if (basConveyor == null) {
|
continue;
|
}
|
|
// 获取输送线plc线程
|
DevpThread devpThread = (DevpThread) SlaveConnection.get(SlaveType.Conveyor, basConveyor.getDeviceId().intValue());
|
// 命令集合
|
boolean reset = true;
|
for (Integer staNo : staArr) {
|
// 获取叉车站点
|
StaProtocol staProtocol = devpThread.getStation().get(staNo);
|
if (staProtocol == null) { continue; }
|
if (staProtocol.getWorkNo() != 0) {
|
reset = false;
|
break;
|
}
|
}
|
// 获取led线程
|
LedThread ledThread = (LedThread) SlaveConnection.get(SlaveType.Led, ledDevice.getId().intValue());
|
// led显示默认内容
|
if (reset && !ledThread.isLedMk()) {
|
ledThread.reset();
|
ledThread.setLedMk(true);
|
}
|
}
|
}
|
|
}
|