Commit 3601d390 sunke

20393Hotayi接口

1 个父辈 0d9247e4
package com.neotel.smfcore.core.barcode.utils;
import com.google.common.base.Strings;
import com.neotel.smfcore.core.barcode.bean.BarcodeRule;
import com.neotel.smfcore.core.barcode.service.po.Barcode;
import lombok.extern.slf4j.Slf4j;
import java.util.HashMap;
import java.util.Map;
/**
* 根据条码和条码字段内容生成条码规则
* @author sunke
* @date 2023/3/3 1:36 PM
*/
@Slf4j
public class BarcodeRuleUtil {
/**
* 根据条码和条码字段内容生成条码规则
* @param codeStr
* @param fieldValueMap
* @return
*/
public static String getCodeRule(String codeStr, Map<String,String> fieldValueMap){
String codeRule = toSplitCodeRule(codeStr,fieldValueMap);
if(codeRule.isEmpty()){
codeRule = toWholeCodeRule(codeStr,fieldValueMap);
}
return codeRule;
}
/**
* 条码整体匹配生成解析规则
* @param codeStr 条码内容
* @param fieldValueMap 字段内容
* @return
*/
private static String toWholeCodeRule(String codeStr, Map<String,String> fieldValueMap){
String oldRule = "";
for (String fieldName : fieldValueMap.keySet()) {
String fieldValue = fieldValueMap.get(fieldName);
int index = codeStr.indexOf(fieldValue);
if(index >=0){
//包含字段值
int length = fieldValue.length();
if(length == codeStr.length()){
length = 0;
}
if(index == 0){
index = -1;
}
oldRule = oldRule+ fieldName + "["+index+":"+length+":-1]";
}else{
log.info("未从条码"+codeStr+"中匹配到"+fieldName+"的值"+ fieldValue+",生成规则失败");
oldRule = "";
break;
}
}
return oldRule;
}
/**
* 条码切割匹配生成解析规则
*/
private static String toSplitCodeRule(String codeStr, Map<String,String> fieldValueMap){
String separator = findSeparator(codeStr);
String[] codeArr = new String[]{codeStr};
if(!Strings.isNullOrEmpty(separator)){
codeArr = codeStr.split(separator);
}
String[] ruleArr = new String[codeArr.length];
for (String fieldName : fieldValueMap.keySet()) {
//所有字段都要匹配
boolean fieldMatched = false;
String fieldValue = fieldValueMap.get(fieldName);
if(fieldValue.isEmpty()){
continue;
}
for (int i = 0; i < codeArr.length; i++) {
String code = codeArr[i];
int index = code.indexOf(fieldValue);
if(index >=0){
//包含字段值,
String oldRule = ruleArr[i];
if(oldRule == null){
oldRule = "";
}
oldRule = oldRule+ fieldName;
if(!code.equals(fieldValue)){
oldRule = oldRule + "["+index+":"+fieldValue.length()+":-1]";
}
ruleArr[i] = oldRule;
fieldMatched = true;
break;
}
}
if(!fieldMatched){
log.info("未从条码"+codeStr+"中匹配到"+fieldName+"的值"+ fieldValue+",使用整体匹配");
return "";
}
}
String result = "";
for (int i = 0; i < ruleArr.length; i++) {
String ruleItem = ruleArr[i];
if(ruleItem == null){
ruleItem = "" + (i+1);
}
result = result + ruleItem;
if(i < ruleArr.length - 1){
result = result + separator;
}
}
return result;
}
/**
* 查找分割符(不是数字,不是字母)
*/
private static String findSeparator(String str){
//先找分割符,分割出来数组数量最多的放第一个
String trySeparator = "";
String result = "";
//找最多的字符
String[] tempArr = new String[]{};
for (int i = 0; i < str.length(); i++) {
char c = str.charAt(i);
if(!Character.isLetterOrDigit(c)){
//不是字母和数字才可以作为分割符
String separator = toRegexStr(c + "");
if(trySeparator.indexOf(c) == -1){
String[] ss = str.split(separator,-1);
if(ss.length > tempArr.length){
trySeparator = c + trySeparator;
result =separator;
tempArr = ss;
}else{
trySeparator = trySeparator + c;
}
};
}
}
return result;
}
/**
* 转义正则特殊字符 ($()*+.[]?\^{}
* @return
*/
private static String toRegexStr(String separator){
//转义正则特殊字符 ($()*+.[]?\^{}
return separator.replace("\\", "\\\\").replace("*", "\\*")
.replace("+", "\\+").replace("|", "\\|")
.replace("{", "\\{").replace("}", "\\}")
.replace("(", "\\(").replace(")", "\\)")
.replace("^", "\\^").replace("$", "\\$")
.replace("[", "\\[").replace("]", "\\]")
.replace("?", "\\?").replace(",", "\\,")
.replace(".", "\\.").replace("&", "\\&");
}
public static void main(String args[]) throws Exception{
String codeStr = "L00002019090199951797;E2019-09-01 0365;B8C.R2003.V81506072019090103000;R506072019102200356";
Map<String,String> filedMap = new HashMap<>();
filedMap.put("RI","R506072019102200356");
filedMap.put("PN","8C.R2003.V81");
filedMap.put("BATCH","L00002019090199951797");
filedMap.put("SP","50607");
filedMap.put("QTY","3000");
filedMap.put("PRODATEyyyy-MM-dd","2019-09-01");
filedMap.put("EXPD","0365");
String rule = getCodeRule(codeStr,filedMap);
System.out.println("====="+rule);
BarcodeRule br = BarcodeRule.newRule(rule);
Barcode b = br.toCodeBean(codeStr).getBarcode();
if(b != null){
System.out.println("PN:"+b.getPartNumber());
System.out.println("RI:"+b.getBarcode());
System.out.println("QTY:"+b.getAmount());
System.out.println("BATCH:"+b.getBatch());
System.out.println("MSL:"+b.getMsl());
System.out.println("PRODATE:"+b.getProduceDate());
System.out.println("EXPDATE:"+b.getExpireDate());
System.out.println("Supllier:"+b.getProvider());
System.out.println("Memo:"+b.getMemo());
System.out.println("MPN:"+b.getMpn());
}else{
System.out.println("解析失败");
log.info("解析失败");
}
}
}
package com.neotel.smfcore.custom.hotayi20393;
import com.neotel.smfcore.common.exception.ValidateException;
import com.neotel.smfcore.common.utils.DateUtil;
import com.neotel.smfcore.common.utils.HttpHelper;
import com.neotel.smfcore.common.utils.JsonUtil;
import com.neotel.smfcore.core.api.bean.ApiResult;
import com.neotel.smfcore.core.api.bean.CodeValidateParam;
import com.neotel.smfcore.core.api.listener.BaseSmfApiListener;
import com.neotel.smfcore.core.barcode.bean.BarcodeRule;
import com.neotel.smfcore.core.barcode.bean.CodeBean;
import com.neotel.smfcore.core.barcode.enums.COMPONENT_TYPE;
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.barcode.utils.CodeResolve;
import com.neotel.smfcore.core.order.service.manager.ILiteOrderItemManager;
import com.neotel.smfcore.core.order.service.po.LiteOrder;
import com.neotel.smfcore.core.order.service.po.LiteOrderItem;
import com.neotel.smfcore.core.system.service.po.DataLog;
import com.neotel.smfcore.custom.hotayi20393.bean.HotayiBean;
import lombok.extern.slf4j.Slf4j;
import org.apache.logging.log4j.util.Strings;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
@Service
@Slf4j
public class HotayiApi extends BaseSmfApiListener {
/**
* MachineID
*/
@Value("${hotayi.MachineID:}")
protected String machineID = "";
/**
* IPAddress
*/
@Value("${hotayi.IPAddress:}")
protected String iPAddress = "";
@Autowired
private ILiteOrderItemManager liteOrderItemManager;
@Autowired
private CodeResolve codeResolve;
@Autowired
private IComponentManager componentManager;
@Override
public boolean isForThisApi(String apiName) {
return apiName != null && apiName.equalsIgnoreCase("20393");
}
/**
* 入库判断发送M6,收到M5
*
* Solder Paste Status
* Direction: MES→Machine
* Fields
* PartNo ExpireDate
* SerialNo
* Type Range
* String Any Datetime Any
* String Any
* Optional Description
* No Solder Paste Part No No Solder Paste Expire
* Date Time
* Format: yyyy-mm-dd No Solder Paste ID
* Sample: (Require machine to check label format prefix)
* {
* “Info”: {
* “MachineID”: “00001”, “IPAddress”: “192.168.0.1”, “MessageNo”: “M7”
* },
* “Data”: {
* “PartNo”: “A005”,
* “ExpireDate”: “2022-01-01”,
* “SerialNo”: ”A005$$A” }
* }
* @param codeResolveUrl
* @param params
* @return
* @throws ValidateException
*/
@Override
public Barcode canPutInBeforeResolve(String codeResolveUrl, CodeValidateParam params) throws ValidateException {
try {
CodeBean codeBean = BarcodeRule.splitCodeAndSize(params.getCode());
String reelId = codeBean.getCodeStr();
Map<String, Object> paramMap = new HashMap<>();
paramMap.put("Barcode", reelId);
log.info(reelId + "入库验证M6,参数" + JsonUtil.toJsonStr(paramMap));
String result = HttpHelper.postJson(codeResolveUrl, paramMap);
log.info(reelId + "入库验证返回" + result);
HotayiBean hotayiBean = JsonUtil.toObj(result, HotayiBean.class);
String resultMsgNo = hotayiBean.getInfoItem("MessageNo");
if (resultMsgNo.equals("M90")) {
String errorCode = hotayiBean.getDataItem("ErrorCode");
String errorMessage = hotayiBean.getDataItem("ErrorMessage");
throw new ValidateException("mes.canputIn.ng","NG: ["+errorCode+"]"+errorMessage);
}else{
Barcode barcode = new Barcode();
String mesReelId = hotayiBean.getDataItem("SerialNo");
String pn = hotayiBean.getDataItem("PartNo");
String expireDateStr = hotayiBean.getDataItem("ExpireDate");
if (Strings.isNotBlank(mesReelId)) {
Barcode dbBarcode = barcodeManager.findByBarcode(mesReelId);
if(dbBarcode != null){
barcode = dbBarcode;
}
barcode.setBarcode(mesReelId);
}
barcode.setPlateSize(codeBean.getReelWidth());
barcode.setHeight(codeBean.getReelHeight());
if (Strings.isNotBlank(pn)) {
barcode.setPartNumber(pn);
}
if (Strings.isNotBlank(expireDateStr)) {
Date expireDate = DateUtil.toDate(expireDateStr, "yyyy-MM-dd");
barcode.setExpireDate(expireDate);
}
resolveComponent(barcode);
barcode = barcodeManager.saveBarcode(barcode);
return barcode;
}
} catch (Exception e) {
log.error("入库验证接口出错:" + e.getMessage());
throw new ValidateException("smfcore.mesApi.inCheck.error", "MES验证出错:" + e.getMessage());
}
}
@Override
public void inTaskStatusChange(String inNotifyUrl, DataLog task) {
String requestParams = "";
String responseInfo = "";
if (task.isFinished()) {
Map<String, Object> paramMap = new HashMap<>();
paramMap.put("reelId", task.getBarcode());
paramMap.put("location", task.getPosName());
paramMap.put("source", "SMF");
Barcode barcode = barcodeManager.findByBarcode(task.getBarcode());
String fullCode = "";
if (barcode != null) {
fullCode = barcode.getFullCode();
}
paramMap.put("fullCode", fullCode);
try {
requestParams = JsonUtil.toJsonStr(paramMap);
log.info(task.getBarcode() + "入库通知,参数" + requestParams);
responseInfo = HttpHelper.postJson(inNotifyUrl, paramMap);
log.info(task.getBarcode() + "入库通知返回" + responseInfo);
ApiResult apiResult = JsonUtil.toObj(responseInfo, ApiResult.class);
} catch (Exception e) {
log.error("入库通知接口出错:" + e.getMessage());
}
}
}
@Override
public void outTaskStatusChange(String outNotifyUrl, DataLog task) {
String requestParams = "";
String responseInfo = "";
if (task.isFinished()) {
Map<String, Object> paramMap = new HashMap<>();
paramMap.put("reelId", task.getBarcode());
paramMap.put("partNum", task.getPartNumber());
paramMap.put("qty", task.getNum() + "");
paramMap.put("boxNo", task.getCid());
paramMap.put("location", task.getPosName());
String hSerial = "";
String so = "";
String slotNum = "";
String feederInfo = "";
String sourceId = task.getSourceId();
if(Strings.isNotBlank(sourceId)){
LiteOrder liteOrder = liteOrderManager.get(task.getSourceId());
if(liteOrder != null){
hSerial = liteOrder.getOrderNo();
so = liteOrder.getSo();
}
String subSourceId = task.getSubSourceId();
LiteOrderItem orderItem = liteOrderItemManager.get(subSourceId);
if(orderItem != null){
slotNum = orderItem.getSlotNum() + "";
feederInfo = orderItem.getFeederInfo();
}
}
paramMap.put("hSerial", hSerial);
paramMap.put("so", so);
paramMap.put("slotNum", slotNum);
paramMap.put("feederInfo", feederInfo);
try {
requestParams = JsonUtil.toJsonStr(paramMap);
log.info(task.getBarcode() + "出库通知,参数" + requestParams);
responseInfo = HttpHelper.postJson(outNotifyUrl, paramMap);
log.info(task.getBarcode() + "出库通知返回" + responseInfo);
ApiResult apiResult = JsonUtil.toObj(responseInfo, ApiResult.class);
} catch (Exception e) {
log.error("出库通知接口出错:" + e.getMessage());
}
}
}
}
package com.neotel.smfcore.custom.hotayi20393;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.neotel.smfcore.common.bean.ResultBean;
import com.neotel.smfcore.common.utils.JsonUtil;
import com.neotel.smfcore.common.utils.StorageConstants;
import com.neotel.smfcore.core.barcode.enums.SOLDER_STATUS;
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.util.DataCache;
import com.neotel.smfcore.core.order.LiteOrderCache;
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.bean.UsageItem;
import com.neotel.smfcore.core.storage.service.dao.IStorageDao;
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.Storage;
import com.neotel.smfcore.core.storage.service.po.StoragePos;
import com.neotel.smfcore.core.system.util.DevicesStatusUtil;
import com.neotel.smfcore.custom.hotayi20393.bean.HotayiBean;
import com.neotel.smfcore.security.annotation.AnonymousAccess;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.*;
@Slf4j
@RestController
@RequestMapping("/rest/api/hotayi")
public class HotayiController {
@Autowired
protected ILiteOrderManager liteOrderManager;
@Autowired
protected LiteOrderCache liteOrderCache;
@Autowired
private DataCache dataCache;
@Autowired
private IStoragePosDao storagePosDao;
/**
* 收到M1返回M2
* M2 Machine Information
* Machine information send after connection establish Direction: MESMachine
* Fields
* Version MESMode
* Sample:
* {
* “Info”: {
* Type Range
* Optional Description
* String x.y No
* Bit 0 = Off No 1 = On
* Communication spec revision
* Hotayi MES mode is turned On / Off
*
* SpecID
* Int
* nnn
* No
* Communication Spec ID followed by this machine, default = 100, others refer to master list
* “MachineID”: “00001”, “IPAddress”: “192.168.0.1”, “MessageNo”: “M2”
* },
* “Data”: {
* “Version”: “1.6”,
* “MESMode”: 1,
* “SpecID”: 100 }
* }
*/
@RequestMapping("/m1")
@AnonymousAccess
public HotayiBean m1(@RequestBody HotayiBean hotayiBean) {
log.info("收到M1请求数据为:{}", JsonUtil.toJsonStr(hotayiBean));
hotayiBean.addInfo("MessageNo","M2");
Map<String,Object> resultData = new HashMap<>();
resultData.put("Version","1.6");
resultData.put("MESMode",1);
resultData.put("SpecID",100);
hotayiBean.setData(resultData);
return hotayiBean;
}
/**
* M4 Machine Status
* Status of the machine Direction: MESMachine
* Fields
* Type Range
* Optional Description
* No Numbers of Solder Paste currently in
* machine
* No Number of operations
* in queuing list
* SolderPasteCount Int QueueCount Int
* Sample 1:
* {
* “Info”: {
* “MachineID”: “00001”, “IPAddress”: “192.168.0.1”, “MessageNo”: “M4”
* },
* “Data”: {
* “SolderPasteCount”: 299, “QueueCount”: 0
* } }
* Sample 2:
* {
* “Info”: {
* “MachineID”: “00001”, “IPAddress”: “192.168.0.1”, “MessageNo”: “M4”
* },
* “Data”: {
* “SolderPasteCount”: 298, “QueueCount”:1
* } }
* @param hotayiBean
* @return
*/
@RequestMapping("/m3")
@AnonymousAccess
public HotayiBean m3(@RequestBody HotayiBean hotayiBean) {
log.info("收到M3请求数据为:{}", JsonUtil.toJsonStr(hotayiBean));
hotayiBean.addInfo("MessageNo","M4");
Map<String,Object> resultData = new HashMap<>();
int solderPasteCount = 0;
int queueCount = 0;
Collection<Storage> allStorage = dataCache.getAllStorage().values();
for (Storage storage : allStorage) {
if (!storage.isSolderPaste()) {
continue;
}
Criteria c = Criteria.where("storageId").is(storage.getId())
.and("enabled").is(true)
.and("barcode.solderStatus").nin(SOLDER_STATUS.NONE.name(),SOLDER_STATUS.UNDER_REFRIGERATION.name(),SOLDER_STATUS.RETREAT_STORAGE.name());
queueCount = storagePosDao.countByQuery(new Query(c));
c = Criteria.where("storageId").is(storage.getId())
.and("enabled").is(true).and("barcode").exists(true);//可用;
solderPasteCount = storagePosDao.countByQuery(new Query(c));
break;
}
resultData.put("SolderPasteCount",solderPasteCount);
resultData.put("QueueCount",queueCount);
hotayiBean.setData(resultData);
return hotayiBean;
}
}
package com.neotel.smfcore.custom.hotayi20393.bean;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.HashMap;
import java.util.Map;
/**
* @author sunke
* @date 2023/1/11 3:01 PM
*/
@Data
public class HotayiBean {
@JsonProperty("Info")
private Map<String,String> info = new HashMap<>();
@JsonProperty("Data")
private Map<String,Object> data = new HashMap<>();
public void addInfo(String key, String value){
info.put(key,value);
}
public void addData(String key, String value){
data.put(key, value);
}
public <T> T getDataItem(String key){
if(data != null){
Object o = data.get(key);
if(o != null){
return (T)o;
}
}
return null;
}
public String getInfoItem(String key){
if(info != null){
String o = info.get(key);
if(o != null){
return o;
}
}
return "";
}
}
支持 Markdown 格式
你添加了 0 到此讨论。请谨慎行事。
Finish editing this message first!