Commit 127bd4ff LN

合入1053分支:新增RobotBoxHandler,接口测试

1 个父辈 120e0694
package com.neotel.smfcore.common.utils; package com.neotel.smfcore.common.utils;
import cn.hutool.core.util.ObjectUtil;
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import com.neotel.smfcore.common.exception.ApiException; import com.neotel.smfcore.common.exception.ApiException;
import com.neotel.smfcore.custom.micron1053.bean.MicronResult;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import lombok.val; import lombok.val;
import org.apache.http.HttpEntity; import org.apache.http.HttpEntity;
...@@ -12,6 +14,7 @@ import org.apache.http.client.HttpClient; ...@@ -12,6 +14,7 @@ import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig; import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost; import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URIBuilder; import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.StringEntity; import org.apache.http.entity.StringEntity;
...@@ -169,4 +172,62 @@ public class HttpHelper { ...@@ -169,4 +172,62 @@ public class HttpHelper {
} }
} }
public static MicronResult getMicronJson(String url ) throws ApiException {
if(ObjectUtil.isEmpty(url)) {
return new MicronResult();
}
HttpGet httpGet = new HttpGet(url);
httpGet.addHeader("Content-Type", "application/json;charset=utf-8");
// // 设置请求参数
// if (params != null && !params.isEmpty()) {
// ObjectMapper mapper = new ObjectMapper();
// try {
// String requestBody = mapper.writeValueAsString(params);
// httpGet.seb(new StringEntity(requestBody,CONTENT_CHARSET));
// } catch (JsonProcessingException e) {
// throw new ApiException("Request params to [" + url + "] failed:" + e.getMessage());
// } catch (Exception e) {
// throw new ApiException("Request params to [" + url + "] failed:" + e.getMessage());
// }
// }
try {
CloseableHttpClient httpClient = HttpClients.createDefault();
CloseableHttpResponse response = httpClient.execute(httpGet);
int code = response.getStatusLine().getStatusCode();
//System.out.println(response.getStatusLine().getStatusCode() + "\n");
HttpEntity entity = response.getEntity();
String responseContent = EntityUtils.toString(entity, CONTENT_CHARSET);
MicronResult result = JsonUtil.toObj(responseContent, MicronResult.class);
if (result == null) {
result = new MicronResult();
}
result.setHttpCode(code);
result.setResponseData(responseContent);
response.close();
httpClient.close();
return result;
} catch (Exception e) {
throw new ApiException("Request to [" + url + "] failed:" + e.getMessage());
}
}
public static MicronResult postMicronJson(String url , Map<String, Object> params) throws ApiException {
try {
if(ObjectUtil.isEmpty(url)) {
return new MicronResult();
}
String responseContent = postJson(url, params);
MicronResult result = JsonUtil.toObj(responseContent, MicronResult.class);
if (result == null) {
result = new MicronResult();
}
result.setResponseData(responseContent);
return result;
} catch (Exception e) {
throw new ApiException("Request to [" + url + "] failed:" + e.getMessage());
}
}
} }
...@@ -38,6 +38,24 @@ public enum OP_STATUS { ...@@ -38,6 +38,24 @@ public enum OP_STATUS {
/** /**
* 已结束 * 已结束
*/ */
END END ,
/**
* 已从仓位中取出
*/
OUTBOX,
/**
* 机器人正在移栽中
*/
INROBOT,
/**
* 已放到料仓门口
*/
BOXDOOR,
/**
* 已放到料仓门口无料盘
*/
BOXDOOR_NOREEL
; ;
} }
package com.neotel.smfcore.core.device.handler.impl;
import cn.hutool.core.util.ObjectUtil;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.neotel.smfcore.common.bean.ResultBean;
import com.neotel.smfcore.common.exception.ValidateException;
import com.neotel.smfcore.common.utils.Constants;
import com.neotel.smfcore.core.barcode.service.po.Barcode;
import com.neotel.smfcore.core.device.bean.BoxStatusBean;
import com.neotel.smfcore.core.device.bean.StatusBean;
import com.neotel.smfcore.core.device.enums.BOX_STATUS;
import com.neotel.smfcore.core.device.enums.OP;
import com.neotel.smfcore.core.device.enums.OP_STATUS;
import com.neotel.smfcore.core.message.util.DeviceMessageUtil;
import com.neotel.smfcore.core.storage.enums.DeviceType;
import com.neotel.smfcore.core.storage.service.po.Storage;
import com.neotel.smfcore.core.storage.service.po.StoragePos;
import com.neotel.smfcore.core.system.service.dao.IAlarmInfoDao;
import com.neotel.smfcore.core.system.service.po.AlarmInfo;
import com.neotel.smfcore.core.system.service.po.DataLog;
import com.neotel.smfcore.security.annotation.AnonymousAccess;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import java.util.*;
@Api(tags = "RobotBox: 机器人料仓(1053)")
@RestController
@Slf4j
public class RobotBoxHandler extends BaseDeviceHandler {
@Autowired
private IAlarmInfoDao alarmInfoDao;
@Override
public StatusBean handleClientRequest(StatusBean statusBean, HttpServletRequest request) {
String cid = statusBean.getCid();
Storage storage = dataCache.getStorage(cid);
if (storage == null) {
log.error("料仓cid: [" + cid + "]不存在");
return null;
}
statusBean.setClientIp(request.getRemoteHost());
handleMsg(statusBean);
statusBean = saveAlarmAndHumidity(statusBean);
statusBean = handleFinished(statusBean);
StatusBean humidityResult = handleHumidity(statusBean);
if (humidityResult != null) {
return humidityResult;
}
if (statusBean.getOp() == OP.PUT_IN) {
log.debug("入库:" + statusBean.toString());
//判断是否有放在门口状态的入库任务
Collection<DataLog> queueTasks = taskService.getQueueTasks();
for (DataLog queueTask : queueTasks) {
if (queueTask.getCid().equals(statusBean.getCid()) && queueTask.isPutInTask() && queueTask.isBoxdoor()) {
String posId = queueTask.getPosName();
String reelId = queueTask.getBarcode();
Barcode barcode = barcodeManager.findByBarcode(reelId);
int plateW = barcode.getPlateSize();
int plateH = barcode.getHeight();
statusBean.addPosInfo(reelId, posId, plateW, plateH, false);
log.info(reelId + "[" + plateW + "x" + plateH + "]开始入库到" + storage.getCid() + "[" + posId + "]");
return statusBean;
}
}
//statusBean = putInLine(storage, statusBean);
} else {
//查看是否有要出库的操作
statusBean = findCheckOutTask(storage, statusBean);
}
return statusBean;
}
/**
* 出库处理
*/
public StatusBean findCheckOutTask(Storage storage, StatusBean statusBean) {
try {
//准备更新暂停出入库
if (dataCache.getCache(Constants.CACHE_StopOut)) {
return statusBean;
}
String cid = statusBean.getCid();
Collection<DataLog> queueTasks = taskService.getQueueTasks();
int executingOutTaskSize = 0;
DataLog outTask = null;
for (DataLog queueTask : queueTasks) {
if (queueTask.getCid().equals(cid)) {
//有入库任务不分配出库任务
if (queueTask.isPutInTask()) {
return statusBean;
} else {
if (queueTask.isExecuting()) {
executingOutTaskSize++;
//已经有出库任务正在执行,超过60秒仍未完成的出库再次发送到客户端
if (queueTask.needReSendToClient()) {
outTask = queueTask;
log.error("cid[" + cid + "]的出库任务[" + queueTask.getPosName() + "]超过60秒仍未完成,重新发送到客户端!");
queueTask.setUpdateDate(new Date());
break;
}
} else if (queueTask.isWait()) {
if (executingOutTaskSize >= 2) {
//log.error("cid["+cid + "]的BOX["+ boxId+"]的出库任务已经超过2个,不再分配!");
outTask = null;
break;
}
outTask = queueTask;
if (queueTask.isUrgentReel()) {
break;
}
}
}
}
}
if (outTask != null) {
log.info("分配出库任务" + outTask.getBarcode() + "[" + outTask.getPosName() + "]到 " + cid);
outTask.setStatus(OP_STATUS.EXECUTING.name());
taskService.updateQueueTask(outTask);
statusBean.setOp(OP.CHECKOUT);
String posName = outTask.getPosName();
Barcode codeObj = barcodeManager.findByBarcode(outTask.getBarcode());
int plateW = 0;
int plateH = 0;
if (codeObj != null) {
plateW = codeObj.getPlateSize();
plateH = codeObj.getHeight();
} else {
log.warn("出库无料仓位" + storage.getName() + "[" + posName + "]");
}
statusBean.addPosInfo(outTask.getBarcode(), posName, plateW, plateH, false);
log.info("出库" + storage.getName() + "[" + posName + "]物料[" + outTask.getBarcode() + "] 发送到客户端" + cid);
}
} catch (Exception e) {
log.error("出库出错", e);
}
return statusBean;
}
protected StatusBean handleFinished(StatusBean statusBean) {
Map<String, BoxStatusBean> statusOfBoxes = statusBean.getBoxStatus();
if (statusOfBoxes != null) {
for (BoxStatusBean boxStatus : statusOfBoxes.values()) {
try {
//出库入库完成处理
int status = boxStatus.getStatus();
String posName = boxStatus.getPosId();
int executeTime = boxStatus.getExecuteTime();
if (!Strings.isNullOrEmpty(posName)) {//客户端发一次完成之后,会发空的 posName,不需要处理
if (BOX_STATUS.IN_FINISHED == status) {//入仓完成
finishedPutIn(statusBean.getCid(), posName, executeTime);
} else if (BOX_STATUS.IN_FAILED == status) {//入库失败
//暂不处理
} else if (BOX_STATUS.OUT_FINISHED == status) {//出仓完成
finishedOutPos(statusBean.getCid(), posName, executeTime);
} else if (BOX_STATUS.OUT_END == status) {//出库完成(放到仓门口
//更改出库状态为OUT_DOOR
List<DataLog> finishedTasks = taskService.getFinishedTasks();
for (DataLog finishedTask : finishedTasks) {
if (finishedTask.getCid().equals(statusBean.getCid()) && finishedTask.isCheckOutTask() && finishedTask.isOutBox()) {
if (posName.equals(finishedTask.getPosName())) {
//已出仓但未放到门口,更改状态
finishedTask.setStatus(OP_STATUS.BOXDOOR.name());
taskService.updateFinishedTask(finishedTask);
log.info("物料" + finishedTask.getBarcode() + "已从库位" + finishedTask.getPosName() + "取出放到门口");
return statusBean;
}
}
}
log.error(posName + "出库放到门口时,未找到对应的出库任务");
} else if (BOX_STATUS.OUT_FAILED == status) {
//更改出库状态为OUT_DOOR
List<DataLog> finishedTasks = taskService.getFinishedTasks();
for (DataLog finishedTask : finishedTasks) {
if (finishedTask.getCid().equals(statusBean.getCid()) && finishedTask.isCheckOutTask() && finishedTask.isOutBox()) {
if (posName.equals(finishedTask.getPosName())) {
//已出仓但未放到门口,更改状态
finishedTask.setStatus(OP_STATUS.BOXDOOR_NOREEL.name());
log.info("物料" + finishedTask.getBarcode() + "已从库位" + finishedTask.getPosName() + "取出放到门口,但未感应到料盘,屏蔽库位");
StoragePos pos = storagePosManager.getByPosName(finishedTask.getPosName());
if (pos != null) {
pos.setEnabled(false);
storagePosManager.save(pos);
DeviceMessageUtil.addEnabledPosMessage(pos, "SYSTEM");
}
taskService.updateFinishedTask(finishedTask);
return statusBean;
}
}
}
}
}
} catch (ValidateException e) {
log.error("更新状态时出错" + e.getMessage());
}
}
}
return statusBean;
}
@ApiOperation("扫码后获取库位号")
@PostMapping(value = "/service/store/robotBox/emptyPosForPutin")
@ResponseBody
@AnonymousAccess
public Map<String, Object> emptyPosForPutin(HttpServletRequest request) {
String code = request.getParameter("code");
String cids = request.getParameter("cids");
String lastPosId = "";
String lineMsg = "";
log.info("流水线[" + cids + "]获取[" + code + "]的入库库位");
Map<String, Object> resultMap = Maps.newHashMap();
String okMsg = "";
String errorMsg = "";
List<Storage> storageList = Lists.newArrayList();
List<String> cidList = dataCache.getAvailableStorageIds(this.getDeviceType());
for (String cid : cidList) {
String notIntoCids = dataCache.getSettings().getNotIntoCids();
if (notIntoCids != null) {
if (notIntoCids.contains(cid)) {
log.info("料仓[" + cid + "]已被屏蔽入库");
continue;
}
}
Storage storage = dataCache.getStorage(cid);
if (storage != null) {
storageList.add(storage);
}
}
if (storageList.isEmpty()) {
resultMap.put("result", "99");
errorMsg = "无可用的料仓";
resultMap.put("msg", errorMsg);
} else {
try {
Barcode barcode = codeResolve.resolveOneValideBarcode(code);
for (DataLog dataLog : taskService.getQueueTasks()) {
if (dataLog.getBarcode().equals(barcode.getBarcode())) {
if (dataLog.isPutInTask()) {
//已有入库任务
errorMsg = "物料[" + dataLog.getBarcode() + "]已有入库任务,需继续执行入库动作";
resultMap.put("result","97");
resultMap.put("msg", errorMsg);
resultMap.put("pos", dataLog.getPosName());
resultMap.put("barcode", barcode.getBarcode());
resultMap.put("cid", dataLog.getCid());
resultMap.put("taskId", dataLog.getId());
return resultMap;
} else {
//已有出库任务
errorMsg = "物料[" + dataLog.getBarcode() + "]已有出库任务,需继续执行出库动作";
resultMap.put("result", "98");
resultMap.put("msg", errorMsg);
resultMap.put("posId", dataLog.getPosName());
resultMap.put("plateW", barcode.getPlateSize());
resultMap.put("plateH", barcode.getHeight());
resultMap.put("singleOut", dataLog.isSingleOut() + "");
//紧急料
resultMap.put("urgentReel", dataLog.isUrgentReel() + "");
//需要分盘,进入分盘料
resultMap.put("cutReel", dataLog.isCutReel() + "");
resultMap.put("rfid", "");
resultMap.put("realRfid", "");
resultMap.put("rfidLoc", "");
resultMap.put("barcode", dataLog.getBarcode());
boolean smallReel = barcode.isSmallReel();
resultMap.put("smallReel", smallReel + "");
resultMap.put("taskId", dataLog.getId());
return resultMap;
}
}
}
/*try{
barcode = verifyPutInFromApi(barcode);
}catch (ValidateException ex){
lineMsg = "不允许入库," + ex.getDefaultMsg();
DeviceMessageUtil.updateLineMsg(lineMsg, code, cids, "", "smfcore.linemsg.update", null);
resultMap.put("result", "107");
resultMap.put("msg", lineMsg);
return resultMap;
}*/
StoragePos pos = taskService.findEmptyPosForPutIn(storageList, barcode, "", lastPosId);
if (pos != null) {
Storage storage = dataCache.getStorageById(pos.getStorageId());
//如果所在料仓有出库任务未完成,暂停入库
Collection<DataLog> tasks = taskService.getAllTasks();
for (DataLog task : tasks) {
if (task.isCheckOutTask() && task.getStorageId().equals(pos.getStorageId())) {
if (!task.isFinished() && !task.isInRobot()) {
errorMsg = "库位[" + pos.getPosName() + "]所在料仓有出库任务,暂停入库";
lineMsg = errorMsg;
resultMap.put("result", "99");
resultMap.put("msg", errorMsg);
return resultMap;
}
}
}
resultMap.put("result", "0");
resultMap.put("msg", "ok");
DataLog newTask = taskService.addPutInTaskToExecute(storage, barcode, pos);
okMsg = "[" + barcode.getBarcode() + "]锁定库位[" + pos.getPosName() + "]优先级[" + pos.getPriority() + "] 上个库位号[" + lastPosId + "]";
log.info(okMsg);
resultMap.put("pos", pos.getPosName());
resultMap.put("barcode", barcode.getBarcode());
resultMap.put("cid", storage.getCid());
resultMap.put("taskId", newTask.getId());
} else {
resultMap.put("result", "104");
errorMsg = "[" + barcode.getBarcode() + "]未找到可用的[" + barcode.getPlateSize() + "x" + barcode.getHeight() + "]仓位";
resultMap.put("msg", errorMsg);
}
} catch (ValidateException ve) {
errorMsg = ve.getMessage();
log.info("查找空库位失败:" + errorMsg);
resultMap.put("result", "105");
resultMap.put("msg", errorMsg);
} catch (Exception e) {
errorMsg = e.getMessage();
log.info("查找空库位失败,", e);
resultMap.put("result", "105");
resultMap.put("msg", errorMsg);
}
}
// }
//没入成功
if (!errorMsg.isEmpty()) {
//有错误,记录日志
AlarmInfo alarmInfo = new AlarmInfo();
alarmInfo.setBoxId("0");
alarmInfo.setStorageName("流水线");
alarmInfo.setInOutStatus("1");
alarmInfo.setAlarmType("入库");
Date date = new Date();
alarmInfo.setStartTime(date);
alarmInfo.setEndTime(date);
String msg = "[" + code + "]" + errorMsg;
alarmInfo.setAlarmMsg(msg);
alarmInfoDao.save(alarmInfo);
lineMsg = errorMsg;
DeviceMessageUtil.updateLineMsg(lineMsg, code, cids, "", "", null);
} else {
lineMsg = okMsg;
}
return resultMap;
}
@ApiOperation("机器人更新任务状态")
@PostMapping(value = "/service/store/robotBox/updateLocInfo")
@ResponseBody
@AnonymousAccess
public ResultBean updateLocInfo(HttpServletRequest request) {
String taskId = request.getParameter("taskId");
String barcode = request.getParameter("barcode");
String statusStr = request.getParameter("status");
String locInfo = request.getParameter("locInfo");
log.debug("收到料盘[" + barcode + "]更新位置指令[" + statusStr + "]=" + locInfo);
if (ObjectUtil.isEmpty(locInfo)) {
locInfo = statusStr;
}
DataLog opTask = null;
List<DataLog> allTasks = taskService.getAllTasks();
for (DataLog task : allTasks) {
if (task.getId().equals(taskId) && task.getBarcode().equals(barcode)) {
opTask = task;
break;
}
}
if (opTask == null) {
return ResultBean.newErrorResult(301, "smfcore.task.notExist", "任务不存在");
}
if (opTask.isFinished()) {
return ResultBean.newErrorResult(302, "smfcore.task.hasEnd", "任务已完成");
}
// if (opTask.isCancel()) {
// return ResultBean.newErrorResult(303, "smfcore.task.hasCancel", "更新状态时{0}的出库任务[{1}]已被取消", new String[]{opTask.getBarcode(), opTask.getId()});
// }
statusStr = statusStr.toUpperCase();
log.info("更新料盘[" + barcode + "]的任务状态[" + opTask.getStatus() + "=" + opTask.getLocInfo() + "]为[" + statusStr + "=" + locInfo + "]");
opTask.setStatus(statusStr);
opTask.setLocInfo(locInfo);
//如果是出库任务并且放到料仓门口,需要发送任务给料仓
// if(task.isInBelt() || task.isPackageReel()){
// //已经放上皮带线
// AppendInfo appendInfo = task.getAppendInfo();
// if(org.apache.logging.log4j.util.Strings.isBlank(appendInfo.gethSerial())){
// log.info("手动出库料盘["+barcode+"]放上皮带线或包装料架,结束任务");
// task.setStatus(StorageConstants.OP_STATUS.FINISHED.name());
// }else if(appendInfo.isCheckAction()){
// log.info("盘点料盘["+barcode+"]放上皮带线或包装料架,结束任务");
// task.setStatus(StorageConstants.OP_STATUS.FINISHED.name());
// //盘点料,出到皮带线上即算完成
// int slotSeq = appendInfo.getSlotIndex();
// int sendQty = task.getNum();
// outInfoCache.incTaskFinishNum(appendInfo.gethSerial(),slotSeq, sendQty);
// }
// }
if (opTask.isPutInTask()) {
taskService.updateQueueTask(opTask);
} else {
taskService.updateFinishedTask(opTask);
}
return ResultBean.newOkResult("");
}
@ApiOperation("机器人定时获取任务")
@PostMapping(value = "/service/store/robotBox/getRobotTask")
@ResponseBody
@AnonymousAccess
public ResultBean getRobotTask(HttpServletRequest request) {
Collection<DataLog> datalogs = taskService.getAllTasks();
//先查找已在机器人的
// for (DataLog task : datalogs) {
// if (task.isInRobot()) {
// //获取任务失败,还有未完成的任务
// return ResultBean.newErrorResult(1, "smfcore.task.lastNotEnd", "上个任务未结束{0}{1}", new String[]{task.getPosName(), task.getBarcode()});
// }
// }
//查找出库已经到门口的
for (DataLog task : datalogs) {
if (task.isCheckOutTask()) {
if (task.isBoxdoor()) {
Map<String, String> taskMap = new HashMap<>();
taskMap.put("cid", task.getCid());//取料位置
// taskMap.put("targetPos", "out");//放料位置
taskMap.put("type", task.getType() + "");//类型,1=入库,2=出库
taskMap.put("posId", task.getPosName());
Barcode barcode = barcodeManager.findByBarcode(task.getBarcode());
int plateW = 0;
int plateH = 0;
if (barcode != null) {
plateW = barcode.getPlateSize();
plateH = barcode.getHeight();
}
taskMap.put("plateW", plateW + "");
taskMap.put("plateH", plateH + "");
taskMap.put("barcode", task.getBarcode());
taskMap.put("taskId", task.getId());
return ResultBean.newOkResult(taskMap);
}
}
}
return ResultBean.newErrorResult(-1, "", "");
}
@ApiOperation("料仓判断仓门口是否可以放料")
@PostMapping(value = "/service/store/robotBox/getBoxDoorStatus")
@ResponseBody
@AnonymousAccess
public ResultBean getBoxDoorStatus(HttpServletRequest request) {
String cid = request.getParameter("cid");
//判断仓门口状态,0=空闲,返回其他表示仓门口有料或机器人正在取料
Storage storage = dataCache.getStorage(cid);
if (storage == null) {
return ResultBean.newErrorResult(99, "smfcore.robotBox.notFound", "未找到机器人料仓[{0}]", new String[]{cid});
}
if (!storage.isRobotBox()) {
return ResultBean.newErrorResult(99, "smfcore.robotBox.notFound", "未找到机器人料仓[{0}]", new String[]{cid});
}
Collection<DataLog> tasks = taskService.getQueueTasks();
for (DataLog task : tasks) {
if (task.getStorageId().equals(storage.getId())) {
if (task.isBoxdoor()) {
return ResultBean.newErrorResult(-1, "smfcore.robotBox.boxHasTask", "任务[{0}][{1}]类型{2}状态{3}", new String[]{task.getPosName(), task.getBarcode(), task.getType() + "", task.getStatus()});
}
// else if(task.isPutInTask()&&task.isInRobot()){
// return ResultBean.newErrorResult(-1, "smfcore.robotBox.boxHasTask", "任务[{0}][{1}]类型{2}状态{3}", new String[]{task.getPosName(), task.getBarcode(),task.getType()+"", task.getStatus()});
// }
}
}
return ResultBean.newOkResult("");
}
@ApiOperation("点料后更新物料数量")
@PostMapping(value = "/service/store/robotBox/updateReelQty")
@ResponseBody
@AnonymousAccess
public ResultBean updateReelQty(HttpServletRequest request) {
String barcode = request.getParameter("barcode");
Integer qty = Integer.parseInt(request.getParameter("qty")) ;
return ResultBean.newOkResult("");
}
@ApiOperation("获取对应托盘信息")
@PostMapping(value = "/service/store/robotBox/getTrayInfo")
@ResponseBody
@AnonymousAccess
public ResultBean getTrayInfo(HttpServletRequest request) {
Integer trayNum = Integer.parseInt(request.getParameter("trayNum")) ;
return ResultBean.newOkResult("");
}
@ApiOperation("清空托盘信息")
@PostMapping(value = "/service/store/robotBox/clearTrayInfo")
@ResponseBody
@AnonymousAccess
public ResultBean clearTrayInfo(HttpServletRequest request) {
Integer trayNum = Integer.parseInt(request.getParameter("trayNum")) ;
return ResultBean.newOkResult("");
}
@Override
public DeviceType getDeviceType() {
return DeviceType.ROBOT_BOX;
}
}
...@@ -10,6 +10,7 @@ import com.neotel.smfcore.common.bean.ResultBean; ...@@ -10,6 +10,7 @@ import com.neotel.smfcore.common.bean.ResultBean;
import com.neotel.smfcore.common.exception.ValidateException; import com.neotel.smfcore.common.exception.ValidateException;
import com.neotel.smfcore.common.utils.Constants; import com.neotel.smfcore.common.utils.Constants;
import com.neotel.smfcore.common.utils.ReelLockPosUtil; import com.neotel.smfcore.common.utils.ReelLockPosUtil;
import com.neotel.smfcore.common.utils.SecurityUtils;
import com.neotel.smfcore.core.api.SmfApi; import com.neotel.smfcore.core.api.SmfApi;
import com.neotel.smfcore.core.api.bean.CodeValidateParam; import com.neotel.smfcore.core.api.bean.CodeValidateParam;
import com.neotel.smfcore.core.barcode.service.po.Barcode; import com.neotel.smfcore.core.barcode.service.po.Barcode;
...@@ -570,5 +571,17 @@ public class DeviceController { ...@@ -570,5 +571,17 @@ public class DeviceController {
// } // }
return ResultBean.newOkResult(""); return ResultBean.newOkResult("");
} }
@ApiOperation("全部出库")
@RequestMapping(value = "/service/store/outAll")
@ResponseBody
@AnonymousAccess
public ResultBean outAll(){
//查找全部库位
List<StoragePos> storagePosList = storagePosManager.findNotEmpty();
//开始进行出库操作
for (StoragePos storagePos : storagePosList) {
taskService.addTaskToFinished(storagePos,null, SecurityUtils.getCurrentUsername()+"outAll");
}
return ResultBean.newOkResult("");
}
} }
...@@ -715,6 +715,19 @@ public class DataCache { ...@@ -715,6 +715,19 @@ public class DataCache {
} }
return availableStorageIds; return availableStorageIds;
} }
public List<String> getAvailableStorageIds(DeviceType deviceType){
List<String> availableStorageIds = new ArrayList<>();
for (Storage storage : getAllStorage().values()) {
if(storage.getType().equals(deviceType.name())) {
StatusBean bean = DevicesStatusUtil.getStatusBean(storage.getCid());
if (bean == null || bean.timeOut() || !bean.isAvailable()) {
continue;
}
availableStorageIds.add(storage.getCid());
}
}
return availableStorageIds;
}
public Storage AutoCreateStorage(String cid,String deviceType) { public Storage AutoCreateStorage(String cid,String deviceType) {
//判断cid存在 //判断cid存在
Storage storage = null; Storage storage = null;
......
...@@ -117,7 +117,12 @@ public enum DeviceType { ...@@ -117,7 +117,12 @@ public enum DeviceType {
/** /**
* 18 (默认料仓) * 18 (默认料仓)
*/ */
DEFAULT("storage.type.default") DEFAULT("storage.type.default"),
/**
* 19 机器人料仓
*/
ROBOT_BOX("storage.type.robotBox");
; ;
private String key; private String key;
......
...@@ -309,4 +309,7 @@ public class Storage extends BasePo implements Serializable { ...@@ -309,4 +309,7 @@ public class Storage extends BasePo implements Serializable {
return getGroupId().equals(groupId); return getGroupId().equals(groupId);
} }
public boolean isRobotBox() {
return DeviceType.ROBOT_BOX.name().equals(type);
}
} }
...@@ -204,7 +204,10 @@ public class DataLog extends BasePo implements Serializable { ...@@ -204,7 +204,10 @@ public class DataLog extends BasePo implements Serializable {
* 如果是出库任务,需要记录入库时间 * 如果是出库任务,需要记录入库时间
*/ */
private Date putInDate; private Date putInDate;
/**
* 位置信息,如料架编号,托盘编号,移栽编号,皮带线编号,机器人编号等
*/
private String locInfo = "";
/** /**
* MSD附加信息 * MSD附加信息
*/ */
...@@ -256,7 +259,16 @@ public class DataLog extends BasePo implements Serializable { ...@@ -256,7 +259,16 @@ public class DataLog extends BasePo implements Serializable {
return theStatus.name().equals(status); return theStatus.name().equals(status);
} }
public boolean isOutBox(){
return OP_STATUS.OUTBOX.name().equals(status);
}
public boolean isInRobot(){
return OP_STATUS.INROBOT.name().equals(status);
}
public boolean isBoxdoor(){
return OP_STATUS.BOXDOOR.name().equals(status) || OP_STATUS.BOXDOOR_NOREEL.equals(status);
}
/** /**
* 是否是入库任务 * 是否是入库任务
*/ */
......
package com.neotel.smfcore.custom.micron1053.bean;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Data
@Slf4j
@AllArgsConstructor
@NoArgsConstructor
public class MaterialInfo implements Serializable {
// "Label2DID": "<Label2DID>",
// "TowerID": "<TowerID>|null",
// "StorageBin": "<StorageBin>|null",
// "Qty": "<Label Qty>|<X-Ray Qty>",
// "X-RayCheck": "Yes|No|N/A",
// "ErrorCode": "0-Success|1-Rejected",
// "ErrorMessage": "N/A|<ErrorMessage>"
private String Label2DID;
private String TowerID;
private String StorageBin;
private String Qty;
private String XRayCheck;
private String ErrorCode;
private String ErrorMessage;
// "Label2DID": "<Label2DID>",
// "FromTowerID": "<TowerID>",
// "FromStorageBin": "<StorageBin>",
// "Qty": "<Qty>",
private String FromTowerID;
private String FromStorageBin;
public static MaterialInfo NewMaterial(Map<String,String> map) {
MaterialInfo mInfo = new MaterialInfo();
try {
mInfo.setLabel2DID(map.getOrDefault("Label2DID", ""));
mInfo.setTowerID(map.getOrDefault("TowerID", ""));
mInfo.setStorageBin(map.getOrDefault("StorageBin", ""));
mInfo.setXRayCheck(map.getOrDefault("X-RayCheck", ""));
mInfo.setErrorCode(map.getOrDefault("ErrorCode", ""));
mInfo.setErrorMessage(map.getOrDefault("ErrorMessage", ""));
mInfo.setQty( map.getOrDefault("Qty", "0"));
mInfo.setFromTowerID(map.getOrDefault("FromTowerID", ""));
mInfo.setFromStorageBin(map.getOrDefault("FromStorageBin", ""));
} catch (Exception ex) {
}
return mInfo;
}
public static List<MaterialInfo> GetObjList(List<Map<String,String>> arrList){
List<MaterialInfo> materialInfos=new ArrayList<>();
for (Map<String, String> o :
arrList) {
MaterialInfo mInfo = MaterialInfo.NewMaterial(o);
materialInfos.add(mInfo);
}
return materialInfos;
}
public static List<Map<String,String>> ToLoadingList(List<MaterialInfo> list){
List<Map<String,String>> arrList=new ArrayList<>();
for (MaterialInfo obj :list
) {
Map<String,String> map=new HashMap<>();
map.put("Label2DID",obj.getLabel2DID());
map.put("TowerID",obj.getTowerID());
map.put("StorageBin",obj.getStorageBin());
map.put("X-RayCheck",obj.getXRayCheck());
map.put("ErrorCode",obj.getErrorCode());
map.put("ErrorMessage",obj.getErrorMessage());
map.put("Qty",obj.getQty().toString());
arrList.add(map);
}
return arrList;
}
public static List<Map<String,String>> ToDispatchList(List<MaterialInfo> list){
List<Map<String,String>> arrList=new ArrayList<>();
for (MaterialInfo obj :list
) {
Map<String,String> map=new HashMap<>();
map.put("FromTowerID",obj.getFromTowerID());
map.put("FromStorageBin",obj.getFromStorageBin());
map.put("Qty",obj.getQty().toString());
arrList.add(map);
}
return arrList;
}
}
package com.neotel.smfcore.custom.micron1053.bean;
import cn.hutool.core.util.ObjectUtil;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import java.io.Serializable;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Slf4j
public class MicronResult implements Serializable {
// {
// Status : <Success|Fail>
// Message : <Error Message>
// }
private Integer httpCode=0;
private String status;
private String message;
private String responseData;
public boolean isSuccess() {
if (ObjectUtil.isNotEmpty(status) && status.equals("Success")) {
return true;
}
return false;
}
}
package com.neotel.smfcore.custom.micron1053.controller;
import cn.hutool.core.util.ObjectUtil;
import com.neotel.smfcore.common.utils.HttpHelper;
import com.neotel.smfcore.core.api.listener.BaseSmfApiListener;
import com.neotel.smfcore.custom.micron1053.bean.MaterialInfo;
import com.neotel.smfcore.custom.micron1053.bean.MicronResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import java.text.MessageFormat;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Controller
@RequestMapping("/rest/api/micron")
@Slf4j
public class MicronApi extends BaseSmfApiListener {
private static MicronConfig config;
@Autowired
public void setConfig(MicronConfig config){
MicronApi.config=config;
}
@Override
public boolean isForThisApi(String apiName) {
// return apiName != null && apiName.equalsIgnoreCase("Micron");
return ObjectUtil.isNotEmpty(config.micronAddr);
}
private static String GetSkipSap(String skipSap) {
if(skipSap.toUpperCase().toString().equals("TRUE")||skipSap.toUpperCase().toString().equals("YES")){
return "YES";
}
return "NO";
}
public static MicronResult validateMRB(String mbrId, String skipSap) {
//Validate if MBR (From Warehouse )  is valid
// if (skipSap instanceof Boolean) {
//
// skipSapStr = (boolean) skipSap ? "YES" : "NO";
// } else {
// skipSapStr = skipSap.toString();
// }
String skipSapStr = GetSkipSap(skipSap);
String url =config. getUrl(MessageFormat.format("validate/mrb/{0}/{1}", mbrId, skipSapStr));
try {
MicronResult result = HttpHelper.getMicronJson(url);
return result;
} catch (Exception e) {
log.error(url + "出错", e);
}
return null;
}
public static MicronResult validateREQ(String reqId) {
//Validate if REQ (From Outside Shelf) is valid
String url = config.getUrl(MessageFormat.format("validate/req/{0}", reqId));
try {
MicronResult result = HttpHelper.getMicronJson(url);
return result;
} catch (Exception e) {
log.error(url + "出错", e);
}
return null;
}
public static MicronResult validateMCL(String PurchaseOrder, String PackagingSlip, String skipSap) {
//Validate if MCL GR  is valid
//validate/mcl/{PurchaseOrder}/{PackagingSlip}/{SkipSap}
// {PurchaseOrder}=<purchase order>,
// {PackagingSlip}=<packaging slide>,
// {SkipSAP}="YES|No"
String skipSapStr = GetSkipSap(skipSap);
String url = config.getUrl(MessageFormat.format("validate/mcl/{0}/{1}/{2}", PurchaseOrder, PackagingSlip, skipSapStr));
try {
MicronResult result = HttpHelper.getMicronJson(url);
return result;
} catch (Exception e) {
log.error(url + "出错", e);
}
return null;
}
public static MicronResult validateMaterial(String Label2DID, String LoadingMode) {
//Validate the material before loading into the storage bin
//validate/material
// {
// "Label2DID" : "<2DID String that contains SAP P/N; S/N; Supplier..etc>",
// "LoadingMode" : "MBR|REQ|GR|MCL|RET|NPI"
// }
String url = config.getUrl( "validate/material" );
Map<String, Object> dataMap = new HashMap<String, Object>();
dataMap.put("Label2DID", Label2DID);
dataMap.put("LoadingMode", LoadingMode);
try {
MicronResult result = HttpHelper.postMicronJson(url, dataMap);
return result;
} catch (Exception e) {
log.error(url + "出错", e);
}
return null;
}
public static MicronResult loadReport(String JobId, List<MaterialInfo> materialInfos) {
//Update material storage location at rod or magazine slot level (One JobID per rod or slot).
//load-report
// {
// "JobId": "<job Id>",
// "Materials": [
// {
// "Label2DID": "<Label2DID>",
// "TowerID": "<TowerID>|null",
// "StorageBin": "<StorageBin>|null",
// "Qty": "<Label Qty>|<X-Ray Qty>",
// "X-RayCheck": "Yes|No|N/A",
// "ErrorCode": "0-Success|1-Rejected",
// "ErrorMessage": "N/A|<ErrorMessage>"
// }
//]
// }
String url = config.getUrl( "load-report" );
Map<String, Object> dataMap = new HashMap<String, Object>();
dataMap.put("JobId", JobId);
dataMap.put("Materials", MaterialInfo.ToLoadingList(materialInfos));
try {
MicronResult result = HttpHelper.postMicronJson(url, dataMap);
return result;
} catch (Exception e) {
log.error(url + "出错", e);
}
return null;
}
public static MicronResult dispatchList(String Facility, String DispatchType) {
//Get ready Pretask/LinePrep/RET list from Auto Kitting System
//dispatch-list/{Facility}/{DispatchType}
// {Facility} = "Grouping that need to align with KitView"
// {DispatchType}="PreTask|LinePrep|RET"
String url = config.getUrl(MessageFormat.format("dispatch-list/{0}/{1}", Facility, DispatchType));
try {
MicronResult result = HttpHelper.getMicronJson(url);
return result;
} catch (Exception e) {
log.error(url + "出错", e);
}
return null;
}
public static MicronResult dispatchMaterial(String DispatchType, String Id) {
//Get dispatch Material list  from Autokitting system to fullfil the Pretask or LinePrep
//dispatch-material/{DispatchType}/{Id}
// {DispatchType}="PreTask|LinePrep|RET"
// Id="<PretaskId>|<LinePrepId>|<RetId>"
String url = config.getUrl(String.format("dispatch-material/{0}/{1}", DispatchType, Id));
try {
MicronResult result = HttpHelper.getMicronJson(url);
return result;
} catch (Exception e) {
log.error(url + "出错", e);
}
return null;
}
public static MicronResult dispatchReport(String JobId, String dispatchType, List<MaterialInfo> materialInfos) {
//Update dispatch information by Job Level
//dispatch-report
// "JobId": "<JobId>",
// "DispatchType": "PreTask|LinePrep|RET|Warehouse|Controlled",
// "Materials": [
// {
// "Label2DID": "<Label2DID>",
// "FromTowerID": "<TowerID>",
// "FromStorageBin": "<StorageBin>",
// "Qty": "<Qty>",
// }
//]
String url = config.getUrl( "dispatch-report" );
Map<String, Object> dataMap = new HashMap<String, Object>();
dataMap.put("JobId", JobId);
dataMap.put("DispatchType", dispatchType);
dataMap.put("Materials", MaterialInfo.ToDispatchList(materialInfos));
try {
MicronResult result = HttpHelper.postMicronJson(url, dataMap);
return result;
} catch (Exception e) {
log.error(url + "出错", e);
}
return null;
}
}
package com.neotel.smfcore.custom.micron1053.controller;
import cn.hutool.core.util.ObjectUtil;
import com.neotel.smfcore.core.device.util.DataCache;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
@Service
@Slf4j
public class MicronConfig {
@Value("${micron.addr}")
public String micronAddr;
@Autowired
private DataCache dataCache;
public String getUrl(String apiName) {
if (ObjectUtil.isEmpty(micronAddr)) {
return "";
}
String url = micronAddr + apiName;
if (micronAddr.endsWith("/")) {
if (apiName.startsWith("/")) {
url = micronAddr + apiName.substring(1, apiName.length());
}
} else {
if (!apiName.startsWith("/")) {
url = micronAddr + "/" + apiName;
}
}
return micronAddr + apiName;
}
@PostConstruct
public void init() {
// host = dataCache.GetConfigCache("siemens.host", "siemens.host", url);
// port = dataCache.GetConfigCache("siemens.port", "siemens.port", url);
// url = dataCache.GetConfigCache("siemens.url", "siemens.url", url);
// action_GetMaterialLot = dataCache.GetConfigCache("siemens.action.GetMaterialLot", "siemens.action.GetMaterialLot", action_GetMaterialLot);
// action_ProcessMaterialLot = dataCache.GetConfigCache("siemens.action.ProcessMaterialLot", "siemens.action.ProcessMaterialLot", action_ProcessMaterialLot);
log.info("Micron sesrver addr:" + micronAddr );
}
}
package com.neotel.smfcore.custom.micron1053.controller;
import cn.hutool.core.util.ObjectUtil;
import com.neotel.smfcore.common.utils.JsonUtil;
import com.neotel.smfcore.custom.micron1053.bean.MaterialInfo;
import com.neotel.smfcore.custom.micron1053.bean.MicronResult;
import com.neotel.smfcore.security.annotation.AnonymousAccess;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Map;
@Slf4j
@RestController
@RequiredArgsConstructor
@Api(tags = "API测试")
@RequestMapping("rest/api/test")
public class MicronTestController {
@Autowired
private MicronApi apiController;
@ApiOperation("API-001 validate/mrb/{Id}/{SkipSap}")
@GetMapping("/validateMRB")
@AnonymousAccess
public String validateMRB(String Id, String SkipSap) {
MicronResult result = apiController.validateMRB(Id, SkipSap);
if (ObjectUtil.isEmpty(result)) {
return "";
}
return result.getResponseData();
}
@ApiOperation("API-002 validate/req/{Id}")
@GetMapping("/validateREQ")
@AnonymousAccess
public String validateREQ(String Id) {
MicronResult result = apiController.validateREQ(Id);
if (ObjectUtil.isEmpty(result)) {
return "";
}
return result.getResponseData();
}
@ApiOperation("API-003 validate/mcl/{PurchaseOrder}/{PackagingSlip}/{SkipSap}")
@GetMapping("/validateMCL")
@AnonymousAccess
public String validateMCL(String PurchaseOrder, String PackagingSlip, String skipSap) {
MicronResult result = apiController.validateMCL(PurchaseOrder, PackagingSlip, skipSap);
if (ObjectUtil.isEmpty(result)) {
return "";
}
return result.getResponseData();
}
@ApiOperation("API-004 validate/material")
@GetMapping("/validateMaterial")
@AnonymousAccess
public String validateMaterial(String Label2DID, String LoadingMode) {
MicronResult result = apiController.validateMaterial(Label2DID, LoadingMode);
if (ObjectUtil.isEmpty(result)) {
return "";
}
return result.getResponseData();
}
@ApiOperation("API-005 load-report")
@GetMapping("/loadReport")
@AnonymousAccess
public String loadReport(String params ) {
Map<String,Object> paramsMap=JsonUtil.toMap(params);
String JobId = paramsMap.get("JobId").toString();
Object obj=paramsMap.get("Materials");
List<Map<String,String>> arr=(List<Map<String, String>>)obj;
List<MaterialInfo> materialInfos=MaterialInfo.GetObjList(arr);
MicronResult result = apiController.loadReport(JobId, materialInfos);
if (ObjectUtil.isEmpty(result)) {
return "";
}
return result.getResponseData();
}
@ApiOperation("API-007 dispatch-list/{Facility}/{DispatchType}")
@GetMapping("/dispatchList")
@AnonymousAccess
public String dispatchList(String Facility, String DispatchType) {
MicronResult result = apiController.dispatchList(Facility, DispatchType);
if (ObjectUtil.isEmpty(result)) {
return "";
}
return result.getResponseData();
}
@ApiOperation("API-009 dispatch-material/{DispatchType}/{Id}")
@GetMapping("/dispatchMaterial")
@AnonymousAccess
public String dispatchMaterial(String DispatchType, String Id) {
MicronResult result = apiController.dispatchMaterial(DispatchType, Id);
if (ObjectUtil.isEmpty(result)) {
return "";
}
return result.getResponseData();
}
@ApiOperation("API-010 dispatch-report")
@GetMapping("/dispatchReport")
@AnonymousAccess
public String dispatchReport(String params) {
Map<String,Object> paramsMap=JsonUtil.toMap(params);
String JobId = paramsMap.get("JobId").toString();
String dispatchType = paramsMap.get("DispatchType").toString();
Object obj=paramsMap.get("Materials");
List<Map<String,String>> arr=(List<Map<String, String>>)obj;
List<MaterialInfo> materialInfos=MaterialInfo.GetObjList(arr);
MicronResult result = apiController.dispatchReport(JobId, dispatchType, materialInfos);
if (ObjectUtil.isEmpty(result)) {
return "";
}
return result.getResponseData();
}
}
支持 Markdown 格式
你添加了 0 到此讨论。请谨慎行事。
Finish editing this message first!