Commit eba0d589 LN

Merge remote-tracking branch 'origin/master'

# Conflicts:
#	src/main/java/com/neotel/smfcore/security/service/manager/IGroupManager.java
2 个父辈 1a64803c 8641e00b
正在显示 29 个修改的文件 包含 1158 行增加260 行删除
......@@ -149,6 +149,13 @@
<artifactId>mapstruct-jdk8</artifactId>
<version>1.4.0.Final</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.mina/mina-core -->
<dependency>
<groupId>org.apache.mina</groupId>
<artifactId>mina-core</artifactId>
<version>2.1.0</version>
</dependency>
</dependencies>
......
package com.neotel.smfcore.common.bean;
import lombok.extern.slf4j.Slf4j;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
/**
* Created by sunke on 2019/12/12.
*/
@Slf4j
public class ResultBean {
public static ResultBean newErrorResult(int code, String msg){
return newErrorResult(code, msg, true);
}
public static ResultBean newErrorResult(int code, String msg, boolean writeLog){
ResultBean result = new ResultBean();
result.setCode(code);
result.setMsg(msg);
if(writeLog){
log.info(msg);
}
return result;
}
public static ResultBean newOkResult(String msg, Object data){
ResultBean result = new ResultBean();
result.setCode(0);
result.setMsg(msg);
result.setData(data);
return result;
}
public static ResultBean newOkResult(Object data){
return newOkResult("ok", data);
}
/**
* 结果码,0为正常,其他值表示异常
*/
private int code;
/**
* 提示信息
*/
private String msg;
/**
* 数据结果
*/
private Object data;
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
}
......@@ -199,26 +199,6 @@ public class StorageConstants {
}
}
public static class BARCODE_STATUS{
/**
*-1新建
*/
public static int NEW = -1;
/**
* 0在库
*/
public static int IN_STORE = 0;
/**
* 1已出库正常
*/
public static int OUT_NORMAL = 1;
/**
* 2已出库且已过期
*/
public static int OUT_EXPIRED = 2;
}
public static class CABINET_STEP{
/**
......@@ -234,90 +214,4 @@ public class StorageConstants {
*/
public static int WAIT_CLOSE_DOOR = 2;
}
/**
* 轻工单执行状态
*/
public static class LITEORDER_STATUS{
/**新建的工单*/
public static int NEW=0;
/**首套料正在执行*/
public static int BOM=1;
/**首盘料已结束,等待出尾料*/
public static int BOM_FINISHED=2;
/**正在出尾料*/
public static int TAILS=3;
/**尾料已完成*/
public static int TAILS_FINISHED=4;
/**正在补料*/
public static int ONE=5;
/**补料已完成*/
public static int ONE_FINISHED=6;
}
private static int currentColorIndex = -1;
/**
* 工单颜色, 入库绿色,出库红色,库位检查使用黄色, 其他颜色用于工单出库颜色
*/
public enum ORDER_COLOR{
//magenta,cyan,firebrick,purple,skyblue,pink,forestgreen,lightblue,indianred,darkgreen
//洋红,青色,砖红色,紫色,天蓝色,粉色,森林绿,浅蓝色,印度红,深绿色
BLUE("0000FF"),
MAGENTA("FF00FF"),
CYAN("00FFFF"),
FIREBRICK("B22222"),
PURPLE("A020F0"),
SKYBLUE("6CA6CD"),
PINK("FF1493"),
FORESTGREEN("228B22"),
LIGHTBLUE("8470FF"),
INDIANRED("8B3A3A"),
DARKGREEN("556B2F");
private String rgb;
ORDER_COLOR(String rgb){
this.rgb = rgb;
}
public String getRgb() {
return rgb;
}
public void setRgb(String rgb) {
this.rgb = rgb;
}
public static ORDER_COLOR fromRgb(String rgb){
for (ORDER_COLOR order_color : values()) {
if(order_color.getRgb().equals(rgb)){
return order_color;
}
}
return null;
}
public static ORDER_COLOR nextColor(Collection<String> excludeColors){
ORDER_COLOR[] allColors = values();
if (excludeColors.size() >= allColors.length){
return null;
}
int nextColorIndex = (currentColorIndex + 1) % allColors.length;
for (ORDER_COLOR color : allColors) {
if(!excludeColors.contains(color.getRgb()) && color.ordinal() >= nextColorIndex){
currentColorIndex = color.ordinal();
return color;
}
}
return null;
}
}
}
package com.neotel.smfcore.core.barcode.enums;
/**
* Created by sunke on 2021/7/19.
*/
public class BARCODE_STATUS {
/**
*-1新建
*/
public static int NEW = -1;
/**
* 0在库
*/
public static int IN_STORE = 0;
/**
* 1已出库正常
*/
public static int OUT_NORMAL = 1;
/**
* 2已出库且已过期
*/
public static int OUT_EXPIRED = 2;
}
......@@ -4,9 +4,11 @@ import com.google.common.collect.Lists;
import com.neotel.smfcore.common.base.BasePo;
import com.neotel.smfcore.common.utils.DateUtil;
import com.neotel.smfcore.common.utils.StorageConstants;
import com.neotel.smfcore.core.barcode.enums.BARCODE_STATUS;
import com.neotel.smfcore.core.barcode.enums.COMPONENT_TYPE;
import com.neotel.smfcore.core.barcode.enums.SOLDER_STATUS;
import lombok.Data;
import lombok.*;
import org.springframework.data.annotation.Transient;
import org.springframework.data.mongodb.core.mapping.Document;
......@@ -39,7 +41,7 @@ public class Barcode extends BasePo implements Serializable {
/**
* 过期状态,-1未入库0在库,1已出库正常,2已出库且已过期
*/
private int status = StorageConstants.BARCODE_STATUS.NEW;
private int status = BARCODE_STATUS.NEW;
/**
* 锡膏状态
......@@ -168,6 +170,16 @@ public class Barcode extends BasePo implements Serializable {
* 锁定ID(目前只有指定批次会锁定)
*/
private String lockId;
/**
* 锁定名
*/
private String lockName;
/**
* 原始条码
*/
private String fullCode;
/**
* 添加相关联条码
*
......@@ -189,7 +201,7 @@ public class Barcode extends BasePo implements Serializable {
this.putInDate = new Date(putInTime);
}
status = StorageConstants.BARCODE_STATUS.IN_STORE;
status = BARCODE_STATUS.IN_STORE;
updateExpTime();
......@@ -268,9 +280,9 @@ public class Barcode extends BasePo implements Serializable {
updateExpTime();
if(expTime != null && checkOutDate.after(expTime)){
//过期时间小于出库时间,说明出库的时候已经过期了
status = StorageConstants.BARCODE_STATUS.OUT_EXPIRED;
status = BARCODE_STATUS.OUT_EXPIRED;
}else{
status = StorageConstants.BARCODE_STATUS.OUT_NORMAL;
status = BARCODE_STATUS.OUT_NORMAL;
}
}
}
......
......@@ -30,6 +30,7 @@ import com.neotel.smfcore.core.system.service.po.AlarmInfo;
import com.neotel.smfcore.core.system.service.po.DataLog;
import com.neotel.smfcore.core.system.service.po.Humiture;
import com.neotel.smfcore.core.system.util.TaskService;
import com.neotel.smfcore.security.service.manager.IGroupManager;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
......@@ -46,7 +47,7 @@ import java.util.concurrent.ConcurrentHashMap;
public class BaseDeviceHandler implements IDeviceHandler {
@Autowired
private DataCache dataCache;
protected DataCache dataCache;
@Autowired
private IAlarmInfoDao alarmInfoDao;
......@@ -66,6 +67,10 @@ public class BaseDeviceHandler implements IDeviceHandler {
@Autowired
protected CodeResolve codeResolve;
@Autowired
protected IGroupManager groupManager;
/**
* 状态 map,key为 cid value 为状态 Bean
*/
......
package com.neotel.smfcore.core.device.handler.impl;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import com.neotel.smfcore.common.bean.ResultBean;
import com.neotel.smfcore.common.exception.ValidateException;
import com.neotel.smfcore.common.utils.StorageConstants;
import com.neotel.smfcore.core.barcode.enums.COMPONENT_TYPE;
import com.neotel.smfcore.core.barcode.service.manager.IBarcodeManager;
import com.neotel.smfcore.core.barcode.service.manager.IComponentManager;
import com.neotel.smfcore.core.barcode.service.po.Barcode;
import com.neotel.smfcore.core.barcode.service.po.Component;
import com.neotel.smfcore.core.device.api.IOpAuthApi;
import com.neotel.smfcore.core.device.bean.StatusBean;
import com.neotel.smfcore.core.device.enums.OP;
import com.neotel.smfcore.core.device.enums.OP_STATUS;
import com.neotel.smfcore.core.order.enums.ORDER_COLOR;
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.po.DataLog;
import com.neotel.smfcore.security.service.po.Group;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.*;
/**
* 锡膏料仓
* Created by sunke on 2021/7/12.
*/
@RestController
@Slf4j
public class SensorShelfHandler extends BaseDeviceHandler {
public SensorShelfHandler(List<IOpAuthApi> apiList) {
super(apiList);
}
@Override
public StatusBean handleClientRequest(StatusBean statusBean, HttpServletRequest request) {
handleMsg(statusBean);
statusBean = saveAlarmAndHumidity(statusBean);
//亮灯
Collection<DataLog> queueTasks = taskService.getQueueTasks(statusBean.getCid());
for (DataLog queueTask : queueTasks) {
if(queueTask.isWait()){
queueTask.setStatus(OP_STATUS.EXECUTING.name());
taskService.updateQueueTask(queueTask);
String rgb = queueTask.getLightColor();
ORDER_COLOR color = ORDER_COLOR.fromRgb(rgb);
if(color == null){
if(queueTask.isPutInTask()){
color = ORDER_COLOR.DARKGREEN;
}else{
color = ORDER_COLOR.BLUE;
}
}
statusBean.addData("open",queueTask.getPosName()+"="+color.name());
log.info("库位["+queueTask.getPosName()+"]+亮灯:" + color.name());
}
}
return statusBean;
}
/**
* 客户端sensor变化
*/
@RequestMapping("/service/store/sensorShelf/sensorChange")
@ResponseBody
public ResultBean sensorChange(HttpServletRequest request, HttpSession httpSession){
String cid = request.getParameter("cid");
Storage storage = dataCache.getStorage(cid);
if(storage == null){
return ResultBean.newErrorResult(-1,cid + "对应的料架不存在");
}
String groupId = storage.getGroupId();
String groupName = "";
Group group = groupManager.get(groupId);
if(group != null){
groupName = group.getGroupName();
}
String[] hasReelPosList = request.getParameterValues("hasReelPosList");
String[] noReelPosList = request.getParameterValues("noReelPosList");
List<String> inOkList = new ArrayList<>();
List<String> inNgList = new ArrayList<>();
List<String> outOkList = new ArrayList<>();
List<String> outNgList = new ArrayList<>();
if(hasReelPosList != null){
//入库的库位列表
if(hasReelPosList.length > 1){
log.error("不可同时放入多盘物料:"+ hasReelPosList);
for (String posStr : hasReelPosList) {
inNgList.add(posStr);
}
}else{
StoragePos pos = storagePosManager.getByPosName(hasReelPosList[0]);
if(pos == null){
inNgList.add(hasReelPosList[0]);
log.error("未找到库位:"+ hasReelPosList);
}else{
Collection<DataLog> queueTasks = taskService.getQueueTasks();
for (DataLog queueTask : queueTasks) {
if(queueTask.isPutInTask() && queueTask.getSourceName().equals(groupName)){
queueTask.setCid(cid);
queueTask.setPosId(pos.getId());
queueTask.setPosName(pos.getPosName());
queueTask.setStorageId(pos.getStorageId());
queueTask.setStorageName(storage.getName());
try {
//入库完成,发送入库完成请求
super.finishedPutIn(cid,pos.getPosName());
inOkList.add(hasReelPosList[0]);
break;
} catch (Exception e) {
log.error("入库出错",e);
return ResultBean.newErrorResult(-1,"入库出错:" + e.getMessage());
}
}
}
if(inOkList.size() == 0){
inNgList.add(hasReelPosList[0]);
log.error("未找到["+pos.getPosName()+"]的入库任务");
}
}
}
}
if(noReelPosList != null){
//出库
for (String posName : noReelPosList) {
String outResult = "";
Collection<DataLog> queueTasks = taskService.getQueueTasks();
for (DataLog queueTask : queueTasks) {
if(queueTask.isCheckOutTask() && queueTask.getPosName().equals(posName)){
//出库完成
try {
outResult = posName;
super.finishedOutPos(cid,posName);
break;
} catch (Exception e) {
log.error("出库出错",e);
return ResultBean.newErrorResult(-1,"出库出错:" + e.getMessage());
}
}
}
if(outResult.isEmpty()){
log.info("未找到["+posName+"]的出库任务");
outNgList.add(posName);
}else{
outOkList.add(outResult);
}
}
}
Map<String,List<String>> dataMap = new HashMap<>();
dataMap.put("inOkList",inOkList);
dataMap.put("inNgList",inNgList);
dataMap.put("outOkList",outOkList);
dataMap.put("outNgList",outNgList);
return ResultBean.newOkResult(dataMap);
}
/**
* 获取料架的库位占用情况
*/
@RequestMapping("/service/store/sensorShelf/hasReelPosList")
@ResponseBody
public ResultBean checkAll(HttpServletRequest request){
String cid = request.getParameter("cid");
Storage storage = dataCache.getStorage(cid);
List<StoragePos> allPos = storagePosManager.findNotEmptyByStorageId(storage.getId());
List<String> posList = new ArrayList<>();
for (StoragePos pos : allPos) {
posList.add(pos.getPosName());
}
return ResultBean.newOkResult(posList);
}
@Override
public DeviceType getDeviceType() {
return DeviceType.SOLDERPASTE;
}
}
package com.neotel.smfcore.core.device.util;
import com.google.common.base.Strings;
import com.google.common.collect.Maps;
import com.neotel.smfcore.common.exception.ValidateException;
import com.neotel.smfcore.common.utils.StorageConstants;
import com.neotel.smfcore.core.barcode.service.po.Barcode;
import com.neotel.smfcore.core.barcode.utils.CodeResolve;
......@@ -98,15 +100,15 @@ public class DataCache {
return settings;
}
//
// /**
// * 出库方式
// */
// public CHECKOUT_TYPE getCheckOutType(){
// String outType = getSettings().getOutType();
// return CHECKOUT_TYPE.valueOf(outType);
// }
//
/**
* 出库方式
*/
public CHECKOUT_TYPE getCheckOutType(){
String outType = getSettings().getOutType();
return CHECKOUT_TYPE.valueOf(outType);
}
public Settings updateSettings(Settings newSetting){
settings = settingsDao.save(newSetting);
List<String> ruleItems = settings.getCodeRuleList();
......@@ -239,78 +241,78 @@ public class DataCache {
return null;
}
// public Storage reloadStorage(Storage storage) throws ValidateException {
// List<PlateSizeBean> plateSizeBeanList = storagePosManager.getStoragePosUsage(storage.getId());
// storage.initUsage(plateSizeBeanList);
// storage = storageManager.save(storage);
// allStorage.put(storage.getCid(), storage);
// return storage;
// }
//
//
// /**
// * 锁定库存
// * @param cid
// * @param partNumber 物料编号
// * @return 锁定结果,true 表示有足够的库存,锁定成功;false表示库存不足,锁定失败
// */
// public boolean lockOneReel(String cid, String partNumber){
// boolean result = false;
// InventoryItem inventoryItem = getStorageInventoryByPartNumber(cid, partNumber);
// if(inventoryItem != null) {
// int lockReel = inventoryItem.getLockReel();
// //理论上这里是同一个对象,不需要再显式的放入map 中
// result = inventoryItem.lockOne();
// log.info("锁定料仓["+cid+"]物料["+partNumber+"],锁定数量["+lockReel+"]=>["+inventoryItem.getLockReel()+"],当前库存:"+inventoryItem.getStockReel());
// updateStorageInventory(cid,inventoryItem);
// }
// return result;
// }
// /**
// * 解除锁定库存(出库任务完成或取消时调用)
// */
// public void unLockOneReel(String cid, String partNumber){
// InventoryItem partNumberInventory = getStorageInventoryByPartNumber(cid, partNumber);
// if(partNumberInventory != null) {
// int lockReel = partNumberInventory.getLockReel();
// //理论上这里是同一个对象,不需要再显式的放入map 中
// partNumberInventory.unLock(1);
// log.info("解除锁定料仓["+cid+"]物料["+partNumber+"],锁定数量["+lockReel+"]=>["+partNumberInventory.getLockReel()+"],当前库存:"+partNumberInventory.getStockReel());
// updateStorageInventory(cid,partNumberInventory);
// }
// }
//
// /**
// * 获取库存信息,key 为 PN
// */
// public Map<String,InventoryItem> getAllInventory(){
// Map<String, Storage> allStorages = getAllStorage();
// return getInventory(allStorages.values());
// }
//
// /**
// * 获取某些料仓的库存信息
// */
// public Map<String,InventoryItem> getInventory(Collection<Storage> storageList){
// Map<String,InventoryItem> resultMap = Maps.newHashMap();
// for (Storage storage : storageList) {
// Map<String, InventoryItem> storageInventory = getStorageInventory(storage.getCid());
// for(InventoryItem storageInventoryItem : storageInventory.values()){
// String partNumber = storageInventoryItem.getPartNumber();
// InventoryItem pnInventoryItem = resultMap.get(storageInventoryItem.getPartNumber());
// if(pnInventoryItem == null){
// pnInventoryItem = new InventoryItem();
// }
// pnInventoryItem.setPartNumber(partNumber);
// pnInventoryItem.setStockCount(pnInventoryItem.getStockCount() + storageInventoryItem.getStockCount());
// pnInventoryItem.setLockCount(pnInventoryItem.getLockCount() + storageInventoryItem.getLockCount());
// pnInventoryItem.setStockReel(pnInventoryItem.getStockReel() + storageInventoryItem.getStockReel());
// pnInventoryItem.setLockReel(pnInventoryItem.getLockReel() + storageInventoryItem.getLockReel());
// resultMap.put(partNumber,pnInventoryItem);
// }
// }
// return resultMap;
// }
public Storage reloadStorage(Storage storage) throws ValidateException {
List<PlateSizeBean> plateSizeBeanList = storagePosManager.getStoragePosUsage(storage.getId());
storage.initUsage(plateSizeBeanList);
storage = storageManager.save(storage);
allStorage.put(storage.getCid(), storage);
return storage;
}
/**
* 锁定库存
* @param cid
* @param partNumber 物料编号
* @return 锁定结果,true 表示有足够的库存,锁定成功;false表示库存不足,锁定失败
*/
public boolean lockOneReel(String cid, String partNumber){
boolean result = false;
InventoryItem inventoryItem = getStorageInventoryByPartNumber(cid, partNumber);
if(inventoryItem != null) {
int lockReel = inventoryItem.getLockReel();
//理论上这里是同一个对象,不需要再显式的放入map 中
result = inventoryItem.lockOne();
log.info("锁定料仓["+cid+"]物料["+partNumber+"],锁定数量["+lockReel+"]=>["+inventoryItem.getLockReel()+"],当前库存:"+inventoryItem.getStockReel());
updateStorageInventory(cid,inventoryItem);
}
return result;
}
/**
* 解除锁定库存(出库任务完成或取消时调用)
*/
public void unLockOneReel(String cid, String partNumber){
InventoryItem partNumberInventory = getStorageInventoryByPartNumber(cid, partNumber);
if(partNumberInventory != null) {
int lockReel = partNumberInventory.getLockReel();
//理论上这里是同一个对象,不需要再显式的放入map 中
partNumberInventory.unLock(1);
log.info("解除锁定料仓["+cid+"]物料["+partNumber+"],锁定数量["+lockReel+"]=>["+partNumberInventory.getLockReel()+"],当前库存:"+partNumberInventory.getStockReel());
updateStorageInventory(cid,partNumberInventory);
}
}
/**
* 获取库存信息,key 为 PN
*/
public Map<String,InventoryItem> getAllInventory(){
Map<String, Storage> allStorages = getAllStorage();
return getInventory(allStorages.values());
}
/**
* 获取某些料仓的库存信息
*/
public Map<String,InventoryItem> getInventory(Collection<Storage> storageList){
Map<String,InventoryItem> resultMap = Maps.newHashMap();
for (Storage storage : storageList) {
Map<String, InventoryItem> storageInventory = getStorageInventory(storage.getCid());
for(InventoryItem storageInventoryItem : storageInventory.values()){
String partNumber = storageInventoryItem.getPartNumber();
InventoryItem pnInventoryItem = resultMap.get(storageInventoryItem.getPartNumber());
if(pnInventoryItem == null){
pnInventoryItem = new InventoryItem();
}
pnInventoryItem.setPartNumber(partNumber);
pnInventoryItem.setStockCount(pnInventoryItem.getStockCount() + storageInventoryItem.getStockCount());
pnInventoryItem.setLockCount(pnInventoryItem.getLockCount() + storageInventoryItem.getLockCount());
pnInventoryItem.setStockReel(pnInventoryItem.getStockReel() + storageInventoryItem.getStockReel());
pnInventoryItem.setLockReel(pnInventoryItem.getLockReel() + storageInventoryItem.getLockReel());
resultMap.put(partNumber,pnInventoryItem);
}
}
return resultMap;
}
/**
* 获取料仓的库存信息
......
package com.neotel.smfcore.core.order.listener;
package com.neotel.smfcore.core.order;
import com.google.common.base.Strings;
import com.neotel.smfcore.common.bean.ResultBean;
import com.neotel.smfcore.common.exception.ValidateException;
import com.neotel.smfcore.core.barcode.service.po.Barcode;
import com.neotel.smfcore.core.device.enums.OP;
import com.neotel.smfcore.core.device.enums.OP_STATUS;
import com.neotel.smfcore.core.device.util.DataCache;
import com.neotel.smfcore.core.order.enums.ORDER_COLOR;
import com.neotel.smfcore.core.order.service.dao.ILiteOrderDao;
import com.neotel.smfcore.core.order.service.manager.ILiteOrderItemManager;
import com.neotel.smfcore.core.order.service.manager.ILiteOrderManager;
import com.neotel.smfcore.core.order.service.po.LiteOrder;
import com.neotel.smfcore.core.order.service.po.LiteOrderItem;
import com.neotel.smfcore.core.storage.service.manager.IStoragePosManager;
import com.neotel.smfcore.core.storage.service.po.Storage;
import com.neotel.smfcore.core.storage.service.po.StoragePos;
import com.neotel.smfcore.core.system.listener.ITaskListener;
import com.neotel.smfcore.core.system.service.po.DataLog;
import com.neotel.smfcore.core.system.util.TaskService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
/**
......@@ -24,7 +31,7 @@ import java.util.concurrent.ConcurrentHashMap;
*/
@Service
@Slf4j
public class LiteOrderListener implements ITaskListener {
public class LiteOrderCache implements ITaskListener {
@Autowired
private ILiteOrderManager liteOrderManager;
......@@ -32,6 +39,15 @@ public class LiteOrderListener implements ITaskListener {
@Autowired
private ILiteOrderItemManager liteOrderItemManager;
@Autowired
private TaskService taskService;
@Autowired
private DataCache dataCache;
@Autowired
private IStoragePosManager storagePosManager;
/**
* 正在执行的liteOrderMap, key 为orderNo,value 为order
*/
......@@ -46,6 +62,47 @@ public class LiteOrderListener implements ITaskListener {
}
}
public ResultBean checkOutOrders(LiteOrder liteOrder) throws ValidateException {
//设置颜色
Set<String> currentColors = new HashSet<>();
for (DataLog dataLog : taskService.getQueueTasks()) {
currentColors.add(dataLog.getLightColor());
}
ORDER_COLOR nextColor = ORDER_COLOR.nextColor(currentColors);
//其他出库模式一次性全部生成任务
List<StoragePos> lockPosList = storagePosManager.findLockPos(liteOrder.getOrderNo());
int taskReelCount = 0;
for (StoragePos lockPos : lockPosList) {
Storage storage = dataCache.getStorageById(lockPos.getStorageId());
Barcode barcode = lockPos.getBarcode();
DataLog task = new DataLog(storage,barcode,lockPos);
task.setSourceId(liteOrder.getId());
task.setSourceName(liteOrder.getOrderNo());
task.setSubSourceId(barcode.getLockName());
task.setSubSourceInfo(barcode.getLockName());
task.setType(OP.CHECKOUT);
task.setLightColor(nextColor.getRgb());
task.setStatus(OP_STATUS.WAIT.name());
taskService.addTaskToExecute(task);
taskReelCount = taskReelCount + 1;
log.info("工单[" + liteOrder.getOrderNo() + "]出库位置仓位【" + task.getPosName() + "】RI=[" + task.getBarcode() + "] PN=[" + task.getPartNumber() + "] ");
}
liteOrder.setTaskReelCount(taskReelCount);
log.info("工单[" + liteOrder.getOrderNo() + "]任务分配结束,任务数[" + taskReelCount + "]");
//有需要出库的
if (taskReelCount <= 0) {
liteOrder.finishedTasks();
}
liteOrderManager.save(liteOrder);
if (taskReelCount <= 0) {
return ResultBean.newErrorResult(-1,"No task in this order");
}
return ResultBean.newOkResult("total task is :" + taskReelCount,"");
}
/**
* 更新工单状态信息
*/
......
package com.neotel.smfcore.core.order.enums;
/**
* Created by sunke on 2021/7/19.
*/
public class LITEORDER_STATUS {
/**新建的工单*/
public static int NEW=0;
/**首套料正在执行*/
public static int BOM=1;
/**首盘料已结束,等待出尾料*/
public static int BOM_FINISHED=2;
/**正在出尾料*/
public static int TAILS=3;
/**尾料已完成*/
public static int TAILS_FINISHED=4;
/**正在补料*/
public static int ONE=5;
/**补料已完成*/
public static int ONE_FINISHED=6;
}
package com.neotel.smfcore.core.order.enums;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
/**
* Created by sunke on 2021/7/19.
*/
public enum ORDER_COLOR {
//magenta,cyan,firebrick,purple,skyblue,pink,forestgreen,lightblue,indianred,darkgreen
//洋红,青色,砖红色,紫色,天蓝色,粉色,森林绿,浅蓝色,印度红,深绿色
BLUE("0000FF"),
MAGENTA("FF00FF"),
CYAN("00FFFF"),
FIREBRICK("B22222"),
PURPLE("A020F0"),
SKYBLUE("6CA6CD"),
PINK("FF1493"),
FORESTGREEN("228B22"),
LIGHTBLUE("8470FF"),
INDIANRED("8B3A3A"),
DARKGREEN("556B2F"), ;
private static int currentColorIndex = -1;
private String rgb;
ORDER_COLOR(String rgb){
this.rgb = rgb;
}
public String getRgb() {
return rgb;
}
public void setRgb(String rgb) {
this.rgb = rgb;
}
public static ORDER_COLOR fromRgb(String rgb){
for (ORDER_COLOR order_color : values()) {
if(order_color.getRgb().equals(rgb)){
return order_color;
}
}
return null;
}
public static ORDER_COLOR nextColor(Collection<String> excludeColors){
ORDER_COLOR[] allColors = values();
if (excludeColors.size() >= allColors.length){
return null;
}
int nextColorIndex = (currentColorIndex + 1) % allColors.length;
for (ORDER_COLOR color : allColors) {
if(!excludeColors.contains(color.getRgb()) && color.ordinal() >= nextColorIndex){
currentColorIndex = color.ordinal();
return color;
}
}
return null;
}
}
package com.neotel.smfcore.core.order.service.manager;
import com.neotel.smfcore.common.base.IBaseManager;
import com.neotel.smfcore.common.exception.ValidateException;
import com.neotel.smfcore.core.barcode.service.po.Barcode;
import com.neotel.smfcore.core.order.service.po.LiteOrder;
public interface ILiteOrderManager extends IBaseManager<LiteOrder> {
LiteOrder findByOrderNo(String orderNo);
LiteOrder createWithItems(LiteOrder liteOrder) throws ValidateException;
}
package com.neotel.smfcore.core.order.service.manager.impl;
import com.google.common.collect.Lists;
import com.neotel.smfcore.common.exception.ValidateException;
import com.neotel.smfcore.core.barcode.service.dao.IBarcodeDao;
import com.neotel.smfcore.core.barcode.service.manager.IBarcodeManager;
......@@ -9,6 +10,7 @@ import com.neotel.smfcore.core.order.service.manager.ILiteOrderItemManager;
import com.neotel.smfcore.core.order.service.manager.ILiteOrderManager;
import com.neotel.smfcore.core.order.service.po.LiteOrder;
import com.neotel.smfcore.core.order.service.po.LiteOrderItem;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Pageable;
......@@ -33,26 +35,38 @@ public class LiteOrderManagerImpl implements ILiteOrderManager {
@Override
public LiteOrder get(String id) {
return null;
return liteOrderDao.findOneById(id);
}
@Override
public LiteOrder save(LiteOrder object) throws ValidateException {
return null;
return liteOrderDao.save(object);
}
@Override
public void delete(LiteOrder object) throws ValidateException {
}
@Override
public LiteOrder createWithItems(LiteOrder liteOrder) throws ValidateException {
List<LiteOrderItem> items = Lists.newArrayList();
for (LiteOrderItem liteOrderItem : liteOrder.getOrderItems()) {
liteOrderItem.setOrderNo(liteOrder.getOrderNo());
liteOrderItem = liteOrderItemManager.save(liteOrderItem);
items.add(liteOrderItem);
}
liteOrder = save(liteOrder);
liteOrder.setOrderItems(items);
return liteOrder;
}
@Override
public List<LiteOrder> findByPage(Query query, Pageable pageable) {
return null;
return liteOrderDao.findByQuery(query,pageable);
}
@Override
public List<LiteOrder> findByQuery(Query query) {
return null;
return liteOrderDao.findByQuery(query);
}
}
......@@ -2,6 +2,7 @@ package com.neotel.smfcore.core.order.service.po;
import com.neotel.smfcore.common.base.BasePo;
import com.neotel.smfcore.common.utils.StorageConstants;
import com.neotel.smfcore.core.order.enums.LITEORDER_STATUS;
import lombok.Data;
import org.springframework.data.annotation.Transient;
import org.springframework.data.mongodb.core.mapping.Document;
......@@ -38,7 +39,7 @@ public class LiteOrder extends BasePo implements Serializable {
/**
* 订单状态
*/
private int status = StorageConstants.LITEORDER_STATUS.NEW;
private int status = LITEORDER_STATUS.NEW;
/**
* 出库状态, 2表示已完成
......@@ -74,11 +75,11 @@ public class LiteOrder extends BasePo implements Serializable {
*/
public void finishedTasks(){
if(isOutOne()){
setStatus(StorageConstants.LITEORDER_STATUS.ONE_FINISHED);
setStatus(LITEORDER_STATUS.ONE_FINISHED);
}else if(isOutBom()){
setStatus(StorageConstants.LITEORDER_STATUS.BOM_FINISHED);
setStatus(LITEORDER_STATUS.BOM_FINISHED);
}else if(isOutTails()){
setStatus(StorageConstants.LITEORDER_STATUS.TAILS_FINISHED);
setStatus(LITEORDER_STATUS.TAILS_FINISHED);
}
setTaskFinishedTime(System.currentTimeMillis());
......@@ -89,18 +90,18 @@ public class LiteOrder extends BasePo implements Serializable {
* @return
*/
public boolean isOutBom(){
return status == StorageConstants.LITEORDER_STATUS.BOM;
return status == LITEORDER_STATUS.BOM;
}
/**
* 是否是未执行过的工单
*/
public boolean isNew(){
return status == StorageConstants.LITEORDER_STATUS.NEW;
return status == LITEORDER_STATUS.NEW;
}
public boolean isOutOne(){
return status == StorageConstants.LITEORDER_STATUS.ONE;
return status == LITEORDER_STATUS.ONE;
}
/**
......@@ -108,21 +109,21 @@ public class LiteOrder extends BasePo implements Serializable {
* @return
*/
public boolean isOutOneFinished(){
return status == StorageConstants.LITEORDER_STATUS.ONE_FINISHED;
return status == LITEORDER_STATUS.ONE_FINISHED;
}
/**
* 是否正在出尾料
*/
public boolean isOutTails(){
return status == StorageConstants.LITEORDER_STATUS.TAILS;
return status == LITEORDER_STATUS.TAILS;
}
/**
* 任务料盘是否已出完
*/
public boolean isTaskFinished(){
return status == StorageConstants.LITEORDER_STATUS.BOM_FINISHED || status == StorageConstants.LITEORDER_STATUS.TAILS_FINISHED || status == StorageConstants.LITEORDER_STATUS.ONE_FINISHED;
return status == LITEORDER_STATUS.BOM_FINISHED || status == LITEORDER_STATUS.TAILS_FINISHED || status == LITEORDER_STATUS.ONE_FINISHED;
}
......
......@@ -14,6 +14,11 @@ public class LiteOrderItem extends BasePo implements Serializable {
//需求数量
private int needNum = 0;
/**
* 需求料盘数
*/
private int needReelCount = 0;
//已出数量
private int outNum = 0;
......
......@@ -3,8 +3,10 @@ package com.neotel.smfcore.core.storage.service.manager;
import com.neotel.smfcore.common.base.IBaseManager;
import com.neotel.smfcore.core.barcode.bean.PlateSizeBean;
import com.neotel.smfcore.core.storage.bean.InventoryItem;
import com.neotel.smfcore.core.storage.enums.CHECKOUT_TYPE;
import com.neotel.smfcore.core.storage.service.po.StoragePos;
import java.util.Collection;
import java.util.List;
import java.util.Map;
......@@ -15,4 +17,10 @@ public interface IStoragePosManager extends IBaseManager<StoragePos> {
Map<String,InventoryItem> getInventory(String id);
StoragePos getByBarcode(String barcode);
List<StoragePos> findNotEmptyByStorageId(String storageId);
List<StoragePos> findLockPos(String lockId);
StoragePos findPartNumberInStorages(List<String> storageIdList, String pn, Collection<String> excludePosIds, CHECKOUT_TYPE checkOutType);
}
package com.neotel.smfcore.core.storage.service.manager.impl;
import com.google.common.base.Strings;
import com.google.common.collect.Maps;
import com.neotel.smfcore.common.exception.ValidateException;
import com.neotel.smfcore.core.barcode.bean.PlateSizeBean;
import com.neotel.smfcore.core.storage.bean.InventoryItem;
import com.neotel.smfcore.core.storage.enums.CHECKOUT_TYPE;
import com.neotel.smfcore.core.storage.service.dao.IStoragePosDao;
import com.neotel.smfcore.core.storage.service.manager.IStoragePosManager;
import com.neotel.smfcore.core.storage.service.po.StoragePos;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.aggregation.Aggregation;
import org.springframework.data.mongodb.core.aggregation.AggregationResults;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;
import java.util.Collection;
import java.util.List;
import java.util.Map;
@Service
@Slf4j
public class StoragePosManagerImpl implements IStoragePosManager {
@Autowired
......@@ -173,6 +179,60 @@ public class StoragePosManagerImpl implements IStoragePosManager {
}
@Override
public List<StoragePos> findNotEmptyByStorageId(String storageId){
Criteria c = Criteria.where("barcode").exists(true)
.and("enabled").is(true);//可用;
if(!Strings.isNullOrEmpty(storageId)){
c = c.and("storageId").is(storageId);
}
Query query = new Query(c);
query.with(Sort.by(Sort.Direction.ASC, "updateDate"));
return storagePosDao.findByQuery(query);
}
@Override
public List<StoragePos> findLockPos(String lockId) {
Criteria c = Criteria.where("barcode.lockId").is(lockId);
return findByQuery(new Query(c));
}
@Override
public StoragePos findPartNumberInStorages(List<String> storageIdList, String pn, Collection<String> excludePosIds, CHECKOUT_TYPE checkOutType) {
Criteria c = Criteria.where("barcode.partNumber").is(pn)
.and("id").nin(excludePosIds)
.and("enabled").is(true)//可用
.and("barcode.lockId").is(null);//没有被锁定的仓位;
if(storageIdList != null){
c = c.and("storageId").in(storageIdList);
}
Query q = new Query(c);
Sort sort = getSortByCheckOutType(checkOutType);
q.with(sort);
log.info("使用"+checkOutType+"策略出库partNumber="+pn);
return storagePosDao.findOne(q);
}
/**
* 根据出库方式获取不同的 Sort
*/
private Sort getSortByCheckOutType(CHECKOUT_TYPE checkoutType){
Sort sort = null;
if(CHECKOUT_TYPE.EXPIRE_FIRST.equals(checkoutType)){//先过期先出
sort = Sort.by(Sort.Direction.ASC, "barcode.expTime","barcode.expireDate","canCheckOutTime");
}else if(CHECKOUT_TYPE.FIFO.equals(checkoutType)){//严格的先进先出
sort = Sort.by(Sort.Direction.ASC, "canCheckOutTime", "barcode.usedCount");
}else if(CHECKOUT_TYPE.USED_FIRST.equals(checkoutType)){//尾料优先
sort = Sort.by(Sort.Direction.ASC, "barcode.amount", "canCheckOutTime");
}else if(CHECKOUT_TYPE.PRODUCE_DATE.equals(checkoutType)){
//先生产先出
sort = Sort.by(Sort.Direction.ASC, "barcode.produceDate", "canCheckOutTime");
}else{//效率优先
sort = Sort.by(Sort.Direction.ASC, "canCheckOutTime", "createDate");
}
return sort;
}
@Override
public List<StoragePos> findByPage(Query query, Pageable pageable) {
return storagePosDao.findByQuery(query,pageable);
}
......
......@@ -56,6 +56,11 @@ public class Storage extends BasePo implements Serializable {
private boolean available = true;
/**
* 分组
*/
private String groupId = "";
/**
* 是否是上下层的在线料仓
......
......@@ -3,8 +3,11 @@ package com.neotel.smfcore.core.system.service.po;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import com.neotel.smfcore.common.base.BasePo;
import com.neotel.smfcore.core.barcode.service.po.Barcode;
import com.neotel.smfcore.core.device.enums.OP;
import com.neotel.smfcore.core.device.enums.OP_STATUS;
import com.neotel.smfcore.core.storage.service.po.Storage;
import com.neotel.smfcore.core.storage.service.po.StoragePos;
import lombok.Data;
import org.springframework.data.mongodb.core.mapping.Document;
......@@ -15,6 +18,25 @@ import java.util.List;
@Document
public class DataLog extends BasePo implements Serializable {
public DataLog(){
}
public DataLog(Storage storage, Barcode barcode, StoragePos pos) {
if (barcode != null) {
setPartNumber(barcode.getPartNumber());
setBarcode(barcode.getBarcode());
setNum(barcode.getAmount());
setMemo(barcode.getMemo());
}
setCid(storage.getCid());
setStorageId(storage.getId());
setStorageName(storage.getName());
setPosId(pos.getId());
setPosName(pos.getPosName());
}
/**
* 是否是单盘出库(联电指出库项目,默认为false即默认批量出库)
*/
......
package com.neotel.smfcore.core.system.util;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.neotel.smfcore.common.exception.ValidateException;
......@@ -17,10 +18,7 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.*;
/**
* Created by sunke on 2021/7/13.
......@@ -32,6 +30,7 @@ public class TaskService {
@Autowired
protected IDataLogDao dataLogDao;
@Autowired
private List<ITaskListener> taskListenerList = new ArrayList<>();
/**
......@@ -44,54 +43,55 @@ public class TaskService {
*/
private static Map<String,DataLog> theFinishedTaskMap = Maps.newConcurrentMap();
public TaskService(List<ITaskListener> listenerList){
for (ITaskListener taskListener: listenerList) {
taskListenerList.add(taskListener);
}
// public TaskService(List<ITaskListener> listenerList){
// for (ITaskListener taskListener: listenerList) {
// taskListenerList.add(taskListener);
// }
// }
private void check(String barcode, String posName) throws ValidateException {
}
/**
* 加入要执行的任务
* 条码入库,加入要执行的任务
*/
public synchronized DataLog addPutInTaskToExecute(Storage storage, Barcode barcode, StoragePos storagePos) throws ValidateException {
Collection<DataLog> tasks = taskMap.values();
for (DataLog task : tasks) {
//检查 barcode
if (task.getBarcode().equals(barcode.getBarcode())) {
log.info("二维码:[" + barcode.getBarcode() + "]已在操作队列中,操作失败");
throw new ValidateException("error.barcode.inQueue", new String[]{storagePos.getPosName()});
} else if (task.getPosId().equals(storagePos.getId())) {
log.info("位置:[" + storagePos.getPosName() + "]已在操作队列中,操作失败");
throw new ValidateException("error.pos.inQueue", new String[]{storagePos.getPosName()});
}
}
DataLog dataLog = new DataLog();
dataLog.setStorageId(storage.getId());
dataLog.setStorageName(storage.getName());
dataLog.setBarcode(barcode.getBarcode());
dataLog.setMemo(barcode.getMemo());
dataLog.setType(OP.PUT_IN);
dataLog.setNum(barcode.getAmount());
dataLog.setCid(storage.getCid());
//dataLog.setComponentName(barcode.getComponentName());
//TODO:上次出库时间
//dataLog.setLastOperateDate();
//操作人
DataLog task = new DataLog(storage, barcode, storagePos);
task.setType(OP.PUT_IN);
task.setStatus(OP_STATUS.EXECUTING.name());
String loginUser = SecurityUtils.getLoginUsername();
dataLog.setOperator(loginUser);
dataLog.setPartNumber(barcode.getPartNumber());
dataLog.setPosId(storagePos.getId());
dataLog.setPosName(storagePos.getPosName());
dataLog.setStatus(OP_STATUS.EXECUTING.name());
//dataLog.setSourceType();
dataLogDao.save(dataLog);
taskMap.put(dataLog.getId(), dataLog);
log.info("cid:[" + storage.getCid() + "] barcode:[" + barcode.getBarcode() + "] partNumber:[" + dataLog.getPartNumber() + "]位置[" + storagePos.getPosName() + "]的入库操作成功加入队列");
return dataLog;
task.setOperator(loginUser);
task = updateQueueTask(task);
log.info("cid:[" + storage.getCid() + "] barcode:[" + barcode.getBarcode() + "] partNumber:[" + task.getPartNumber() + "]位置[" + storagePos.getPosName() + "]的入库操作成功加入队列");
return task;
}
/**
* 库位出库
* @param storage 料仓
* @param pos 库位
* @param isSingleOut 是否是单盘出库
* @return
* @throws ValidateException
*/
public synchronized String checkout(Storage storage, StoragePos pos, boolean isSingleOut) throws ValidateException {
if (pos.getBarcode() == null) {
String msg = "库位[" + pos.getPosName() + "]中已无物料,忽略";
log.info(msg);
throw new ValidateException("allBoxView.noReel","库位中无物料");
}
DataLog task = new DataLog(storage, pos.getBarcode(), pos);
task.setType(OP.CHECKOUT);
task.setStatus(OP_STATUS.WAIT.name());
task.setSingleOut(isSingleOut);
addTaskToExecute(task);
return "";
}
/**
......@@ -104,18 +104,43 @@ public class TaskService {
}
}
public void updateQueueTask(DataLog task) {
dataLogDao.save(task);
/**
* 更新队列中的任务状态
* @param task
*/
public DataLog updateQueueTask(DataLog task) {
task = dataLogDao.save(task);
taskMap.put(task.getId(), task);
tiggerTaskChangeListener(task);
return task;
}
/**
* 更新完成列表中的任务状态
* @param task
*/
public void updateFinishedTask(DataLog task){
dataLogDao.save(task);
theFinishedTaskMap.put(task.getId(), task);
tiggerTaskChangeListener(task);
}
public void addTaskToExecute(DataLog taskToExecute) throws ValidateException {
Collection<DataLog> tasks = taskMap.values();
for (DataLog task : tasks) {
String barcode = taskToExecute.getBarcode();
String posName = taskToExecute.getPosName();
if (!Strings.isNullOrEmpty(barcode) && task.getBarcode().equals(barcode)) {
log.info("二维码:[" + barcode + "]已在操作队列中,操作失败");
throw new ValidateException("error.barcode.inQueue", new String[]{barcode});
} else if (task.getPosName().equals(posName)) {
log.info("位置:[" + posName + "]已在操作队列中,操作失败");
throw new ValidateException("error.pos.inQueue", new String[]{posName});
}
}
updateQueueTask(taskToExecute);
}
/**
* 获取所有任务队列中的任务(等待中和执行中)
*/
......
package com.neotel.smfcore.hella.rest;
import com.neotel.smfcore.common.bean.ResultBean;
import com.neotel.smfcore.core.barcode.service.manager.IBarcodeManager;
import com.neotel.smfcore.core.barcode.service.po.Barcode;
import com.neotel.smfcore.core.device.util.DataCache;
import com.neotel.smfcore.core.storage.service.manager.IStoragePosManager;
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.po.DataLog;
import com.neotel.smfcore.core.system.util.TaskService;
import com.neotel.smfcore.hella.handler.HellaServiceHandler;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.*;
/**
* 扫码料架
*/
@Controller
@Slf4j
public class HellaSensorShelfController {
@Autowired
private DataCache dataCache;
@Autowired
private HellaServiceHandler hellaServiceHandler;
@Autowired
private TaskService taskService;
@Autowired
protected IStoragePosManager storagePosManager;
@Autowired
protected IBarcodeManager barcodeManager;
}
package com.neotel.smfcore.hella.tcp;
import com.google.common.base.Strings;
import com.neotel.smfcore.common.bean.ResultBean;
import com.neotel.smfcore.core.device.util.DataCache;
import com.neotel.smfcore.core.system.service.po.Settings;
import com.neotel.smfcore.hella.handler.HellaServiceHandler;
import lombok.extern.slf4j.Slf4j;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.mina.core.filterchain.IoFilterAdapter;
import org.apache.mina.core.future.ConnectFuture;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.codec.textline.LineDelimiter;
import org.apache.mina.filter.codec.textline.TextLineCodecFactory;
import org.apache.mina.filter.logging.MdcInjectionFilter;
import org.apache.mina.transport.socket.nio.NioSocketConnector;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.net.InetSocketAddress;
import java.nio.charset.Charset;
/**
* Created by sunke on 2019/4/17.
*/
@Slf4j
@Service
public class HellaTcpClient {
private static NioSocketConnector connector;
private static String host = "";
private static int port = 9999;
@Value("${hella.host:}")
public void setHost(String host) {
HellaTcpClient.host = host;
}
@Value("${hella.port:9999}")
public void setPort(int port) {
HellaTcpClient.port = port;
}
@Autowired
private HellaServiceHandler hellaServiceHandler;
private static IoSession theSession;
@PostConstruct
public void init(){
updateServerInfo(host, port);
start();
}
public static void updateServerInfo(String serverHost, int serverPort){
host = serverHost;
port = serverPort;
log.info("设置Tcp连接信息为["+host+":"+port+"]");
if(connector != null){
connector.dispose();
}
//connectThreadStart();
}
public void start(){
connector = new NioSocketConnector(); //创建连接客户端
connector.setConnectTimeoutMillis(30000); //设置连接超时
//断线重连回调拦截器
connector.getFilterChain().addFirst("reconnection", new IoFilterAdapter() {
@Override
public void sessionClosed(NextFilter nextFilter, IoSession ioSession) throws Exception {
log.info("执行断线重连");
connectThreadStart();
}
});
connector.getFilterChain().addLast("mdc", new MdcInjectionFilter());
TextLineCodecFactory factory = new TextLineCodecFactory(Charset.defaultCharset(), LineDelimiter.CRLF,LineDelimiter.CRLF);
// factory.setDecoderMaxLineLength(10240);
// factory.setEncoderMaxLineLength(10240);
//加入解码器
connector.getFilterChain().addLast("codec", new ProtocolCodecFilter(factory));
connector.getSessionConfig().setReceiveBufferSize(10240); // 设置接收缓冲区的大小
connector.getSessionConfig().setSendBufferSize(10240);// 设置输出缓冲区的大小
connector.getSessionConfig().setIdleTime(IdleStatus.BOTH_IDLE, 30000); //读写都空闲时间:30秒
connector.getSessionConfig().setIdleTime(IdleStatus.READER_IDLE, 40000);//读(接收通道)空闲时间:40秒
connector.getSessionConfig().setIdleTime(IdleStatus.WRITER_IDLE, 50000);//写(发送通道)空闲时间:50秒
//添加处理器
connector.setHandler(hellaServiceHandler);
log.info("开始连接");
connectThreadStart();
}
// 停止MINA服务
@PreDestroy
public void stop() {
try {
log.info("stopping the TCP Client");
connector.dispose();
} catch (Exception e) {
log.error("TCP Server stop error:",e);
}
}
private static boolean isConnectThreadRunning = false;
public static void connectThreadStart(){
if(isConnectThreadRunning){
return;
}
isConnectThreadRunning = true;
new Thread(new Runnable() {
public void run() {
for (;;) {
try {
Thread.sleep(5000);// 连接失败后,重连
if(!Strings.isNullOrEmpty(host)){
connector.setDefaultRemoteAddress(new InetSocketAddress(host, port));// 设置默认访问地址
ConnectFuture future = connector.connect();
// 等待连接创建成功
future.awaitUninterruptibly();
// 获取会话
IoSession ioSession = future.getSession();
if(ioSession.isConnected()){
theSession = ioSession;
log.info("连接["+ connector.getDefaultRemoteAddress().getHostName() +":"+ connector.getDefaultRemoteAddress().getPort()+"]成功");
break;
}else{
theSession = null;
}
}
} catch (Exception e) {
log.error("连接服务端" + host + ":" + port + "失败" + ",异常内容:" + e.getMessage(), e);
}
}
isConnectThreadRunning = false;
}
}).start();
}
public static ResultBean sendMsg(String msg){
if(theSession != null && theSession.isConnected()){
log.info("发送消息到Tcp Server:" + msg);
theSession.write("\02"+msg);
return ResultBean.newOkResult("");
}else{
return ResultBean.newErrorResult(-1,"no connecttion");
}
}
}
package com.neotel.smfcore.hella.tcp.command;
import java.util.Date;
/**
* Created by sunke on 2021/5/26.
*/
public class HellaCommand {
private String cmd;
private String eventId;
private Object data;
private Date date = new Date();
public String getCmd() {
return cmd;
}
public void setCmd(String cmd) {
this.cmd = cmd;
}
public String getEventId() {
return eventId;
}
public void setEventId(String eventId) {
this.eventId = eventId;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
public String toReqMsg(){
return getCmd() + ";" + getEventId() + ";" + getData().toString();
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
}
package com.neotel.smfcore.hella.tcp.command;
/**
* Created by sunke on 2021/5/26.
*/
public class HellaReqCommand extends HellaCommand {
/**
* 来源
*/
private String groupId;
/**
* 料仓Id;
*/
private String loginUser;
/**
* 检查物料条码
* <STX>checkMaterial;eventId;scannedCode<CR><LF>
* @param eventId
* @param scannedCode
* @return
*/
public static HellaReqCommand newCheckMaterialCmd(long eventId, String scannedCode){
HellaReqCommand command = new HellaReqCommand();
command.setCmd("checkMaterial");
command.setEventId(eventId + "");
command.setData(scannedCode);
return command;
}
public boolean isCheckMaterialReq(){
return getCmd().equalsIgnoreCase("checkMaterial");
}
/**
* 入库完成通知
* <STX>loadMaterial;eventId;scannedCode;shelfNumber;shelfSlot<CR><LF>
* @param eventId
* @param scannedCode
* @return
*/
public static HellaReqCommand newLoadMaterialCmd(long eventId, String scannedCode,String shelfNumber, String shelfSlot){
HellaReqCommand command = new HellaReqCommand();
command.setCmd("loadMaterial");
command.setEventId(eventId + "");
String dataStr = scannedCode + ";" + shelfNumber+";" + shelfSlot;
command.setData(dataStr);
return command;
}
public String getLoginUser() {
return loginUser;
}
public void setLoginUser(String loginUser) {
this.loginUser = loginUser;
}
public String getGroupId() {
return groupId;
}
public void setGroupId(String groupId) {
this.groupId = groupId;
}
}
package com.neotel.smfcore.hella.tcp.command;
/**
* Created by sunke on 2021/5/26.
*/
public class HellaRespCommand extends HellaCommand {
private String returnCode;
private String messageText;
public String getMessageText() {
return messageText;
}
public void setMessageText(String messageText) {
this.messageText = messageText;
}
public String getReturnCode() {
return returnCode;
}
public void setReturnCode(String returnCode) {
this.returnCode = returnCode;
}
public boolean isOkResp(){
return returnCode.equals("0");
}
public boolean isCheckMaterialResp(){
return getCmd().equalsIgnoreCase("checkMaterial");
}
public boolean isLoadMaterialResp(){
return getCmd().equalsIgnoreCase("loadMaterial");
}
public boolean isUnloadMaterialCmd(){
return getCmd().equalsIgnoreCase("unloadMaterial");
}
//<STX>orderMaterialExt;eventId;lineNumber;workorderNumber;currentWorkorderflag;reflowgroupNumber;numberofPartnumbers;partNumber1;numberofReels;…;partNumberN;numberofReels<CR><LF>
public boolean isOrderMaterialExtCmd(){
return getCmd().equalsIgnoreCase("orderMaterialExt");
}
//<STX>getInventory;eventId;shelfNumber<CR><LF>
public boolean isGetInventoryCmd(){
return getCmd().equalsIgnoreCase("getInventory");
}
}
......@@ -4,5 +4,4 @@ import com.neotel.smfcore.common.base.IBaseManager;
import com.neotel.smfcore.security.service.po.Group;
public interface IGroupManager extends IBaseManager<Group> {
Group findOneByGroupName(String groupName);
}
......@@ -16,6 +16,11 @@ public class GroupManagerImpl implements IGroupManager {
IGroupDao groupDao;
@Override
public Group getByGroupName(String groupName){
return groupDao.findOneByCondition(new String[]{"groupName"}, new String[]{groupName});
}
@Override
public Group get(String id) {
return groupDao.findOneById(id);
}
......
server:
port: 8800
hella:
host: 192.168.1.3
port: 9900
spring:
freemarker:
......
支持 Markdown 格式
你添加了 0 到此讨论。请谨慎行事。
Finish editing this message first!