initialize
This commit is contained in:
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright (c) 2010 iTAC Software AG, Germany. All Rights Reserved.
|
||||
*
|
||||
* This software is protected by copyright. Under no circumstances may any part of this file in any form be copied,
|
||||
* printed, edited or otherwise distributed, be stored in a retrieval system, or be translated into another language
|
||||
* without the written permission of iTAC Software AG.
|
||||
*/
|
||||
|
||||
package com.itac.mes.datainterface.data;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import com.itac.panacim.Message.Body.Comps.Comp;
|
||||
|
||||
/**
|
||||
* @author frankp created 2011
|
||||
*/
|
||||
public class CurrentProduction {
|
||||
|
||||
private String station;
|
||||
private String product;
|
||||
private String layer;
|
||||
private Map<Integer, String> partTable;
|
||||
private Map<String, Comp> compTable;
|
||||
|
||||
/**
|
||||
* @param stationNumber
|
||||
* @param layer
|
||||
* @param name
|
||||
* @param partTable
|
||||
* @param compTable
|
||||
*/
|
||||
public void set(String stationNumber, String product, String layer, Map<Integer, String> partTable,
|
||||
Map<String, Comp> compTable) {
|
||||
this.station = stationNumber;
|
||||
this.product = product;
|
||||
this.layer = layer;
|
||||
this.partTable = partTable;
|
||||
this.compTable = compTable;
|
||||
}
|
||||
|
||||
public String getStation() {
|
||||
return station;
|
||||
}
|
||||
|
||||
public String getProduct() {
|
||||
return product;
|
||||
}
|
||||
|
||||
public String getLayer() {
|
||||
return layer;
|
||||
}
|
||||
|
||||
public Map<Integer, String> getPartTable() {
|
||||
return partTable;
|
||||
}
|
||||
|
||||
public Map<String, Comp> getCompTable() {
|
||||
return compTable;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,524 @@
|
||||
/*
|
||||
* Copyright (c) 2010 iTAC Software AG, Germany. All Rights Reserved.
|
||||
*
|
||||
* This software is protected by copyright. Under no circumstances may any part of this file in any form be copied,
|
||||
* printed, edited or otherwise distributed, be stored in a retrieval system, or be translated into another language
|
||||
* without the written permission of iTAC Software AG.
|
||||
*/
|
||||
package com.itac.mes.datainterface.data;
|
||||
|
||||
import static com.itac.mes.datainterface.data.smt.MessageLogger.MSG_LOGGER;
|
||||
import static com.itac.mes.datainterface.process.IProcessor.Code.SERVICE_NOT_AVAILABLE;
|
||||
import static com.itac.util.logging.LogLevel.DEBUG;
|
||||
import static com.itac.util.logging.LogLevel.ERROR;
|
||||
import static com.itac.util.logging.LogLevel.INFO;
|
||||
import static com.itac.util.logging.LogLevel.WARN;
|
||||
|
||||
import java.lang.reflect.UndeclaredThrowableException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.itac.mes.datainterface.annotations.AAutoHandler;
|
||||
import com.itac.mes.datainterface.annotations.ACondition;
|
||||
import com.itac.mes.datainterface.annotations.AInit;
|
||||
import com.itac.mes.datainterface.annotations.AInstantiationType;
|
||||
import com.itac.mes.datainterface.annotations.InstantiationType;
|
||||
import com.itac.mes.datainterface.data.panacim.IPanaCimMessageReceiver;
|
||||
import com.itac.mes.datainterface.data.panacim.MessageException;
|
||||
import com.itac.mes.datainterface.data.panacim.PanaCimActionCode;
|
||||
import com.itac.mes.datainterface.data.panacim.PanaCimHeaderResult;
|
||||
import com.itac.mes.datainterface.data.panacim.PanaCimMessage;
|
||||
import com.itac.mes.datainterface.data.panacim.ParseException;
|
||||
import com.itac.mes.datainterface.data.smt.BadmarkEvaluator;
|
||||
import com.itac.mes.datainterface.data.smt.BadmarkInfo;
|
||||
import com.itac.mes.datainterface.data.smt.HTMLLogger;
|
||||
import com.itac.mes.datainterface.data.smt.PanelState;
|
||||
import com.itac.mes.datainterface.data.smt.PlacementRecipeCheck;
|
||||
import com.itac.mes.datainterface.data.smt.PlacementRecipePatternType;
|
||||
import com.itac.mes.datainterface.data.smt.SmtConfiguration;
|
||||
import com.itac.mes.datainterface.factories.AConfigurableHandler;
|
||||
import com.itac.mes.datainterface.messaging.Condition;
|
||||
import com.itac.mes.datainterface.messaging.EventHandler;
|
||||
import com.itac.mes.datainterface.messaging.EventSourceInfo;
|
||||
import com.itac.mes.datainterface.parser.IParser.Code;
|
||||
import com.itac.mes.datainterface.parser.PanaCimParser;
|
||||
import com.itac.mes.datainterface.process.IProcessor;
|
||||
import com.itac.mes.imsapi.domain.container.Result_smtSerialNumberCheckIn;
|
||||
import com.itac.panacim.Message.Body;
|
||||
import com.itac.panacim.Message.Body.MatBlocks;
|
||||
import com.itac.panacim.Message.Body.MatBlocks.MatBlock;
|
||||
import com.itac.panacim.Message.Body.Material;
|
||||
import com.itac.panacim.Message.Body.Material.Detail;
|
||||
import com.itac.panacim.Message.Body.Pcb;
|
||||
import com.itac.panacim.Message.Body.Product;
|
||||
import com.itac.panacim.Message.Body.Result;
|
||||
import com.itac.panacim.Message.Body.WorkItems;
|
||||
import com.itac.panacim.Message.Body.WorkItems.WorkItem;
|
||||
import com.itac.util.constants.imsapi.ImsApiKey;
|
||||
import com.itac.util.logging.LogHandler;
|
||||
|
||||
/**
|
||||
* @author frankp created 2011
|
||||
*/
|
||||
@AInstantiationType(name = "panacim", type = InstantiationType.APPLICATION)
|
||||
public class PanaCimApplication extends AConfigurableHandler implements IPanaCimMessageReceiver, IPlacementRecipeChangeListener, IMachineDataUnitListReceiver {
|
||||
|
||||
private static final String ERROR_PROCESSING_UPLOAD_UNIT = "Error processing uploadUnit:\n";
|
||||
private static final String RESPONSE_MESSAGE = "\nResponse Message:\n";
|
||||
private static final String SERVER_NOT_AVAILABLE = "iTAC.MES.Suite server connection not available";
|
||||
private static final String LOGGER = PanaCimApplication.class.getSimpleName();
|
||||
private static final int PLACING = 0;
|
||||
private static final int NO_PLACING = 1;
|
||||
@AAutoHandler(InstantiationType.PARSER)
|
||||
|
||||
private PanaCimParser parser;
|
||||
@AAutoHandler(InstantiationType.PROCESSOR)
|
||||
private IProcessor processor;
|
||||
private boolean isPaused;
|
||||
@AAutoHandler(InstantiationType.TOOL)
|
||||
private PlacementRecipeChangeManager placementRecipeMgr;
|
||||
@AAutoHandler(InstantiationType.TOOL)
|
||||
protected Toolbox toolbox;
|
||||
@AAutoHandler(InstantiationType.TOOL)
|
||||
private EventHandler eventHandler;
|
||||
@AAutoHandler(InstantiationType.TOOL)
|
||||
private BadmarkEvaluator badmarkEvaluator;
|
||||
@AAutoHandler(InstantiationType.TOOL)
|
||||
private SmtConfiguration smtConfiguration;
|
||||
|
||||
@ACondition
|
||||
private static final Condition PANA_CIM_ERROR_CONDITION = new Condition("PanaCimError");
|
||||
|
||||
public PanaCimApplication() {
|
||||
super();
|
||||
}
|
||||
|
||||
@AInit
|
||||
public void atInit() {
|
||||
placementRecipeMgr.setPlacementRecipeChangeListener(this);
|
||||
}
|
||||
|
||||
// es geht eine Nachricht ein...
|
||||
// die Nachricht konnte zumindest in eine Klasse unmarshalled werden, d.H. strukturell ist der eingegangene Text OK
|
||||
//
|
||||
@Override
|
||||
public void setMessage(PanaCimMessage inMessage) {
|
||||
// die PanaCimMessage enthaelt an dieser Stelle lediglich den xmlMessageContent,
|
||||
// Message parsen...
|
||||
LogHandler.log(MSG_LOGGER, DEBUG, inMessage.getXmlRequestMessage());
|
||||
PanaCimDataUnit panaCimDataUnit = new PanaCimDataUnit();
|
||||
eventSourceInfo = new EventSourceInfo(null);
|
||||
parser.setEventSourceInfo(eventSourceInfo);
|
||||
Code parseCode = parser.parse(inMessage, panaCimDataUnit);
|
||||
|
||||
processor.setEventSourceInfo(eventSourceInfo);
|
||||
com.itac.mes.datainterface.process.IProcessor.Code processCode = com.itac.mes.datainterface.process.IProcessor.Code.NOT_SENT;
|
||||
|
||||
try {
|
||||
switch (parseCode) {
|
||||
case OK:// wenn jetzt das result-Object gesetzt ist, muessen diese Daten
|
||||
if (!isPaused) {
|
||||
processCode = processor.send(panaCimDataUnit);
|
||||
} else {
|
||||
processCode = SERVICE_NOT_AVAILABLE;
|
||||
}
|
||||
break;
|
||||
case PARSE_ERROR:// wenn mind eine Information aus den Quelldaten nicht verarbeitet werden kann
|
||||
case PREPARE_ERROR:// wenn auf die gelesenen Daten keine Mappings angewendet werden konnten
|
||||
PanaCimHeaderResult phr = new PanaCimHeaderResult();
|
||||
phr.errorCode = 1;
|
||||
if (eventSourceInfo.getException() != null) {
|
||||
phr.errorText = eventSourceInfo.getException().getMessage();
|
||||
} else {
|
||||
phr.errorText = parseCode.getCodeText();
|
||||
}
|
||||
phr.actionCode = PanaCimActionCode.STOP_PCB;
|
||||
processFaultReply(inMessage, phr);
|
||||
LogHandler.log(HTMLLogger.LOG_NAME, ERROR, phr.errorText);
|
||||
return;
|
||||
|
||||
case IGNORE: // , wenn die Daten aus fachlichen Gruenden nicht verarbeitet werden sollen
|
||||
case NOT_IMPLEMENTED:
|
||||
case NOT_INIT:
|
||||
case NOT_PARSED:
|
||||
case UNSUPPORTED_DATA_FORMAT:
|
||||
case STOP:
|
||||
LogHandler.log(LOGGER, INFO, panaCimDataUnit.resultText.toString());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} catch (UndeclaredThrowableException e) {
|
||||
processCode = com.itac.mes.datainterface.process.IProcessor.Code.NOT_SENT;
|
||||
LogHandler.log(LOGGER, ERROR, "Server not available:\n" + e.getMessage(), e);
|
||||
eventSourceInfo.setException(e);
|
||||
eventHandler.raise(PANA_CIM_ERROR_CONDITION, eventSourceInfo);
|
||||
|
||||
// geschrieben wurde
|
||||
PanaCimHeaderResult phr = new PanaCimHeaderResult();
|
||||
phr.errorCode = -99;
|
||||
phr.errorText = SERVER_NOT_AVAILABLE;
|
||||
phr.actionCode = PanaCimActionCode.STOP_PCB;
|
||||
try {
|
||||
processFaultReply(inMessage, phr);
|
||||
LogHandler.log(HTMLLogger.LOG_NAME, ERROR, phr.errorText);
|
||||
return;
|
||||
} catch (ParseException e1) {
|
||||
LogHandler.log(LOGGER, ERROR, "sending failed response not successful");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LogHandler.log(LOGGER, ERROR, ERROR_PROCESSING_UPLOAD_UNIT + e.getMessage(), e);
|
||||
LogHandler.log(HTMLLogger.LOG_NAME, ERROR, ERROR_PROCESSING_UPLOAD_UNIT + e.getMessage());
|
||||
eventSourceInfo.setException(e);
|
||||
eventHandler.raise(PANA_CIM_ERROR_CONDITION, eventSourceInfo);
|
||||
}
|
||||
|
||||
try {
|
||||
switch (processCode) {
|
||||
case SERVICE_NOT_AVAILABLE:
|
||||
LogHandler.log(LOGGER, ERROR, "Service not available:\n");
|
||||
eventHandler.raise(PANA_CIM_ERROR_CONDITION, eventSourceInfo);
|
||||
// geschrieben wurde
|
||||
PanaCimHeaderResult phr = new PanaCimHeaderResult();
|
||||
phr.errorCode = -99;
|
||||
phr.errorText = SERVER_NOT_AVAILABLE;
|
||||
phr.actionCode = PanaCimActionCode.STOP_PCB;
|
||||
try {
|
||||
processFaultReply(inMessage, phr);
|
||||
LogHandler.log(HTMLLogger.LOG_NAME, ERROR, phr.errorText);
|
||||
return;
|
||||
} catch (ParseException e1) {
|
||||
LogHandler.log(LOGGER, ERROR, "sending failed response not successful");
|
||||
}
|
||||
break;
|
||||
case NOT_SENT:
|
||||
phr = new PanaCimHeaderResult();
|
||||
phr.errorCode = -99;
|
||||
phr.errorText = SERVER_NOT_AVAILABLE;
|
||||
phr.actionCode = PanaCimActionCode.STOP_PCB;
|
||||
|
||||
break;
|
||||
case OK:
|
||||
case NO_UPLOAD_UNITS_TO_SEND:
|
||||
case DISCARD:
|
||||
case SKIPPED_OR_UNPROCESSED:
|
||||
case UNABLE_TO_PROCESS_RESULTS:
|
||||
case UNKNOWN_ERROR:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LogHandler.log(LOGGER, ERROR, ERROR_PROCESSING_UPLOAD_UNIT + e.getMessage(), e);
|
||||
eventSourceInfo.setException(e);
|
||||
eventHandler.raise(PANA_CIM_ERROR_CONDITION, eventSourceInfo);
|
||||
}
|
||||
|
||||
try {
|
||||
processReply(inMessage, panaCimDataUnit);
|
||||
} catch (ParseException e) {
|
||||
LogHandler.log(LOGGER, ERROR, "Error processing message reply:\n" + e.getMessage(), e);
|
||||
eventSourceInfo.setException(e);
|
||||
eventHandler.raise(PANA_CIM_ERROR_CONDITION, eventSourceInfo);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param inMessage
|
||||
* @param phr
|
||||
* @throws ParseException
|
||||
*/
|
||||
private void processFaultReply(PanaCimMessage inMessage, PanaCimHeaderResult phr) throws ParseException {
|
||||
// wenn das replyFlag gestzt ist reply zusammen bauen und zurueck senden...
|
||||
if (!inMessage.replyRequested()) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// es wird ein ResultObject gesetzt sein...
|
||||
inMessage.createResponseMessage();
|
||||
// leeren Header erzeugen
|
||||
Result result = new Result();
|
||||
result.setErrorCode(phr.errorCode);
|
||||
result.setActionCode(phr.actionCode);
|
||||
result.setErrorText(phr.errorText);
|
||||
inMessage.getOrCreateBody(inMessage.getResponseMessage()).setResult(result);
|
||||
} catch (MessageException e) {
|
||||
if (eventSourceInfo.getContent() != null) {
|
||||
eventSourceInfo.getContent().append(RESPONSE_MESSAGE).append(inMessage.getXmlResponseMessageString());
|
||||
}
|
||||
eventSourceInfo.setException(e);
|
||||
eventHandler.raise(PANA_CIM_ERROR_CONDITION, eventSourceInfo);
|
||||
LogHandler.log(LOGGER, ERROR, "Error setting response value:\n" + e.getMessage(), e);
|
||||
}
|
||||
if (eventSourceInfo.getContent() != null) {
|
||||
eventSourceInfo.getContent().append(RESPONSE_MESSAGE).append(inMessage.getXmlResponseMessageString());
|
||||
}
|
||||
try {
|
||||
inMessage.sendResponseMessage();
|
||||
} catch (Exception e) {
|
||||
LogHandler.log(LOGGER, ERROR, "Error sending response value:\n" + e.getMessage(), e);
|
||||
eventSourceInfo.setException(e);
|
||||
eventHandler.raise(PANA_CIM_ERROR_CONDITION, eventSourceInfo);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param inMessage
|
||||
* @param panaCimDataUnit
|
||||
* @throws ParseException
|
||||
*/
|
||||
protected void processReply(PanaCimMessage inMessage, PanaCimDataUnit panaCimDataUnit) throws ParseException {
|
||||
// wenn das replyFlag gestzt ist reply zusammen bauen und zurueck senden...
|
||||
if (!inMessage.replyRequested()) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
if (eventSourceInfo == null) {
|
||||
eventSourceInfo = new EventSourceInfo(inMessage);
|
||||
}
|
||||
// es wird ein ResultObject gesetzt sein...
|
||||
inMessage.createResponseMessage();
|
||||
// leeren Header erzeugen
|
||||
Result result = new Result();
|
||||
result.setErrorCode(0);
|
||||
result.setActionCode(PanaCimActionCode.DO_NOTHING);
|
||||
result.setErrorText("");
|
||||
inMessage.getOrCreateBody(inMessage.getResponseMessage()).setResult(result);
|
||||
|
||||
Object resultObject = null;
|
||||
if (panaCimDataUnit.processResultList != null && !panaCimDataUnit.processResultList.isEmpty()) {
|
||||
for (ProcessResult resultItem : panaCimDataUnit.processResultList) {
|
||||
resultObject = resultItem.getResultObject();
|
||||
|
||||
// erzeugen der Ergebnisse für das XML
|
||||
Body responseMessageBody = inMessage.getOrCreateBody(inMessage.getResponseMessage());
|
||||
|
||||
if (resultObject instanceof Result_smtSerialNumberCheckIn) {
|
||||
// Pcb Item duplizieren...
|
||||
UploadSmtSerialNumberCheckInUnit uploadUnit = (UploadSmtSerialNumberCheckInUnit) resultItem.getUploadUnitReference();
|
||||
Result_smtSerialNumberCheckIn checkinResult = (Result_smtSerialNumberCheckIn) resultObject;
|
||||
uploadUnit.setCheckInResult(checkinResult);
|
||||
|
||||
Pcb sourcePcb = inMessage.getBody().getPcb();
|
||||
Pcb pcb = new Pcb();
|
||||
pcb.setBarcode(sourcePcb.getBarcode());
|
||||
pcb.setScannerMountSide(sourcePcb.getScannerMountSide());
|
||||
pcb.setPcbSide(sourcePcb.getPcbSide());
|
||||
if (inMessage.getHeader().getMessageClass() == 501) {
|
||||
// Bestueckprogrammverwaltung seitens PanaCim
|
||||
pcb.setBarcode(sourcePcb.getBarcode());
|
||||
pcb.setSerialNo(sourcePcb.getSerialNo());
|
||||
pcb.setModelCode(sourcePcb.getModelCode());
|
||||
} else {
|
||||
// always set the calculated PlacementRecipe name into the return structure
|
||||
pcb.setModelCode(calculatePlacementRecipeName(uploadUnit));
|
||||
pcb.setSerialNo(sourcePcb.getSerialNo());
|
||||
}
|
||||
responseMessageBody.setPcb(pcb);
|
||||
// construct a avlid product item
|
||||
Product product = new Product();
|
||||
product.setName(uploadUnit.getSerialNoCheckUploadResultValue(ImsApiKey.PART_NUMBER));
|
||||
product.setSide(sourcePcb.getPcbSide());
|
||||
responseMessageBody.setProduct(product);
|
||||
String currentPlacementRecipe = inMessage.getBody().getPcb().getModelCode();
|
||||
int conveyorLane = inMessage.getHeader().getLocation().getLaneNo();
|
||||
|
||||
PlacementRecipeCheck placementRecipeCheck = smtConfiguration.getPlacementRecipeCheck();
|
||||
BadmarkInfo checkResult = badmarkEvaluator.evaluate(null, placementRecipeCheck, uploadUnit, checkinResult,
|
||||
currentPlacementRecipe, conveyorLane);
|
||||
// aus den Results die Workitems bauen
|
||||
if (checkResult.getPanelStates() != null) {
|
||||
WorkItems workItems = new WorkItems();
|
||||
responseMessageBody.setWorkItems(workItems);
|
||||
for (PanelState panelState : checkResult.getPanelStates()) {
|
||||
WorkItem workItem = new WorkItem();
|
||||
try {
|
||||
workItem.setPos(Integer.parseInt(panelState.getPosition()));
|
||||
} catch (Exception e) {
|
||||
LogHandler.log(LOGGER, WARN, "panelState.position {0} has an invalid (non-numerical) value",
|
||||
panelState.getPosition());
|
||||
}
|
||||
if (panelState.isPlace()) {
|
||||
workItem.setPlace(PLACING);
|
||||
} else {
|
||||
workItem.setPlace(NO_PLACING);
|
||||
}
|
||||
workItems.getWorkItem().add(workItem);
|
||||
}
|
||||
responseMessageBody.getWorkItems().getWorkItem();
|
||||
}
|
||||
|
||||
LogHandler.log(LOGGER, INFO, checkResult.toString());
|
||||
if (checkResult.isAcceptBoard()) {
|
||||
LogHandler.log(LOGGER, INFO, "accept board " + sourcePcb.getBarcode());
|
||||
// no problem,
|
||||
// allow this board to enter, because all panels are pass or scrap, or line is in pass through mode
|
||||
result.setErrorCode(0);
|
||||
result.setErrorText("");
|
||||
result.setActionCode(PanaCimActionCode.DO_NOTHING);
|
||||
} else {
|
||||
LogHandler.log(LOGGER, INFO, "deny board " + sourcePcb.getBarcode());
|
||||
result.setErrorCode(1);
|
||||
result.setErrorText(checkResult.getReason());
|
||||
result.setActionCode(PanaCimActionCode.STOP_PCB);
|
||||
}
|
||||
if (inMessage.getHeader().getMessageClass() == 501 && !result.getErrorText().isEmpty()) {
|
||||
result.setActionCode(PanaCimActionCode.DISPLAY_MESSAGE);
|
||||
}
|
||||
}
|
||||
if (resultObject instanceof PanaCimCheckMaterialResult) {
|
||||
// Pcb Item duplizieren...
|
||||
PanaCimCheckMaterialResult pcmr = (PanaCimCheckMaterialResult) resultObject;
|
||||
if (panaCimDataUnit.getMessageClass() == 530) {
|
||||
// checks ausführen
|
||||
if (pcmr.materialBinData != null && pcmr.errorText != null && !pcmr.errorText.isEmpty()) {
|
||||
MatBlock matBlock = new MatBlock();
|
||||
MatBlocks matBlocks = new MatBlocks();
|
||||
matBlock.setMaterialID(pcmr.materialBinData[0].getMaterialBinNr());
|
||||
matBlock.setReasonID(pcmr.errorCode);
|
||||
matBlock.setReasonText(pcmr.errorText);
|
||||
matBlocks.getMatBlock().add(matBlock);
|
||||
responseMessageBody.setMatBlocks(matBlocks);
|
||||
// wenn das so aufgetreten ist muss der Header Result folgendermassen gesetzt werden:
|
||||
result.setErrorCode(0);
|
||||
result.setErrorText("MES detected a warning");
|
||||
result.setActionCode(PanaCimActionCode.WARNING);
|
||||
}
|
||||
} else if (panaCimDataUnit.getMessageClass() == 520) {
|
||||
if (pcmr.materialBinData != null && pcmr.errorText != null && !pcmr.errorText.isEmpty()) {
|
||||
MatBlocks matBlocks = new MatBlocks();
|
||||
MatBlock matBlock = new MatBlock();
|
||||
matBlock.setMaterialID(inMessage.getRequestMessage().getBody().getMaterial().get(0).getId());
|
||||
matBlock.setReasonID(pcmr.errorCode);
|
||||
matBlock.setReasonText(pcmr.errorText);
|
||||
matBlocks.getMatBlock().add(matBlock);
|
||||
responseMessageBody.setMatBlocks(matBlocks);
|
||||
|
||||
result.setErrorCode(0);
|
||||
result.setErrorText("MES detected a warning");
|
||||
result.setActionCode(PanaCimActionCode.STOP_PCB);
|
||||
}
|
||||
} else {
|
||||
// return a single material block or a materials list block dependeing on the incoming message
|
||||
if (pcmr.errorCode == 0 && pcmr.materialBinData != null) {
|
||||
// response-OK
|
||||
for (SmtContainerData container : pcmr.materialBinData) {
|
||||
Material material = new Material();
|
||||
material.setId(container.getMaterialBinNr());
|
||||
material.setState(pcmr.panaCimState);
|
||||
Detail detail = new Detail();
|
||||
detail.setPart(container.getProduct());
|
||||
detail.setQty((int) container.getQuantity());
|
||||
detail.setLot(container.getChargeNo());
|
||||
detail.setVendor(container.getSupplierName());
|
||||
detail.setUserdata(container.getClassification());
|
||||
material.setDetail(detail);
|
||||
responseMessageBody.getMaterial().add(material);
|
||||
}
|
||||
} else {
|
||||
// Fehlerhafte verarbeitung des Gebindes..
|
||||
Material material = new Material();
|
||||
material.setId(pcmr.materialId);
|
||||
// je nach Ergebnis der Abfrage den Status setzen...
|
||||
material.setState(pcmr.panaCimState);
|
||||
responseMessageBody.getMaterial().add(material);
|
||||
}
|
||||
}
|
||||
}
|
||||
// zum Schluss noch den Header Ressult setzen...
|
||||
if (resultObject instanceof PanaCimHeaderResult) {
|
||||
// Header nur dann ueberschreiben, wenn die Action Do_NOTHING ist, also noch keine spezifische Aktion
|
||||
// geschrieben wurde
|
||||
PanaCimHeaderResult phr = (PanaCimHeaderResult) resultObject;
|
||||
if (result.getActionCode() == PanaCimActionCode.DO_NOTHING) {
|
||||
result.setErrorCode(phr.errorCode);
|
||||
result.setErrorText(phr.errorText);
|
||||
result.setActionCode(phr.actionCode);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (MessageException e) {
|
||||
if (eventSourceInfo.getContent() != null) {
|
||||
eventSourceInfo.getContent().append(RESPONSE_MESSAGE).append(inMessage.getXmlResponseMessageString());
|
||||
}
|
||||
eventSourceInfo.setException(e);
|
||||
eventHandler.raise(PANA_CIM_ERROR_CONDITION, eventSourceInfo);
|
||||
LogHandler.log(LOGGER, ERROR, "Error setting response value:\n" + e.getMessage(), e);
|
||||
}
|
||||
if (eventSourceInfo.getContent() != null) {
|
||||
eventSourceInfo.getContent().append(RESPONSE_MESSAGE).append(inMessage.getXmlResponseMessageString());
|
||||
}
|
||||
try {
|
||||
inMessage.sendResponseMessage();
|
||||
} catch (Exception e) {
|
||||
LogHandler.log(LOGGER, ERROR, "Error sending response value:\n" + e.getMessage(), e);
|
||||
eventSourceInfo.setException(e);
|
||||
eventHandler.raise(PANA_CIM_ERROR_CONDITION, eventSourceInfo);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* construct a placementRecipeName out of the available values from the PlacementRecipeCheck
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
protected String calculatePlacementRecipeName(ISmtSerialNumberCheckIn uploadUnitRef) {
|
||||
List<String> valueList = new ArrayList<String>();
|
||||
for (PlacementRecipePatternType item : PlacementRecipePatternType.values()) {
|
||||
String sKeyValue = uploadUnitRef.getSerialNoCheckUploadResultValue(item.getImsApiKey());
|
||||
// Sonderfall Layer: hier muss die mit textMapping abgebildete Lage benutzt werden
|
||||
if (item.getImsApiKey() == ImsApiKey.WORKSTEP_AVO) {
|
||||
sKeyValue = uploadUnitRef.getSerialNoCheckUploadResultValue(ImsApiKey.PROCESS_LAYER);
|
||||
if (toolbox.getTextMap().containsKey(sKeyValue)) {
|
||||
sKeyValue = toolbox.getTextMap().get(sKeyValue);
|
||||
}
|
||||
}
|
||||
LogHandler.log(LOGGER, INFO, item.getImsApiKey() + ":" + sKeyValue);
|
||||
valueList.add(sKeyValue);
|
||||
}
|
||||
return uploadUnitRef.getPlacementRecipeCheck().getPlacementRecipeGeneratePattern().get(valueList.toArray());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param parser
|
||||
*/
|
||||
public void setParser(PanaCimParser parser) {
|
||||
this.parser = parser;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param processor
|
||||
*/
|
||||
public void setProcessor(IProcessor processor) {
|
||||
this.processor = processor;
|
||||
}
|
||||
|
||||
public void setPaused(boolean b) {
|
||||
isPaused = b;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean doPlacementRecipeChange(String programName, ISmtSerialNumberCheckIn uploadUnitRef, int conveyor) {
|
||||
uploadUnitRef.setProgramName(programName);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.itac.mes.datainterface.data.IMachineDataUnitListReceiver#put(java.util.List)
|
||||
*/
|
||||
@Override
|
||||
public void put(List<MachineDataUnit2> machineDataUnitList) {
|
||||
UploadMachineData2Unit uploadMachineData2Unit = new UploadMachineData2Unit();
|
||||
uploadMachineData2Unit.set(machineDataUnitList);
|
||||
try {
|
||||
PanaCimDataUnit panacimDataUnit = new PanaCimDataUnit();
|
||||
panacimDataUnit.uploadUnitList.add(uploadMachineData2Unit);
|
||||
processor.send(panacimDataUnit);
|
||||
} catch (Exception e) {
|
||||
LogHandler.log(LOGGER, ERROR, "failed to process machineDataUnits");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright (c) 2010 iTAC Software AG, Germany. All Rights Reserved.
|
||||
*
|
||||
* This software is protected by copyright. Under no circumstances may any part of this file in any form be copied,
|
||||
* printed, edited or otherwise distributed, be stored in a retrieval system, or be translated into another language
|
||||
* without the written permission of iTAC Software AG.
|
||||
*/
|
||||
|
||||
package com.itac.mes.datainterface.data;
|
||||
|
||||
import com.itac.mes.datainterface.data.panacim.PanaCimHeaderResult;
|
||||
|
||||
/**
|
||||
* @author frankp created 2011
|
||||
*/
|
||||
public class PanaCimCheckMaterialResult extends PanaCimHeaderResult {
|
||||
|
||||
// Ergebnis der API getMaterialBinData, darf aber auch null sein...
|
||||
public SmtContainerData[] materialBinData;
|
||||
// see Doku Kapitel 4.3.3 MaterialSetupRequest.
|
||||
// panaCimState muss den status enthalten, der
|
||||
public int panaCimState = 1;
|
||||
// MaterialId der Abfrage, wie sie von PanaCim kommt, entspricht der MaterialBinNo
|
||||
public String materialId = "???";
|
||||
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (c) 2010 iTAC Software AG, Germany. All Rights Reserved.
|
||||
*
|
||||
* This software is protected by copyright. Under no circumstances may any part of this file in any form be copied,
|
||||
* printed, edited or otherwise distributed, be stored in a retrieval system, or be translated into another language
|
||||
* without the written permission of iTAC Software AG.
|
||||
*/
|
||||
package com.itac.mes.datainterface.data;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* @author frankp created 2010
|
||||
*/
|
||||
public class PanaCimDataUnit extends BasicDataUnit {
|
||||
|
||||
// detailiierter Ergebnistext
|
||||
public StringBuffer resultText = new StringBuffer();
|
||||
private int messageClass;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public PanaCimDataUnit() {
|
||||
super();
|
||||
uploadUnitList = new ArrayList<BasicUploadUnit>();
|
||||
processResultList = new ArrayList<ProcessResult>();
|
||||
}
|
||||
|
||||
public void setMessageClass(int messageClass) {
|
||||
this.messageClass = messageClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
public int getMessageClass() {
|
||||
return messageClass;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright (c) 2010 iTAC Software AG, Germany. All Rights Reserved.
|
||||
*
|
||||
* This software is protected by copyright. Under no circumstances may any part of this file in any form be copied,
|
||||
* printed, edited or otherwise distributed, be stored in a retrieval system, or be translated into another language
|
||||
* without the written permission of iTAC Software AG.
|
||||
*/
|
||||
package com.itac.mes.datainterface.data;
|
||||
|
||||
/**
|
||||
* @author frankp created 2011
|
||||
*/
|
||||
public class UploadPanaCimCheckMaterialUnit extends UploadSmtCheckMaterialBinUnit {
|
||||
|
||||
@Override
|
||||
public String[] getImsApiValues() {
|
||||
// fuer alle Gebinde jetzt die qtyUpdate und CreateContainer eintragen, erst danach die getimsapi aufrufen...
|
||||
for (SmtContainerData item : getSmtCheckContainerData()) {
|
||||
item.setQuantityUpdate(false);
|
||||
item.setSetupFlag(0);
|
||||
}
|
||||
return super.getImsApiValues();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright (c) 2010 iTAC Software AG, Germany. All Rights Reserved.
|
||||
*
|
||||
* This software is protected by copyright. Under no circumstances may any part of this file in any form be copied,
|
||||
* printed, edited or otherwise distributed, be stored in a retrieval system, or be translated into another language
|
||||
* without the written permission of iTAC Software AG.
|
||||
*/
|
||||
|
||||
package com.itac.mes.datainterface.data.panacim;
|
||||
|
||||
/**
|
||||
* @author frankp created 2011
|
||||
*/
|
||||
public interface IPanaCimClientMessageReceiver {
|
||||
|
||||
public void setMessage(PanaCimClientMessage message);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright (c) 2010 iTAC Software AG, Germany. All Rights Reserved.
|
||||
*
|
||||
* This software is protected by copyright. Under no circumstances may any part of this file in any form be copied,
|
||||
* printed, edited or otherwise distributed, be stored in a retrieval system, or be translated into another language
|
||||
* without the written permission of iTAC Software AG.
|
||||
*/
|
||||
|
||||
package com.itac.mes.datainterface.data.panacim;
|
||||
|
||||
/**
|
||||
* @author frankp created 2011
|
||||
*/
|
||||
public interface IPanaCimMessageReceiver {
|
||||
|
||||
public void setMessage(PanaCimMessage message) throws ParseException;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright (c) 2010 iTAC Software AG, Germany. All Rights Reserved.
|
||||
*
|
||||
* This software is protected by copyright. Under no circumstances may any part of this file in any form be copied,
|
||||
* printed, edited or otherwise distributed, be stored in a retrieval system, or be translated into another language
|
||||
* without the written permission of iTAC Software AG.
|
||||
*/
|
||||
|
||||
package com.itac.mes.datainterface.data.panacim;
|
||||
|
||||
/**
|
||||
* @author frankp created 2011
|
||||
*/
|
||||
public class MessageException extends Exception {
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = -4308459134920924735L;
|
||||
|
||||
/**
|
||||
* @param string
|
||||
*/
|
||||
public MessageException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,466 @@
|
||||
/*
|
||||
* Copyright (c) 2010 iTAC Software AG, Germany. All Rights Reserved.
|
||||
*
|
||||
* This software is protected by copyright. Under no circumstances may any part of this file in any form be copied,
|
||||
* printed, edited or otherwise distributed, be stored in a retrieval system, or be translated into another language
|
||||
* without the written permission of iTAC Software AG.
|
||||
*/
|
||||
package com.itac.mes.datainterface.data.panacim;
|
||||
|
||||
import com.itac.mes.datainterface.data.smt.HTMLLogger;
|
||||
import com.itac.panacim.Message.Body;
|
||||
import com.itac.panacim.Message.Body.Components;
|
||||
import com.itac.panacim.Message.Body.Comps;
|
||||
import com.itac.panacim.Message.Body.Comps.Comp;
|
||||
import com.itac.panacim.Message.Body.MachineEvent;
|
||||
import com.itac.panacim.Message.Body.MachineStatus;
|
||||
import com.itac.panacim.Message.Body.Material;
|
||||
import com.itac.panacim.Message.Body.Materials;
|
||||
import com.itac.panacim.Message.Body.Operation;
|
||||
import com.itac.panacim.Message.Body.Panel;
|
||||
import com.itac.panacim.Message.Body.Parts.Part;
|
||||
import com.itac.panacim.Message.Body.Pcb;
|
||||
import com.itac.panacim.Message.Body.Position;
|
||||
import com.itac.panacim.Message.Body.PrdData;
|
||||
import com.itac.panacim.Message.Body.PrdData.Data;
|
||||
import com.itac.panacim.Message.Body.Product;
|
||||
import com.itac.panacim.Message.Body.Timestamp;
|
||||
import com.itac.util.logging.LogHandler;
|
||||
import com.itac.util.logging.LogLevel;
|
||||
|
||||
/**
|
||||
* @author frankp created 2011
|
||||
*/
|
||||
public class MessageVerifier {
|
||||
|
||||
private static final String PANEL = "panel";
|
||||
private static final String MACHINE_EVENT = "machineEvent";
|
||||
private static final String PRODUCT = "product";
|
||||
private static final String COMPS = "comps";
|
||||
private static final String MACHINE_STATUS = "machineStatus";
|
||||
private static final String MATERIALS = "materials";
|
||||
private static final String POSITION = "position";
|
||||
private static final String OPERATION = "operation";
|
||||
private static final String TIMESTAMP = "timestamp";
|
||||
private static final String MATERIAL = "material";
|
||||
|
||||
/**
|
||||
* @param message
|
||||
* @param string
|
||||
* @param string2
|
||||
* @return
|
||||
*/
|
||||
private String noTagInTag(PanaCimMessage message, String string, String string2) {
|
||||
return message.getLogHeader() + "no tag <" + string + "> found in tag <" + string2 + ">\n";
|
||||
}
|
||||
|
||||
private String checkAttribute(PanaCimMessage message, String attributeName, String tagName, Object value) {
|
||||
if (value == null) {
|
||||
return message.getLogHeader() + "attribute " + attributeName + " not found in tag <" + tagName + ">\n";
|
||||
}
|
||||
if (value instanceof String && ((String) value).isEmpty()) {
|
||||
return message.getLogHeader() + "value for attribute " + attributeName + " in tag <" + tagName + "> is empty\n";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
private String checkAttributeAllowEmpty(PanaCimMessage message, String attributeName, String tagName, Object value) {
|
||||
if (value == null) {
|
||||
return message.getLogHeader() + "attribute " + attributeName + " not found in tag <" + tagName + ">\n";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* @param message
|
||||
* @param i
|
||||
*/
|
||||
private void startVerify(PanaCimMessage message, int messageClass) {
|
||||
LogHandler.log(getClass().getSimpleName(), LogLevel.TRACE, message.getLogHeader() + "start verifying message class "
|
||||
+ messageClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param message
|
||||
* @param i
|
||||
*/
|
||||
private void endVerify(PanaCimMessage message, int messageClass) {
|
||||
LogHandler.log(getClass().getSimpleName(), LogLevel.TRACE, message.getLogHeader() + "message class " + messageClass
|
||||
+ " successfully verified" + messageClass);
|
||||
}
|
||||
|
||||
public void verifyClass500Message(PanaCimMessage message) throws ParseException {
|
||||
startVerify(message, 500);
|
||||
StringBuilder plausiResult = new StringBuilder();
|
||||
Pcb pcb = message.getBody().getPcb(); // exception, wenn es keinen Tag pcb mit einem Element gibt
|
||||
plausiResult.append(checkAttribute(message, "barcode", "pcb", pcb.getBarcode()));
|
||||
plausiResult.append(checkAttributeAllowEmpty(message, "serialNo", "pcb", pcb.getSerialNo()));
|
||||
plausiResult.append(checkAttribute(message, "pcbSide", "pcb", pcb.getPcbSide()));
|
||||
|
||||
if (plausiResult.length() != 0) {
|
||||
LogHandler.log(getClass().getSimpleName(), LogLevel.ERROR, plausiResult.toString());
|
||||
LogHandler.log(HTMLLogger.LOG_NAME, LogLevel.ERROR, plausiResult.toString());
|
||||
throw new ParseException(plausiResult.toString());
|
||||
}
|
||||
endVerify(message, 500);
|
||||
}
|
||||
|
||||
public void verifyClass501Message(PanaCimMessage message) throws ParseException {
|
||||
startVerify(message, 501);
|
||||
StringBuilder plausiResult = new StringBuilder();
|
||||
Pcb pcb = message.getBody().getPcb(); // exception, wenn es keinen Tag pcb mit einem Element gibt
|
||||
plausiResult.append(checkAttribute(message, "barcode", "pcb", pcb.getBarcode()));
|
||||
plausiResult.append(checkAttributeAllowEmpty(message, "serialNo", "pcb", pcb.getSerialNo()));
|
||||
plausiResult.append(checkAttribute(message, "pcbSide", "pcb", pcb.getPcbSide()));
|
||||
|
||||
if (plausiResult.length() != 0) {
|
||||
LogHandler.log(getClass().getSimpleName(), LogLevel.ERROR, plausiResult.toString());
|
||||
LogHandler.log(HTMLLogger.LOG_NAME, LogLevel.ERROR, plausiResult.toString());
|
||||
throw new ParseException(plausiResult.toString());
|
||||
}
|
||||
endVerify(message, 501);
|
||||
}
|
||||
|
||||
public void verifyClass510Message(PanaCimMessage message) throws ParseException {
|
||||
startVerify(message, 510);
|
||||
StringBuilder plausiResult = new StringBuilder();
|
||||
Body body = message.getBody(); // exception, wenn es keinen body gibt.
|
||||
|
||||
if (body.getMaterial().isEmpty()) {
|
||||
plausiResult.append(noTagInTag(message, MATERIAL, "body"));
|
||||
} else {
|
||||
Material material = body.getMaterial().get(0);
|
||||
plausiResult.append(checkAttribute(message, "id", MATERIAL, material.getId()));
|
||||
}
|
||||
|
||||
if (plausiResult.length() != 0) {
|
||||
LogHandler.log(getClass().getSimpleName(), LogLevel.ERROR, plausiResult.toString());
|
||||
LogHandler.log(HTMLLogger.LOG_NAME, LogLevel.ERROR, plausiResult.toString());
|
||||
throw new ParseException(plausiResult.toString());
|
||||
}
|
||||
endVerify(message, 510);
|
||||
}
|
||||
|
||||
public void verifyClass520Message(PanaCimMessage message) throws ParseException {
|
||||
startVerify(message, 520);
|
||||
StringBuilder plausiResult = new StringBuilder();
|
||||
Body body = message.getBody(); // exception, wenn es keinen body gibt.
|
||||
if (body.getMaterial().isEmpty()) {
|
||||
plausiResult.append(noTagInTag(message, MATERIAL, "body"));
|
||||
} else {
|
||||
Material material = body.getMaterial().get(0);
|
||||
plausiResult.append(checkAttribute(message, "id", MATERIAL, material.getId()));
|
||||
plausiResult.append(checkAttribute(message, "part", MATERIAL, material.getPart()));
|
||||
plausiResult.append(checkAttribute(message, "qty", MATERIAL, material.getQty()));
|
||||
plausiResult.append(checkAttributeAllowEmpty(message, "lot", MATERIAL, material.getLot()));
|
||||
plausiResult.append(checkAttributeAllowEmpty(message, "vendor", MATERIAL, material.getVendor()));
|
||||
plausiResult.append(checkAttributeAllowEmpty(message, "userdata", MATERIAL, material.getUserdata()));
|
||||
}
|
||||
if (body.getOperation() == null) {
|
||||
plausiResult.append(noTagInTag(message, OPERATION, "body"));
|
||||
} else {
|
||||
plausiResult.append(checkAttribute(message, "type", OPERATION, body.getOperation().getType()));
|
||||
// plausiResult.append(checkAttribute(message, "operator", "operation",
|
||||
plausiResult.append(checkAttribute(message, TIMESTAMP, OPERATION, body.getOperation().getTimestamp()));
|
||||
}
|
||||
if (body.getPosition() == null) {
|
||||
plausiResult.append(noTagInTag(message, POSITION, "body"));
|
||||
} else {
|
||||
Position position = body.getPosition();
|
||||
plausiResult.append(checkAttribute(message, "p1", POSITION, position.getP1()));
|
||||
plausiResult.append(checkAttribute(message, "p2", POSITION, position.getP2()));
|
||||
plausiResult.append(checkAttribute(message, "p3", POSITION, position.getP3()));
|
||||
plausiResult.append(checkAttribute(message, "p3", POSITION, position.getP4()));
|
||||
}
|
||||
|
||||
if (plausiResult.length() != 0) {
|
||||
LogHandler.log(getClass().getSimpleName(), LogLevel.ERROR, plausiResult.toString());
|
||||
LogHandler.log(HTMLLogger.LOG_NAME, LogLevel.ERROR, plausiResult.toString());
|
||||
throw new ParseException(plausiResult.toString());
|
||||
}
|
||||
endVerify(message, 520);
|
||||
}
|
||||
|
||||
public void verifyClass530Message(PanaCimMessage message) throws ParseException {
|
||||
startVerify(message, 530);
|
||||
StringBuilder plausiResult = new StringBuilder();
|
||||
Body body = message.getBody(); // exception, wenn es keinen body gibt.
|
||||
if (body.getTimestamp() == null) {
|
||||
plausiResult.append(noTagInTag(message, TIMESTAMP, "body"));
|
||||
} else {
|
||||
Timestamp timestamp = body.getTimestamp();
|
||||
plausiResult.append(checkAttribute(message, "value", TIMESTAMP, timestamp.getValue()));
|
||||
|
||||
}
|
||||
|
||||
if (body.getMaterials() == null) {
|
||||
plausiResult.append(noTagInTag(message, MATERIALS, "body"));
|
||||
} else {
|
||||
Materials materials = body.getMaterials();
|
||||
if (materials.getMaterial().isEmpty()) {
|
||||
plausiResult.append(noTagInTag(message, MATERIAL, MATERIALS));
|
||||
} else {
|
||||
for (com.itac.panacim.Message.Body.Materials.Material material : materials.getMaterial()) {
|
||||
plausiResult.append(checkAttribute(message, "id", MATERIAL, material.getId()));
|
||||
plausiResult.append(checkAttributeAllowEmpty(message, "part", MATERIAL, material.getPart()));
|
||||
plausiResult.append(checkAttributeAllowEmpty(message, "p1", MATERIAL, material.getP1()));
|
||||
plausiResult.append(checkAttributeAllowEmpty(message, "p2", MATERIAL, material.getP2()));
|
||||
plausiResult.append(checkAttributeAllowEmpty(message, "p3", MATERIAL, material.getP3()));
|
||||
plausiResult.append(checkAttributeAllowEmpty(message, "p4", MATERIAL, material.getP4()));
|
||||
plausiResult.append(checkAttribute(message, "qty", MATERIAL, material.getQty()));
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (plausiResult.length() != 0) {
|
||||
LogHandler.log(getClass().getSimpleName(), LogLevel.ERROR, plausiResult.toString());
|
||||
LogHandler.log(HTMLLogger.LOG_NAME, LogLevel.ERROR, plausiResult.toString());
|
||||
throw new ParseException(plausiResult.toString());
|
||||
}
|
||||
endVerify(message, 530);
|
||||
}
|
||||
|
||||
public void verifyClass540Message(PanaCimMessage message) throws ParseException {
|
||||
startVerify(message, 540);
|
||||
StringBuilder plausiResult = new StringBuilder();
|
||||
Body body = message.getBody(); // exception, wenn es keinen body gibt.
|
||||
if (body.getMachineStatus() == null) {
|
||||
plausiResult.append(noTagInTag(message, MACHINE_STATUS, "body"));
|
||||
} else {
|
||||
MachineStatus machineStatus = body.getMachineStatus();
|
||||
plausiResult.append(checkAttribute(message, "id", MACHINE_STATUS, machineStatus.getId()));
|
||||
plausiResult.append(checkAttribute(message, "text", MACHINE_STATUS, machineStatus.getText()));
|
||||
plausiResult.append(checkAttribute(message, TIMESTAMP, MACHINE_STATUS, machineStatus.getTimestamp()));
|
||||
|
||||
}
|
||||
|
||||
if (plausiResult.length() != 0) {
|
||||
LogHandler.log(getClass().getSimpleName(), LogLevel.ERROR, plausiResult.toString());
|
||||
LogHandler.log(HTMLLogger.LOG_NAME, LogLevel.ERROR, plausiResult.toString());
|
||||
throw new ParseException(plausiResult.toString());
|
||||
}
|
||||
endVerify(message, 540);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param message
|
||||
* @return
|
||||
* @throws ParseException
|
||||
*/
|
||||
public void verifyClass550Message(PanaCimMessage message) throws ParseException {
|
||||
startVerify(message, 550);
|
||||
StringBuilder plausiResult = new StringBuilder();
|
||||
Body body = message.getBody(); // exception, wenn es keinen body gibt.
|
||||
if (body.getMaterials() == null) {
|
||||
plausiResult.append(noTagInTag(message, MATERIALS, "body"));
|
||||
} else {
|
||||
Materials materialListItem = body.getMaterials();
|
||||
if (materialListItem.getMaterial().isEmpty()) {
|
||||
// explicitly allow record without comps for machines operating in runThrough mode
|
||||
} else {
|
||||
for (com.itac.panacim.Message.Body.Materials.Material materialItem : materialListItem.getMaterial()) {
|
||||
// Tag MaterialItem plausibilisieren
|
||||
plausiResult.append(checkAttribute(message, "id", MATERIAL, materialItem.getId()));
|
||||
plausiResult.append(checkAttribute(message, "part", MATERIAL, materialItem.getPart()));
|
||||
plausiResult.append(checkAttribute(message, "ref", MATERIAL, materialItem.getRef()));
|
||||
plausiResult.append(checkAttribute(message, "qty", MATERIAL, materialItem.getQty()));
|
||||
plausiResult.append(checkAttributeAllowEmpty(message, "p1", MATERIAL, materialItem.getP1()));
|
||||
plausiResult.append(checkAttributeAllowEmpty(message, "p2", MATERIAL, materialItem.getP2()));
|
||||
plausiResult.append(checkAttributeAllowEmpty(message, "p3", MATERIAL, materialItem.getP3()));
|
||||
plausiResult.append(checkAttributeAllowEmpty(message, "p4", MATERIAL, materialItem.getP4()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (body.getPanel() == null) {
|
||||
plausiResult.append(noTagInTag(message, PANEL, "body"));
|
||||
} else {
|
||||
Panel panel = body.getPanel();
|
||||
plausiResult.append(checkAttribute(message, "pcbId", PANEL, panel.getPcbID()));
|
||||
plausiResult.append(checkAttribute(message, "productName", PANEL, panel.getProductName()));
|
||||
plausiResult.append(checkAttribute(message, "productSide", PANEL, panel.getProductSide()));
|
||||
plausiResult.append(checkAttribute(message, "state", PANEL, panel.getState()));
|
||||
plausiResult.append(checkAttribute(message, "timeStamp", PANEL, panel.getTimestamp()));
|
||||
}
|
||||
|
||||
if (body.getComps() == null) {
|
||||
plausiResult.append(noTagInTag(message, COMPS, "body"));
|
||||
} else {
|
||||
Comps comp = body.getComps();
|
||||
if (comp.getComp().isEmpty()) {
|
||||
// explicitly allow record without comps for machines operating in runThrough mode
|
||||
} else {
|
||||
for (Comp cmp : comp.getComp()) {
|
||||
// benutzte Attribute im Tag pruefen
|
||||
plausiResult.append(checkAttribute(message, "pos", "comp", cmp.getPos()));
|
||||
plausiResult.append(checkAttribute(message, "ref", "comp", cmp.getRef()));
|
||||
plausiResult.append(checkAttribute(message, "refDes", "comp", cmp.getRefDes()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (plausiResult.length() != 0) {
|
||||
LogHandler.log(getClass().getSimpleName(), LogLevel.ERROR, plausiResult.toString());
|
||||
LogHandler.log(HTMLLogger.LOG_NAME, LogLevel.ERROR, plausiResult.toString());
|
||||
throw new ParseException(plausiResult.toString());
|
||||
}
|
||||
endVerify(message, 550);
|
||||
}
|
||||
|
||||
public void verifyClass560Message(PanaCimMessage message) throws ParseException {
|
||||
startVerify(message, 560);
|
||||
StringBuilder plausiResult = new StringBuilder();
|
||||
Body body = message.getBody(); // exception, wenn es keinen body gibt.
|
||||
if (body.getPrdData() == null) {
|
||||
plausiResult.append(noTagInTag(message, "prdData", "body"));
|
||||
} else {
|
||||
PrdData prdData = body.getPrdData();
|
||||
if (prdData.getData().isEmpty()) {
|
||||
plausiResult.append(noTagInTag(message, "data", "prdData"));
|
||||
} else {
|
||||
for (Data data : prdData.getData()) {
|
||||
plausiResult.append(checkAttribute(message, "stageNo", "data", data.getStageNo()));
|
||||
plausiResult.append(checkAttribute(message, "boardProduced", "data", data.getBoardProduced()));
|
||||
plausiResult.append(checkAttribute(message, "blockProduced", "data", data.getBlockProduced()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (plausiResult.length() != 0) {
|
||||
LogHandler.log(getClass().getSimpleName(), LogLevel.ERROR, plausiResult.toString());
|
||||
LogHandler.log(HTMLLogger.LOG_NAME, LogLevel.ERROR, plausiResult.toString());
|
||||
throw new ParseException(plausiResult.toString());
|
||||
}
|
||||
endVerify(message, 560);
|
||||
}
|
||||
|
||||
public void verifyClass561Message(PanaCimMessage message) throws ParseException {
|
||||
startVerify(message, 561);
|
||||
StringBuilder plausiResult = new StringBuilder();
|
||||
if (message.getRequestMessage().getBody() == null) {
|
||||
endVerify(message, 561);
|
||||
return;
|
||||
}
|
||||
Body body = message.getBody(); // exception, wenn es keinen body gibt.
|
||||
if (body.getTimePeriod() == null) {
|
||||
plausiResult.append(noTagInTag(message, "timePeriod", "body"));
|
||||
}
|
||||
if (body.getComponents() == null) {
|
||||
plausiResult.append(noTagInTag(message, "components", "body"));
|
||||
} else {
|
||||
Components component = body.getComponents();
|
||||
if (component.getComp().isEmpty()) {
|
||||
plausiResult.append(noTagInTag(message, "comp", "components"));
|
||||
} else {
|
||||
for (com.itac.panacim.Message.Body.Components.Comp comp : component.getComp()) {
|
||||
// welche Felder werden benutzt? nur diese Pruefen
|
||||
plausiResult.append(checkAttribute(message, "part", "comp", comp.getPart()));
|
||||
plausiResult.append(checkAttribute(message, "scrap", "comp", comp.getScrap()));
|
||||
plausiResult.append(checkAttributeAllowEmpty(message, "p1", "comp", comp.getP1()));
|
||||
plausiResult.append(checkAttributeAllowEmpty(message, "p2", "comp", comp.getP2()));
|
||||
plausiResult.append(checkAttributeAllowEmpty(message, "p3", "comp", comp.getP3()));
|
||||
plausiResult.append(checkAttributeAllowEmpty(message, "p4", "comp", comp.getP4()));
|
||||
plausiResult.append(checkAttributeAllowEmpty(message, "feederID", "comp", comp.getFeederID()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (plausiResult.length() != 0) {
|
||||
LogHandler.log(getClass().getSimpleName(), LogLevel.ERROR, plausiResult.toString());
|
||||
LogHandler.log(HTMLLogger.LOG_NAME, LogLevel.ERROR, plausiResult.toString());
|
||||
throw new ParseException(plausiResult.toString());
|
||||
}
|
||||
endVerify(message, 561);
|
||||
}
|
||||
|
||||
public void verifyClass580Message(PanaCimMessage message) throws ParseException {
|
||||
startVerify(message, 580);
|
||||
StringBuilder plausiResult = new StringBuilder();
|
||||
Body body = message.getBody(); // exception, wenn es keinen body gibt.
|
||||
if (body.getProduct() == null) {
|
||||
plausiResult.append(noTagInTag(message, PRODUCT, "body"));
|
||||
} else {
|
||||
Product product = body.getProduct();
|
||||
plausiResult.append(checkAttribute(message, "name", PRODUCT, product.getName()));
|
||||
plausiResult.append(checkAttribute(message, "side", PRODUCT, product.getSide()));
|
||||
}
|
||||
|
||||
if (body.getParts() == null) {
|
||||
plausiResult.append(noTagInTag(message, "parts", "body"));
|
||||
} else {
|
||||
if (body.getParts() == null) {
|
||||
plausiResult.append(noTagInTag(message, "part", "parts"));
|
||||
} else {
|
||||
for (Part part : body.getParts().getPart()) {
|
||||
plausiResult.append(checkAttribute(message, "stageNo", "name", part.getName()));
|
||||
plausiResult.append(checkAttribute(message, "boardProduced", "ref", part.getRef()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (body.getComps() == null) {
|
||||
plausiResult.append(noTagInTag(message, COMPS, "body"));
|
||||
} else {
|
||||
Comps comps = body.getComps();
|
||||
|
||||
if (comps.getComp().isEmpty()) {
|
||||
plausiResult.append(noTagInTag(message, "comp", COMPS));
|
||||
} else {
|
||||
for (Comp comp : comps.getComp()) {
|
||||
plausiResult.append(checkAttribute(message, "pos", "comp", comp.getPos()));
|
||||
plausiResult.append(checkAttribute(message, "ref", "comp", comp.getRef()));
|
||||
plausiResult.append(checkAttribute(message, "refDes", "comp", comp.getRefDes()));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (plausiResult.length() != 0) {
|
||||
LogHandler.log(getClass().getSimpleName(), LogLevel.ERROR, plausiResult.toString());
|
||||
LogHandler.log(HTMLLogger.LOG_NAME, LogLevel.ERROR, plausiResult.toString());
|
||||
throw new ParseException(plausiResult.toString());
|
||||
}
|
||||
endVerify(message, 580);
|
||||
}
|
||||
|
||||
public void verifyClass590Message(PanaCimMessage message) throws ParseException {
|
||||
startVerify(message, 590);
|
||||
StringBuilder plausiResult = new StringBuilder();
|
||||
Body body = message.getBody(); // exception, wenn es keinen body gibt.
|
||||
if (body.getOperation() == null) {
|
||||
plausiResult.append(noTagInTag(message, OPERATION, "body"));
|
||||
} else {
|
||||
Operation operation = body.getOperation();
|
||||
plausiResult.append(checkAttribute(message, "type", OPERATION, operation.getType()));
|
||||
plausiResult.append(checkAttribute(message, "materialId", OPERATION, operation.getMaterialID()));
|
||||
plausiResult.append(checkAttribute(message, TIMESTAMP, OPERATION, operation.getTimestamp()));
|
||||
plausiResult.append(checkAttribute(message, "operator", OPERATION, operation.getOperator()));
|
||||
plausiResult.append(checkAttribute(message, "reason", OPERATION, operation.getReason()));
|
||||
}
|
||||
if (plausiResult.length() != 0) {
|
||||
LogHandler.log(getClass().getSimpleName(), LogLevel.ERROR, plausiResult.toString());
|
||||
LogHandler.log(HTMLLogger.LOG_NAME, LogLevel.ERROR, plausiResult.toString());
|
||||
throw new ParseException(plausiResult.toString());
|
||||
}
|
||||
endVerify(message, 590);
|
||||
}
|
||||
|
||||
public void verifyClass600Message(PanaCimMessage message) throws ParseException {
|
||||
startVerify(message, 600);
|
||||
StringBuilder plausiResult = new StringBuilder();
|
||||
Body body = message.getBody(); // exception, wenn es keinen body gibt.
|
||||
if (body.getMachineEvent() == null) {
|
||||
plausiResult.append(noTagInTag(message, MACHINE_EVENT, "body"));
|
||||
} else {
|
||||
MachineEvent machineEvent = body.getMachineEvent();
|
||||
plausiResult.append(checkAttribute(message, "code", MACHINE_EVENT, machineEvent.getCode()));
|
||||
plausiResult.append(checkAttribute(message, "text", MACHINE_EVENT, machineEvent.getText()));
|
||||
plausiResult.append(checkAttribute(message, TIMESTAMP, MACHINE_EVENT, machineEvent.getTimestamp()));
|
||||
}
|
||||
if (plausiResult.length() != 0) {
|
||||
LogHandler.log(getClass().getSimpleName(), LogLevel.ERROR, plausiResult.toString());
|
||||
LogHandler.log(HTMLLogger.LOG_NAME, LogLevel.ERROR, plausiResult.toString());
|
||||
throw new ParseException(plausiResult.toString());
|
||||
}
|
||||
endVerify(message, 600);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright (c) 2010 iTAC Software AG, Germany. All Rights Reserved.
|
||||
*
|
||||
* This software is protected by copyright. Under no circumstances may any part of this file in any form be copied,
|
||||
* printed, edited or otherwise distributed, be stored in a retrieval system, or be translated into another language
|
||||
* without the written permission of iTAC Software AG.
|
||||
*/
|
||||
|
||||
package com.itac.mes.datainterface.data.panacim;
|
||||
|
||||
/**
|
||||
* @author frankp created 2011
|
||||
*/
|
||||
public class PanaCimActionCode {
|
||||
public final static int DO_NOTHING = 0;
|
||||
public final static int WARNING = 1;
|
||||
public final static int CANCEL_TRANSACTION = 2;
|
||||
public final static int STOP_PCB = 3;
|
||||
public final static int DISPLAY_MESSAGE = 9;
|
||||
}
|
||||
@@ -0,0 +1,246 @@
|
||||
package com.itac.mes.datainterface.data.panacim;
|
||||
|
||||
import com.itac.mes.datainterface.data.Ascii;
|
||||
import com.itac.util.logging.LogHandler;
|
||||
import com.itac.util.logging.LogLevel;
|
||||
|
||||
/**
|
||||
* Siehe Panasonic MES InterfaceSpecification Chapter 3.1
|
||||
*
|
||||
* @author frankp created 2011
|
||||
*/
|
||||
public class PanaCimClientCommProtocol {
|
||||
|
||||
boolean readyForStartOfMessage = true;
|
||||
boolean readyForEndOfMessage = false;
|
||||
|
||||
private StringBuffer currentMessage;
|
||||
private int messageCounter = 0;
|
||||
private int incompleteMessage = 0;
|
||||
private transient PanaCimClientSocket panaCimClientSocket;
|
||||
private transient IPanaCimClientMessageReceiver messageReceiver;
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* @param panasonicSocket
|
||||
* @param connectionName
|
||||
*/
|
||||
public PanaCimClientCommProtocol(String name, PanaCimClientSocket panaCimClientSocket) {
|
||||
super();
|
||||
this.name = name;
|
||||
this.panaCimClientSocket = panaCimClientSocket;
|
||||
}
|
||||
|
||||
/**
|
||||
* ein einzelnes Zeichen geht ein; die Steuerung, wann ein neuer Datensatz beginnt wird hier vorgenommen; <br>
|
||||
* ebenso die Zählung der Nachrichten. Ist eine Nachricht vollständig, wird sie ausgegeben und der Receiver
|
||||
* benachrichtigt
|
||||
*
|
||||
* @param b
|
||||
*/
|
||||
public synchronized void write(byte b) {
|
||||
// STX wurde empfangen
|
||||
if (readyForEndOfMessage) {
|
||||
switch (b) {
|
||||
case Ascii.ETX:
|
||||
// Message abschliessen und ausliefern...
|
||||
currentMessage.append((char) b);
|
||||
|
||||
// Jetzt ist die Message komplett, es kann geprueft werden, ob die Meldung OK ist, und dann in den Ausgabepuffer
|
||||
// geschoben werden
|
||||
PanaCimClientMessage panaCimClientMessage = new PanaCimClientMessage();
|
||||
panaCimClientMessage.setPanaCimSocket(panaCimClientSocket);
|
||||
panaCimClientMessage.setMessageNumber(messageCounter);
|
||||
|
||||
panaCimClientMessage.setCommunicationProtocol(this);
|
||||
|
||||
LogHandler.log(getClass().getSimpleName(), LogLevel.TRACE, getLogHeader()
|
||||
+ ": ETX received, message completed, ready for next message");
|
||||
LogHandler.log("MESSAGES", LogLevel.TRACE, getLogHeader() + ":\n" + stringBuffer2UserMessage(currentMessage));
|
||||
// setzen der Daten, hiermit wird die weitere Struktur der eingegangenen Daten geprueft
|
||||
|
||||
try {
|
||||
panaCimClientMessage.setContent(getContentFromTransportLayerString(currentMessage.toString()));
|
||||
|
||||
if (messageReceiver != null) {
|
||||
messageReceiver.setMessage(panaCimClientMessage);
|
||||
}
|
||||
} catch (ProtocolException pe) {
|
||||
LogHandler.log("MESSAGES", LogLevel.TRACE, getLogHeader() + ":\n" + stringBuffer2UserMessage(currentMessage) + "\n"
|
||||
+ pe.getMessage());
|
||||
} catch (MessageException me) {
|
||||
LogHandler.log("MESSAGES", LogLevel.TRACE, getLogHeader() + ":\n" + stringBuffer2UserMessage(currentMessage) + "\n"
|
||||
+ me.getMessage());
|
||||
} catch (SendException se) {
|
||||
LogHandler.log("MESSAGES", LogLevel.TRACE, getLogHeader() + ":\n" + stringBuffer2UserMessage(currentMessage) + "\n"
|
||||
+ se.getMessage());
|
||||
}
|
||||
|
||||
// naechste Nachricht vorbereiten
|
||||
currentMessage = new StringBuffer();
|
||||
readyForStartOfMessage = true;
|
||||
readyForEndOfMessage = false;
|
||||
break;
|
||||
case Ascii.STX:
|
||||
// letzte Message als incomplete abhaken...
|
||||
LogHandler.log(getClass().getSimpleName(), LogLevel.ERROR, getLogHeader()
|
||||
+ ": received unexpected STX, start new message");
|
||||
incompleteMessage++;
|
||||
messageCounter++;
|
||||
LogHandler.log(getClass().getSimpleName(), LogLevel.ERROR, getLogHeader() + " is incomplete message# "
|
||||
+ incompleteMessage + ":\n" + stringBuffer2UserMessage(currentMessage));
|
||||
LogHandler.log("MESSAGES", LogLevel.ERROR, getLogHeader() + " is incomplete message# " + incompleteMessage + ":\n"
|
||||
+ stringBuffer2UserMessage(currentMessage));
|
||||
currentMessage = new StringBuffer();
|
||||
currentMessage.append((char) b);
|
||||
|
||||
break;
|
||||
default:
|
||||
// nur Daten anhaengen
|
||||
currentMessage.append((char) b);
|
||||
}
|
||||
} // anfangen mit STX, aufhoeren mit ETX
|
||||
else if (readyForStartOfMessage) {
|
||||
|
||||
switch (b) {
|
||||
case Ascii.STX:
|
||||
// es wird erwartungsgemaess eine neue Nachricht angefangen mit STX
|
||||
messageCounter++;
|
||||
LogHandler.log(getClass().getSimpleName(), LogLevel.TRACE, getLogHeader() + ": STX received");
|
||||
// Datenstruktur für neue Message anfangen, Daten anhaengen
|
||||
currentMessage = new StringBuffer();
|
||||
currentMessage.append((char) b);
|
||||
// theoretisch darf jetzt nach dem Protocol alles andere oder ein ETX kommen, aber kein STX
|
||||
readyForStartOfMessage = false;
|
||||
readyForEndOfMessage = true;
|
||||
break;
|
||||
default:
|
||||
LogHandler.log(getClass().getSimpleName(), LogLevel.ERROR,
|
||||
getLogHeader() + ": unexpected char '" + Ascii.getUserTextForChar((char) b) + "' received, ignore input");
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
// interner Fehler, sowohl readyforStart als auch readyforend sind false
|
||||
LogHandler.log(getClass().getSimpleName(), LogLevel.FATAL, getLogHeader() + ": internal error");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* eine Menge von Bytes aus dem Eingang setzen...
|
||||
*
|
||||
* @param b
|
||||
*/
|
||||
public synchronized void write(byte[] b) {
|
||||
if (b == null) {
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < b.length; i++) {
|
||||
write(b[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// alle Zeichen STX, ETX, SOH werden in der Form "<STX>" ausgegeben, alle anderen Zeichen als Text
|
||||
protected String stringBuffer2UserMessage(StringBuffer source) {
|
||||
return Ascii.toReadableString(source);
|
||||
}
|
||||
|
||||
private String getLogHeader() {
|
||||
if (name != null) {
|
||||
return "message#" + messageCounter + " on connection '" + name + "'";
|
||||
}
|
||||
return "message#" + messageCounter + " on connection '---'";
|
||||
}
|
||||
|
||||
/**
|
||||
* der Transport-LayerString sieht ungefaehr so aus: <STX>len<SOH>content<ETX>.
|
||||
*
|
||||
* @param transportLayerString
|
||||
* @return "content" aus dem Beispiel
|
||||
* @throws ProtocolException
|
||||
*/
|
||||
protected String getContentFromTransportLayerString(String transportLayerString) throws ProtocolException {
|
||||
// verifizieren: STX lengthOfXmlMessage SOH XmlMessage ETX
|
||||
if (transportLayerString == null || transportLayerString.length() == 0) {
|
||||
throw new ProtocolException("empty message");
|
||||
}
|
||||
// erstes Byte muss STX sein
|
||||
byte[] byteData = transportLayerString.getBytes();
|
||||
if (byteData[0] != Ascii.STX) {
|
||||
throw new ProtocolException("missing STX in message");
|
||||
}
|
||||
if (byteData[byteData.length - 1] != Ascii.ETX) {
|
||||
throw new ProtocolException("missing ETX in message");
|
||||
}
|
||||
// wo ist das SOH
|
||||
int sohPos = -1;
|
||||
for (int i = 0; i < byteData.length; i++) {
|
||||
if (byteData[i] == Ascii.SOH) {
|
||||
sohPos = i;
|
||||
}
|
||||
}
|
||||
if (sohPos < 0) {
|
||||
throw new ProtocolException("missing SOH in message");
|
||||
}
|
||||
if (sohPos == 1) {
|
||||
throw new ProtocolException("no length information in message");
|
||||
}
|
||||
// Laenge extrahieren
|
||||
String sLen = new String(byteData, 1, sohPos - 1);
|
||||
int iLen = -1;
|
||||
try {
|
||||
iLen = Integer.parseInt(sLen);
|
||||
} catch (NumberFormatException nfe) {
|
||||
throw new ProtocolException("invalid length information in message");
|
||||
}
|
||||
if (iLen <= 0) {
|
||||
throw new ProtocolException("invalid length information in message (zero or negativ )");
|
||||
}
|
||||
// String extrahieren
|
||||
String sContent = new String(byteData, sohPos + 1, byteData.length - sohPos - 2);
|
||||
// Laenge pruefen
|
||||
if (sContent.length() != iLen) {
|
||||
throw new ProtocolException("length header in message is wrong, length=" + sLen + " and messageSize="
|
||||
+ sContent.length());
|
||||
}
|
||||
return sContent;
|
||||
}
|
||||
|
||||
/**
|
||||
* einen normalen content-String mit STX/Len/SOH/ETX einrahmen
|
||||
*
|
||||
* @param content
|
||||
* @return
|
||||
* @throws ProtocolException
|
||||
*/
|
||||
public String getTransportLayerString(String content) throws ProtocolException {
|
||||
if (content == null) {
|
||||
throw new ProtocolException("empty message");
|
||||
}
|
||||
return (char) Ascii.STX + "" + content.length() + "" + (char) Ascii.SOH + content + (char) Ascii.ETX;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param messageReceiver
|
||||
*/
|
||||
public synchronized void setMessageReceier(IPanaCimClientMessageReceiver messageReceiver) {
|
||||
this.messageReceiver = messageReceiver;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws SendException
|
||||
* @throws MessageException
|
||||
*
|
||||
*/
|
||||
public synchronized void sendPingRequest() throws MessageException, SendException {
|
||||
messageCounter++;
|
||||
// Jetzt ist die Message komplett, es kann geprueft werden, ob die Meldung OK ist, und dann in den Ausgabepuffer
|
||||
// geschoben werden
|
||||
PanaCimClientMessage panaCimMessage = new PanaCimClientMessage();
|
||||
panaCimMessage.setPanaCimSocket(panaCimClientSocket);
|
||||
panaCimMessage.setMessageNumber(messageCounter);
|
||||
panaCimMessage.setCommunicationProtocol(this);
|
||||
// ausgeben der Nachricht wie wir sie senden
|
||||
panaCimMessage.makePingRequest();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,163 @@
|
||||
/*
|
||||
* Copyright (c) 2010 iTAC Software AG, Germany. All Rights Reserved.
|
||||
*
|
||||
* This software is protected by copyright. Under no circumstances may any part of this file in any form be copied,
|
||||
* printed, edited or otherwise distributed, be stored in a retrieval system, or be translated into another language
|
||||
* without the written permission of iTAC Software AG.
|
||||
*/
|
||||
|
||||
package com.itac.mes.datainterface.data.panacim;
|
||||
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.io.IOException;
|
||||
import java.net.ConnectException;
|
||||
import java.net.NoRouteToHostException;
|
||||
import java.net.Socket;
|
||||
import java.net.UnknownHostException;
|
||||
|
||||
import javax.net.SocketFactory;
|
||||
|
||||
import com.itac.util.logging.LogHandler;
|
||||
import com.itac.util.logging.LogLevel;
|
||||
|
||||
/**
|
||||
* @author frankp created 2011
|
||||
*/
|
||||
public class PanaCimClientConnection {
|
||||
|
||||
private final SocketFactory socketFactory = SocketFactory.getDefault();
|
||||
|
||||
private Socket clientSocket;
|
||||
private PanaCimClientSocket panacimClientSocket;
|
||||
private ClientConnectionProperties clientConnProperties;
|
||||
private IPanaCimClientMessageReceiver panaCimSimulation;
|
||||
private PropertyChangeListener propertyListener;
|
||||
|
||||
/**
|
||||
* @param name
|
||||
* @param host
|
||||
* @param port
|
||||
* @param maximumPingResponseTime
|
||||
* @param pingRequestDelayTime
|
||||
*/
|
||||
public PanaCimClientConnection(ClientConnectionProperties clientConnProps) {
|
||||
super();
|
||||
this.clientConnProperties = clientConnProps;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
public String getName() {
|
||||
return clientConnProperties.getName();
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
LogHandler.log(getClass().getSimpleName(), LogLevel.INFO, getLogHeader() + "close sockets now");
|
||||
if (clientSocket != null) {
|
||||
try {
|
||||
clientSocket.close();
|
||||
} catch (IOException e) {
|
||||
LogHandler.log(getClass().getSimpleName(), LogLevel.ERROR, "closing socket failed", e);
|
||||
}
|
||||
clientSocket = null;
|
||||
fireStateChange();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true, if connection was established
|
||||
*/
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public boolean start() {
|
||||
LogHandler.log(getClass().getSimpleName(), LogLevel.DEBUG, getLogHeader() + "start Client connection ");
|
||||
|
||||
if (clientSocket == null) {
|
||||
try {
|
||||
clientSocket = socketFactory.createSocket(clientConnProperties.getHost(), clientConnProperties.getPort());
|
||||
// clientSocket.setKeepAlive(true);
|
||||
if (clientSocket != null) {
|
||||
LogHandler.log(getClass().getSimpleName(), LogLevel.DEBUG, getLogHeader() + "connected to remoteSocketAddress "
|
||||
+ clientSocket.getRemoteSocketAddress());
|
||||
}
|
||||
panacimClientSocket = new PanaCimClientSocket(getLogHeader(), clientConnProperties.getPingRequestDelayTime(),
|
||||
clientConnProperties.getMaximumPingResponseTime());
|
||||
panacimClientSocket.setSocket(clientSocket);
|
||||
// jetzt muessen die sockets noch gestartet werden, also z.B. die Timer für PingMechanismus
|
||||
panacimClientSocket.startSocket();
|
||||
panacimClientSocket.setMessageReceiver(panaCimSimulation);
|
||||
fireStateChange();
|
||||
return true;
|
||||
} catch (NoRouteToHostException nrthe) {
|
||||
LogHandler.log(getClass().getSimpleName(), LogLevel.ERROR,
|
||||
getLogHeader() + "no route to host " + clientConnProperties.getPort() + "'" + nrthe.getMessage(), nrthe);
|
||||
} catch (ConnectException connectExcep) {
|
||||
LogHandler.log(getClass().getSimpleName(), LogLevel.ERROR,
|
||||
getLogHeader() + "not connected " + clientConnProperties.getName() + "'" + connectExcep.getMessage(), 1);
|
||||
return false;
|
||||
} catch (UnknownHostException e1) {
|
||||
LogHandler.log(getClass().getSimpleName(), LogLevel.ERROR, getLogHeader() + "Host '" + clientConnProperties.getHost()
|
||||
+ "' is unknown for connection\n" + e1.getMessage(), e1);
|
||||
} catch (IOException e1) {
|
||||
LogHandler.log(getClass().getSimpleName(), LogLevel.ERROR, getLogHeader() + "TCP/IP IO Exception on host '"
|
||||
+ clientConnProperties.getHost() + "'");
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private void fireStateChange() {
|
||||
if (propertyListener != null) {
|
||||
propertyListener.propertyChange(new PropertyChangeEvent(this, "", "", ""));
|
||||
}
|
||||
}
|
||||
|
||||
public String getLogHeader() {
|
||||
return "client connection " + getName() + " ";
|
||||
}
|
||||
|
||||
/**
|
||||
* @param panaCimSimulation
|
||||
*/
|
||||
public void setMessageReceiver(IPanaCimClientMessageReceiver panaCimSimulation) {
|
||||
this.panaCimSimulation = panaCimSimulation;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param rawSendString
|
||||
* der vollständige Inhalt inklusive den Framing Characters
|
||||
* @throws SendException
|
||||
* @throws MessageException
|
||||
*/
|
||||
public void send(String rawSendString) throws MessageException, SendException {
|
||||
PanaCimClientMessage message = new PanaCimClientMessage();
|
||||
message.setPanaCimSocket(panacimClientSocket);
|
||||
message.setRawRequestString(rawSendString);
|
||||
if (panacimClientSocket == null){
|
||||
throw new SendException("client socket for connection is not null");
|
||||
}
|
||||
panacimClientSocket.sendRequest(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param guiComponent
|
||||
*/
|
||||
public void setConnectStateChangeListener(PropertyChangeListener propertyListener) {
|
||||
// Der Verbindungsstatus einer Verbindung ändert sich..
|
||||
// alle neu darstellen
|
||||
this.propertyListener = propertyListener;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
public boolean isConnected() {
|
||||
return panacimClientSocket != null && panacimClientSocket.isConnected();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,300 @@
|
||||
/*
|
||||
* Copyright (c) 2010 iTAC Software AG, Germany. All Rights Reserved.
|
||||
*
|
||||
* This software is protected by copyright. Under no circumstances may any part of this file in any form be copied,
|
||||
* printed, edited or otherwise distributed, be stored in a retrieval system, or be translated into another language
|
||||
* without the written permission of iTAC Software AG.
|
||||
*/
|
||||
|
||||
package com.itac.mes.datainterface.data.panacim;
|
||||
|
||||
import java.io.StringReader;
|
||||
|
||||
import javax.xml.bind.JAXBContext;
|
||||
import javax.xml.bind.JAXBException;
|
||||
import javax.xml.bind.Marshaller;
|
||||
import javax.xml.bind.Unmarshaller;
|
||||
|
||||
import com.itac.panacim.Message;
|
||||
import com.itac.panacim.Message.Body;
|
||||
import com.itac.panacim.Message.Header;
|
||||
import com.itac.util.logging.LogHandler;
|
||||
import com.itac.util.logging.LogLevel;
|
||||
|
||||
/**
|
||||
* @author frankp created 2011
|
||||
*/
|
||||
public class PanaCimClientMessage {
|
||||
|
||||
// über diese Verbindung sind die Daten eingegangen
|
||||
// die Confirmation muss über die selbe Verbindung hinausgehen...
|
||||
// es kann natürlich sein, daß diese connection irgendwann vom Client beendet wurde.
|
||||
// in diesem Fall muessen alle ausgehenden Nachrichten gepuffert werden
|
||||
private PanaCimClientSocket panaCimSocket;
|
||||
|
||||
/** der JAXB context ist fuer die Erzeugung der Marshaller/Unmarshaller notwendig */
|
||||
private static JAXBContext jaxbContext;
|
||||
|
||||
/** diese Instanz macht aus einem String (eingabe-Datenstrom) die strukturierte Instanz */
|
||||
private static Unmarshaller unmarshaller;
|
||||
/**
|
||||
* diese Instanz macht aus einer strukturierte Instanz einer Message einen String, der dann weiter verarbeitet und
|
||||
* versendet werden kann
|
||||
*/
|
||||
private static Marshaller marshaller;
|
||||
|
||||
private int messageNumber;
|
||||
|
||||
/** ueber diese Instanz des Protocol Stacks ist die Message eingegangen */
|
||||
private PanaCimClientCommProtocol communicationProtocol;
|
||||
|
||||
private String xmlRequestMessage;
|
||||
|
||||
/** die ausgehende Message */
|
||||
private Message requestMessage;
|
||||
/** auf Basis der eingegangenen Message kann eine Antwort */
|
||||
private String xmlContentResponse;
|
||||
private String rawRequestMessage;
|
||||
private boolean isPingRequest;
|
||||
|
||||
private boolean isPingResponse;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public PanaCimClientMessage() {
|
||||
super();
|
||||
try {
|
||||
getUnmarshaller();
|
||||
getMarshaller();
|
||||
} catch (JAXBException e) {
|
||||
LogHandler.log(getClass().getSimpleName(), LogLevel.ERROR, "failed to create JAXBContext\n" + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
private static JAXBContext getJAXBContext() throws JAXBException {
|
||||
if (jaxbContext == null) {
|
||||
jaxbContext = JAXBContext.newInstance(Message.class);
|
||||
}
|
||||
return jaxbContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws JAXBException
|
||||
*/
|
||||
private static Unmarshaller getUnmarshaller() throws JAXBException {
|
||||
if (unmarshaller == null) {
|
||||
unmarshaller = getJAXBContext().createUnmarshaller();
|
||||
}
|
||||
return unmarshaller;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws JAXBException
|
||||
*/
|
||||
private static Marshaller getMarshaller() throws JAXBException {
|
||||
if (marshaller == null) {
|
||||
marshaller = getJAXBContext().createMarshaller();
|
||||
}
|
||||
return marshaller;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param messageCounter
|
||||
*/
|
||||
public void setMessageNumber(int messageNumber) {
|
||||
this.messageNumber = messageNumber;
|
||||
}
|
||||
|
||||
public String getLogHeader() {
|
||||
if (messageNumber == 0) {
|
||||
return "message#(unnumbered)";
|
||||
}
|
||||
return "message#" + messageNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param contentFromTransportLayerString
|
||||
* @throws MessageException
|
||||
* @throws SendException
|
||||
*/
|
||||
public void setContent(String xmlMessageString) throws MessageException, SendException {
|
||||
if (xmlMessageString == null || xmlMessageString.isEmpty()) {
|
||||
throw new MessageException(getLogHeader() + " has empty xmlMessageString");
|
||||
}
|
||||
this.xmlRequestMessage = xmlMessageString;
|
||||
|
||||
// jedweder Eingang setzt den aktiv-Timer zurueck...
|
||||
// weder PING_REQ noch PING_RESP xml-parsen...
|
||||
if (xmlRequestMessage.equals(PanaCimMessage.PING_RSP)) {
|
||||
LogHandler.log(getClass().getSimpleName(), LogLevel.TRACE, getLogHeader() + " received special Message PING_RESP");
|
||||
isPingResponse = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (xmlRequestMessage.equals(PanaCimMessage.PING_REQ)) {
|
||||
LogHandler.log(getClass().getSimpleName(), LogLevel.TRACE, getLogHeader() + " received special Message PING_REQ");
|
||||
isPingRequest = true;
|
||||
xmlContentResponse = PanaCimMessage.PING_RSP;
|
||||
LogHandler.log(getClass().getSimpleName(), LogLevel.TRACE, getLogHeader() + " send special Message PING_RESP");
|
||||
sendXMLContent();
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
requestMessage = (Message) getUnmarshaller().unmarshal(new StringReader(xmlMessageString));
|
||||
} catch (JAXBException e) {
|
||||
LogHandler.log(getClass().getSimpleName(), LogLevel.ERROR, getLogHeader() + " unmarshalling failed!\n" + e.getMessage(),
|
||||
e);
|
||||
throw new MessageException(getLogHeader() + " unmarshalling failed!\n" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param panaCimSocket
|
||||
*/
|
||||
public void setPanaCimSocket(PanaCimClientSocket panaCimSocket) {
|
||||
this.panaCimSocket = panaCimSocket;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
public String getXmlRequestMessage() {
|
||||
return xmlRequestMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
public Message getRequestMessage() {
|
||||
return requestMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws MessageException
|
||||
*/
|
||||
public void createResponseMessage() throws MessageException {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @throws MessageException
|
||||
* @throws SendException
|
||||
*
|
||||
*/
|
||||
private void sendXMLContent() throws MessageException, SendException {
|
||||
if (xmlContentResponse == null || xmlContentResponse.isEmpty()) {
|
||||
throw new MessageException(getLogHeader() + " xmlContent of marshalled response message is empty");
|
||||
}
|
||||
|
||||
// die als xmlResonseMessage vorliegenden String in ein versendbares Format bringen
|
||||
LogHandler.log(getClass().getSimpleName(), LogLevel.TRACE, getLogHeader() + " apply protocol to response message");
|
||||
try {
|
||||
rawRequestMessage = communicationProtocol.getTransportLayerString(xmlContentResponse);
|
||||
} catch (ProtocolException e) {
|
||||
LogHandler.log(getClass().getSimpleName(), LogLevel.ERROR, getLogHeader()
|
||||
+ " applying protocol to response message failed!\n" + e.getMessage(), e);
|
||||
throw new MessageException(getLogHeader() + " applying protocol to response message failed!\n" + e.getMessage());
|
||||
}
|
||||
|
||||
panaCimSocket.sendRequest(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param communicationProtocol
|
||||
*/
|
||||
public void setCommunicationProtocol(PanaCimClientCommProtocol communicationProtocol) {
|
||||
this.communicationProtocol = communicationProtocol;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
public String getXmlResponseMessageString() {
|
||||
return xmlContentResponse;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param x
|
||||
*/
|
||||
public void setRawResponseMessage(String rawResonseMessage) {
|
||||
this.rawRequestMessage = rawResonseMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
public String getRawRequestMessageString() {
|
||||
return rawRequestMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
public boolean replyRequested() {
|
||||
return getHeader() != null && getHeader().getReply() != null && getHeader().getReply() == 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
private Header getHeader() {
|
||||
if (requestMessage == null) {
|
||||
return null;
|
||||
}
|
||||
// header / body pruefen
|
||||
if (requestMessage.getHeader() == null) {
|
||||
return null;
|
||||
}
|
||||
return requestMessage.getHeader();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param responseMessage2
|
||||
* @return
|
||||
* @throws MessageException
|
||||
*/
|
||||
public Body getOrCreateBody(Message responseMessage) throws MessageException {
|
||||
if (responseMessage == null) {
|
||||
throw new MessageException(getLogHeader() + " response message is null");
|
||||
}
|
||||
if (responseMessage.getBody() != null) {
|
||||
return responseMessage.getBody();
|
||||
}
|
||||
|
||||
Body body = new Body();
|
||||
responseMessage.setBody(body);
|
||||
return body;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws SendException
|
||||
* @throws MessageException
|
||||
*
|
||||
*/
|
||||
public void makePingRequest() throws MessageException, SendException {
|
||||
xmlContentResponse = PanaCimMessage.PING_REQ;
|
||||
|
||||
sendXMLContent();
|
||||
}
|
||||
|
||||
public boolean isPingRequest() {
|
||||
return isPingRequest;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
public boolean isPingResponse() {
|
||||
return isPingResponse;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param rawSendString
|
||||
*/
|
||||
public void setRawRequestString(String rawSendString) {
|
||||
this.rawRequestMessage = rawSendString;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,303 @@
|
||||
/*
|
||||
* Copyright (c) 2010 iTAC Software AG, Germany. All Rights Reserved.
|
||||
*
|
||||
* This software is protected by copyright. Under no circumstances may any part of this file in any form be copied,
|
||||
* printed, edited or otherwise distributed, be stored in a retrieval system, or be translated into another language
|
||||
* without the written permission of iTAC Software AG.
|
||||
*/
|
||||
|
||||
package com.itac.mes.datainterface.data.panacim;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.Socket;
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
|
||||
import com.itac.util.logging.LogHandler;
|
||||
import com.itac.util.logging.LogLevel;
|
||||
|
||||
/**
|
||||
* @author frankp created 2011
|
||||
*/
|
||||
public class PanaCimClientSocket implements IPanaCimClientMessageReceiver {
|
||||
|
||||
private String connectionName;
|
||||
private transient PanaCimClientCommProtocol clientCommProtocol;
|
||||
private transient Socket clientSocket;
|
||||
private transient Thread readThread;
|
||||
private transient IPanaCimClientMessageReceiver messageReceiver;
|
||||
private long nextPingResponseExpected = Long.MAX_VALUE;
|
||||
/** Zeitpunkt, wann der naechste Ping-Request zu senden ist */
|
||||
private long nextPingRequest = Long.MAX_VALUE;
|
||||
private long pingRequestDelay;
|
||||
private long maxPingResponseTime;
|
||||
|
||||
/** statistik, wie lange die Request-Response zyklen dauern */
|
||||
private transient Stat responseStatistics = new Stat(10);
|
||||
/** Zeitpunkt, zu dem der letzte PING_REQ gesendet wurde... */
|
||||
private long pingRequestSent;
|
||||
|
||||
private transient SimpleDateFormat timeFormatter = (SimpleDateFormat) DateFormat.getTimeInstance();
|
||||
|
||||
// maximale Zeit zwischen 2 eingehenden Nachrichten auf einer Verbindung
|
||||
private transient Thread aliveThread;
|
||||
private boolean isShuttingDown;
|
||||
|
||||
/**
|
||||
* @param connectionName
|
||||
* Name der Verbindung
|
||||
* @param pingRequestDelay
|
||||
* Wert = 0: Server Socket sendet keine ping requests aus. <br>
|
||||
* Wert > 0: Server vermerkt den Eingang einer pingResponse und nach dem verstreichen der pingRequestDelay
|
||||
* millies wird der nächste pingReq gesendet
|
||||
* @param maxPingResponseTime
|
||||
* maximale Zeit in millies, die vergehen darf bevor eine ping response auf die soeben versendete PingRequest
|
||||
* empfangen worden sein muss. Die Verbindung wird geschlossen, wenn keine Response empfangen wird. Wird nur
|
||||
* ausgewertet, wenn auch ein PingRequest gesendet werden soll.<br>
|
||||
*/
|
||||
public PanaCimClientSocket(String connectionName, long pingRequestDelay, long maxPingResponseTime) {
|
||||
super();
|
||||
this.connectionName = connectionName;
|
||||
clientCommProtocol = new PanaCimClientCommProtocol(connectionName, this);
|
||||
clientCommProtocol.setMessageReceier(this);
|
||||
timeFormatter.applyPattern("HH:mm:ss,S");
|
||||
this.pingRequestDelay = pingRequestDelay;
|
||||
this.maxPingResponseTime = maxPingResponseTime;
|
||||
// implizites initialisierung des JaxBContext
|
||||
PanaCimClientMessage pMsg = new PanaCimClientMessage();
|
||||
LogHandler.log(getClass().getSimpleName(), LogLevel.TRACE, pMsg.getLogHeader());
|
||||
}
|
||||
|
||||
public void setSocket(Socket socket) {
|
||||
this.clientSocket = socket;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public void startSocket() {
|
||||
// inputStream und outputStream verbinden...
|
||||
String readThreadName = connectionName + "ReadThread";
|
||||
LogHandler.log(getClass().getSimpleName(), LogLevel.INFO, "startup " + readThreadName + " for " + connectionName);
|
||||
readThread = new Thread(readThreadName) {
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
try {
|
||||
while (clientSocket.getInputStream() != null && !isShuttingDown) {
|
||||
try {
|
||||
Thread.sleep(10);
|
||||
} catch (InterruptedException e1) {
|
||||
shutdownConnection();
|
||||
}
|
||||
try {
|
||||
final int bytesAvail = clientSocket.getInputStream().available();
|
||||
if (bytesAvail > 0) {
|
||||
final byte[] inData = new byte[bytesAvail];
|
||||
clientSocket.getInputStream().read(inData);
|
||||
// alle eingehenden Daten des Stroms an den Eingangspuffer weiterleiten
|
||||
clientCommProtocol.write(inData);
|
||||
}
|
||||
} catch (final IOException e) {
|
||||
// jetzt koenne keine weiteren Daten gelesen werden, also wird der Thread beendet!
|
||||
doDataExchangeFailed("reading");
|
||||
shutdownConnection();
|
||||
return;
|
||||
}
|
||||
}
|
||||
} catch (IOException ioe) {
|
||||
// jetzt koenne keine weiteren Daten gelesen werden, also wird der Thread beendet!
|
||||
doDataExchangeFailed("reading");
|
||||
shutdownConnection();
|
||||
return;
|
||||
}
|
||||
}
|
||||
};
|
||||
readThread.start();
|
||||
// jetzt muss auch der MessageReceiveTimer gesetzt werden...
|
||||
// bis zu einem gewissen Zeitpunkt muss immer die naechste Nachricht empfangen worden sein
|
||||
|
||||
String aliveThreadName = connectionName + "AliveThread";
|
||||
LogHandler.log(getClass().getSimpleName(), LogLevel.INFO, "startup " + aliveThreadName + " for " + connectionName);
|
||||
aliveThread = new Thread(aliveThreadName) {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
while (!isInterrupted() && !isShuttingDown) {
|
||||
try {
|
||||
try {
|
||||
Thread.sleep(10);
|
||||
} catch (InterruptedException e1) { // Hier diese Exception ignorieren
|
||||
}
|
||||
|
||||
if (System.currentTimeMillis() > nextPingResponseExpected) {
|
||||
// wenn eine Verbindung aufgebaut ist diese jetzt schliessen
|
||||
LogHandler.log(getName(), LogLevel.ERROR, "connection " + connectionName
|
||||
+ " did not receive PING_RESP in time, close connection now!");
|
||||
shutdownConnection();
|
||||
return;
|
||||
}
|
||||
if (System.currentTimeMillis() >= nextPingRequest) {
|
||||
// wenn eine Verbindung aufgebaut ist diese jetzt schliessen
|
||||
LogHandler.log(getName(), LogLevel.ERROR, getLogHeader() + "send Ping Request now...");
|
||||
nextPingRequest = Long.MAX_VALUE;
|
||||
setNextPingResponse();
|
||||
pingRequestSent = System.currentTimeMillis();
|
||||
clientCommProtocol.sendPingRequest();
|
||||
}
|
||||
|
||||
try {
|
||||
Thread.sleep(1);
|
||||
} catch (InterruptedException e) {
|
||||
LogHandler.log(getName(), LogLevel.ERROR, "connection " + getName() + " alive thread died...!");
|
||||
return;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LogHandler.log(getName(), LogLevel.ERROR, "connection " + getName() + " alive thread problem...!", e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
aliveThread.start();
|
||||
if (pingRequestDelay > 0) {
|
||||
setNextPingRequest();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* vollstaendiges Schliessen einer Verbindung, gestartete ative Threads anhalten (Lese-Thread, ping Thread,
|
||||
* keepaliveThread)
|
||||
*/
|
||||
protected void shutdownConnection() {
|
||||
if (isShuttingDown) {
|
||||
// shutdown is in progress
|
||||
return;
|
||||
}
|
||||
isShuttingDown = true;
|
||||
LogHandler.log(getClass().getSimpleName(), LogLevel.INFO, getLogHeader() + "shutting down");
|
||||
|
||||
if (readThread != null && readThread.isAlive()) {
|
||||
LogHandler.log(getClass().getSimpleName(), LogLevel.DEBUG, getLogHeader() + "interrupting " + readThread.getName());
|
||||
readThread.interrupt();
|
||||
}
|
||||
if (aliveThread != null && aliveThread.isAlive()) {
|
||||
LogHandler.log(getClass().getSimpleName(), LogLevel.DEBUG, getLogHeader() + "interrupting " + aliveThread.getName());
|
||||
aliveThread.interrupt();
|
||||
}
|
||||
try {
|
||||
LogHandler.log(getClass().getSimpleName(), LogLevel.DEBUG, getLogHeader() + "closing socket " + connectionName);
|
||||
clientSocket.close();
|
||||
} catch (IOException e) {
|
||||
LogHandler.log(getClass().getSimpleName(), LogLevel.DEBUG, getLogHeader() + "closing socket " + connectionName + " failed: "
|
||||
+ e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
private void doDataExchangeFailed(String operation) {
|
||||
LogHandler.log(getClass().getSimpleName(), LogLevel.INFO, getLogHeader() + "problems " + operation);
|
||||
// if (tcpServerCommunicationListener != null) {
|
||||
// tcpServerCommunicationListener.dataExchangeFailed();
|
||||
// }
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
public String getLogHeader() {
|
||||
return "connection " + connectionName + " ";
|
||||
}
|
||||
|
||||
/**
|
||||
* @param message
|
||||
* @return
|
||||
*/
|
||||
private String getLogHeader(PanaCimClientMessage message) {
|
||||
return message.getLogHeader() + " on " + getLogHeader();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param application
|
||||
*/
|
||||
public void setMessageReceiver(IPanaCimClientMessageReceiver messageReceiver) {
|
||||
this.messageReceiver = messageReceiver;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws MessageException
|
||||
* @throws SendException
|
||||
*
|
||||
*/
|
||||
public void sendRequest(PanaCimClientMessage message) throws MessageException, SendException {
|
||||
// es muss den Content als xml geben
|
||||
LogHandler.log(getClass().getSimpleName(), LogLevel.INFO, getLogHeader(message) + "send request");
|
||||
if (message.getRawRequestMessageString() == null || message.getRawRequestMessageString().isEmpty()) {
|
||||
throw new MessageException(getLogHeader(message) + "raw response message is empty");
|
||||
}
|
||||
|
||||
// ausgeben der Nachricht wie wir sie senden
|
||||
StringBuffer stb = new StringBuffer(message.getRawRequestMessageString());
|
||||
LogHandler.log("MESSAGES", LogLevel.TRACE,
|
||||
getLogHeader(message) + "send:\n" + PanaCimCommProtocol.stringBuffer2UserMessage(stb));
|
||||
|
||||
try {
|
||||
clientSocket.getOutputStream().write(message.getRawRequestMessageString().getBytes());
|
||||
clientSocket.getOutputStream().flush();
|
||||
} catch (IOException e) {
|
||||
// Fehler beim schreiben
|
||||
doDataExchangeFailed("writing");
|
||||
shutdownConnection();
|
||||
throw new SendException(getLogHeader(message) + "raw response message not send!\n" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.itac.mes.datainterface.data.panacim.IPanaCimClientMessageReceiver#setMessage(com.itac.mes.datainterface.data.panacim.PanaCimClientMessage)
|
||||
*/
|
||||
@Override
|
||||
public void setMessage(PanaCimClientMessage message) {
|
||||
|
||||
// eingehende Nachricht weiter leiten
|
||||
LogHandler.log(getClass().getSimpleName(), LogLevel.INFO, getLogHeader(message) + "received");
|
||||
LogHandler.log("MESSAGES", LogLevel.TRACE, getLogHeader(message) + "received:\n");
|
||||
|
||||
if (message.isPingResponse()) {
|
||||
// Zeit zwischen resp und req ermitteln
|
||||
long delta = System.currentTimeMillis() - pingRequestSent;
|
||||
responseStatistics.set(delta);
|
||||
responseStatistics.writeStatistics(getLogHeader(message));
|
||||
setNextPingRequest();
|
||||
}
|
||||
|
||||
if (messageReceiver != null) {
|
||||
LogHandler.log(getClass().getSimpleName(), LogLevel.TRACE, getLogHeader(message) + "dispatch received message");
|
||||
messageReceiver.setMessage(message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private void setNextPingRequest() {
|
||||
nextPingResponseExpected = Long.MAX_VALUE;
|
||||
nextPingRequest = System.currentTimeMillis() + pingRequestDelay;
|
||||
LogHandler.log(getClass().getSimpleName(), LogLevel.TRACE,
|
||||
getLogHeader() + "scheduled next ping request for " + timeFormatter.format(new Date(nextPingRequest)));
|
||||
|
||||
}
|
||||
|
||||
private void setNextPingResponse() {
|
||||
nextPingResponseExpected = System.currentTimeMillis() + maxPingResponseTime;
|
||||
LogHandler.log(getClass().getSimpleName(), LogLevel.TRACE, getLogHeader() + "ping response must be recieved before "
|
||||
+ timeFormatter.format(new Date(nextPingResponseExpected)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
public boolean isConnected() {
|
||||
return clientSocket != null && clientSocket.isConnected() && !clientSocket.isClosed();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,284 @@
|
||||
/*
|
||||
* Copyright (c) 2010 iTAC Software AG, Germany. All Rights Reserved.
|
||||
*
|
||||
* This software is protected by copyright. Under no circumstances may any part of this file in any form be copied,
|
||||
* printed, edited or otherwise distributed, be stored in a retrieval system, or be translated into another language
|
||||
* without the written permission of iTAC Software AG.
|
||||
*/
|
||||
|
||||
package com.itac.mes.datainterface.data.panacim;
|
||||
|
||||
import com.itac.mes.datainterface.data.Ascii;
|
||||
import com.itac.util.logging.LogHandler;
|
||||
import com.itac.util.logging.LogLevel;
|
||||
|
||||
/**
|
||||
* Siehe PanaCim MES InterfaceSpecification Chapter 3.1 Deses Protokoll wird ausschliesslich für den Server (also das DataInterface benutzt, nicht
|
||||
* jedoch für die Simulation. Deswegen kann auch hier fest von send und receive gesprochen werden (resp im logging so bezeichnet werden).
|
||||
*
|
||||
* @author frankp created 2011
|
||||
*/
|
||||
public class PanaCimCommProtocol {
|
||||
|
||||
boolean readyForStartOfMessage = true;
|
||||
boolean readyForEndOfMessage = false;
|
||||
|
||||
private StringBuffer currentMessage;
|
||||
private int messageCounter = 0;
|
||||
private int incompleteMessage = 0;
|
||||
private PanaCimSocket panaCimSocket;
|
||||
private IPanaCimMessageReceiver messageReceiver;
|
||||
|
||||
/** konstante Kennungen im PanaCim Protokoll */
|
||||
public static final String PANACIM_MESSAGES = "PANACIM_MESSAGES";
|
||||
|
||||
/**
|
||||
* @param panaCimSocket
|
||||
* @param connectionName
|
||||
*/
|
||||
public PanaCimCommProtocol(PanaCimSocket panaCimSocket) {
|
||||
super();
|
||||
|
||||
Ascii.directPrintableConstants.add(Ascii.NL);
|
||||
Ascii.directPrintableConstants.add(Ascii.CR);
|
||||
Ascii.explicitPrintableConstants.add(Ascii.STX);
|
||||
Ascii.explicitPrintableConstants.add(Ascii.ETX);
|
||||
Ascii.explicitPrintableConstants.add(Ascii.SOH);
|
||||
Ascii.explicitPrintableConstants.add(Ascii.TAB);
|
||||
|
||||
this.panaCimSocket = panaCimSocket;
|
||||
}
|
||||
|
||||
/**
|
||||
* ein einzelnes Zeichen geht ein; die Steuerung, wann ein neuer Datensatz beginnt wird hier vorgenommen; <br>
|
||||
* ebenso die Zählung der Nachrichten. Ist eine NAchricht vollständig, wird sie ausgegeben und der Receiver benachrichtigt
|
||||
*
|
||||
* @param b
|
||||
*/
|
||||
public synchronized void write(byte b) {
|
||||
// STX wurde empfangen
|
||||
if (readyForEndOfMessage) {
|
||||
switch (b) {
|
||||
case Ascii.ETX:
|
||||
// Message abschliessen und ausliefern...
|
||||
currentMessage.append((char) b);
|
||||
|
||||
// Jetzt ist die Message komplett, es kann geprueft werden, ob die Meldung OK ist, und dann in den Ausgabepuffer
|
||||
// geschoben werden
|
||||
PanaCimMessage panaCimMessage = new PanaCimMessage();
|
||||
panaCimMessage.setPanaCimSocket(panaCimSocket);
|
||||
panaCimMessage.setMessageNumber(messageCounter);
|
||||
|
||||
panaCimMessage.setCommunicationProtocol(this);
|
||||
|
||||
LogHandler.log(getClass().getSimpleName(), LogLevel.TRACE, getLogHeader()
|
||||
+ ": ETX received, message completed, ready for next message");
|
||||
LogHandler.log(PANACIM_MESSAGES, LogLevel.INFO, getLogHeader() + "received:\n"
|
||||
+ stringBuffer2UserMessage(currentMessage));
|
||||
// setzen der Daten, hiermit wird die weitere Struktur der eingegangenen Daten geprueft
|
||||
|
||||
try {
|
||||
panaCimMessage.setContent(getContentFromTransportLayerString(currentMessage.toString()));
|
||||
|
||||
if (messageReceiver != null) {
|
||||
messageReceiver.setMessage(panaCimMessage);
|
||||
}
|
||||
} catch (Exception pe) {
|
||||
LogHandler.log(PANACIM_MESSAGES, LogLevel.ERROR, getLogHeader() + ":\n" + stringBuffer2UserMessage(currentMessage)
|
||||
+ "\n" + pe.getMessage());
|
||||
}
|
||||
|
||||
// naechste Nachricht vorbereiten
|
||||
currentMessage = new StringBuffer();
|
||||
readyForStartOfMessage = true;
|
||||
readyForEndOfMessage = false;
|
||||
break;
|
||||
case Ascii.STX:
|
||||
// letzte Message als incomplete abhaken...
|
||||
LogHandler.log(getClass().getSimpleName(), LogLevel.ERROR, getLogHeader()
|
||||
+ ": received unexpected STX, start new message");
|
||||
incompleteMessage++;
|
||||
messageCounter++;
|
||||
LogHandler.log(getClass().getSimpleName(), LogLevel.ERROR, getLogHeader() + " is incomplete message# "
|
||||
+ incompleteMessage + ":\n" + stringBuffer2UserMessage(currentMessage));
|
||||
LogHandler.log(PANACIM_MESSAGES, LogLevel.ERROR, getLogHeader() + " is incomplete message# " + incompleteMessage
|
||||
+ ":\n" + stringBuffer2UserMessage(currentMessage));
|
||||
currentMessage = new StringBuffer();
|
||||
currentMessage.append((char) b);
|
||||
|
||||
break;
|
||||
default:
|
||||
// nur Daten anhaengen
|
||||
currentMessage.append((char) b);
|
||||
}
|
||||
} // anfangen mit STX, aufhoeren mit ETX
|
||||
else if (readyForStartOfMessage) {
|
||||
|
||||
switch (b) {
|
||||
case Ascii.STX:
|
||||
// es wird erwartungsgemaess eine neue Nachricht angefangen mit STX
|
||||
messageCounter++;
|
||||
LogHandler.log(getClass().getSimpleName(), LogLevel.TRACE, getLogHeader() + ": STX received");
|
||||
// Datenstruktur für neue Message anfangen, Daten anhaengen
|
||||
currentMessage = new StringBuffer();
|
||||
currentMessage.append((char) b);
|
||||
// theoretisch darf jetzt nach dem Protocol alles andere oder ein ETX kommen, aber kein STX
|
||||
readyForStartOfMessage = false;
|
||||
readyForEndOfMessage = true;
|
||||
break;
|
||||
default:
|
||||
LogHandler.log(getClass().getSimpleName(), LogLevel.ERROR, getLogHeader() + ": unexpected char '"
|
||||
+ getUserTextForChar((char) b) + "' received, ignore input");
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
// interner Fehler, sowohl readyforStart als auch readyforend sind false
|
||||
LogHandler.log(getClass().getSimpleName(), LogLevel.FATAL, getLogHeader() + ": internal error");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* eine Menge von Bytes aus dem Eingang setzen...
|
||||
*
|
||||
* @param b
|
||||
*/
|
||||
public synchronized void write(byte[] b) {
|
||||
if (b == null) {
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < b.length; i++) {
|
||||
write(b[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// alle Zeichen STX, ETX, SOH werden in der Form "<STX>" ausgegeben, alle anderen Zeichen als Text
|
||||
public static String stringBuffer2UserMessage(StringBuffer source) {
|
||||
StringBuffer result = new StringBuffer();
|
||||
for (int i = 0; i < source.length(); i++) {
|
||||
char c = source.charAt(i);
|
||||
result.append(getUserTextForChar(c));
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param c
|
||||
* @return
|
||||
*/
|
||||
private static Object getUserTextForChar(char c) {
|
||||
if (c == Ascii.STX) {
|
||||
return "<STX>";
|
||||
} else if (c == Ascii.SOH) {
|
||||
return "<SOH>";
|
||||
} else if (c == Ascii.ETX) {
|
||||
return "<ETX>";
|
||||
} else if (c == 0x0a || c == 0x0d || c == 0x09) {
|
||||
return c;
|
||||
} else if (c < 0x20 || c >= 127) {
|
||||
// alle normalerweise nicht druckbaren Zeichen in Hex-ausgeben
|
||||
return "<0x" + Integer.toHexString((byte) c) + ">";
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
private String getLogHeader() {
|
||||
if (panaCimSocket != null) {
|
||||
return "message#" + messageCounter + " on " + panaCimSocket.getLogHeader();
|
||||
}
|
||||
return "message#" + messageCounter + " on connection '???'";
|
||||
}
|
||||
|
||||
/**
|
||||
* der Transport-LayerString sieht ungefaehr so aus: <STX>len<SOH>content<ETX>.
|
||||
*
|
||||
* @param transportLayerString
|
||||
* @return "content" aus dem Beispiel
|
||||
* @throws ProtocolException
|
||||
*/
|
||||
protected String getContentFromTransportLayerString(String transportLayerString) throws ProtocolException {
|
||||
// verifizieren: STX lengthOfXmlMessage SOH XmlMessage ETX
|
||||
if (transportLayerString == null || transportLayerString.length() == 0) {
|
||||
throw new ProtocolException(getLogHeader() + "empty message");
|
||||
}
|
||||
// erstes Byte muss STX sein
|
||||
byte[] byteData = transportLayerString.getBytes();
|
||||
if (byteData[0] != Ascii.STX) {
|
||||
throw new ProtocolException(getLogHeader() + "missing STX in message");
|
||||
}
|
||||
if (byteData[byteData.length - 1] != Ascii.ETX) {
|
||||
throw new ProtocolException(getLogHeader() + "missing ETX in message");
|
||||
}
|
||||
// wo ist das SOH
|
||||
int sohPos = -1;
|
||||
for (int i = 0; i < byteData.length; i++) {
|
||||
if (byteData[i] == Ascii.SOH) {
|
||||
sohPos = i;
|
||||
}
|
||||
}
|
||||
if (sohPos < 0) {
|
||||
throw new ProtocolException(getLogHeader() + "missing SOH in message");
|
||||
}
|
||||
if (sohPos == 1) {
|
||||
throw new ProtocolException(getLogHeader() + "no length information in message");
|
||||
}
|
||||
// Laenge extrahieren
|
||||
String sLen = new String(byteData, 1, sohPos - 1);
|
||||
int iLen = -1;
|
||||
try {
|
||||
iLen = Integer.parseInt(sLen);
|
||||
} catch (NumberFormatException nfe) {
|
||||
throw new ProtocolException(getLogHeader() + "invalid length information in message");
|
||||
}
|
||||
if (iLen <= 0) {
|
||||
throw new ProtocolException(getLogHeader() + "invalid length information in message (zero or negativ )");
|
||||
}
|
||||
// String extrahieren
|
||||
String sContent = new String(byteData, sohPos + 1, byteData.length - sohPos - 2);
|
||||
// Laenge pruefen
|
||||
if (sContent.length() != iLen) {
|
||||
throw new ProtocolException(getLogHeader() + "length header in message is wrong, length=" + sLen + " and messageSize="
|
||||
+ sContent.length());
|
||||
}
|
||||
return sContent;
|
||||
}
|
||||
|
||||
/**
|
||||
* einen normalen content-String mit STX/Len/SOH/ETX einrahmen
|
||||
*
|
||||
* @param content
|
||||
* @return
|
||||
* @throws ProtocolException
|
||||
*/
|
||||
public String getTransportLayerString(String content) throws ProtocolException {
|
||||
if (content == null) {
|
||||
throw new ProtocolException(getLogHeader() + "empty message");
|
||||
}
|
||||
return (char) Ascii.STX + "" + content.length() + "" + (char) Ascii.SOH + content + (char) Ascii.ETX;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param messageReceiver
|
||||
*/
|
||||
public synchronized void setMessageReceier(IPanaCimMessageReceiver messageReceiver) {
|
||||
this.messageReceiver = messageReceiver;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
* @return
|
||||
* @throws SendException
|
||||
* @throws MessageException
|
||||
*/
|
||||
public void sendPingReqMessage() throws MessageException, SendException {
|
||||
messageCounter++;
|
||||
// Jetzt ist die Message komplett, es kann geprueft werden, ob die Meldung OK ist, und dann in den Ausgabepuffer
|
||||
// geschoben werden
|
||||
PanaCimMessage panaCimMessage = new PanaCimMessage();
|
||||
panaCimMessage.setPanaCimSocket(panaCimSocket);
|
||||
panaCimMessage.setMessageNumber(messageCounter);
|
||||
panaCimMessage.setCommunicationProtocol(this);
|
||||
// ausgeben der Nachricht wie wir sie senden
|
||||
panaCimMessage.makePingRequest();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright (c) 2010 iTAC Software AG, Germany. All Rights Reserved.
|
||||
*
|
||||
* This software is protected by copyright. Under no circumstances may any part of this file in any form be copied,
|
||||
* printed, edited or otherwise distributed, be stored in a retrieval system, or be translated into another language
|
||||
* without the written permission of iTAC Software AG.
|
||||
*/
|
||||
|
||||
package com.itac.mes.datainterface.data.panacim;
|
||||
|
||||
/**
|
||||
* @author frankp created 2011
|
||||
*/
|
||||
public class PanaCimHeaderResult {
|
||||
public int errorCode;
|
||||
public String errorText = "";
|
||||
public int actionCode = PanaCimActionCode.DO_NOTHING;
|
||||
}
|
||||
@@ -0,0 +1,446 @@
|
||||
/*
|
||||
* Copyright (c) 2010 iTAC Software AG, Germany. All Rights Reserved.
|
||||
*
|
||||
* This software is protected by copyright. Under no circumstances may any part of this file in any form be copied,
|
||||
* printed, edited or otherwise distributed, be stored in a retrieval system, or be translated into another language
|
||||
* without the written permission of iTAC Software AG.
|
||||
*/
|
||||
|
||||
package com.itac.mes.datainterface.data.panacim;
|
||||
|
||||
import static com.itac.mes.datainterface.data.smt.MessageLogger.MSG_LOGGER;
|
||||
import static com.itac.util.logging.LogLevel.DEBUG;
|
||||
import static com.itac.util.logging.LogLevel.ERROR;
|
||||
import static com.itac.util.logging.LogLevel.INFO;
|
||||
import static com.itac.util.logging.LogLevel.TRACE;
|
||||
|
||||
import java.io.StringReader;
|
||||
import java.io.StringWriter;
|
||||
|
||||
import javax.xml.bind.JAXBContext;
|
||||
import javax.xml.bind.JAXBException;
|
||||
import javax.xml.bind.Marshaller;
|
||||
import javax.xml.bind.Unmarshaller;
|
||||
|
||||
import com.itac.mes.datainterface.data.Station;
|
||||
import com.itac.panacim.Message;
|
||||
import com.itac.panacim.Message.Body;
|
||||
import com.itac.panacim.Message.Header;
|
||||
import com.itac.panacim.Message.Header.Location;
|
||||
import com.itac.util.logging.LogHandler;
|
||||
|
||||
/**
|
||||
* @author frankp created 2011
|
||||
*/
|
||||
public class PanaCimMessage {
|
||||
|
||||
public static final String PING_REQ = "PING_REQ";
|
||||
public static final String PING_RSP = "PING_RSP";
|
||||
private static final String LOGGER = PanaCimMessage.class.getSimpleName();
|
||||
private static int maxMarshallingRetry = 2;
|
||||
|
||||
// über diese Verbindung sind die Daten eingegangen
|
||||
// die Confirmation muss über die selbe Verbindung hinausgehen...
|
||||
// es kann natürlich sein, daß diese connection irgendwann vom Client beendet wurde.
|
||||
// in diesem Fall muessen alle ausgehenden Nachrichten gepuffert werden
|
||||
private PanaCimSocket panaCimSocket;
|
||||
|
||||
/** der JAXB context ist fuer die Erzeugung der Marshaller/Unmarshaller notwendig */
|
||||
private static JAXBContext jaxbContext;
|
||||
|
||||
/** diese Instanz macht aus einem String (eingabe-Datenstrom) die strukturierte Instanz */
|
||||
private static Unmarshaller unmarshaller;
|
||||
/**
|
||||
* diese Instanz macht aus einer strukturierte Instanz einer Message einen String, der dann weiter verarbeitet und versendet werden kann
|
||||
*/
|
||||
private static Marshaller marshaller;
|
||||
|
||||
private int messageNumber;
|
||||
|
||||
/** ueber diese Instanz des Protocol Stacks ist die Message eingegangen */
|
||||
private PanaCimCommProtocol communicationProtocol;
|
||||
|
||||
private String xmlRequestMessage;
|
||||
|
||||
/** die eingehende Message */
|
||||
private Message requestMessage;
|
||||
|
||||
/** auf Basis der eingegangenen Message kann eine Antwort */
|
||||
private Message responseMessage;
|
||||
private String xmlContentResponse;
|
||||
private String rawResponseMessage;
|
||||
private boolean isPingResponse;
|
||||
private boolean isPingRequest;
|
||||
private Object syncObject = new Object();
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public PanaCimMessage() {
|
||||
super();
|
||||
if (maxMarshallingRetry < 1 || maxMarshallingRetry > 5) {
|
||||
LogHandler.log(LOGGER, INFO, "Value for max Marshalling set to {0}", maxMarshallingRetry);
|
||||
}
|
||||
try {
|
||||
getUnmarshaller();
|
||||
getMarshaller();
|
||||
} catch (JAXBException e) {
|
||||
LogHandler.log(LOGGER, ERROR, "failed to create JAXBContext\n" + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
private static JAXBContext getJAXBContext() throws JAXBException {
|
||||
if (jaxbContext == null) {
|
||||
jaxbContext = JAXBContext.newInstance(Message.class);
|
||||
}
|
||||
return jaxbContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws JAXBException
|
||||
*/
|
||||
private static Unmarshaller getUnmarshaller() throws JAXBException {
|
||||
if (unmarshaller == null) {
|
||||
unmarshaller = getJAXBContext().createUnmarshaller();
|
||||
}
|
||||
return unmarshaller;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws JAXBException
|
||||
*/
|
||||
private static Marshaller getMarshaller() throws JAXBException {
|
||||
if (marshaller == null) {
|
||||
marshaller = getJAXBContext().createMarshaller();
|
||||
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
|
||||
}
|
||||
return marshaller;
|
||||
}
|
||||
|
||||
private static void clearMarshallerAndUnmarshaller() {
|
||||
jaxbContext = null;
|
||||
unmarshaller = null;
|
||||
marshaller = null;
|
||||
}
|
||||
|
||||
public void newMarshallerAndUnmarshaller() {
|
||||
LogHandler.log(LOGGER, INFO, getLogHeader() + "destroy unmarshaller now, next call will create a new unmarshaller");
|
||||
clearMarshallerAndUnmarshaller();
|
||||
try {
|
||||
getUnmarshaller();
|
||||
} catch (JAXBException e) {
|
||||
LogHandler.log(LOGGER, ERROR, "failed to create JAXBContext\n" + e.getMessage(), e);
|
||||
}
|
||||
try {
|
||||
getMarshaller();
|
||||
} catch (JAXBException e) {
|
||||
LogHandler.log(LOGGER, ERROR, "failed to create JAXBContext\n" + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param messageCounter
|
||||
*/
|
||||
public void setMessageNumber(int messageNumber) {
|
||||
this.messageNumber = messageNumber;
|
||||
}
|
||||
|
||||
public String getLogHeader() {
|
||||
if (messageNumber == 0) {
|
||||
return "message#(unnumbered) ";
|
||||
}
|
||||
return "message#" + messageNumber + " ";
|
||||
}
|
||||
|
||||
public String getLogHeaderForStation(Station station) {
|
||||
return getLogHeader() + "for station " + station.getStationNumber() + " ";
|
||||
}
|
||||
|
||||
/**
|
||||
* @param contentFromTransportLayerString
|
||||
* @throws MessageException
|
||||
* @throws SendException
|
||||
*/
|
||||
public void setContent(String xmlMessageString) throws MessageException, SendException {
|
||||
if (xmlMessageString == null || xmlMessageString.isEmpty()) {
|
||||
throw new MessageException(getLogHeader() + "has empty xmlMessageString");
|
||||
}
|
||||
this.xmlRequestMessage = xmlMessageString;
|
||||
|
||||
// jedweder Eingang setzt den aktiv-Timer zurueck...
|
||||
// weder PING_REQ noch PING_RSP xml-parsen...
|
||||
if (xmlRequestMessage.equals(PING_REQ)) {
|
||||
LogHandler.log(LOGGER, TRACE, getLogHeader() + "received special Message " + PING_RSP);
|
||||
// sofort feste Message PING_REQ senden...
|
||||
xmlContentResponse = PING_RSP;
|
||||
LogHandler.log(LOGGER, TRACE, getLogHeader() + "send special Message " + PING_RSP);
|
||||
isPingRequest = true;
|
||||
sendXMLContent();
|
||||
return;
|
||||
}
|
||||
|
||||
if (xmlRequestMessage.equals(PING_RSP)) {
|
||||
LogHandler.log(LOGGER, TRACE, getLogHeader() + "received special Message " + PING_RSP);
|
||||
// nichts weiter tun
|
||||
isPingResponse = true;
|
||||
return;
|
||||
}
|
||||
int retryCounter = 0;
|
||||
boolean retry = true;
|
||||
boolean ok = false;
|
||||
synchronized (syncObject) {
|
||||
while (retry) {
|
||||
try {
|
||||
requestMessage = (Message) getUnmarshaller().unmarshal(new StringReader(xmlMessageString));
|
||||
ok = true;
|
||||
retry = false;
|
||||
} catch (JAXBException th) {
|
||||
retry = retryCounter <= maxMarshallingRetry;
|
||||
retryCounter++;
|
||||
LogHandler.log(LOGGER, ERROR, getLogHeader() + "unmarshalling failed!\n" + th.getMessage(), th);
|
||||
newMarshallerAndUnmarshaller();
|
||||
}
|
||||
}
|
||||
if (!ok) {
|
||||
throw new MessageException(getLogHeader() + "unmarshalling failed " + retryCounter + " times!\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param panaCimSocket
|
||||
*/
|
||||
public void setPanaCimSocket(PanaCimSocket panaCimSocket) {
|
||||
this.panaCimSocket = panaCimSocket;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
public String getXmlRequestMessage() {
|
||||
return xmlRequestMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
public Message getRequestMessage() {
|
||||
return requestMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws MessageException
|
||||
* @throws ParseException
|
||||
*/
|
||||
public void createResponseMessage() throws MessageException, ParseException {
|
||||
// wenn moeglich fuer diese Nachricht eine Response erzeugen.
|
||||
LogHandler.log(LOGGER, TRACE, getLogHeader() + "create response");
|
||||
if (requestMessage == null) {
|
||||
throw new MessageException(getLogHeader() + "has no request message");
|
||||
}
|
||||
if (!replyRequested()) {
|
||||
LogHandler.log(LOGGER, INFO, getLogHeader() + "reply flag is not set, no response message is created");
|
||||
return;
|
||||
}
|
||||
responseMessage = new Message();
|
||||
// header duplizieren
|
||||
|
||||
Header requestHeader = getHeader(); // aus dem request
|
||||
Header header = new Header();
|
||||
header.setMessageClass(requestHeader.getMessageClass());
|
||||
header.setReply(0);
|
||||
header.setTransactionID(requestHeader.getTransactionID());
|
||||
header.setLocation(getRequestLocation());
|
||||
|
||||
LogHandler.log(LOGGER, TRACE, getLogHeader() + "copy header from requestMessage");
|
||||
responseMessage.setHeader(header);
|
||||
// hier kann die Nachricht noch nicht vollstaendig aufbereitet werden, da
|
||||
// noch nicht alle Daten eingetragen sind.
|
||||
// das erzeugen der Response-Message erzeugt nur den Header...
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws MessageException
|
||||
* @throws SendException
|
||||
*/
|
||||
public void sendResponseMessage() throws MessageException, SendException {
|
||||
LogHandler.log(LOGGER, INFO, getLogHeader() + "send response");
|
||||
|
||||
if (responseMessage == null) {
|
||||
throw new MessageException(getLogHeader() + "response text is empty");
|
||||
}
|
||||
// die als Klasse vorliegende Nachricht in einen XML-String wandeln
|
||||
LogHandler.log(LOGGER, TRACE, getLogHeader() + "marshal response");
|
||||
StringWriter stringWriter = new StringWriter();
|
||||
int retryCounter = 0;
|
||||
boolean retry = true;
|
||||
boolean ok = false;
|
||||
synchronized (stringWriter) {
|
||||
while (retry) {
|
||||
try {
|
||||
getMarshaller().marshal(responseMessage, stringWriter);
|
||||
ok = true;
|
||||
retry = false;
|
||||
} catch (JAXBException th) {
|
||||
// versuchen das Marshalling zu wiederolen
|
||||
retryCounter++;
|
||||
retry = retryCounter <= maxMarshallingRetry;
|
||||
LogHandler.log(LOGGER, ERROR, getLogHeader() + "marshalling response failed!\n" + th.getMessage(), th);
|
||||
newMarshallerAndUnmarshaller();
|
||||
}
|
||||
}
|
||||
if (!ok) {
|
||||
throw new MessageException(getLogHeader() + "marshalling response failed " + retryCounter + " times!\n");
|
||||
}
|
||||
}
|
||||
xmlContentResponse = stringWriter.toString();
|
||||
sendXMLContent();
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws MessageException
|
||||
* @throws SendException
|
||||
*
|
||||
*/
|
||||
private void sendXMLContent() throws MessageException, SendException {
|
||||
if (xmlContentResponse == null || xmlContentResponse.isEmpty()) {
|
||||
throw new MessageException(getLogHeader() + "xmlContent of marshalled response is empty");
|
||||
}
|
||||
|
||||
LogHandler.log(MSG_LOGGER, DEBUG, xmlContentResponse);
|
||||
|
||||
// die als xmlResponseMessage vorliegenden String in ein versendbares Format bringen
|
||||
LogHandler.log(LOGGER, TRACE, getLogHeader() + "apply protocol to response");
|
||||
try {
|
||||
rawResponseMessage = communicationProtocol.getTransportLayerString(xmlContentResponse);
|
||||
} catch (ProtocolException e) {
|
||||
LogHandler.log(LOGGER, ERROR, getLogHeader() + " applying protocol to response message failed!\n" + e.getMessage(), e);
|
||||
throw new MessageException(getLogHeader() + "applying protocol to response failed!\n" + e.getMessage());
|
||||
}
|
||||
|
||||
panaCimSocket.sendResponse(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param communicationProtocol
|
||||
*/
|
||||
public void setCommunicationProtocol(PanaCimCommProtocol communicationProtocol) {
|
||||
this.communicationProtocol = communicationProtocol;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
public String getXmlResponseMessageString() {
|
||||
return xmlContentResponse;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param x
|
||||
*/
|
||||
public void setRawResponseMessage(String rawResonseMessage) {
|
||||
this.rawResponseMessage = rawResonseMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
public String getRawResponseMessageString() {
|
||||
return rawResponseMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
* @throws ParseException
|
||||
*/
|
||||
public boolean replyRequested() throws ParseException {
|
||||
return getHeader() != null && getHeader().getReply() != null && getHeader().getReply() == 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param responseMessage2
|
||||
* @return
|
||||
* @throws MessageException
|
||||
*/
|
||||
public Body getOrCreateBody(Message responseMessage) throws MessageException {
|
||||
if (responseMessage == null) {
|
||||
throw new MessageException(getLogHeader() + "response is null");
|
||||
}
|
||||
if (responseMessage.getBody() != null) {
|
||||
return responseMessage.getBody();
|
||||
}
|
||||
|
||||
Body body = new Body();
|
||||
responseMessage.setBody(body);
|
||||
return body;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param header
|
||||
* @return
|
||||
* @throws MessageException
|
||||
*/
|
||||
private Location getRequestLocation() throws MessageException {
|
||||
Header reqHeader = getRequestMessage().getHeader();
|
||||
if (reqHeader == null) {
|
||||
throw new MessageException(getLogHeader() + "no <header> tag found in <message>");
|
||||
}
|
||||
Location locationTag = reqHeader.getLocation();
|
||||
if (locationTag == null) {
|
||||
throw new MessageException(getLogHeader() + "no <location> tag found in <header>");
|
||||
}
|
||||
return reqHeader.getLocation();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
public Message getResponseMessage() {
|
||||
return responseMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws SendException
|
||||
* @throws MessageException
|
||||
*
|
||||
*/
|
||||
public void makePingRequest() throws MessageException, SendException {
|
||||
xmlContentResponse = PING_REQ;
|
||||
|
||||
sendXMLContent();
|
||||
}
|
||||
|
||||
public boolean isPingResponse() {
|
||||
return isPingResponse;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
* @throws ParseException
|
||||
*/
|
||||
public Body getBody() throws ParseException {
|
||||
if (requestMessage.getBody() == null) {
|
||||
throw new ParseException(getLogHeader() + "no <body> tag found in <message>");
|
||||
}
|
||||
return requestMessage.getBody();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param message
|
||||
* @return
|
||||
* @throws ParseException
|
||||
* @throws MessageException
|
||||
*/
|
||||
public Header getHeader() throws ParseException {
|
||||
Message message = getRequestMessage();
|
||||
// message.getHeaderOrBodyOrItemResults() kann nicht null sein...
|
||||
if (message.getHeader() != null) {
|
||||
return message.getHeader();
|
||||
}
|
||||
throw new ParseException(getLogHeader() + "no <header> tag found in <message>");
|
||||
}
|
||||
|
||||
public boolean isPingRequest() {
|
||||
return isPingRequest;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright (c) 2010 iTAC Software AG, Germany. All Rights Reserved.
|
||||
*
|
||||
* This software is protected by copyright. Under no circumstances may any part of this file in any form be copied,
|
||||
* printed, edited or otherwise distributed, be stored in a retrieval system, or be translated into another language
|
||||
* without the written permission of iTAC Software AG.
|
||||
*/
|
||||
|
||||
package com.itac.mes.datainterface.data.panacim;
|
||||
|
||||
/**
|
||||
* @author frankp created 2011
|
||||
*/
|
||||
public interface PanaCimOperationType {
|
||||
|
||||
final static int REPLACED = 1;
|
||||
final static int SPLICED = 2;
|
||||
final static int REMOVED = 3;
|
||||
final static int ADDED = 4;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,187 @@
|
||||
package com.itac.mes.datainterface.data.panacim;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketException;
|
||||
|
||||
import com.itac.mes.datainterface.data.PanaCimApplication;
|
||||
import com.itac.mes.datainterface.datasource.PanaCimDataSource;
|
||||
import com.itac.util.logging.LogHandler;
|
||||
import com.itac.util.logging.LogLevel;
|
||||
|
||||
public class PanaCimServerConnection {
|
||||
|
||||
private Thread connectThread = null;
|
||||
private ServerSocket serverSocket;
|
||||
private int port;
|
||||
private String connectionName;
|
||||
private int counter = 0;
|
||||
private PanaCimDataSource panaCimSocketListener;
|
||||
private PanaCimApplication messageReceiver;
|
||||
private long maximumMessageInterval;
|
||||
private long maximumPingResponseTime;
|
||||
private long pingRequestDelayTime;
|
||||
|
||||
public PanaCimServerConnection(String connectionName, int port, long maximumMessageInterval, long maximumPingResponseTime,
|
||||
long pingRequestDelayTime) {
|
||||
super();
|
||||
this.connectionName = connectionName;
|
||||
this.port = port;
|
||||
this.maximumMessageInterval = maximumMessageInterval;
|
||||
this.maximumPingResponseTime = maximumPingResponseTime;
|
||||
this.pingRequestDelayTime = pingRequestDelayTime;
|
||||
}
|
||||
|
||||
public void cutConnection() {
|
||||
LogHandler.debug(getName() + ": start Server cut connection");
|
||||
if (connectThread != null) {
|
||||
// keine weiteren Connects zulassen, wenn noch nichts connected war
|
||||
connectThread.interrupt();
|
||||
while (connectThread != null && !connectThread.isInterrupted()) {
|
||||
LogHandler.info(getName() + ": Server cut connection");
|
||||
try {
|
||||
Thread.sleep(5);
|
||||
} catch (InterruptedException e) {
|
||||
// ignore this exception
|
||||
}
|
||||
LogHandler.debug(getName() + ": Server connection cut completed");
|
||||
connectThread = null;
|
||||
}
|
||||
} else {
|
||||
LogHandler.debug(getName() + ": Server connection already closed");
|
||||
}
|
||||
// neue Verbindung akzeptieren
|
||||
newConnectThread();
|
||||
}
|
||||
|
||||
public PanaCimServerConnection getServerConnection() {
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean start() throws IOException {
|
||||
if (serverSocket == null) {
|
||||
LogHandler.log(PanaCimServerConnection.class.getSimpleName(), LogLevel.INFO,
|
||||
getName() + "start a new socket on port " + port);
|
||||
serverSocket = new ServerSocket(port);
|
||||
}
|
||||
return newConnectThread();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private boolean newConnectThread() {
|
||||
if (connectThread == null) {
|
||||
connectThread = new Thread(connectionName) {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
// blockierender Aufruf
|
||||
while (!isInterrupted() && serverSocket != null) {
|
||||
try {
|
||||
LogHandler.trace(getName() + ": wait for TCP client #" + (++counter) + " to connect on port " + port + " ...");
|
||||
if (serverSocket == null) {
|
||||
// darf hier nicht auftauchen,
|
||||
return;
|
||||
}
|
||||
@SuppressWarnings("resource")
|
||||
Socket socket = serverSocket.accept(); // blockiert, bis sich ein Client angemeldet hat
|
||||
|
||||
try {
|
||||
socket.setKeepAlive(true);
|
||||
LogHandler.log(PanaCimServerConnection.class.getSimpleName(), LogLevel.INFO,
|
||||
getName() + " connection keepAlive is (" + socket.getKeepAlive() + ")");
|
||||
} catch (SocketException e) {
|
||||
LogHandler.log(PanaCimServerConnection.class.getSimpleName(), LogLevel.ERROR,
|
||||
getName() + " connection setting keepAlive failed: " + e.getMessage(), e);
|
||||
}
|
||||
|
||||
LogHandler.log(PanaCimServerConnection.class.getSimpleName(), LogLevel.INFO,
|
||||
getName() + " client connected, start now a new socket");
|
||||
PanaCimSocket panasocket = new PanaCimSocket(connectionName + "#" + counter, maximumMessageInterval,
|
||||
maximumPingResponseTime, pingRequestDelayTime);
|
||||
panasocket.setSocket(socket);
|
||||
panasocket.startSocket();
|
||||
panasocket.setMessageReceiver(messageReceiver);
|
||||
|
||||
if (panaCimSocketListener != null) {
|
||||
panaCimSocketListener.newPanaCimSocket(panasocket);
|
||||
}
|
||||
|
||||
// doClientConnected();
|
||||
|
||||
} catch (final IOException e) {
|
||||
// IO-Exception wen die Verbindung abgebrochen wurde
|
||||
LogHandler.log(PanaCimServerConnection.class.getSimpleName(), LogLevel.TRACE,
|
||||
getName() + ": connection closed by client");
|
||||
// doClientDisconnected();
|
||||
connectThread = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
if (connectThread != null) {
|
||||
if (connectThread.isAlive()) {
|
||||
LogHandler.log(getClass().getSimpleName(), LogLevel.ERROR, getName() + ": Connect thread already alive");
|
||||
return false;
|
||||
}
|
||||
connectThread.start();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
public String getName() {
|
||||
return connectionName;
|
||||
}
|
||||
|
||||
public void unbind() throws IOException {
|
||||
serverSocket.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true, wenn die Verbindung abgebaut wurde
|
||||
*/
|
||||
public boolean stop() {
|
||||
if (connectThread == null) {
|
||||
return false;
|
||||
}
|
||||
connectThread.interrupt();
|
||||
shutdown();
|
||||
|
||||
connectThread = null;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* sauberes beenden und herunterfahren, aber ohne Exceptions und Meldungen...
|
||||
*/
|
||||
public void shutdown() {
|
||||
if (serverSocket != null) {
|
||||
try {
|
||||
serverSocket.close();
|
||||
} catch (IOException e) {
|
||||
LogHandler.log(getClass().getSimpleName(), LogLevel.ERROR, "closing socket failed", e);
|
||||
}
|
||||
serverSocket = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param panaCimDataSource
|
||||
*/
|
||||
public void setPanaSocketListener(PanaCimDataSource panaCimDataSource) {
|
||||
this.panaCimSocketListener = panaCimDataSource;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param application
|
||||
*/
|
||||
public void setMessageReceiver(PanaCimApplication messageReceiver) {
|
||||
this.messageReceiver = messageReceiver;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
* Copyright (c) 2010 iTAC Software AG, Germany. All Rights Reserved.
|
||||
*
|
||||
* This software is protected by copyright. Under no circumstances may any part of this file in any form be copied,
|
||||
* printed, edited or otherwise distributed, be stored in a retrieval system, or be translated into another language
|
||||
* without the written permission of iTAC Software AG.
|
||||
*/
|
||||
|
||||
package com.itac.mes.datainterface.data.panacim;
|
||||
|
||||
/**
|
||||
* @author frankp created 2011
|
||||
*/
|
||||
public class PanaCimSmtInterlockingResult extends PanaCimHeaderResult {
|
||||
}
|
||||
@@ -0,0 +1,358 @@
|
||||
/*
|
||||
* Copyright (c) 2010 iTAC Software AG, Germany. All Rights Reserved.
|
||||
*
|
||||
* This software is protected by copyright. Under no circumstances may any part of this file in any form be copied,
|
||||
* printed, edited or otherwise distributed, be stored in a retrieval system, or be translated into another language
|
||||
* without the written permission of iTAC Software AG.
|
||||
*/
|
||||
|
||||
package com.itac.mes.datainterface.data.panacim;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.Socket;
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
|
||||
import com.itac.util.logging.LogHandler;
|
||||
import com.itac.util.logging.LogLevel;
|
||||
|
||||
/**
|
||||
* @author frankp created 2011
|
||||
*/
|
||||
public class PanaCimSocket implements IPanaCimMessageReceiver {
|
||||
|
||||
private String connectionName;
|
||||
private PanaCimCommProtocol communicationProtocol;
|
||||
private Socket socket;
|
||||
private Thread readThread;
|
||||
private IPanaCimMessageReceiver messageReceiver;
|
||||
private long nextMessageExpected = Long.MAX_VALUE;
|
||||
private long nextPingResponseExpected = Long.MAX_VALUE;
|
||||
/** Zeitpunkt, wann der naechste Ping-Request zu senden ist */
|
||||
private long nextPingRequest = Long.MAX_VALUE;
|
||||
|
||||
/** statistik, wie lange die Request-Response zyklen dauern */
|
||||
private Stat responseStatistics = new Stat(10);
|
||||
/** Zeitpunkt, zu dem der letzte PING_REQ gesendet wurde... */
|
||||
private long pingRequestSent;
|
||||
|
||||
private SimpleDateFormat timeFormatter = (SimpleDateFormat) DateFormat.getTimeInstance();
|
||||
|
||||
// maximale Zeit zwischen 2 eingehenden Nachrichten auf einer Verbindung
|
||||
private long maximumMessageInterval;
|
||||
private Thread connectionAliveThread;
|
||||
private boolean isShuttingDown;
|
||||
private long pingRequestDelay;
|
||||
private long maxPingResponseTime;
|
||||
|
||||
/**
|
||||
* @param connectionName
|
||||
* Name der Verbindung
|
||||
* @param maximumMessageInterval
|
||||
* maximale Zeit zwischen 2 eingehenden Nachrichten in millies, die vergehen darf bevor die Connection
|
||||
* automatisch geschlossen wird. Wert 0 ist nicht aktiviert...
|
||||
* @param pingRequestDelay
|
||||
* Wert = 0: Server Socket sendet keine ping requests aus. <br>
|
||||
* Wert > 0: Server vermerkt den Eingang einer pingResponse und nach dem verstreichen der pingRequestDelay
|
||||
* millies wird der nächste pingReq gesendet
|
||||
* @param maxPingResponseTime
|
||||
* maximale Zeit in millies, die vergehen darf bevor eine ping response auf die soeben versendete PingRequest
|
||||
* empfangen worden sein muss. Die Verbindung wird geschlossen, wenn keine Response empfangen wird. Wird nur
|
||||
* ausgewertet, wenn auch ein PingRequest gesendet werden soll.<br>
|
||||
*/
|
||||
public PanaCimSocket(String connectionName, long maximumMessageInterval, long pingRequestDelay, long maxPingResponseTime) {
|
||||
super();
|
||||
this.connectionName = connectionName;
|
||||
this.maximumMessageInterval = maximumMessageInterval;
|
||||
this.pingRequestDelay = pingRequestDelay;
|
||||
this.maxPingResponseTime = maxPingResponseTime;
|
||||
communicationProtocol = new PanaCimCommProtocol(this);
|
||||
communicationProtocol.setMessageReceier(this);
|
||||
timeFormatter.applyPattern("HH:mm:ss,S");
|
||||
// implizites initialisierung des JaxBContext
|
||||
PanaCimClientMessage pMsg = new PanaCimClientMessage();
|
||||
LogHandler.log(getClass().getSimpleName(), LogLevel.TRACE, pMsg.getLogHeader());
|
||||
}
|
||||
|
||||
public void setSocket(Socket socket) {
|
||||
this.socket = socket;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public void startSocket() {
|
||||
// inputStream und outputStream verbinden...
|
||||
String readThreadName = connectionName + "ReadThread";
|
||||
LogHandler.log(getClass().getSimpleName(), LogLevel.INFO, "startup " + readThreadName + " for " + connectionName);
|
||||
readThread = new Thread(readThreadName) {
|
||||
@Override
|
||||
public void run() {
|
||||
setNextMessageExpected();
|
||||
|
||||
try {
|
||||
while (socket.getInputStream() != null && !isShuttingDown) {
|
||||
try {
|
||||
try {
|
||||
Thread.sleep(10);
|
||||
} catch (InterruptedException e1) {
|
||||
LogHandler.log(getName(), LogLevel.ERROR, "connection " + getName() + " read thread interrupted!");
|
||||
}
|
||||
final int bytesAvail = socket.getInputStream().available();
|
||||
if (bytesAvail > 0) {
|
||||
final byte[] inData = new byte[bytesAvail];
|
||||
socket.getInputStream().read(inData);
|
||||
// alle eingehenden Daten des Stroms an den Eingangspuffer weiterleiten
|
||||
communicationProtocol.write(inData);
|
||||
}
|
||||
} catch (final IOException e) {
|
||||
// jetzt koenne keine weiteren Daten gelesen werden, also wird der Thread beendet!
|
||||
doDataExchangeFailed("reading");
|
||||
shutdownConnection();
|
||||
return;
|
||||
}
|
||||
}
|
||||
} catch (IOException ioe) {
|
||||
// jetzt koenne keine weiteren Daten gelesen werden, also wird der Thread beendet!
|
||||
doDataExchangeFailed("reading");
|
||||
shutdownConnection();
|
||||
return;
|
||||
}
|
||||
}
|
||||
};
|
||||
readThread.start();
|
||||
|
||||
// jetzt muss auch der MessageReceiveTimer gesetzt werden...
|
||||
// bis zu einem gewissen Zeitpunkt muss immer die naechste Nachricht empfangen worden sein
|
||||
|
||||
if (maximumMessageInterval > 0) {
|
||||
LogHandler.log(getClass().getSimpleName(), LogLevel.INFO, getLogHeader() + "maximal incoming message interval is "
|
||||
+ pingRequestDelay + " millies");
|
||||
} else {
|
||||
LogHandler.log(getClass().getSimpleName(), LogLevel.INFO, getLogHeader() + "no keep alive, function disabled");
|
||||
}
|
||||
if (pingRequestDelay > 0) {
|
||||
LogHandler.log(getClass().getSimpleName(), LogLevel.INFO, getLogHeader() + "active ping request interval is "
|
||||
+ pingRequestDelay + " millies");
|
||||
setNextPingRequest();
|
||||
} else {
|
||||
LogHandler.log(getClass().getSimpleName(), LogLevel.INFO, getLogHeader() + "no active ping request, funcion disabled");
|
||||
}
|
||||
|
||||
if (maximumMessageInterval > 0 || pingRequestDelay > 0) {
|
||||
String connectionAliveThreadName = connectionName + "AliveThread";
|
||||
LogHandler.log(getClass().getSimpleName(), LogLevel.INFO, "startup " + connectionAliveThreadName + " for " + connectionName);
|
||||
connectionAliveThread = new Thread(connectionAliveThreadName) {
|
||||
@Override
|
||||
public void run() {
|
||||
while (!isInterrupted() && !isShuttingDown) {
|
||||
try {
|
||||
try {
|
||||
Thread.sleep(10);
|
||||
} catch (InterruptedException e1) {
|
||||
// ignore interrupt Exception
|
||||
LogHandler.log(getName(), LogLevel.ERROR, "connection " + getName() + " alive thread interrupted!");
|
||||
}
|
||||
if (System.currentTimeMillis() > nextMessageExpected) {
|
||||
// wenn eine Verbindung aufgebaut ist diese jetzt schliessen
|
||||
LogHandler.log(getName(), LogLevel.INFO, "connection " + connectionName
|
||||
+ " inactive too long, close connection now!");
|
||||
shutdownConnection();
|
||||
return;
|
||||
}
|
||||
if (System.currentTimeMillis() > nextPingResponseExpected) {
|
||||
// wenn eine Verbindung aufgebaut ist diese jetzt schliessen
|
||||
LogHandler.log(getName(), LogLevel.ERROR, "connection " + connectionName + " did not receive "
|
||||
+ PanaCimMessage.PING_RSP + " in time, close connection now!");
|
||||
shutdownConnection();
|
||||
return;
|
||||
}
|
||||
if (System.currentTimeMillis() >= nextPingRequest) {
|
||||
// wenn eine Verbindung aufgebaut ist diese jetzt schliessen
|
||||
sendPingRequest();
|
||||
}
|
||||
try {
|
||||
Thread.sleep(1);
|
||||
} catch (InterruptedException e) {
|
||||
LogHandler.log(getName(), LogLevel.ERROR, "connection " + getName() + " alive thread died...!");
|
||||
return;
|
||||
}
|
||||
} catch (SendException se) {
|
||||
LogHandler.log(getName(), LogLevel.ERROR, "connection " + getName() + " alive thread problem: " + se.getMessage());
|
||||
shutdownConnection();
|
||||
} catch (Exception e) {
|
||||
LogHandler.log(getName(), LogLevel.ERROR, "connection " + getName() + " alive thread problem...!", e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
connectionAliveThread.start();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* vollstaendiges Schliessen einer Verbindung, gestartete ative Threads anhalten (Lese-Thread, ping Thread,
|
||||
* keepaliveThread)
|
||||
*/
|
||||
protected void shutdownConnection() {
|
||||
if (isShuttingDown) {
|
||||
// shutdown is in progress
|
||||
return;
|
||||
}
|
||||
isShuttingDown = true;
|
||||
LogHandler.log(getClass().getSimpleName(), LogLevel.INFO, getLogHeader() + "shutting down");
|
||||
|
||||
// Keine weitere Überwachung eingehender Nachrichten
|
||||
nextMessageExpected = Long.MAX_VALUE;
|
||||
|
||||
if (readThread != null && readThread.isAlive()) {
|
||||
LogHandler.log(getClass().getSimpleName(), LogLevel.DEBUG, getLogHeader() + "interrupting " + readThread.getName());
|
||||
readThread.interrupt();
|
||||
}
|
||||
if (connectionAliveThread != null && connectionAliveThread.isAlive()) {
|
||||
LogHandler
|
||||
.log(getClass().getSimpleName(), LogLevel.DEBUG, getLogHeader() + "interrupting " + connectionAliveThread.getName());
|
||||
connectionAliveThread.interrupt();
|
||||
}
|
||||
try {
|
||||
LogHandler.log(getClass().getSimpleName(), LogLevel.DEBUG, getLogHeader() + "closing socket " + connectionName);
|
||||
socket.close();
|
||||
} catch (IOException e) {
|
||||
LogHandler.log(getClass().getSimpleName(), LogLevel.DEBUG, getLogHeader() + "closing socket " + connectionName + " failed: "
|
||||
+ e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
private void doDataExchangeFailed(String operation) {
|
||||
LogHandler.log(getClass().getSimpleName(), LogLevel.INFO, getLogHeader() + "problems " + operation);
|
||||
// if (tcpServerCommunicationListener != null) {
|
||||
// tcpServerCommunicationListener.dataExchangeFailed();
|
||||
// }
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
public String getLogHeader() {
|
||||
return "connection " + connectionName + " ";
|
||||
}
|
||||
|
||||
/**
|
||||
* @param message
|
||||
* @return
|
||||
*/
|
||||
private String getLogHeader(PanaCimMessage message) {
|
||||
return message.getLogHeader() + "on " + getLogHeader();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param application
|
||||
*/
|
||||
public void setMessageReceiver(IPanaCimMessageReceiver messageReceiver) {
|
||||
this.messageReceiver = messageReceiver;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws MessageException
|
||||
* @throws SendException
|
||||
*
|
||||
*/
|
||||
public void sendResponse(PanaCimMessage message) throws MessageException, SendException {
|
||||
// es muss den Content als xml geben
|
||||
LogHandler.log(getClass().getSimpleName(), LogLevel.INFO, getLogHeader(message) + "send response");
|
||||
if (message.getRawResponseMessageString() == null || message.getRawResponseMessageString().isEmpty()) {
|
||||
throw new MessageException(getLogHeader(message) + "raw response message is empty");
|
||||
}
|
||||
|
||||
// ausgeben der Nachricht wie wir sie senden
|
||||
StringBuffer stb = new StringBuffer(message.getRawResponseMessageString());
|
||||
LogHandler.log(PanaCimCommProtocol.PANACIM_MESSAGES, LogLevel.INFO,
|
||||
getLogHeader(message) + "send:\n" + PanaCimCommProtocol.stringBuffer2UserMessage(stb));
|
||||
try {
|
||||
|
||||
socket.getOutputStream().write(message.getRawResponseMessageString().getBytes());
|
||||
socket.getOutputStream().flush();
|
||||
} catch (IOException e) {
|
||||
// Fehler beim schreiben
|
||||
LogHandler.log(getClass().getSimpleName(), LogLevel.ERROR,
|
||||
getLogHeader(message) + "write exception:\n" + PanaCimCommProtocol.stringBuffer2UserMessage(stb), e);
|
||||
doDataExchangeFailed("writing");
|
||||
shutdownConnection();
|
||||
throw new SendException(getLogHeader(message) + "raw response message not send!\n" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws MessageException
|
||||
* @throws SendException
|
||||
*
|
||||
*/
|
||||
public void sendPingRequest() throws MessageException, SendException {
|
||||
// es muss den Content als xml geben
|
||||
LogHandler.log(getClass().getSimpleName(), LogLevel.INFO, getLogHeader() + "send " + PanaCimMessage.PING_REQ);
|
||||
nextPingRequest = Long.MAX_VALUE;
|
||||
pingRequestSent = System.currentTimeMillis();
|
||||
this.nextPingResponseExpected = pingRequestSent + maxPingResponseTime;
|
||||
LogHandler.log(getClass().getSimpleName(), LogLevel.INFO, getLogHeader() + "next " + PanaCimMessage.PING_RSP
|
||||
+ " must be received before " + timeFormatter.format(new Date(nextPingResponseExpected)));
|
||||
communicationProtocol.sendPingReqMessage();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.itac.mes.datainterface.data.panacim.PanaCimMessageReceiver#setMessage(com.itac.mes.datainterface.data.panacim.PanaCimMessage)
|
||||
*/
|
||||
@Override
|
||||
public void setMessage(PanaCimMessage message) throws ParseException {
|
||||
// eingehende Nachricht weiter leiten
|
||||
LogHandler.log(getClass().getSimpleName(), LogLevel.TRACE, getLogHeader(message) + "received");
|
||||
// Ping-Request nur senden, wenn client nichts sendet..
|
||||
if (nextPingRequest < Long.MAX_VALUE) {
|
||||
setNextPingRequest();
|
||||
}
|
||||
|
||||
if (message.isPingResponse()) {
|
||||
// Zeit zwischen resp und req ermitteln
|
||||
long delta = System.currentTimeMillis() - pingRequestSent;
|
||||
responseStatistics.set(delta);
|
||||
responseStatistics.writeStatistics(getLogHeader(message));
|
||||
setNextPingRequest();
|
||||
}
|
||||
setNextMessageExpected();
|
||||
if (message.isPingRequest() || message.isPingResponse()) {
|
||||
return;
|
||||
}
|
||||
if (messageReceiver != null) {
|
||||
LogHandler.log(getClass().getSimpleName(), LogLevel.TRACE, getLogHeader(message) + "dispatch received message");
|
||||
messageReceiver.setMessage(message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
protected void setNextMessageExpected() {
|
||||
if (maximumMessageInterval == 0) {
|
||||
return;
|
||||
}
|
||||
long start = System.currentTimeMillis();
|
||||
this.nextMessageExpected = start + maximumMessageInterval;
|
||||
LogHandler.log(getClass().getSimpleName(), LogLevel.INFO, getLogHeader() + "next message must be received before "
|
||||
+ timeFormatter.format(new Date(nextMessageExpected)));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
protected void setNextPingRequest() {
|
||||
if (pingRequestDelay == 0) {
|
||||
return;
|
||||
}
|
||||
nextPingResponseExpected = Long.MAX_VALUE;
|
||||
long start = System.currentTimeMillis();
|
||||
this.nextPingRequest = start + pingRequestDelay;
|
||||
LogHandler.log(getClass().getSimpleName(), LogLevel.INFO, getLogHeader() + "schedule next " + PanaCimMessage.PING_REQ + " to "
|
||||
+ timeFormatter.format(new Date(nextPingRequest)));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright (c) 2010 iTAC Software AG, Germany. All Rights Reserved.
|
||||
*
|
||||
* This software is protected by copyright. Under no circumstances may any part of this file in any form be copied,
|
||||
* printed, edited or otherwise distributed, be stored in a retrieval system, or be translated into another language
|
||||
* without the written permission of iTAC Software AG.
|
||||
*/
|
||||
|
||||
package com.itac.mes.datainterface.data.panacim;
|
||||
|
||||
/**
|
||||
* @author frankp created 2011
|
||||
*/
|
||||
public interface PanaCimSocketListener {
|
||||
|
||||
public void newPanaCimSocket(PanaCimSocket panasocket);
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright (c) 2010 iTAC Software AG, Germany. All Rights Reserved.
|
||||
*
|
||||
* This software is protected by copyright. Under no circumstances may any part of this file in any form be copied,
|
||||
* printed, edited or otherwise distributed, be stored in a retrieval system, or be translated into another language
|
||||
* without the written permission of iTAC Software AG.
|
||||
*/
|
||||
|
||||
package com.itac.mes.datainterface.data.panacim;
|
||||
|
||||
/**
|
||||
* @author frankp created 2011
|
||||
*/
|
||||
public class ParseException extends Exception {
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 5131243469715734166L;
|
||||
|
||||
/**
|
||||
* @param format
|
||||
*/
|
||||
public ParseException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright (c) 2010 iTAC Software AG, Germany. All Rights Reserved.
|
||||
*
|
||||
* This software is protected by copyright. Under no circumstances may any part of this file in any form be copied,
|
||||
* printed, edited or otherwise distributed, be stored in a retrieval system, or be translated into another language
|
||||
* without the written permission of iTAC Software AG.
|
||||
*/
|
||||
|
||||
package com.itac.mes.datainterface.data.panacim;
|
||||
|
||||
/**
|
||||
* @author frankp created 2011
|
||||
*/
|
||||
public class ProtocolException extends Exception {
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = -773100451955903330L;
|
||||
|
||||
/**
|
||||
* @param string
|
||||
*/
|
||||
public ProtocolException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright (c) 2010 iTAC Software AG, Germany. All Rights Reserved.
|
||||
*
|
||||
* This software is protected by copyright. Under no circumstances may any part of this file in any form be copied,
|
||||
* printed, edited or otherwise distributed, be stored in a retrieval system, or be translated into another language
|
||||
* without the written permission of iTAC Software AG.
|
||||
*/
|
||||
|
||||
package com.itac.mes.datainterface.data.panacim;
|
||||
|
||||
/**
|
||||
* @author frankp created 2011
|
||||
*/
|
||||
public class SendException extends Exception {
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = -773100451955903330L;
|
||||
|
||||
/**
|
||||
* @param string
|
||||
*/
|
||||
public SendException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (c) 2010 iTAC Software AG, Germany. All Rights Reserved.
|
||||
*
|
||||
* This software is protected by copyright. Under no circumstances may any part of this file in any form be copied,
|
||||
* printed, edited or otherwise distributed, be stored in a retrieval system, or be translated into another language
|
||||
* without the written permission of iTAC Software AG.
|
||||
*/
|
||||
package com.itac.mes.datainterface.data.panacim;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
|
||||
import com.itac.util.logging.LogHandler;
|
||||
import com.itac.util.logging.LogLevel;
|
||||
|
||||
/**
|
||||
* @author frankp created 2011
|
||||
*/
|
||||
public class Stat {
|
||||
|
||||
private long minTime = Long.MAX_VALUE;
|
||||
private long maxTime = 0;
|
||||
private long counter = 0;
|
||||
private long sumTime = 0;
|
||||
private int display = 100;
|
||||
|
||||
/**
|
||||
* @param i
|
||||
*/
|
||||
public Stat(int i) {
|
||||
display = i;
|
||||
}
|
||||
|
||||
// Zaehler für min, max, average, count
|
||||
public void set(long time) {
|
||||
counter++;
|
||||
if (time < minTime) {
|
||||
minTime = time;
|
||||
}
|
||||
if (time > maxTime) {
|
||||
maxTime = time;
|
||||
}
|
||||
sumTime += time;
|
||||
}
|
||||
|
||||
public void writeStatistics(String string) {
|
||||
if ((counter % display) > 0) {
|
||||
return;
|
||||
}
|
||||
LogHandler.log("Statistik", LogLevel.INFO, MessageFormat.format("{0} min={1}ms, max={2}ms, avg={3}ms over {4} messages",
|
||||
new Object[]{string, minTime, maxTime, (sumTime / counter), counter}));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* To change this template, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package com.itac.mes.datainterface.datasource;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author frankp
|
||||
*/
|
||||
public class PanaCimConnectionProperties {
|
||||
|
||||
private int port;
|
||||
private String name;
|
||||
|
||||
public int getPort() {
|
||||
return port;
|
||||
}
|
||||
|
||||
public void setPort(int port) {
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,263 @@
|
||||
/*
|
||||
* Copyright (c) 2010 iTAC Software AG, Germany. All Rights Reserved.
|
||||
*
|
||||
* This software is protected by copyright. Under no circumstances may any part of this file in any form be copied,
|
||||
* printed, edited or otherwise distributed, be stored in a retrieval system, or be translated into another language
|
||||
* without the written permission of iTAC Software AG.
|
||||
*/
|
||||
package com.itac.mes.datainterface.datasource;
|
||||
|
||||
import static com.itac.util.logging.LogLevel.DEBUG;
|
||||
import static com.itac.util.logging.LogLevel.ERROR;
|
||||
import static com.itac.util.logging.LogLevel.INFO;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.itac.mes.config.domain.Parameter;
|
||||
import com.itac.mes.datainterface.annotations.AAutoHandler;
|
||||
import com.itac.mes.datainterface.annotations.AInit;
|
||||
import com.itac.mes.datainterface.annotations.AInstantiationType;
|
||||
import com.itac.mes.datainterface.annotations.AParamValue;
|
||||
import com.itac.mes.datainterface.annotations.AParameter;
|
||||
import com.itac.mes.datainterface.annotations.AParameterDefaultValue;
|
||||
import com.itac.mes.datainterface.annotations.InstantiationType;
|
||||
import com.itac.mes.datainterface.data.Duration;
|
||||
import com.itac.mes.datainterface.data.PanaCimApplication;
|
||||
import com.itac.mes.datainterface.data.panacim.PanaCimServerConnection;
|
||||
import com.itac.mes.datainterface.data.panacim.PanaCimSocket;
|
||||
import com.itac.mes.datainterface.data.panacim.PanaCimSocketListener;
|
||||
import com.itac.mes.datainterface.data.panacim.ServerConnectionProperties;
|
||||
import com.itac.mes.datainterface.parser.PanaCimParser;
|
||||
import com.itac.mes.datainterface.process.IProcessor;
|
||||
import com.itac.util.logging.LogHandler;
|
||||
|
||||
/**
|
||||
* @author frankp created 2011
|
||||
*/
|
||||
@AInstantiationType(name = "panacim", type = InstantiationType.DATASOURCE)
|
||||
public class PanaCimDataSource extends BasicDataSource implements PanaCimSocketListener {
|
||||
|
||||
private static final String DATASOURCE_PANACIM = "datasource.panacim";
|
||||
/** Liste mit Namen der Verbindungen; diese werden instantiiert */
|
||||
private static final String CONNECTIONS = DATASOURCE_PANACIM + ".connections";
|
||||
/**
|
||||
* innerhalb dieser Zeitspanne muss eine Nachricht auf der Verbindung eingeangen sein, bevor sie automatisch geschlossen wird.<br>
|
||||
* dieser Mechanismus ist ncht aktiv, wenn der Wert 0 ist
|
||||
*/
|
||||
private static final String MAXIMUM_MESSAGE_INTERVAL = DATASOURCE_PANACIM + ".maximumMessageInterval";
|
||||
/**
|
||||
* innerhalb dieser Zeitspanne muss eine Antwort vom client auf ein PING_REQ des Servers eingeangen sein, bevor sie automatisch
|
||||
* geschlossen wird.<br>
|
||||
* dieser Mechanismus ist ncht aktiv, wenn der Wert 0 ist
|
||||
*/
|
||||
private static final String MAXIMUM_PING_RESPONSE_TIME = DATASOURCE_PANACIM + ".maximumPingResponseTime";
|
||||
/**
|
||||
* Nach der Verbindung eines Clients oder nach dem letzten erfolgreichen Empfang eines PING_RSP vom Client wird diese Zeit
|
||||
* gewartet, bis erneut ein PING_REQ zum Client gesendet wird
|
||||
*/
|
||||
private static final String PING_REQUEST_DELAY_TIME = DATASOURCE_PANACIM + ".pingRequestDelayTime";
|
||||
private static final String AUTORUN = DATASOURCE_PANACIM + ".autorun";
|
||||
private static final String LOGGER = PanaCimDataSource.class.getSimpleName();
|
||||
|
||||
@AParameter(name = DATASOURCE_PANACIM, description = "PanaCim Datasource",
|
||||
visibility = "DataSource=com.itac.mes.datainterface.datasource.PanaCimDataSource")
|
||||
private Parameter paramSource;
|
||||
|
||||
@AParameter(name = MAXIMUM_MESSAGE_INTERVAL, parent = DATASOURCE_PANACIM, description = "maximum message interval",
|
||||
type = Duration.class)
|
||||
private Parameter paramMaxMessages;
|
||||
@AParameter(name = MAXIMUM_PING_RESPONSE_TIME, parent = DATASOURCE_PANACIM, description = "maximum ping response",
|
||||
type = Duration.class)
|
||||
private Parameter paramMaxPingResponse;
|
||||
@AParameter(name = PING_REQUEST_DELAY_TIME, parent = DATASOURCE_PANACIM, description = "ping request delay",
|
||||
type = Duration.class)
|
||||
private Parameter paramPingRequest;
|
||||
@AParameter(name = CONNECTIONS, parent = DATASOURCE_PANACIM, description = "list with server connections", type = List.class,
|
||||
metaType = ServerConnectionProperties.class)
|
||||
private Parameter paramRegInstances;
|
||||
@AParameter(name = AUTORUN, parent = DATASOURCE_PANACIM, description = "should datasource start automatically",
|
||||
type = Boolean.class)
|
||||
private Parameter paramAutorun;
|
||||
|
||||
@AParameterDefaultValue(name = MAXIMUM_MESSAGE_INTERVAL)
|
||||
private Duration defMaxMessageInterval = new Duration("00:02:15,00");
|
||||
@AParameterDefaultValue(name = MAXIMUM_PING_RESPONSE_TIME)
|
||||
private Duration defMaxPingInterval = new Duration("00:01:00,00");
|
||||
@AParameterDefaultValue(name = PING_REQUEST_DELAY_TIME)
|
||||
private Duration defPingReqeuestDelay;
|
||||
@AParameterDefaultValue(name = AUTORUN)
|
||||
private boolean defAutorun = false;
|
||||
|
||||
private List<PanaCimServerConnection> serverConnectionList = new ArrayList<PanaCimServerConnection>();
|
||||
private boolean isRunning;
|
||||
private boolean isInitialized;
|
||||
// @AAutoHandler(InstantiationType.APPLICATION)
|
||||
private PanaCimApplication application;
|
||||
// die Menge der Namen aus der Konfiguration, die zu oeffnen sind
|
||||
private List<ServerConnectionProperties> connections;
|
||||
|
||||
private long maximumMessageInterval;
|
||||
private long maximumPingResponseTime;
|
||||
private long pingRequestDelayTime;
|
||||
|
||||
@AAutoHandler(InstantiationType.PARSER)
|
||||
private PanaCimParser parser;
|
||||
@AAutoHandler(InstantiationType.PROCESSOR)
|
||||
private IProcessor processor;
|
||||
|
||||
/**
|
||||
*/
|
||||
public PanaCimDataSource() {
|
||||
super();
|
||||
}
|
||||
|
||||
@AAutoHandler(InstantiationType.APPLICATION)
|
||||
public void setPanaCimApplication(PanaCimApplication application) {
|
||||
for (PanaCimServerConnection serverConnection : serverConnectionList) {
|
||||
serverConnection.setMessageReceiver(application);
|
||||
}
|
||||
parser.setMachineDataListReceiver(application);
|
||||
}
|
||||
|
||||
@AParamValue(value = AUTORUN)
|
||||
public void setAutorun(boolean value) {
|
||||
super.setAutorun(value);
|
||||
}
|
||||
|
||||
@AParamValue(value = MAXIMUM_MESSAGE_INTERVAL)
|
||||
public void setMaxMessageInterval(Duration value) {
|
||||
maximumMessageInterval = value.getMillies();
|
||||
}
|
||||
|
||||
@AParamValue(value = MAXIMUM_PING_RESPONSE_TIME)
|
||||
public void setMaxPingResponse(Duration value) {
|
||||
maximumPingResponseTime = value.getMillies();
|
||||
}
|
||||
|
||||
@AParamValue(value = PING_REQUEST_DELAY_TIME)
|
||||
public void setPingRequestDelay(Duration value) {
|
||||
pingRequestDelayTime = value.getMillies();
|
||||
}
|
||||
|
||||
@AParamValue(value = CONNECTIONS)
|
||||
public void setConnections(List<ServerConnectionProperties> value) {
|
||||
connections = value;
|
||||
// alle einzelnen Werte durchgehen
|
||||
for (ServerConnectionProperties connectionProperties : connections) {
|
||||
PanaCimServerConnection serverConnection = new PanaCimServerConnection(connectionProperties.getName(),
|
||||
connectionProperties.getPort(), maximumMessageInterval, maximumPingResponseTime, pingRequestDelayTime);
|
||||
serverConnectionList.add(serverConnection);
|
||||
}
|
||||
}
|
||||
|
||||
@AInit
|
||||
protected void init() {
|
||||
setDescription("Source=" + getName() + ", Parser=" + (parser == null ? "" : parser.getName()) + ", Processor="
|
||||
+ (processor == null ? "" : processor.getName()));
|
||||
parser.setMachineDataListReceiver(application);
|
||||
isInitialized = true;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see com.itac.easyworks.datainterface.datasource.BasicDataSource#isRunning()
|
||||
*/
|
||||
@Override
|
||||
public boolean isRunning() {
|
||||
return isRunning;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see com.itac.easyworks.datainterface.datasource.BasicDataSource#start()
|
||||
*/
|
||||
@Override
|
||||
public void start() {
|
||||
if (!isInitialized) {
|
||||
writeMessage(ERROR, InstantiationType.DATASOURCE + " " + getName() + " is not initialized");
|
||||
LogHandler.log(LOGGER, ERROR, InstantiationType.DATASOURCE + " " + getName() + " is not initialized");
|
||||
return;
|
||||
}
|
||||
if (isRunning) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
if (serverConnectionList != null || serverConnectionList.size() > 0) {
|
||||
for (int i = 0; i < serverConnectionList.size(); i++) {
|
||||
serverConnectionList.get(i).start();
|
||||
}
|
||||
}
|
||||
writeMessage(INFO, InstantiationType.DATASOURCE + " " + getName() + " started");
|
||||
LogHandler.log(LOGGER, INFO, InstantiationType.DATASOURCE + " " + getName() + " started");
|
||||
isRunning = true;
|
||||
} catch (Exception e) {
|
||||
writeMessage(INFO, "Problem starting " + InstantiationType.DATASOURCE + " " + getName() + ": " + e.getMessage());
|
||||
LogHandler.log(LOGGER, INFO, InstantiationType.DATASOURCE + " " + getName() + " not started");
|
||||
isRunning = false;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see com.itac.easyworks.datainterface.datasource.BasicDataSource#stop()
|
||||
*/
|
||||
@Override
|
||||
public void stop() {
|
||||
if (!isInitialized) {
|
||||
writeMessage(ERROR, InstantiationType.DATASOURCE + " " + getName() + " is not initialized");
|
||||
LogHandler.log(LOGGER, ERROR, InstantiationType.DATASOURCE + " " + getName() + " is not initialized");
|
||||
return;
|
||||
}
|
||||
if (!isRunning) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
LogHandler.log(LOGGER, DEBUG, "stop server socket for " + getName() + "now.");
|
||||
if (serverConnectionList != null || serverConnectionList.size() > 0) {
|
||||
for (int i = 0; i < serverConnectionList.size(); i++) {
|
||||
serverConnectionList.get(i).stop();
|
||||
}
|
||||
}
|
||||
|
||||
LogHandler.log(LOGGER, DEBUG, "stop all active connections for " + getName() + "now.");
|
||||
} finally {
|
||||
LogHandler.log(LOGGER, INFO, InstantiationType.DATASOURCE + " " + getName() + " stopped");
|
||||
writeMessage(INFO, InstantiationType.DATASOURCE + " " + getName() + " stopped");
|
||||
isRunning = false;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see com.itac.easyworks.datainterface.datasource.BasicDataSource#unInitialize()
|
||||
*/
|
||||
@Override
|
||||
public void unInitialize() {
|
||||
stop();
|
||||
}
|
||||
|
||||
/**
|
||||
* Beginn einer Pause. Diese Methode muss von den Datasourcen überschrieben werden
|
||||
*/
|
||||
@Override
|
||||
public void startPause() {
|
||||
application.setPaused(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ende einer Pause. Diese Methode muss von den Datasourcen überschrieben werden.
|
||||
*/
|
||||
@Override
|
||||
public void endPause() {
|
||||
application.setPaused(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void newPanaCimSocket(PanaCimSocket panaSocket) {
|
||||
// eine Verbindung hat einen neuen Socket geoeffnet
|
||||
LogHandler.log(LOGGER, INFO, panaSocket.getLogHeader() + " opened (client connected)");
|
||||
panaSocket.setMessageReceiver(application);
|
||||
}
|
||||
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,176 @@
|
||||
/*
|
||||
* Copyright (c) 2010 iTAC Software AG, Germany. All Rights Reserved.
|
||||
*
|
||||
* This software is protected by copyright. Under no circumstances may any part of this file in any form be copied,
|
||||
* printed, edited or otherwise distributed, be stored in a retrieval system, or be translated into another language
|
||||
* without the written permission of iTAC Software AG.
|
||||
*/
|
||||
package com.itac.mes.datainterface.parser.panacim;
|
||||
|
||||
import static com.itac.util.logging.LogLevel.ERROR;
|
||||
import static com.itac.util.logging.LogLevel.TRACE;
|
||||
|
||||
import java.io.StringWriter;
|
||||
|
||||
import javax.xml.transform.OutputKeys;
|
||||
import javax.xml.transform.Transformer;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import javax.xml.transform.TransformerFactory;
|
||||
import javax.xml.transform.dom.DOMSource;
|
||||
import javax.xml.transform.stream.StreamResult;
|
||||
|
||||
import org.w3c.dom.NamedNodeMap;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
import com.itac.mes.datainterface.data.panacim.PanaCimClientMessage;
|
||||
import com.itac.mes.datainterface.data.xmlapi.TestcaseException;
|
||||
import com.itac.mes.datainterface.data.xmlapi.XmlMachineConstruct;
|
||||
import com.itac.mes.datainterface.gui.IMachineSimulation;
|
||||
import com.itac.mes.datainterface.service.DataInterfaceServices;
|
||||
import com.itac.mes.datainterface.simulation.PanaCimSimulation;
|
||||
import com.itac.panacim.Message.Body.Result;
|
||||
import com.itac.util.logging.LogHandler;
|
||||
|
||||
public class PanaCimXmlConstruct extends XmlMachineConstruct {
|
||||
|
||||
public static final String ACTION_SEND = "send";
|
||||
private static final String LOGGER = PanaCimXmlConstruct.class.getSimpleName();
|
||||
|
||||
private PanaCimSimulation machineSimulation;
|
||||
private Node node;
|
||||
// die auszuführende Aktion
|
||||
private String connectionName;
|
||||
|
||||
public PanaCimXmlConstruct(String id) {
|
||||
super(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "PanaCim Simulation id(" + getId() + ") ";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(DataInterfaceServices services) throws TestcaseException {
|
||||
super.execute(services);
|
||||
|
||||
// Wenn Clients aktiv Funktionen am Panasonic aufrufen werden die Daten in die aktuelle Variablenliste eingetragen
|
||||
// die Variablen
|
||||
String id = "$" + getId() + '.';
|
||||
|
||||
try {
|
||||
if (machineSimulation.hasAction(action)) {
|
||||
machineSimulation.executeAction(action, timeout * 1000L);
|
||||
return;
|
||||
}
|
||||
if (action.equals(ACTION_SEND) && node != null) {
|
||||
// in diesem Knoten alle Variablen ersetzen, z.B. Datum, stationsnamen, liniennamen etc...
|
||||
replaceVariableFields(node);// guenstig, da hier alles Texte sind...
|
||||
// aus diesem Knoten ein Object machen (z.B. StationEventComposite, etc
|
||||
// den Knoten incl aller subknoten als Text ...
|
||||
|
||||
StringWriter sw = new StringWriter();
|
||||
try {
|
||||
Transformer t = TransformerFactory.newInstance().newTransformer();
|
||||
t.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
|
||||
t.transform(new DOMSource(node), new StreamResult(sw));
|
||||
} catch (TransformerException te) {
|
||||
LogHandler.log(LOGGER, ERROR, "nodeToString Transformer Exception", te);
|
||||
}
|
||||
String asText = sw.toString();
|
||||
|
||||
// für jede Objektklasse ist definiert, was mit ihr geschehen soll.
|
||||
// ist timeout gesetzt, wird auch auf eine Antwort gewartet (max Zeit)
|
||||
Object result = machineSimulation.send(connectionName, asText, timeout * 1000L);
|
||||
|
||||
if (result != null) {
|
||||
if (result instanceof PanaCimClientMessage) {
|
||||
// zu den Variablen hinzufuegen
|
||||
PanaCimClientMessage clientMessage = (PanaCimClientMessage) result;
|
||||
String resultAsText = clientMessage.getXmlRequestMessage();
|
||||
getTestCase().getVariableEngine().put(id + "response", clientMessage);
|
||||
getTestCase().getVariableEngine().put(id + "return", clientMessage.getRequestMessage());
|
||||
// einzelne Felder gezielt aufloesen
|
||||
try {
|
||||
Result resObj = clientMessage.getRequestMessage().getBody().getResult();
|
||||
getTestCase().getVariableEngine().put(id + "result.errorCode", resObj.getErrorCode());
|
||||
getTestCase().getVariableEngine().put(id + "result.errorText", resObj.getErrorText());
|
||||
getTestCase().getVariableEngine().put(id + "result.actionCode", resObj.getActionCode());
|
||||
} catch (Exception e) {
|
||||
LogHandler.log(LOGGER, TRACE, resultAsText);
|
||||
}
|
||||
LogHandler.log(LOGGER, TRACE, resultAsText);
|
||||
} else {
|
||||
LogHandler.log(LOGGER, TRACE, "result object is not instance of " + PanaCimClientMessage.class.getName());
|
||||
}
|
||||
} else {
|
||||
LogHandler.log(LOGGER, TRACE, "no result object from send");
|
||||
}
|
||||
} else if (action.equals(ACTION_CHANGE_CONFIGURATION)) {
|
||||
changeSimulationConfiguration(machineSimulation);
|
||||
}
|
||||
|
||||
getTestCase().getVariableEngine().put(id + "result", "0");
|
||||
endPass();
|
||||
} catch (Throwable e) {
|
||||
LogHandler.log(LOGGER, ERROR, "Error at action: " + action, e);
|
||||
getTestCase().getVariableEngine().put(id + "result", "-1");
|
||||
endFail();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* im XML-Knoten all Variablen in Attributen durch Werte ersetzen
|
||||
*
|
||||
* @param node2
|
||||
*/
|
||||
private void replaceVariableFields(Node node) {
|
||||
if (node == null) {
|
||||
return;
|
||||
}
|
||||
// Attribute
|
||||
if (node.getAttributes() != null) {
|
||||
// alle Attribute umsetzen
|
||||
NamedNodeMap attributes = node.getAttributes();
|
||||
for (int i = 0; i < attributes.getLength(); i++) {
|
||||
if (attributes.item(i).getNodeValue().startsWith("$")
|
||||
&& getTestCase().getVariableEngine().containsVariable(attributes.item(i).getNodeValue())) {
|
||||
String newValue = getTestCase().getVariableEngine().get(attributes.item(i).getNodeValue()).toString();
|
||||
attributes.item(i).setNodeValue(newValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (node.getNodeType() == Node.TEXT_NODE) {
|
||||
if (getTestCase().getVariableEngine().containsVariable(node.getNodeValue())) {
|
||||
String newValue = getTestCase().getVariableEngine().get(node.getNodeValue()).toString();
|
||||
node.setNodeValue(newValue);
|
||||
}
|
||||
}
|
||||
if (node.getChildNodes() != null) {
|
||||
for (int j = 0; j < node.getChildNodes().getLength(); j++) {
|
||||
replaceVariableFields(node.getChildNodes().item(j));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setSubnode(Node node) {
|
||||
this.node = node;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param machine
|
||||
*/
|
||||
@Override
|
||||
public void setSimulation(IMachineSimulation machineSimulation) {
|
||||
if (machineSimulation instanceof PanaCimSimulation) {
|
||||
this.machineSimulation = (PanaCimSimulation) machineSimulation;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param nodeValue
|
||||
*/
|
||||
public void setConnection(String nodeValue) {
|
||||
this.connectionName = nodeValue;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
package com.itac.mes.datainterface.parser.panacim;
|
||||
|
||||
import static com.itac.mes.datainterface.data.xmlapi.XmlMachineConstruct.ACTION_CHANGE_CONFIGURATION;
|
||||
import static com.itac.mes.datainterface.parser.panacim.PanaCimXmlConstruct.ACTION_SEND;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.w3c.dom.NamedNodeMap;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
|
||||
import com.itac.mes.datainterface.gui.IMachineSimulation;
|
||||
import com.itac.mes.datainterface.data.Toolbox;
|
||||
import com.itac.mes.datainterface.data.xmlapi.XmlConstruct;
|
||||
import com.itac.mes.datainterface.parser.MachinePluginParser;
|
||||
import com.itac.mes.datainterface.simulation.PanaCimSimulation;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author frankp
|
||||
*
|
||||
*/
|
||||
public class PanaCimXmlParser extends MachinePluginParser {
|
||||
|
||||
private static final String CONNECTION = "connection";
|
||||
|
||||
public PanaCimXmlParser(String name, Toolbox toolbox) {
|
||||
super(name, toolbox);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean includeSubNodes() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* alle Nodes, die unterhalb des fuji-Nodes liegen werden als Strukturen betrachtet
|
||||
*
|
||||
* @throws Exception
|
||||
*
|
||||
* @see com.itac.easyworks.datainterface.parser.PluginParser#parse(org.w3c.dom.Node, java.lang.StringBuffer)
|
||||
*/
|
||||
@Override
|
||||
public XmlConstruct parse(Node node) throws Exception {
|
||||
NamedNodeMap attributes = node.getAttributes();
|
||||
checkAttributesNotEmpty(attributes, new String[] { XmlConstruct.ID, SIMULATION }, getName());
|
||||
|
||||
String id = getAttributeValue(attributes, XmlConstruct.ID);
|
||||
String simulation = getAttributeValue(attributes, SIMULATION);
|
||||
|
||||
IMachineSimulation machine = getToolBox().getSimulation(simulation);
|
||||
checkMachineSimulation(machine, getName(), simulation, id, PanaCimSimulation.class);
|
||||
|
||||
String action = getAttributeValue(attributes, ACTION);
|
||||
checkActions(getName(), action, id, machine.getCustomActionNames(), new String[] { ACTION_SEND, ACTION_CHANGE_CONFIGURATION });
|
||||
|
||||
PanaCimXmlConstruct panacimXmlConstruct = new PanaCimXmlConstruct(id);
|
||||
panacimXmlConstruct.setAction(action);
|
||||
panacimXmlConstruct.setSimulation(machine);
|
||||
if (machine.hasAction(action)) {
|
||||
return panacimXmlConstruct;
|
||||
}
|
||||
if (action.equals(ACTION_SEND)) {
|
||||
// alle subknoten des Knotens als Strukturen parsen
|
||||
checkAttributesNotEmpty(attributes, new String[] { XmlConstruct.ID, CONNECTION, TIMEOUT }, getName());
|
||||
panacimXmlConstruct.setConnection(getAttributeValue(attributes, CONNECTION));
|
||||
String sTimeout = getAttributeValue(attributes, TIMEOUT);
|
||||
int timeout = 0;
|
||||
try {
|
||||
timeout = Integer.parseInt(sTimeout);
|
||||
} catch (Exception e) {
|
||||
throw new Exception(getIdConstructHeader(id, getName()) + ": parsing failed\n"
|
||||
+ "attribute 'timeout' is not a valid integer value; required is a value in seconds!\n");
|
||||
}
|
||||
|
||||
ArrayList<Node> subObjects = null;
|
||||
if (node.hasChildNodes()) {
|
||||
subObjects = parseSubNodes(node.getChildNodes());
|
||||
}
|
||||
|
||||
if (subObjects == null || subObjects.size() == 0) {
|
||||
throw new Exception(getIdConstructHeader(id, getName()) + ": parsing failed for action send");
|
||||
}
|
||||
panacimXmlConstruct.setSubnode(subObjects.get(0));
|
||||
panacimXmlConstruct.setTimeout(timeout);
|
||||
} else if (action.equals(ACTION_CHANGE_CONFIGURATION)) {
|
||||
parseChangeConfiguration(panacimXmlConstruct, attributes);
|
||||
}
|
||||
return panacimXmlConstruct;
|
||||
}
|
||||
|
||||
private ArrayList<Node> parseSubNodes(NodeList childNodes) {
|
||||
ArrayList<Node> retValue = new ArrayList<Node>();
|
||||
for (int i = 0; i < childNodes.getLength(); i++) {
|
||||
Node node = childNodes.item(i);
|
||||
|
||||
if (node.getNodeType() != Node.ELEMENT_NODE) {
|
||||
continue;
|
||||
}
|
||||
retValue.add(node);
|
||||
}
|
||||
return retValue;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,313 @@
|
||||
package com.itac.mes.datainterface.process;
|
||||
|
||||
import static com.itac.mes.core.domain.mig.exception.ItacMesErrorCodeIMSApi.COMMON_SUCCESSFULL_COMPLETED;
|
||||
import static com.itac.util.logging.LogLevel.INFO;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import com.itac.artes.ihas.LookupException;
|
||||
import com.itac.easyworks.api.idl.MaterialBinBookings;
|
||||
import com.itac.easyworks.api.idl.MdataBomItem;
|
||||
import com.itac.mes.api.domain.container.Result_getMaterialSetupData;
|
||||
import com.itac.mes.api.domain.container.Result_mdataBomVerify;
|
||||
import com.itac.mes.api.domain.container.Result_uploadMaterialBookings;
|
||||
import com.itac.mes.core.domain.mig.exception.ItacMesErrorCodeApi;
|
||||
import com.itac.mes.core.domain.mig.exception.ItacMesErrorCodeIMSApi;
|
||||
import com.itac.mes.datainterface.annotations.AInstantiationType;
|
||||
import com.itac.mes.datainterface.annotations.Dispatch;
|
||||
import com.itac.mes.datainterface.annotations.InstantiationType;
|
||||
import com.itac.mes.datainterface.annotations.LicenseProvider;
|
||||
import com.itac.mes.datainterface.data.PanaCimCheckMaterialResult;
|
||||
import com.itac.mes.datainterface.data.ProcessResult;
|
||||
import com.itac.mes.datainterface.data.SmtContainerData;
|
||||
import com.itac.mes.datainterface.data.UploadPanaCimCheckMaterialUnit;
|
||||
import com.itac.mes.datainterface.data.UploadSmtMaterialBinBookingsUnit;
|
||||
import com.itac.mes.datainterface.data.UploadSmtPreBomCheckUnit;
|
||||
import com.itac.mes.datainterface.data.UploadSmtSerialNumberCheckInUnit;
|
||||
import com.itac.mes.datainterface.data.UploadSmtSerialNumberSetupUnit;
|
||||
import com.itac.mes.datainterface.data.panacim.PanaCimActionCode;
|
||||
import com.itac.mes.datainterface.data.panacim.PanaCimHeaderResult;
|
||||
import com.itac.mes.datainterface.data.panacim.PanaCimSmtInterlockingResult;
|
||||
import com.itac.mes.imsapi.domain.container.Result_smtCheckMaterialBin;
|
||||
import com.itac.mes.imsapi.domain.container.Result_smtSerialNumberCheckIn;
|
||||
import com.itac.util.date.DateConvert;
|
||||
import com.itac.util.logging.LogHandler;
|
||||
|
||||
@LicenseProvider
|
||||
@AInstantiationType(name = "panacim", type = InstantiationType.PROCESSOR)
|
||||
public class PanaCimSmtProcessor extends SmtProcessor {
|
||||
|
||||
protected static String LOGGER = PanaCimSmtProcessor.class.getSimpleName();
|
||||
|
||||
public PanaCimSmtProcessor() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param uploadUnit
|
||||
* @param result
|
||||
* @return
|
||||
* @throws LookupException
|
||||
*/
|
||||
@Dispatch(clazz = UploadSmtSerialNumberCheckInUnit.class)
|
||||
protected Code sendSmtSerialNumberCheckIn(UploadSmtSerialNumberCheckInUnit uploadUnit, ProcessResult processResult)
|
||||
throws LookupException {
|
||||
Code code = Code.NOT_SENT;
|
||||
PanaCimSmtInterlockingResult panaCimSmtInterlockResult = new PanaCimSmtInterlockingResult();
|
||||
processResult.setResultObject(panaCimSmtInterlockResult);
|
||||
try {
|
||||
Result_smtSerialNumberCheckIn serialNumberCheckIn = services.getIMSApiService().smtSerialNumberCheckIn(getImsSession(),
|
||||
uploadUnit.getStationNr(), uploadUnit.getSerialNoCheckUploadKeys(), uploadUnit.getSerialNoCheckUploadValues(),
|
||||
uploadUnit.getLogInfoUploadKeys(), uploadUnit.getLogInfoUploadValues(), uploadUnit.getSerialNumberStateResultKeys(),
|
||||
uploadUnit.getRecipeResultKeys());
|
||||
processResult.setResultObject(serialNumberCheckIn);
|
||||
if (isIn(serialNumberCheckIn.return_value, COMMON_SUCCESSFULL_COMPLETED)) {
|
||||
LogHandler.log(LOGGER, INFO, "sendUploadSmtSerialNumberCheckIn checked OK");
|
||||
code = Code.OK;
|
||||
} else if (serialNumberCheckIn.return_value < 0) {
|
||||
String errorRetcode = getImsApiErrorMessage(serialNumberCheckIn.return_value);
|
||||
processResult.setDetailText("sendUploadSmtSerialNumberCheckIn failed: " + errorRetcode);
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
// bei unbekannten Fehlern zumindest weitermachen
|
||||
handleException(t, "sendUploadSmtSerialNumberCheckIn() failed: ", processResult);
|
||||
panaCimSmtInterlockResult.actionCode = PanaCimActionCode.STOP_PCB;
|
||||
panaCimSmtInterlockResult.errorCode = 1;// Fehler
|
||||
panaCimSmtInterlockResult.errorText = t.getMessage();
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
@Dispatch(clazz = UploadPanaCimCheckMaterialUnit.class)
|
||||
protected Code sendCheckMaterialBinUnit(UploadPanaCimCheckMaterialUnit uploadUnit, ProcessResult result) throws LookupException {
|
||||
|
||||
PanaCimCheckMaterialResult pcmr = new PanaCimCheckMaterialResult();
|
||||
result.setResultObject(pcmr);
|
||||
pcmr.materialId = uploadUnit.getSmtCheckContainerData().get(0).getMaterialBinNr();
|
||||
pcmr.panaCimState = 0;
|
||||
pcmr.errorCode = 0;
|
||||
|
||||
Code code = Code.OK;
|
||||
try {
|
||||
pcmr.errorText = "";
|
||||
Result_smtCheckMaterialBin ret = services.getIMSApiService().smtCheckMaterialBin(getImsSession(), uploadUnit.getStation(),
|
||||
uploadUnit.getImsApiKeys(), uploadUnit.getImsApiValues());
|
||||
|
||||
// setting the result back to the uploadUnit creates the resulting array with SmtContainerData
|
||||
uploadUnit.setResult(ret);
|
||||
|
||||
SmtContainerData[] resultSmtContainerData = uploadUnit.getResultContainerData();
|
||||
pcmr.materialBinData = resultSmtContainerData;
|
||||
result.setDetailCode(ret.return_value);
|
||||
if (ret.return_value < 0) {
|
||||
result.setResultCode(Code.NOT_SENT);
|
||||
result.setDetailText("sendCheckMaterialBinUnit() failed: " + uploadUnit.getSmtCheckContainerData().get(0) + getImsApiErrorMessage(
|
||||
ret.return_value));
|
||||
code = Code.NOT_SENT;
|
||||
pcmr.actionCode = PanaCimActionCode.DO_NOTHING;
|
||||
pcmr.errorText = uploadUnit.getSmtCheckContainerData().get(0) + " is unknown in iTAC.MES.Suite";
|
||||
pcmr.panaCimState = 1; // material is not defined
|
||||
return code;
|
||||
}
|
||||
|
||||
if (resultSmtContainerData.length != uploadUnit.getSmtCheckContainerData().size()) {
|
||||
result.setResultCode(Code.NOT_SENT);
|
||||
result.setDetailText("material bin is not unique " + uploadUnit.getSmtCheckContainerData().get(0) + getImsApiErrorMessage(ret.return_value));
|
||||
code = Code.NOT_SENT;
|
||||
pcmr.actionCode = PanaCimActionCode.DO_NOTHING;
|
||||
pcmr.errorText = uploadUnit.getSmtCheckContainerData().get(0) + " is unknown in iTAC.MES.Suite";
|
||||
pcmr.panaCimState = 1; // material is not defined
|
||||
return code;
|
||||
}
|
||||
for (int i = 0; i < uploadUnit.getSmtCheckContainerData().size(); i++) {
|
||||
SmtContainerData callValue = uploadUnit.getSmtCheckContainerData().get(i);
|
||||
SmtContainerData returnValue = resultSmtContainerData[i];
|
||||
|
||||
if (returnValue.getErrorCode() < 0 && !returnValue.isCreateContainer()) {
|
||||
result.setResultCode(Code.NOT_SENT);
|
||||
result.setDetailText("sendCheckMaterialBinUnit() failed: " + uploadUnit.getSmtCheckContainerData().get(0) + getImsApiErrorMessage(
|
||||
returnValue.getErrorCode()));
|
||||
code = Code.NOT_SENT;
|
||||
pcmr.actionCode = PanaCimActionCode.DO_NOTHING;
|
||||
pcmr.errorText = callValue.getMaterialBinNr() + " is unknown in iTAC.MES.Suite";
|
||||
pcmr.panaCimState = 1; // material is not defined
|
||||
continue;
|
||||
}
|
||||
if (!returnValue.isCreateContainer()) {
|
||||
|
||||
if (uploadUnit.isCheckState() && !notLockedStates.contains(returnValue.getMatState())) {
|
||||
result.setDetailCode(ItacMesErrorCodeApi.LOT_IS_LOCKED.getReturnValue());
|
||||
pcmr.actionCode = PanaCimActionCode.DO_NOTHING;
|
||||
pcmr.errorText = addText(pcmr.errorText, callValue.getMaterialBinNr() + " is locked in iTAC.MES.Suite");
|
||||
pcmr.panaCimState = 8; // material can not be used since it is a restricted material
|
||||
code = Code.NOT_SENT;
|
||||
}
|
||||
if (uploadUnit.isCheckExpiration() && returnValue.getExpirationDate().before(new Date())) {
|
||||
result.setDetailCode(ItacMesErrorCodeApi.EQUIPMENT_EXPIRED.getReturnValue());
|
||||
pcmr.actionCode = PanaCimActionCode.DO_NOTHING;
|
||||
pcmr.errorText = addText(pcmr.errorText, callValue.getMaterialBinNr() + " is expired in iTAC.MES.Suite");
|
||||
pcmr.panaCimState = 4; // Material can't be used due to MSD expiration
|
||||
code = Code.NOT_SENT;
|
||||
}
|
||||
if (uploadUnit.isCheckQuantity() && returnValue.getQuantity() <= 0.0D) {
|
||||
result.setDetailCode(ItacMesErrorCodeIMSApi.ML_CONTAINER_IS_EMPTY.getReturnValue());
|
||||
code = Code.NOT_SENT;
|
||||
pcmr.actionCode = PanaCimActionCode.DO_NOTHING;
|
||||
pcmr.panaCimState = 2;// Material defined but can not be used...
|
||||
pcmr.errorText = addText(pcmr.errorText, callValue.getMaterialBinNr() + " is empty in iTAC.MES.Suite");
|
||||
}
|
||||
if (uploadUnit.isCheckPart() && !callValue.getProduct().equals(returnValue.getProduct())) {
|
||||
result.setDetailCode(ItacMesErrorCodeApi.PRODUCT_BELONGS_NOT_TO_MATERIAL_BIN.getReturnValue());
|
||||
pcmr.actionCode = PanaCimActionCode.DO_NOTHING;
|
||||
pcmr.errorText = addText(pcmr.errorText, "PanaCim container " + callValue.getMaterialBinNr() + "("
|
||||
+ callValue.getProduct() + ") has a different part in iTAC.MES.Suite(" + returnValue.getProduct() + ")");
|
||||
pcmr.panaCimState = 8;
|
||||
code = Code.NOT_SENT;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
handleException(t, "sendPanaCimContainerCheck() failed: ", result);
|
||||
pcmr.actionCode = PanaCimActionCode.CANCEL_TRANSACTION;
|
||||
pcmr.errorCode = 1;
|
||||
pcmr.errorText = addText(pcmr.errorText, "internal error in iTAC.MES.Suite");
|
||||
pcmr.panaCimState = -1; // Material can't be used due to MSD expiration
|
||||
code = Code.NOT_SENT;
|
||||
}
|
||||
result.setDetailText("sendCheckMaterialBinUnit():\n" + pcmr.errorText);
|
||||
result.setResultCode(code);
|
||||
return code;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Dispatch(clazz = UploadSmtSerialNumberSetupUnit.class)
|
||||
protected Code sendSmtSerialNumberSetup(UploadSmtSerialNumberSetupUnit unit, ProcessResult result)
|
||||
throws ProcessorException, LookupException {
|
||||
Code code = super.sendSmtSerialNumberSetup(unit, result);
|
||||
if (code == Code.NOT_SENT || result.getDetailCode() != 0) {
|
||||
PanaCimHeaderResult pchr = new PanaCimHeaderResult();
|
||||
pchr.actionCode = PanaCimActionCode.STOP_PCB;
|
||||
pchr.errorCode = 1;
|
||||
pchr.errorText = result.getDetailText();
|
||||
result.setResultObject(pchr);
|
||||
} else {
|
||||
if (code == Code.NOT_SENT || result.getDetailCode() != 0) {
|
||||
PanaCimHeaderResult pchr = new PanaCimHeaderResult();
|
||||
pchr.actionCode = PanaCimActionCode.STOP_PCB;
|
||||
pchr.errorCode = 1;
|
||||
pchr.errorText = result.getDetailText();
|
||||
result.setResultObject(pchr);
|
||||
}
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Code sendSmtMaterialBinBookingsUnit(UploadSmtMaterialBinBookingsUnit uploadUnit, ProcessResult processResult)
|
||||
throws LookupException {
|
||||
Code sendCode = Code.NOT_SENT;
|
||||
if (uploadUnit.size() == 0) {
|
||||
return Code.DISCARD;
|
||||
}
|
||||
|
||||
try {
|
||||
MaterialBinBookings[] k = uploadUnit.getMaterialBinBookings();
|
||||
// Besonderheit PanaCim: es muss der zum Zeitpunkt gegebene Auftrag ermittelt werden...
|
||||
|
||||
if (k.length > 0) {
|
||||
if (k[0].workorder == null) {
|
||||
|
||||
int time = k[0].bookDate;
|
||||
int setupState = 2;
|
||||
Result_getMaterialSetupData x = services.getAPIServices().getMaterialSetupData(uploadUnit.getStation(), setupState, time);
|
||||
if (x.return_value >= 0) {
|
||||
// auftragsNummer in alle Datensätze übertragen
|
||||
for (MaterialBinBookings binBooking : k) {
|
||||
binBooking.workorder = x.setupWorkOrder;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Result_uploadMaterialBookings code = services.getAPIServices().uploadMaterialBookings(uploadUnit.getStation(), k);
|
||||
if (code.return_value < 0) {
|
||||
processResult.setDetailCode(code.return_value);
|
||||
processResult.setDetailText("sendTempConsumptionUnit() failed: " + code.errorString);
|
||||
} else {
|
||||
sendCode = Code.OK;
|
||||
}
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
// bei unbekannten Fehlern zumindest weitermachen
|
||||
handleException(t, "sendTempConsumptionUnit() failed: ", processResult);
|
||||
}
|
||||
return sendCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param uploadUnit
|
||||
* @param result
|
||||
* @return
|
||||
* @throws LookupException
|
||||
*/
|
||||
@Override
|
||||
@Dispatch(clazz = UploadSmtPreBomCheckUnit.class)
|
||||
protected Code sendSmtPreBomCheck(UploadSmtPreBomCheckUnit uploadUnit, ProcessResult result) throws LookupException {
|
||||
Code code = Code.NOT_SENT;
|
||||
PanaCimHeaderResult pchr = new PanaCimHeaderResult();
|
||||
result.setResultObject(pchr);
|
||||
try {
|
||||
Result_mdataBomVerify retCode = services.getAPIServices().mdataBomVerify(uploadUnit.getStationNr(),
|
||||
uploadUnit.getProcessLayer(), uploadUnit.getWorkorder(), uploadUnit.getProductNo(), uploadUnit.getBareBoardNo(),
|
||||
uploadUnit.getBomIndex(), uploadUnit.getBomInfo(), uploadUnit.getBomValidFrom(), uploadUnit.getBomVersionERP(),
|
||||
uploadUnit.getVerifyCompNameBased(), uploadUnit.getCreateNewBom(), uploadUnit.getBomItemArray());
|
||||
|
||||
int start = DateConvert.convertLongDateToInt(System.currentTimeMillis());
|
||||
int end = start + (5 * 24 * 60 * 60);
|
||||
|
||||
if (retCode.return_value != 0) {
|
||||
StringBuilder retComBuffer = new StringBuilder();
|
||||
retComBuffer.append(retCode.errorString).append('\n');
|
||||
|
||||
if (retCode.return_value == ItacMesErrorCodeApi.BOM_VERIFY_FAILED.getReturnValue()) {
|
||||
for (MdataBomItem bomItem : retCode.mdataBomItemArray) {
|
||||
if (bomItem.returnComment.length() > 0) {
|
||||
retComBuffer.append(bomItem.compName).append(": ").append(bomItem.returnComment).append('\n');
|
||||
}
|
||||
}
|
||||
}
|
||||
// write result to mde_station_log
|
||||
String errorString = retComBuffer.toString();
|
||||
if (errorString.length() > 250) {
|
||||
errorString = errorString.substring(0, 240) + "....";
|
||||
}
|
||||
|
||||
services.getAPIServices().mdcCreateLog(uploadUnit.getStationNrPm(), start, end, uploadUnit.getProgramName(), errorString,
|
||||
0);
|
||||
pchr.errorCode = 1;
|
||||
pchr.errorText = errorString;
|
||||
result.setResultCode(Code.NOT_SENT);
|
||||
result.setDetailCode(retCode.return_value);
|
||||
result.setDetailText(uploadUnit.getStationNrPm() + " preBomVerify() failed: " + retComBuffer.toString());
|
||||
} else {
|
||||
services.getAPIServices().mdcCreateLog(uploadUnit.getStationNrPm(), start, end, uploadUnit.getProgramName(), "", 0);
|
||||
|
||||
code = Code.OK;
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
handleException(t, "mdataBomVerify() failed: ", result);
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param errorText
|
||||
* @param string
|
||||
* @return
|
||||
*/
|
||||
private String addText(String errorText, String string) {
|
||||
if (errorText.isEmpty()) {
|
||||
return string;
|
||||
}
|
||||
return errorText + "\n+" + string;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,224 @@
|
||||
/*
|
||||
* Copyright (c) 2010 iTAC Software AG, Germany. All Rights Reserved.
|
||||
*
|
||||
* This software is protected by copyright. Under no circumstances may any part of this file in any form be copied,
|
||||
* printed, edited or otherwise distributed, be stored in a retrieval system, or be translated into another language
|
||||
* without the written permission of iTAC Software AG.
|
||||
*/
|
||||
|
||||
package com.itac.mes.datainterface.simulation;
|
||||
|
||||
import static com.itac.util.logging.LogLevel.DEBUG;
|
||||
import static com.itac.util.logging.LogLevel.ERROR;
|
||||
import static com.itac.util.logging.LogLevel.INFO;
|
||||
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.itac.mes.config.domain.Parameter;
|
||||
import com.itac.mes.datainterface.annotations.AInit;
|
||||
import com.itac.mes.datainterface.annotations.AInstantiationType;
|
||||
import com.itac.mes.datainterface.annotations.AParamValue;
|
||||
import com.itac.mes.datainterface.annotations.AParameter;
|
||||
import com.itac.mes.datainterface.annotations.InstantiationType;
|
||||
import com.itac.mes.datainterface.data.panacim.ClientConnectionProperties;
|
||||
import com.itac.mes.datainterface.data.panacim.IPanaCimClientMessageReceiver;
|
||||
import com.itac.mes.datainterface.data.panacim.PanaCimClientConnection;
|
||||
import com.itac.mes.datainterface.data.panacim.PanaCimClientMessage;
|
||||
import com.itac.mes.datainterface.gui.DataInterfaceMenuAction;
|
||||
import com.itac.mes.datainterface.parser.panacim.PanaCimXmlParser;
|
||||
import com.itac.util.logging.LogHandler;
|
||||
|
||||
/**
|
||||
* @author frankp created 2010
|
||||
*/
|
||||
@AInstantiationType(name = "panacim", type = InstantiationType.MACHINESIMULATION)
|
||||
public class PanaCimSimulation extends DefaultMachineSimulation implements IPanaCimClientMessageReceiver, PropertyChangeListener {
|
||||
|
||||
private static final String LOGGER = PanaCimSimulation.class.getSimpleName();
|
||||
|
||||
private final static String SIMULATION_PANACIM = "simulation.panacim";
|
||||
private final static String CONNECTIONS = SIMULATION_PANACIM + ".connections";
|
||||
|
||||
@AParameter(name = SIMULATION_PANACIM, description = "PanaCim Simulation",
|
||||
visibility = "MachineSimulation=com.itac.mes.datainterface.simulation.PanaCimSimulation")
|
||||
private Parameter paramSource;
|
||||
@AParameter(name = CONNECTIONS, parent = SIMULATION_PANACIM, description = "PanaCim connection list", type = List.class,
|
||||
metaType = ClientConnectionProperties.class)
|
||||
private Parameter paramServerConnections;
|
||||
|
||||
public static final String ID_STOP = "stop";
|
||||
public static final String ID_START = "start";
|
||||
public static final String ID_CLEAR = "clear";
|
||||
|
||||
// Map mit allen Clientconnections, key ist der Name...
|
||||
private List<ClientConnectionProperties> connectionPropertiesList;
|
||||
private Map<String, PanaCimClientConnection> clientConnections = new HashMap<String, PanaCimClientConnection>();
|
||||
|
||||
private PanaCimClientMessage lastMessage;
|
||||
|
||||
// die einzelnen Menu-Items werden hier deklariert, und spaeter geadded
|
||||
private DataInterfaceMenuAction startClientsMenuItem = new DataInterfaceMenuAction("start all clients", "startAllClients",
|
||||
ID_START, false);
|
||||
private DataInterfaceMenuAction stopClientsMenuItem = new DataInterfaceMenuAction("stop all clients", "stopAllClients", ID_STOP,
|
||||
false);
|
||||
private DataInterfaceMenuAction clearMenuItem = new DataInterfaceMenuAction("clear", "clear", ID_CLEAR, true);
|
||||
|
||||
public PanaCimSimulation() {
|
||||
super();
|
||||
|
||||
addSimMenuItem(startClientsMenuItem);
|
||||
addSimMenuItem(stopClientsMenuItem);
|
||||
addSimMenuItem(clearMenuItem);
|
||||
}
|
||||
|
||||
@AParamValue(value = CONNECTIONS)
|
||||
protected void setConnections(List<ClientConnectionProperties> value) {
|
||||
connectionPropertiesList = value;
|
||||
// alle einzelnen Werte durchgehen
|
||||
for (ClientConnectionProperties connectionProperties : connectionPropertiesList) {
|
||||
PanaCimClientConnection clientConnection = new PanaCimClientConnection(connectionProperties);
|
||||
clientConnections.put(clientConnection.getName(), clientConnection);
|
||||
clientConnection.setMessageReceiver(this);
|
||||
|
||||
clientConnection.setConnectStateChangeListener(this);
|
||||
((IPanaCimPane) getWorkerPane()).setConnectionText(getConnectionText());
|
||||
}
|
||||
}
|
||||
|
||||
@AInit
|
||||
public void atInit() {
|
||||
// alle einzelnen Werte durchgehen
|
||||
for (ClientConnectionProperties connectionProperties : connectionPropertiesList) {
|
||||
PanaCimClientConnection clientConnection = new PanaCimClientConnection(connectionProperties);
|
||||
clientConnections.put(clientConnection.getName(), clientConnection);
|
||||
clientConnection.setMessageReceiver(this);
|
||||
|
||||
clientConnection.setConnectStateChangeListener(this);
|
||||
((IPanaCimPane) getWorkerPane()).setConnectionText(getConnectionText());
|
||||
}
|
||||
|
||||
try {
|
||||
checkPluginParser();
|
||||
} catch (Throwable th) {
|
||||
}
|
||||
}
|
||||
|
||||
public String getConnectionText() {
|
||||
String text = "Connections: \n";
|
||||
for (PanaCimClientConnection conn : clientConnections.values()) {
|
||||
if (conn.isConnected()) {
|
||||
text = text + conn.getLogHeader() + ": connected\n";
|
||||
} else {
|
||||
text = text + conn.getLogHeader() + ": not connected\n";
|
||||
}
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pruefen, ob es fuer diesen Maschinentyp bereits einen Plugin Parser in der Toolbox gibt. Falls nicht einen erzeugen und
|
||||
* zuweisen. Der Api-Xml-Parser kann dann auf diesen Plugin Parser zugreifen
|
||||
*/
|
||||
private void checkPluginParser() {
|
||||
if (getToolbox().getPluginParser(getSimulationType()) == null) {
|
||||
LogHandler.log(LOGGER, DEBUG, "create plugin parser for '" + getSimulationType() + "'");
|
||||
getToolbox().addPluginParser(new PanaCimXmlParser(getSimulationType(), getToolbox()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* aus einem XML-Script heraus wird mit der Action clear oder auch aus dem Menu heraus die Anzeige der Simulation gelöscht.
|
||||
*/
|
||||
public void clear() {
|
||||
LogHandler.log(LOGGER, INFO, "clear simulation pane");
|
||||
getWorkerPane().clear();
|
||||
}
|
||||
|
||||
protected void startAllClients() {
|
||||
for (PanaCimClientConnection clientConnection : clientConnections.values()) {
|
||||
clientConnection.start();
|
||||
}
|
||||
}
|
||||
|
||||
protected void stopAllClients() {
|
||||
for (PanaCimClientConnection clientConnection : clientConnections.values()) {
|
||||
clientConnection.stop();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void propertyChange(PropertyChangeEvent evt) {
|
||||
LogHandler.log(LOGGER, INFO, evt.getNewValue().toString());
|
||||
((PanaCimClientConnection) evt.getSource()).isConnected();
|
||||
((IPanaCimPane) getWorkerPane()).setConnectionText(getConnectionText());
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Mit dieser Methode wird das Objekt an den Panasonic Server (das Datainterface) gesendet
|
||||
*
|
||||
* @param object
|
||||
* @throws Throwable
|
||||
*/
|
||||
public Object send(String connectionName, String xmlContent, long timeoutMillies) throws Throwable {
|
||||
if (xmlContent == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
PanaCimClientConnection clientConnection = clientConnections.get(connectionName);
|
||||
if (clientConnection == null) {
|
||||
LogHandler.log(LOGGER, DEBUG, "client connection '" + connectionName + "' not found, therefore message not sent");
|
||||
// Text mit der Liste der Verbindungen ausgeben
|
||||
StringBuilder description = new StringBuilder("available client connections are:\n");
|
||||
for (PanaCimClientConnection clientConn : clientConnections.values()) {
|
||||
description.append(clientConn.getName()).append('\n');
|
||||
}
|
||||
LogHandler.log(LOGGER, INFO, description.toString());
|
||||
return null;
|
||||
}
|
||||
|
||||
String res = (char) 02 + "" + xmlContent.length() + "" + (char) 01 + xmlContent + (char) 03;
|
||||
try {
|
||||
clientConnection.send(res);
|
||||
((IPanaCimPane) getWorkerPane()).sendMessage(res);
|
||||
} catch (Throwable th) {
|
||||
LogHandler.log(LOGGER, ERROR, "message sending failed:\n", th);
|
||||
throw th;
|
||||
}
|
||||
|
||||
// das Ergebnis in die Daten eintragen...
|
||||
|
||||
// auf das Ergebnis warten (timeout in secs)
|
||||
lastMessage = null;
|
||||
if (timeoutMillies > 0) {
|
||||
long end = System.currentTimeMillis() + timeoutMillies;
|
||||
while ((System.currentTimeMillis() < end) && (lastMessage == null)) {
|
||||
try {
|
||||
Thread.sleep(50);
|
||||
} catch (InterruptedException e) {
|
||||
LogHandler.log(LOGGER, ERROR, "wait interrupted", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (lastMessage == null) {
|
||||
((IPanaCimPane) getWorkerPane()).receiveMessage("TIMEOUT");
|
||||
}
|
||||
return lastMessage;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see com.itac.mes.datainterface.data.panasonic.PanasonicMessageReceiver#setMessage(com.itac.mes.datainterface.data.panasonic.
|
||||
* PanasonicMessage)
|
||||
*/
|
||||
@Override
|
||||
public void setMessage(PanaCimClientMessage message) {
|
||||
LogHandler.log(LOGGER, INFO, "message received");
|
||||
lastMessage = message;
|
||||
((IPanaCimPane) getWorkerPane()).receiveMessage(lastMessage.getXmlRequestMessage());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
com.itac.mes.datainterface.datasource.PanaCimDataSource
|
||||
com.itac.mes.datainterface.parser.PanaCimParser
|
||||
com.itac.mes.datainterface.process.PanaCimSmtProcessor
|
||||
|
||||
# Simulationen (Rahmenwerk)
|
||||
com.itac.mes.datainterface.simulation.PanaCimSimulation
|
||||
397
interface/panasonic/src/main/xsd/PanaCim.xsd
Normal file
397
interface/panasonic/src/main/xsd/PanaCim.xsd
Normal file
@@ -0,0 +1,397 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
|
||||
|
||||
<xs:schema id="message" xmlns="com.panasonic.mes" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xs:element name="message" msdata:IsDataSet="true" msdata:UseCurrentLocale="true">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="header" minOccurs="1" maxOccurs="1">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="location" minOccurs="0" maxOccurs="1">
|
||||
<xs:complexType>
|
||||
<xs:attribute name="routeID" type="xs:int" />
|
||||
<xs:attribute name="routeName" type="xs:string" />
|
||||
<xs:attribute name="equipmentID" type="xs:int" />
|
||||
<xs:attribute name="equipmentName" type="xs:string" />
|
||||
<xs:attribute name="zoneID" type="xs:int" use="optional"/>
|
||||
<xs:attribute name="zonePos" type="xs:int" />
|
||||
<xs:attribute name="zoneName" type="xs:string" />
|
||||
<xs:attribute name="laneNo" type="xs:int" />
|
||||
<xs:attribute name="controllerGuid" type="xs:string" use="optional"/>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
<xs:attribute name="messageClass" type="xs:int" />
|
||||
<xs:attribute name="transactionID" type="xs:string" />
|
||||
<xs:attribute name="reply" type="xs:int" />
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
|
||||
|
||||
<xs:element name="body" minOccurs="0" maxOccurs="1">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:choice>
|
||||
<!-- AttributeChange -->
|
||||
<xs:element name="operation" minOccurs="0" maxOccurs="1">
|
||||
<xs:complexType>
|
||||
<xs:attribute name="type" type="xs:int" />
|
||||
<xs:attribute name="materialID" type="xs:string" use="optional" />
|
||||
<xs:attribute name="timestamp" type="xs:dateTime" />
|
||||
<xs:attribute name="operator" type="xs:string" />
|
||||
<xs:attribute name="reason" type="xs:string" use="optional" />
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
|
||||
<!-- changeOver -->
|
||||
<xs:element name="product" minOccurs="0" maxOccurs="1">
|
||||
<xs:complexType>
|
||||
<xs:attribute name="name" type="xs:string" />
|
||||
<xs:attribute name="side" type="xs:int" />
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="parts" minOccurs="0" maxOccurs="1">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="part" minOccurs="0" maxOccurs="unbounded">
|
||||
<xs:complexType>
|
||||
<xs:attribute name="name" type="xs:string" />
|
||||
<xs:attribute name="ref" type="xs:int" />
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="comps" minOccurs="0" maxOccurs="1">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="comp" minOccurs="0" maxOccurs="unbounded">
|
||||
<xs:complexType>
|
||||
<xs:attribute name="pos" type="xs:int" />
|
||||
<xs:attribute name="ref" type="xs:int" />
|
||||
<xs:attribute name="refDes" type="xs:string" />
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
|
||||
<!-- MachineStatusRequest -->
|
||||
<xs:element name="machineStatus" minOccurs="0" maxOccurs="1">
|
||||
<xs:complexType>
|
||||
<xs:attribute name="id" type="xs:int" />
|
||||
<xs:attribute name="text" type="xs:string" />
|
||||
<xs:attribute name="timestamp" type="xs:dateTime" />
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
|
||||
<!-- MachineEvent -->
|
||||
<xs:element name="machineEvent" minOccurs="0" maxOccurs="1">
|
||||
<xs:complexType>
|
||||
<xs:attribute name="code" type="xs:int" />
|
||||
<xs:attribute name="text" type="xs:string" />
|
||||
<xs:attribute name="timestamp" type="xs:dateTime" />
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<!-- ManagementBoardRequest -->
|
||||
<xs:element name="timePeriod" minOccurs="0" maxOccurs="1">
|
||||
<xs:complexType>
|
||||
<xs:attribute name="start" type="xs:dateTime" />
|
||||
<xs:attribute name="end" type="xs:dateTime" />
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="prdData" minOccurs="0" maxOccurs="1">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="data" minOccurs="0" maxOccurs="unbounded">
|
||||
<xs:complexType>
|
||||
<xs:attribute name="stageNo" type="xs:int" />
|
||||
<xs:attribute name="boardProduced" type="xs:int" />
|
||||
<xs:attribute name="blockProduced" type="xs:int" />
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
|
||||
<!-- ManagementScrapRequest -->
|
||||
<!--
|
||||
xs:element name="timePeriod" minOccurs="0" maxOccurs="unbounded"> <xs:complexType> <xs:attribute name="start"
|
||||
type="xs:dateTime" /> <xs:attribute name="end" type="xs:dateTime" /> </xs:complexType> </xs:element
|
||||
-->
|
||||
<xs:element name="components" minOccurs="0" maxOccurs="1">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="comp" minOccurs="0" maxOccurs="unbounded">
|
||||
<xs:complexType>
|
||||
<xs:attribute name="materialID" type="xs:string" />
|
||||
<xs:attribute name="part" type="xs:string" />
|
||||
<xs:attribute name="pickupCount" type="xs:int" />
|
||||
<xs:attribute name="placeCount" type="xs:int" />
|
||||
<xs:attribute name="scrap" type="xs:int" />
|
||||
<xs:attribute name="p1" type="xs:string" />
|
||||
<xs:attribute name="p2" type="xs:int" />
|
||||
<xs:attribute name="p3" type="xs:int" />
|
||||
<xs:attribute name="p4" type="xs:int" />
|
||||
<xs:attribute name="feederID" type="xs:string" use="optional" />
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
|
||||
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
|
||||
<!-- Pcbrequest -->
|
||||
<xs:element name="pcb" minOccurs="0" maxOccurs="1">
|
||||
<xs:complexType>
|
||||
<xs:attribute name="barcode" type="xs:string" />
|
||||
<xs:attribute name="modelCode" type="xs:string" />
|
||||
<xs:attribute name="serialNo" type="xs:string" />
|
||||
<xs:attribute name="pcbSide" type="xs:int" />
|
||||
<xs:attribute name="scannerMountSide" type="xs:string" />
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
|
||||
<!-- pcbresponse -->
|
||||
<xs:element name="result" minOccurs="0" maxOccurs="1">
|
||||
<xs:complexType>
|
||||
<xs:attribute name="errorCode" type="xs:int" />
|
||||
<xs:attribute name="errorText" type="xs:string" />
|
||||
<xs:attribute name="actionCode" type="xs:int" />
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<!--
|
||||
xs:element name="pcb" minOccurs="0" maxOccurs="unbounded"> <xs:complexType> <xs:attribute name="barcode"
|
||||
type="xs:string" /> <xs:attribute name="modelCode" type="xs:string" /> <xs:attribute name="serialNo"
|
||||
type="xs:string" /> <xs:attribute name="pcbSide" type="xs:boolean" /> </xs:complexType> </xs:element
|
||||
-->
|
||||
<!--
|
||||
xs:element name="product" minOccurs="0" maxOccurs="unbounded"> <xs:complexType> <xs:attribute name="name"
|
||||
type="xs:string" /> <xs:attribute name="side" type="xs:boolean" /> </xs:complexType> </xs:element
|
||||
-->
|
||||
<xs:element name="workItems" minOccurs="0" maxOccurs="1">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="workItem" minOccurs="0" maxOccurs="unbounded">
|
||||
<xs:complexType>
|
||||
<xs:attribute name="pos" type="xs:int" />
|
||||
<xs:attribute name="place" type="xs:int" />
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
|
||||
|
||||
<!-- SetupRequest -->
|
||||
<!--
|
||||
aus setupResponse xs:element name="material" minOccurs="0" maxOccurs="unbounded"> <xs:complexType> <xs:attribute
|
||||
name="id" type="xs:string" /> </xs:complexType> </xs:element
|
||||
-->
|
||||
|
||||
<!-- SetupResponse_Error -->
|
||||
<!--
|
||||
xs:element name="result" minOccurs="0" maxOccurs="unbounded"> <xs:complexType> <xs:attribute name="errorCode"
|
||||
type="xs:int" /> <xs:attribute name="errorText" type="xs:string" /> <xs:attribute name="actionCode" type="xs:int"
|
||||
/> </xs:complexType> </xs:element
|
||||
-->
|
||||
<!--
|
||||
xs:element name="material" minOccurs="0" maxOccurs="unbounded"> <xs:complexType> <xs:attribute name="id"
|
||||
type="xs:string" /> <xs:attribute name="state" type="xs:int" /> </xs:complexType> </xs:element
|
||||
-->
|
||||
<!-- SetupResponse_NO Error -->
|
||||
|
||||
<!--
|
||||
xs:element name="result" minOccurs="0" maxOccurs="unbounded"> <xs:complexType> <xs:attribute name="errorCode"
|
||||
type="xs:int" /> <xs:attribute name="errorText" type="xs:string" /> <xs:attribute name="actionCode" type="xs:int"
|
||||
/> </xs:complexType> </xs:element
|
||||
-->
|
||||
<xs:element name="material" minOccurs="0" maxOccurs="unbounded">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="detail" minOccurs="0" maxOccurs="1">
|
||||
<xs:complexType>
|
||||
<xs:attribute name="part" type="xs:string" />
|
||||
<xs:attribute name="qty" type="xs:int" />
|
||||
<xs:attribute name="lot" type="xs:string" />
|
||||
<xs:attribute name="vendor" type="xs:string" />
|
||||
<xs:attribute name="userdata" type="xs:string" />
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
<xs:attribute name="id" type="xs:string" />
|
||||
<xs:attribute name="part" type="xs:string" use="optional"/>
|
||||
<xs:attribute name="state" type="xs:int" use="optional" />
|
||||
<xs:attribute name="qty" type="xs:int" use="optional"/>
|
||||
<xs:attribute name="splicedReelId" type="xs:string" use="optional" />
|
||||
<xs:attribute name="lot" type="xs:string" use="optional"/>
|
||||
<xs:attribute name="vendor" type="xs:string" use="optional"/>
|
||||
<xs:attribute name="userdata" type="xs:string" use="optional"/>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
|
||||
|
||||
<!-- SetupconfirmRequest -->
|
||||
<!--
|
||||
xs:element name="operation" minOccurs="0" maxOccurs="unbounded"> <xs:complexType> <xs:attribute name="type"
|
||||
type="xs:int" /> <xs:attribute name="operator" type="xs:string" /> <xs:attribute name="timestamp"
|
||||
type="xs:dateTime" /> </xs:complexType> </xs:element
|
||||
-->
|
||||
<!--
|
||||
xs:element name="material" minOccurs="0" maxOccurs="unbounded"> <xs:complexType> <xs:attribute name="id"
|
||||
type="xs:string" /> </xs:complexType> </xs:element
|
||||
-->
|
||||
<xs:element name="position" minOccurs="0" maxOccurs="1">
|
||||
<xs:complexType>
|
||||
<xs:attribute name="p1" type="xs:string" />
|
||||
<xs:attribute name="p2" type="xs:int" />
|
||||
<xs:attribute name="p3" type="xs:int" />
|
||||
<xs:attribute name="p4" type="xs:int" />
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<!-- SetupConfirm_response_error -->
|
||||
<!--
|
||||
xs:element name="result" minOccurs="0" maxOccurs="unbounded"> <xs:complexType> <xs:attribute name="errorCode"
|
||||
type="xs:int" /> <xs:attribute name="errorText" type="xs:string" /> <xs:attribute name="actionCode" type="xs:int"
|
||||
/> </xs:complexType> </xs:element
|
||||
-->
|
||||
<xs:element name="matBlocks" minOccurs="0" maxOccurs="1">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="matBlock" minOccurs="0" maxOccurs="unbounded">
|
||||
<xs:complexType>
|
||||
<xs:attribute name="materialID" type="xs:string" />
|
||||
<xs:attribute name="reasonID" type="xs:int" />
|
||||
<xs:attribute name="reasonText" type="xs:string" />
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<!-- Setupconfirm_Response -->
|
||||
<!--
|
||||
xs:element name="result" minOccurs="0" maxOccurs="unbounded"> <xs:complexType> <xs:attribute name="errorCode"
|
||||
type="xs:int" /> <xs:attribute name="errorText" type="xs:string" /> <xs:attribute name="actionCode" type="xs:int"
|
||||
/> </xs:complexType> </xs:element
|
||||
-->
|
||||
<!-- TraceComponent -->
|
||||
<xs:element name="panel" minOccurs="0" maxOccurs="1">
|
||||
<xs:complexType>
|
||||
<xs:attribute name="state" type="xs:int" />
|
||||
<xs:attribute name="pcbID" type="xs:string" />
|
||||
<xs:attribute name="productName" type="xs:string" />
|
||||
<xs:attribute name="productSide" type="xs:int" />
|
||||
<xs:attribute name="timestamp" type="xs:dateTime" />
|
||||
<xs:attribute name="stageNo" type="xs:int" />
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<!--
|
||||
xs:element name="materials" minOccurs="0" maxOccurs="unbounded"> <xs:complexType> <xs:sequence> <xs:element
|
||||
name="material" minOccurs="0" maxOccurs="unbounded"> <xs:complexType> <xs:attribute name="id" type="xs:string" />
|
||||
<xs:attribute name="qty" type="xs:int" /> <xs:attribute name="p1" type="xs:string" /> <xs:attribute name="p2"
|
||||
type="xs:int" /> <xs:attribute name="p3" type="xs:int" /> <xs:attribute name="p4" type="xs:int" />
|
||||
</xs:complexType> </xs:element> </xs:sequence> </xs:complexType> </xs:element
|
||||
-->
|
||||
<!-- TracePlamentRemoved_request -->
|
||||
<!-- xs:element name="Panel" minOccurs="0" maxOccurs="unbounded">
|
||||
<xs:complexType>
|
||||
<xs:attribute name="state" type="xs:int" />
|
||||
<xs:attribute name="pcbID" type="xs:string" />
|
||||
<xs:attribute name="productName" type="xs:string" />
|
||||
<xs:attribute name="timestamp" type="xs:dateTime" />
|
||||
</xs:complexType>
|
||||
</xs:element-->
|
||||
<xs:element name="stageNo" minOccurs="0" maxOccurs="1">
|
||||
<xs:complexType>
|
||||
<xs:attribute name="value" type="xs:int" />
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<!-- TracePlacementRequest -->
|
||||
|
||||
<xs:element name="trcplPanel" id="Panel" minOccurs="0" maxOccurs="1">
|
||||
<xs:complexType>
|
||||
<xs:attribute name="state"
|
||||
type="xs:int" />
|
||||
<xs:attribute name="pcbID" type="xs:string" />
|
||||
<xs:attribute name="productName" type="xs:string"
|
||||
/>
|
||||
<xs:attribute name="timestamp" type="xs:dateTime" />
|
||||
</xs:complexType>
|
||||
</xs:element
|
||||
>
|
||||
<!--
|
||||
xs:element name="stageNo" minOccurs="0" maxOccurs="unbounded"> <xs:complexType> <xs:attribute name="value"
|
||||
type="xs:int" /> </xs:complexType> </xs:element
|
||||
-->
|
||||
<xs:element name="materials" minOccurs="0" maxOccurs="1">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="material" minOccurs="0" maxOccurs="unbounded">
|
||||
<xs:complexType>
|
||||
<xs:attribute name="ref" type="xs:int" use="optional" />
|
||||
<xs:attribute name="id" type="xs:string" />
|
||||
<xs:attribute name="qty" type="xs:int" />
|
||||
<xs:attribute name="part" type="xs:string" use="optional"/>
|
||||
<xs:attribute name="p1" type="xs:string" />
|
||||
<xs:attribute name="p2" type="xs:int" />
|
||||
<xs:attribute name="p3" type="xs:int" />
|
||||
<xs:attribute name="p4" type="xs:int" />
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<!--
|
||||
xs:element name="comps" minOccurs="0" maxOccurs="unbounded"> <xs:complexType> <xs:sequence> <xs:element
|
||||
name="comp" minOccurs="0" maxOccurs="unbounded"> <xs:complexType> <xs:attribute name="pos" type="xs:int" />
|
||||
<xs:attribute name="ref" type="xs:int" /> <xs:attribute name="refDes" type="xs:string" /> </xs:complexType>
|
||||
</xs:element> </xs:sequence> </xs:complexType> </xs:element
|
||||
-->
|
||||
|
||||
<!-- Verification_request -->
|
||||
<xs:element name="timestamp" minOccurs="0" maxOccurs="1">
|
||||
<xs:complexType>
|
||||
<xs:attribute name="value" type="xs:dateTime" />
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<!--
|
||||
xs:element name="materials" minOccurs="0" maxOccurs="unbounded"> <xs:complexType> <xs:sequence> <xs:element
|
||||
name="material" minOccurs="0" maxOccurs="unbounded"> <xs:complexType> <xs:attribute name="id" type="xs:string" />
|
||||
<xs:attribute name="qty" type="xs:int" /> <xs:attribute name="p1" type="xs:string" /> <xs:attribute name="p2"
|
||||
type="xs:int" /> <xs:attribute name="p3" type="xs:int" /> <xs:attribute name="p4" type="xs:int" />
|
||||
</xs:complexType> </xs:element> </xs:sequence> </xs:complexType> </xs:element
|
||||
-->
|
||||
|
||||
<!-- Verification_response_error -->
|
||||
|
||||
<!--
|
||||
xs:element name="result" minOccurs="0" maxOccurs="unbounded"> <xs:complexType> <xs:attribute name="errorCode"
|
||||
type="xs:int" /> <xs:attribute name="errorText" type="xs:string" /> <xs:attribute name="actionCode" type="xs:int"
|
||||
/> </xs:complexType> </xs:element
|
||||
-->
|
||||
<!--
|
||||
xs:element name="matBlocks" minOccurs="0" maxOccurs="unbounded"> <xs:complexType> <xs:sequence> <xs:element
|
||||
name="matBlock" minOccurs="0" maxOccurs="unbounded"> <xs:complexType> <xs:attribute name="materialID"
|
||||
type="xs:string" /> <xs:attribute name="reasonID" type="xs:int" /> <xs:attribute name="reasonText"
|
||||
type="xs:string" /> </xs:complexType> </xs:element> </xs:sequence> </xs:complexType> </xs:element
|
||||
-->
|
||||
<!-- Verification_response_no_error -->
|
||||
|
||||
<!--
|
||||
xs:element name="result" minOccurs="0" maxOccurs="unbounded"> <xs:complexType> <xs:attribute name="errorCode"
|
||||
type="xs:int" /> <xs:attribute name="errorText" type="xs:string" /> <xs:attribute name="actionCode" type="xs:int"
|
||||
/> </xs:complexType> </xs:element
|
||||
-->
|
||||
|
||||
</xs:choice>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
|
||||
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:schema>
|
||||
@@ -0,0 +1,396 @@
|
||||
package com.itac.mes.datainterface.data;
|
||||
|
||||
import static junit.framework.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Matchers.anyString;
|
||||
import static org.mockito.Mockito.doNothing;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.UndeclaredThrowableException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
import com.itac.artes.ihas.LookupException;
|
||||
import com.itac.easyworks.api.idl.ServerException;
|
||||
import com.itac.mes.api.domain.EWApiServices;
|
||||
import com.itac.mes.client.Protocol;
|
||||
import com.itac.mes.datainterface.ConfigurationException;
|
||||
import com.itac.mes.datainterface.DataInterfaceConfiguration;
|
||||
import com.itac.mes.datainterface.data.panacim.MessageException;
|
||||
import com.itac.mes.datainterface.data.panacim.PanaCimActionCode;
|
||||
import com.itac.mes.datainterface.data.panacim.PanaCimMessage;
|
||||
import com.itac.mes.datainterface.data.panacim.PanaCimSmtInterlockingResult;
|
||||
import com.itac.mes.datainterface.data.panacim.ParseException;
|
||||
import com.itac.mes.datainterface.data.panacim.SendException;
|
||||
import com.itac.mes.datainterface.data.smt.BadmarkEvaluator;
|
||||
import com.itac.mes.datainterface.data.smt.InterlockingMechanism;
|
||||
import com.itac.mes.datainterface.data.smt.PlacementRecipeCheck;
|
||||
import com.itac.mes.datainterface.data.smt.PlacementRecipeMode;
|
||||
import com.itac.mes.datainterface.data.smt.SearchReplacePattern;
|
||||
import com.itac.mes.datainterface.data.smt.SmtConfiguration;
|
||||
import com.itac.mes.datainterface.data.smt.SmtLineConfiguration;
|
||||
import com.itac.mes.datainterface.data.smt.WorkorderBasedSetupSettings;
|
||||
import com.itac.mes.datainterface.factories.AConfigurableHandler;
|
||||
import com.itac.mes.datainterface.messaging.EventHandler;
|
||||
import com.itac.mes.datainterface.parser.IParser;
|
||||
import com.itac.mes.datainterface.parser.PanaCimParser;
|
||||
import com.itac.mes.datainterface.process.IProcessor;
|
||||
import com.itac.mes.datainterface.process.PanaCimSmtProcessor;
|
||||
import com.itac.mes.datainterface.process.ProcessorException;
|
||||
import com.itac.mes.datainterface.service.DataInterfaceServices;
|
||||
import com.itac.mes.imsapi.domain.IMSApiService;
|
||||
import com.itac.mes.imsapi.domain.container.IMSApiSessionContextStruct;
|
||||
import com.itac.mes.imsapi.domain.container.Result_smtSerialNumberCheckIn;
|
||||
import com.itac.panacim.Message;
|
||||
import com.itac.panacim.Message.Body.Result;
|
||||
|
||||
public class PanaCimApplicationTest {
|
||||
|
||||
private static DataInterfaceConfiguration config;
|
||||
private static SmtLineConfiguration smtLine = new SmtLineConfiguration();
|
||||
|
||||
@BeforeClass
|
||||
public static void setUp() throws Exception {
|
||||
// Standard-Werte setzen...
|
||||
StringBuilder text = new StringBuilder(
|
||||
" <line name=\"line1\" activateSetup=\"true\" activateWorkorder=\"true\" adjustContainerQuantity=\"OFF\" " + //
|
||||
" checkContainerExpiration=\"true\" checkContainerQuantity=\"true\" checkContainerState=\"true\" " + //
|
||||
" createWorkorder=\"false\" maxLifeSpan=\"00:05:00\" " + //
|
||||
" createContainer=\"true\" setupData=\"true\" setupDetails=\"off\" setupSplices=\"true\" >" + //
|
||||
" <trMachine name=\"machine1\" linePattern=\".*\" machinePattern=\".*\" " + //
|
||||
" lanePattern=\".*\" modulePattern=\".*\">" + //
|
||||
" <smtSettings assignSerialnumbers=\"false\" bomCheck=\"true\" bomCheckState=\"true\" " + //
|
||||
" bomCheckFailureType=\"true\" bookSerialnumbers=\"true\" interlocking=\"false\" " + //
|
||||
" preBomCheck=\"true\" " + //
|
||||
" processFailureType=\"true\" " + //
|
||||
" materialQuantityReporting=\"true\" " + //
|
||||
" rejectComponents=\"true\" />" + //
|
||||
" </trMachine>" + //
|
||||
" <pmMachine name=\"pmmachine1\" linePattern=\".*\" machinePattern=\".*\" " + //
|
||||
" lanePattern=\".*\" modulePattern=\".*\">" + //
|
||||
" <smtSettings stationConditions=\"true\" stationMessages=\"ERRORCODE\" />" + //
|
||||
" </pmMachine>" + //
|
||||
" </line>");
|
||||
|
||||
smtLine.setXmlConfigText(text, false);
|
||||
List<SmtLineConfiguration> smtLineConfigurations = new ArrayList<SmtLineConfiguration>();
|
||||
smtLineConfigurations.add(smtLine);
|
||||
|
||||
config = mock(DataInterfaceConfiguration.class);
|
||||
SmtConfiguration smtConfiguration = mock(SmtConfiguration.class);
|
||||
when(smtConfiguration.getMachineListPM()).thenReturn(smtLine.getSmtMachineListPM());
|
||||
when(smtConfiguration.getSmtMachineListTR()).thenReturn(smtLine.getSmtMachineListTR());
|
||||
when(config.getValue("parser.panacim.modelCodePattern", String.class)).thenReturn("{0}_{1}_F{2}");
|
||||
when(config.getValue("parser.panacim.defaultStation", String.class)).thenReturn("machine1");
|
||||
|
||||
when(smtConfiguration.getTransactionTypePlaced()).thenReturn(201);
|
||||
when(smtConfiguration.getProductPattern())
|
||||
.thenReturn(new SearchReplacePattern("productpattern", true, "([0-9]{3})([0-9]{3})([0-9]{2}).*", "$1.$2-$3"));
|
||||
when(smtConfiguration.getPlacementRecipePattern())
|
||||
.thenReturn(new SearchReplacePattern("placementrecipepattern", true, ".*", "$1"));
|
||||
when(smtConfiguration.getMaxLifeSpan()).thenReturn(new Duration(3000000l));
|
||||
when(smtConfiguration.getDefaultAlarmDuration()).thenReturn(new Duration(3000000l));
|
||||
when(smtConfiguration.getDefaultConditionCode()).thenReturn("4711");
|
||||
when(smtConfiguration.getDefaultContainerQuantity()).thenReturn(1000);
|
||||
when(smtConfiguration.getConsumptionDataInterval()).thenReturn(new Duration(3000000l));
|
||||
when(smtConfiguration.getWorkorderBasedSetupSettings()).thenReturn(new WorkorderBasedSetupSettings());
|
||||
when(smtConfiguration.getWorkorderPattern()).thenReturn(new SearchReplacePattern("woPattern", true, ".*", ""));
|
||||
when(smtConfiguration.getReelPositionWithPattern(anyString(), anyString(), anyString(), anyString(), anyString(), anyString()))
|
||||
.thenReturn("22_1_309");
|
||||
when(smtConfiguration.getSerialnumberPattern()).thenReturn(new SearchReplacePattern("serialpattern", false, "(.*)", "$1"));
|
||||
}
|
||||
|
||||
protected Toolbox getToolbox() throws ConfigurationException {
|
||||
Toolbox toolbox = new Toolbox();
|
||||
toolbox.addStation(new Station("Machine1", "12012010", false));
|
||||
toolbox.addStation(new Station("machine1", "12012010", false));
|
||||
toolbox.addStation(new Station("Machine2", "12012011", false));
|
||||
toolbox.addStation(new Station("pmmachine1", "12012011", false));
|
||||
toolbox.setDateTimePattern("yyyyMMddHHmmss");
|
||||
toolbox.addLayer("1", "0");
|
||||
toolbox.addLayer("0", "1");
|
||||
toolbox.addLayer("_W", "3");
|
||||
toolbox.addFailcode("0", 0);
|
||||
toolbox.addStatus("0", 0);
|
||||
toolbox.addFailcode("1", 1);
|
||||
toolbox.addStatus("1", 1);
|
||||
toolbox.addConditionMapItem("2", "Fuji2");
|
||||
toolbox.addConditionMapItem("3", "Fuji3");
|
||||
toolbox.addMessageMapItem("1", "Fuji_R1");
|
||||
toolbox.addMessageMapItem("4", "-1");
|
||||
toolbox.addMessageMapItem("5", "Fuji_R5");
|
||||
return toolbox;
|
||||
}
|
||||
|
||||
public Toolbox getToolboxMock() {
|
||||
Toolbox mockObject = mock(Toolbox.class);
|
||||
when(mockObject.hasConditionMapping()).thenReturn(true);
|
||||
when(mockObject.hasMessageMapping()).thenReturn(true);
|
||||
when(mockObject.getStatus("PASS")).thenReturn(0);
|
||||
when(mockObject.getLayer("_T")).thenReturn(0);
|
||||
when(mockObject.getLayer("_B")).thenReturn(1);
|
||||
when(mockObject.getLayer("_W")).thenReturn(3);
|
||||
when(mockObject.getLayer(anyString())).thenReturn(-1);
|
||||
when(mockObject.getConditionCode("2")).thenReturn("Fuji2");
|
||||
when(mockObject.getConditionCode("3")).thenReturn("Fuji3");
|
||||
when(mockObject.getMessageCode("1")).thenReturn("Fuji_R1");
|
||||
when(mockObject.getMessageCode("4")).thenReturn("-1");
|
||||
when(mockObject.getMessageCode("5")).thenReturn("Fuji_R5");
|
||||
when(mockObject.getFailcode("0")).thenReturn(0);
|
||||
when(mockObject.getTextcode("0")).thenReturn("0");
|
||||
when(mockObject.getStation("Machine1")).thenReturn(new Station("Machine1", "12012010", false));
|
||||
when(mockObject.getStation("machine1")).thenReturn(new Station("machine1", "12012010", false));
|
||||
when(mockObject.getStation("Machine2")).thenReturn(new Station("Machine2", "12012011", false));
|
||||
when(mockObject.getStation("pmmachine1")).thenReturn(new Station("pmmachine1", "12012011", false));
|
||||
return mockObject;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test() throws ParseException, MessageException, SendException, IllegalAccessException, InvocationTargetException,
|
||||
ConfigurationException {
|
||||
PanaCimApplication out = new PanaCimApplication();
|
||||
out.setHandler(getToolboxMock(), Toolbox.class);
|
||||
out.setHandler(config, DataInterfaceConfiguration.class);
|
||||
out.setHandler(mock(EventHandler.class), EventHandler.class);
|
||||
PlacementRecipeChangeManager placeRecipeChangeManager = new PlacementRecipeChangeManager();
|
||||
out.setHandler(placeRecipeChangeManager, PlacementRecipeChangeManager.class);
|
||||
// out.setHandler(smtConfiguration, SmtConfiguration.class);
|
||||
out.configure();
|
||||
out.callAtInit();
|
||||
assertEquals(out.getConfigurationText(), AConfigurableHandler.OK, out.getConfigurationResult());
|
||||
|
||||
String messageTextNoScannerMountSide = //
|
||||
"<message>" + //
|
||||
"<header messageClass=\"501\" transactionID=\"1234567890\" reply=\"1\">" + //
|
||||
" <location routeID=\"1001\" routeName=\"$PanaCimLine\" equipmentID=\"1000\"" + //
|
||||
" equipmentName=\"$PanaCimStation\" zonePos=\"0\" zoneName=\"SMT1\" laneNo=\"0\" />" + //
|
||||
"</header>" + //
|
||||
"<body>" + //
|
||||
" <pcb barcode=\"$serialNumber\" modelCode=\"\" serialNo=\"$serialNumber\" pcbSide=\"1\" />" + //
|
||||
"</body>" + //
|
||||
"</message>";
|
||||
PanaCimMessage inMessage = new PanaCimMessage();
|
||||
inMessage.setContent(messageTextNoScannerMountSide);
|
||||
|
||||
PanaCimDataUnit panaCimDataUnit = new PanaCimDataUnit();
|
||||
panaCimDataUnit.processResultList = new ArrayList<ProcessResult>();
|
||||
|
||||
PanaCimSmtInterlockingResult pcir = new PanaCimSmtInterlockingResult();
|
||||
ProcessResult pr = new ProcessResult(null);
|
||||
pr.setResultObject(pcir);
|
||||
panaCimDataUnit.processResultList.add(pr);
|
||||
pcir.actionCode = PanaCimActionCode.STOP_PCB;
|
||||
pcir.errorCode = 3;
|
||||
|
||||
out.processReply(inMessage, panaCimDataUnit);
|
||||
|
||||
assertEquals(inMessage.getResponseMessage().getBody().getResult().getActionCode().intValue(), 3);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFailedSerialnumber() throws Exception {
|
||||
// den Api Service und DataInterfaceServices mocken
|
||||
EWApiServices apiServiceMock = mock(EWApiServices.class);
|
||||
IMSApiService imsapiServiceMock = mock(IMSApiService.class);
|
||||
DataInterfaceServices serviceMock = mock(DataInterfaceServices.class);
|
||||
when(serviceMock.getAPIServices()).thenReturn(apiServiceMock);
|
||||
when(serviceMock.getIMSApiService()).thenReturn(imsapiServiceMock);
|
||||
when(serviceMock.getProtocol()).thenReturn(new Protocol());
|
||||
|
||||
SmtConfiguration smtConfiguration = mock(SmtConfiguration.class);
|
||||
PlacementRecipeCheck placementRecipeCheck = new PlacementRecipeCheck();
|
||||
placementRecipeCheck.setPlacementRecipeCheckMode(PlacementRecipeMode.OFF);
|
||||
when(smtConfiguration.getPlacementRecipeCheck()).thenReturn(placementRecipeCheck);
|
||||
when(smtConfiguration.getSerialnumberPattern()).thenReturn(new SearchReplacePattern("snPattern", false, ".*", "$1"));
|
||||
when(smtConfiguration.getMachineListPM()).thenReturn(smtLine.getSmtMachineListPM());
|
||||
when(smtConfiguration.getSmtMachineListTR()).thenReturn(smtLine.getSmtMachineListTR());
|
||||
|
||||
// reale Application bauen
|
||||
PanaCimApplication out = new PanaCimApplication();
|
||||
out.setHandler(config, DataInterfaceConfiguration.class);
|
||||
out.setHandler(getToolboxMock(), Toolbox.class);
|
||||
out.setHandler(mock(EventHandler.class), EventHandler.class);
|
||||
PlacementRecipeChangeManager placeRecipeChangeManager = new PlacementRecipeChangeManager();
|
||||
out.setHandler(placeRecipeChangeManager, PlacementRecipeChangeManager.class);
|
||||
out.setHandler(smtConfiguration, SmtConfiguration.class);
|
||||
BadmarkEvaluator badmarkEvaluator = new BadmarkEvaluator();
|
||||
out.setHandler(badmarkEvaluator, BadmarkEvaluator.class);
|
||||
out.configure();
|
||||
out.callAtInit();
|
||||
assertEquals(out.getConfigurationText(), AConfigurableHandler.OK, out.getConfigurationResult());
|
||||
|
||||
// parser fuer die application mocken
|
||||
PanaCimParser parser = new PanaCimParser();
|
||||
parser.setHandler(getToolboxMock(), Toolbox.class);
|
||||
parser.setHandler(config, DataInterfaceConfiguration.class);
|
||||
parser.setHandler(mock(EventHandler.class), EventHandler.class);
|
||||
parser.setHandler(smtConfiguration, SmtConfiguration.class);
|
||||
parser.configure();
|
||||
parser.callAtInit();
|
||||
assertEquals(out.getConfigurationText(), AConfigurableHandler.OK, out.getConfigurationResult());
|
||||
out.setParser(parser);
|
||||
// einen entsprechenden Prozessor bauen
|
||||
PanaCimSmtProcessor processor = new PanaCimSmtProcessor();
|
||||
processor.setHandler(serviceMock, DataInterfaceServices.class);
|
||||
processor.configure();
|
||||
processor.callAtInit();
|
||||
assertEquals(out.getConfigurationText(), AConfigurableHandler.OK, out.getConfigurationResult());
|
||||
|
||||
out.setProcessor(processor);
|
||||
|
||||
// die Testnachricht bauen
|
||||
PanaCimMessage inMessage = new PanaCimMessage();
|
||||
String s = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?> " + "<message>"
|
||||
+ " <header reply=\"1\" transactionID=\"Pana:a605wc84:1380559492\" messageClass=\"501\">"
|
||||
+ " <location controllerGuid=\"\" laneNo=\"2\" zoneName=\"NPM-1C6V0466\" zonePos=\"0\" zoneID=\"1123\" equipmentName=\"NPM1-1C6V0466\" equipmentID=\"1076\" routeName=\"CMS-Ligne-7_12-2012\" routeID=\"1010\"/>"
|
||||
+ " </header>" + " <body>" + " <product side=\"1\" name=\"product\"/>"
|
||||
+ " <pcb scannerMountSide=\"B\" pcbSide=\"1\" serialNo=\"18130670_03\" modelCode=\"002222222_04\" barcode=\"_002222222_04_711_18130670_03_\"/>"
|
||||
+ " </body>" + "</message>";
|
||||
inMessage.setContent(s);
|
||||
|
||||
PanaCimMessage spyMessage = spy(inMessage);
|
||||
doNothing().when(spyMessage).sendResponseMessage();
|
||||
|
||||
Result_smtSerialNumberCheckIn checkinResult = new Result_smtSerialNumberCheckIn();
|
||||
checkinResult.return_value = 0;
|
||||
checkinResult.serialNoCheckResultValues = new String[] { "s1", "01040010", "0", "-1", "true", "1", "0", "0" };
|
||||
checkinResult.logInfoResultValues = new String[0];
|
||||
checkinResult.serialNumberStateResultValues = new String[] { "0", "0", "s1", "1", "1", "0", "0", "s2", "2", "1" };
|
||||
checkinResult.recipeResultValues = new String[0];
|
||||
|
||||
when(imsapiServiceMock.smtSerialNumberCheckIn(any(IMSApiSessionContextStruct.class), any(String.class), any(String[].class),
|
||||
any(String[].class), any(String[].class), any(String[].class), any(String[].class), any(String[].class)))
|
||||
.thenReturn(checkinResult);
|
||||
|
||||
//
|
||||
// Result_getSnrInfoData snrInfoResult = new Result_getSnrInfoData();
|
||||
// snrInfoResult.return_value = 0;
|
||||
// snrInfoResult.errorString = "";
|
||||
// snrInfoResult.customerPartNr = "custPart";
|
||||
// snrInfoResult.partDesc = "partDesc";
|
||||
// snrInfoResult.partNr = "product";
|
||||
// snrInfoResult.bomIndex = "1";
|
||||
// when(apiServiceMock.getSnrInfoData(anyString(), Matchers.eq("_002222222_04_711_18130670_03_"),
|
||||
// anyString())).thenReturn(
|
||||
// snrInfoResult);
|
||||
//
|
||||
// Result_checkSnrStateBySnrRef checkSnrResult = new Result_checkSnrStateBySnrRef();
|
||||
// checkSnrResult.errorString = "Not valid for this Station. Part needs to be seen at one of the previous Stations";
|
||||
// checkSnrResult.return_value = 3;
|
||||
// checkSnrResult.numberOfRecords = 2;
|
||||
// checkSnrResult.testDataArray = new StateData[2];
|
||||
// checkSnrResult.testDataArray[0] = new StateData("s1", "1", 1, 1);
|
||||
// checkSnrResult.testDataArray[1] = new StateData("s2", "2", 1, 1);
|
||||
// when(apiServiceMock.checkSnrStateBySnrRef(anyString(), anyInt(), anyString())).thenReturn(checkSnrResult);
|
||||
//
|
||||
// Result_getSerialNumberBySnrRef getSnrRefResult = new Result_getSerialNumberBySnrRef();
|
||||
// getSnrRefResult.return_value = 0;
|
||||
// getSnrRefResult.errorString = "";
|
||||
// getSnrRefResult.numberOfRecords = 2;
|
||||
// getSnrRefResult.serialNumberArray = new SerialNumberData[2];
|
||||
// getSnrRefResult.serialNumberArray[0] = new SerialNumberData("s1", "1");
|
||||
// getSnrRefResult.serialNumberArray[1] = new SerialNumberData("s2", "2");
|
||||
// when(apiServiceMock.getSerialNumberBySnrRef(anyString(), anyInt(), anyString())).thenReturn(getSnrRefResult);
|
||||
|
||||
// Nachrichteneingang simulieren
|
||||
out.setMessage(spyMessage);
|
||||
|
||||
Message msg = spyMessage.getResponseMessage();
|
||||
assertNotNull("responseMessage is null", msg);
|
||||
assertEquals(PanaCimActionCode.DO_NOTHING, msg.getBody().getResult().getActionCode().intValue());
|
||||
assertEquals(0, msg.getBody().getResult().getErrorCode().intValue());
|
||||
assertEquals("", msg.getBody().getResult().getErrorText());
|
||||
|
||||
// weiterer Modus testen
|
||||
smtLine.getSmtMachineListTR().get("machine1").getSmtSettings().setInterlocking(InterlockingMechanism.CHECK_SN_EXIST);
|
||||
|
||||
// Nachrichteneingang simulieren
|
||||
out.setMessage(spyMessage);
|
||||
//
|
||||
msg = spyMessage.getResponseMessage();
|
||||
assertNotNull("responseMessage is null", msg);
|
||||
assertEquals(PanaCimActionCode.DO_NOTHING, msg.getBody().getResult().getActionCode().intValue());
|
||||
assertEquals(0, msg.getBody().getResult().getErrorCode().intValue());
|
||||
assertEquals("", msg.getBody().getResult().getErrorText());
|
||||
//
|
||||
// weiterer Modus testen
|
||||
smtLine.getSmtMachineListTR().get("machine1").getSmtSettings().setInterlocking(InterlockingMechanism.CHECK_SN_STATE);
|
||||
//
|
||||
// Nachrichteneingang simulieren
|
||||
out.setMessage(spyMessage);
|
||||
//
|
||||
msg = spyMessage.getResponseMessage();
|
||||
assertNotNull("responseMessage is null", msg);
|
||||
assertEquals(PanaCimActionCode.DO_NOTHING, msg.getBody().getResult().getActionCode().intValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProcessExceptionShouldReturnFailure() throws ParseException, MessageException, SendException, LookupException,
|
||||
ServerException, ProcessorException, IllegalAccessException, InvocationTargetException, ConfigurationException {
|
||||
PanaCimApplication out = new PanaCimApplication();
|
||||
out.setHandler(mock(EventHandler.class), EventHandler.class);
|
||||
PanaCimParser parser = Mockito.mock(PanaCimParser.class);
|
||||
parser.setHandler(config, DataInterfaceConfiguration.class);
|
||||
parser.configure();
|
||||
parser.callAtInit();
|
||||
Mockito.when(parser.parse(any(PanaCimMessage.class), any(PanaCimDataUnit.class))).thenReturn(IParser.Code.OK);
|
||||
out.setParser(parser);
|
||||
|
||||
IProcessor processor = Mockito.mock(PanaCimSmtProcessor.class);
|
||||
Mockito.when(processor.send(any(BasicDataUnit.class))).thenThrow(new UndeclaredThrowableException(new NullPointerException()));
|
||||
out.setProcessor(processor);
|
||||
// die Testnachricht bauen
|
||||
PanaCimMessage inMessage = new PanaCimMessage();
|
||||
String s = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?> " + "<message>"
|
||||
+ " <header reply=\"1\" transactionID=\"Pana:a605wc84:1380559492\" messageClass=\"501\">"
|
||||
+ " <location controllerGuid=\"\" laneNo=\"2\" zoneName=\"NPM-1C6V0466\" zonePos=\"0\" zoneID=\"1123\" equipmentName=\"NPM1-1C6V0466\" equipmentID=\"1076\" routeName=\"CMS-Ligne-7_12-2012\" routeID=\"1010\"/>"
|
||||
+ " </header>" + " <body>" + " <product side=\"1\" name=\"product\"/>"
|
||||
+ " <pcb scannerMountSide=\"B\" pcbSide=\"1\" serialNo=\"18130670_03\" modelCode=\"002222222_04\" barcode=\"_002222222_04_711_18130670_03_\"/>"
|
||||
+ " </body>" + "</message>";
|
||||
inMessage.setContent(s);
|
||||
out.setMessage(inMessage);
|
||||
|
||||
Message response = inMessage.getResponseMessage();
|
||||
assertNotNull(response.getBody().getResult());
|
||||
Result r = response.getBody().getResult();
|
||||
assertEquals(-99, r.getErrorCode().intValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPauseShouldReturnFailure()
|
||||
throws ParseException, MessageException, SendException, LookupException, ServerException, ProcessorException, ConfigurationException {
|
||||
PanaCimApplication out = new PanaCimApplication();
|
||||
out.setHandler(mock(EventHandler.class), EventHandler.class);
|
||||
out.setPaused(true);
|
||||
PanaCimParser parser = Mockito.mock(PanaCimParser.class);
|
||||
Mockito.when(parser.parse(any(PanaCimMessage.class), any(PanaCimDataUnit.class))).thenReturn(IParser.Code.OK);
|
||||
out.setParser(parser);
|
||||
|
||||
IProcessor processor = Mockito.mock(PanaCimSmtProcessor.class);
|
||||
Mockito.when(processor.send(any(BasicDataUnit.class))).thenThrow(new UndeclaredThrowableException(new NullPointerException()));
|
||||
out.setProcessor(processor);
|
||||
// die Testnachricht bauen
|
||||
PanaCimMessage inMessage = new PanaCimMessage();
|
||||
String s = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?> " + "<message>"
|
||||
+ " <header reply=\"1\" transactionID=\"Pana:a605wc84:1380559492\" messageClass=\"501\">"
|
||||
+ " <location controllerGuid=\"\" laneNo=\"2\" zoneName=\"NPM-1C6V0466\" zonePos=\"0\" zoneID=\"1123\" equipmentName=\"NPM1-1C6V0466\" equipmentID=\"1076\" routeName=\"CMS-Ligne-7_12-2012\" routeID=\"1010\"/>"
|
||||
+ " </header>" + " <body>" + " <product side=\"1\" name=\"product\"/>"
|
||||
+ " <pcb scannerMountSide=\"B\" pcbSide=\"1\" serialNo=\"18130670_03\" modelCode=\"002222222_04\" barcode=\"_002222222_04_711_18130670_03_\"/>"
|
||||
+ " </body>" + "</message>";
|
||||
inMessage.setContent(s);
|
||||
out.setMessage(inMessage);
|
||||
|
||||
Message response = inMessage.getResponseMessage();
|
||||
assertNotNull(response.getBody().getResult());
|
||||
Result r = response.getBody().getResult();
|
||||
assertEquals(-99, r.getErrorCode().intValue());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
package com.itac.mes.datainterface.data.panacim;
|
||||
|
||||
import static junit.framework.Assert.assertEquals;
|
||||
import static junit.framework.Assert.assertNotNull;
|
||||
import static junit.framework.Assert.assertNull;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class PanaCimMessage501Test {
|
||||
|
||||
@Test
|
||||
public void testParseMessage() throws MessageException, SendException, ParseException {
|
||||
// parsen ohne das Feld scannerMountSide im pcb-Tag
|
||||
String messageTextNoScannerMountSide = //
|
||||
"<message>" + //
|
||||
"<header messageClass=\"501\" transactionID=\"1234567890\" reply=\"1\">" + //
|
||||
" <location routeID=\"1001\" routeName=\"$PanaCimLine\" equipmentID=\"1000\"" + //
|
||||
" equipmentName=\"$PanaCimStation\" zonePos=\"0\" zoneName=\"SMT1\" laneNo=\"0\" />" + //
|
||||
"</header>" + //
|
||||
"<body>" + //
|
||||
" <pcb barcode=\"$serialNumber\" modelCode=\"\" serialNo=\"$serialNumber\" pcbSide=\"1\" />" + //
|
||||
"</body>" + //
|
||||
"</message>";
|
||||
PanaCimMessage msg = new PanaCimMessage();
|
||||
msg.setContent(messageTextNoScannerMountSide);
|
||||
assertNotNull("message is empty", msg);
|
||||
assertNotNull("message does not contain body", msg.getBody());
|
||||
assertNotNull("message does not contain body", msg.getBody());
|
||||
assertNotNull("body does not contain pcb", msg.getBody().getPcb());
|
||||
assertNull("pcb does contain scannerMountside", msg.getBody().getPcb().getScannerMountSide());
|
||||
|
||||
// parsen mit Feld scannerMountSide im pcb-Tag
|
||||
messageTextNoScannerMountSide = //
|
||||
"<message>" + //
|
||||
"<header messageClass=\"501\" transactionID=\"1234567890\" reply=\"1\">" + //
|
||||
" <location routeID=\"1001\" routeName=\"$PanaCimLine\" equipmentID=\"1000\"" + //
|
||||
" equipmentName=\"$PanaCimStation\" zonePos=\"0\" zoneName=\"SMT1\" laneNo=\"0\" />" + //
|
||||
"</header>" + //
|
||||
"<body>" + //
|
||||
" <pcb barcode=\"$serialNumber\" modelCode=\"\" serialNo=\"$serialNumber\" pcbSide=\"1\" scannerMountSide=\"-1\"/>" + //
|
||||
"</body>" + //
|
||||
"</message>";
|
||||
msg = new PanaCimMessage();
|
||||
msg.setContent(messageTextNoScannerMountSide);
|
||||
assertNotNull("message is empty", msg);
|
||||
assertNotNull("message does not contain body", msg.getBody());
|
||||
assertNotNull("message does not contain body", msg.getBody());
|
||||
assertNotNull("body does not contain pcb", msg.getBody().getPcb());
|
||||
assertEquals("pcb does contain scannerMountside", "-1", msg.getBody().getPcb().getScannerMountSide());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParseMessageAdditionalHeaderFields() throws MessageException, SendException, ParseException {
|
||||
// parsen mit und ohne Feld zoneId und controllerGuid
|
||||
String messageTextNoScannerMountSide = //
|
||||
"<message>" + //
|
||||
"<header messageClass=\"501\" transactionID=\"1234567890\" reply=\"1\">" + //
|
||||
" <location routeID=\"1001\" routeName=\"$PanaCimLine\" equipmentID=\"1000\"" + //
|
||||
" equipmentName=\"$PanaCimStation\" zonePos=\"0\" zoneName=\"SMT1\" " + //
|
||||
" laneNo=\"0\" />" + //
|
||||
"</header>" + //
|
||||
"<body>" + //
|
||||
" <pcb barcode=\"$serialNumber\" modelCode=\"\" serialNo=\"$serialNumber\" pcbSide=\"1\" />" + //
|
||||
"</body>" + //
|
||||
"</message>";
|
||||
PanaCimMessage msg = new PanaCimMessage();
|
||||
msg.setContent(messageTextNoScannerMountSide);
|
||||
assertNotNull("message is empty", msg);
|
||||
assertNotNull("message does not contain header", msg.getHeader());
|
||||
assertNotNull("header does not contain location", msg.getHeader().getLocation());
|
||||
assertNull("location does not contain controllerGUID", msg.getHeader().getLocation().getControllerGuid());
|
||||
assertNull("location does not contain zoneID", msg.getHeader().getLocation().getZoneID());
|
||||
|
||||
messageTextNoScannerMountSide = //
|
||||
"<message>" + //
|
||||
"<header messageClass=\"501\" transactionID=\"1234567890\" reply=\"1\">" + //
|
||||
" <location routeID=\"1001\" routeName=\"$PanaCimLine\" equipmentID=\"1000\"" + //
|
||||
" equipmentName=\"$PanaCimStation\" zoneID=\"12\" zonePos=\"0\" zoneName=\"SMT1\" " + //
|
||||
" laneNo=\"0\" controllerGuid=\"contGuid\" />" + //
|
||||
"</header>" + //
|
||||
"<body>" + //
|
||||
" <pcb barcode=\"$serialNumber\" modelCode=\"\" serialNo=\"$serialNumber\" pcbSide=\"1\" />" + //
|
||||
"</body>" + //
|
||||
"</message>";
|
||||
msg = new PanaCimMessage();
|
||||
msg.setContent(messageTextNoScannerMountSide);
|
||||
assertNotNull("message is empty", msg);
|
||||
assertNotNull("message does not contain header", msg.getHeader());
|
||||
assertNotNull("location does not contain controllerGUID", msg.getHeader().getLocation().getControllerGuid());
|
||||
assertNotNull("location does not contain zoneID", msg.getHeader().getLocation().getZoneID());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (c) 2010 iTAC Software AG, Germany. All Rights Reserved.
|
||||
*
|
||||
* This software is protected by copyright. Under no circumstances may any part of this file in any form be copied,
|
||||
* printed, edited or otherwise distributed, be stored in a retrieval system, or be translated into another language
|
||||
* without the written permission of iTAC Software AG.
|
||||
*/
|
||||
|
||||
package com.itac.mes.datainterface.data.panacim;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.itac.util.logging.LogHandler;
|
||||
import com.itac.util.logging.LogLevel;
|
||||
|
||||
/**
|
||||
* @author frankp created 2011
|
||||
*/
|
||||
public class PanaCimMessageTest {
|
||||
@Test
|
||||
public void testNullMessage() {
|
||||
PanaCimMessage message = new PanaCimMessage();
|
||||
try {
|
||||
message.setContent(null);
|
||||
Assert.fail("setting null as xmlText generates no messageException");
|
||||
} catch (MessageException me) { // ignore Message Exception
|
||||
} catch (SendException e) {
|
||||
LogHandler.log(LogLevel.ERROR, "sending failed", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEmptyMessage() {
|
||||
PanaCimMessage message = new PanaCimMessage();
|
||||
try {
|
||||
message.setContent("");
|
||||
Assert.fail("setting empty xmlText generates no messageException");
|
||||
} catch (MessageException me) { // ignore Message Exception
|
||||
} catch (SendException e) {
|
||||
LogHandler.log(LogLevel.ERROR, "sending failed", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,174 @@
|
||||
package com.itac.mes.datainterface.parser;
|
||||
|
||||
import static junit.framework.Assert.assertEquals;
|
||||
import static junit.framework.Assert.assertNotNull;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Matchers.anyString;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.itac.mes.datainterface.ConfigurationException;
|
||||
import com.itac.mes.datainterface.DataInterfaceConfiguration;
|
||||
import com.itac.mes.datainterface.data.Duration;
|
||||
import com.itac.mes.datainterface.data.PanaCimDataUnit;
|
||||
import com.itac.mes.datainterface.data.Station;
|
||||
import com.itac.mes.datainterface.data.Toolbox;
|
||||
import com.itac.mes.datainterface.data.UploadSmtSerialNumberCheckInUnit;
|
||||
import com.itac.mes.datainterface.data.panacim.MessageException;
|
||||
import com.itac.mes.datainterface.data.panacim.PanaCimMessage;
|
||||
import com.itac.mes.datainterface.data.panacim.SendException;
|
||||
import com.itac.mes.datainterface.data.smt.Filter;
|
||||
import com.itac.mes.datainterface.data.smt.InterlockingMechanism;
|
||||
import com.itac.mes.datainterface.data.smt.PlacementRecipeCheck;
|
||||
import com.itac.mes.datainterface.data.smt.PlacementRecipeMode;
|
||||
import com.itac.mes.datainterface.data.smt.SearchReplacePattern;
|
||||
import com.itac.mes.datainterface.data.smt.SmtConfiguration;
|
||||
import com.itac.mes.datainterface.data.smt.SmtLineConfiguration;
|
||||
import com.itac.mes.datainterface.data.smt.TraceabilityMode;
|
||||
import com.itac.mes.datainterface.data.smt.WorkorderBasedSetupSettings;
|
||||
import com.itac.mes.datainterface.factories.AConfigurableHandler;
|
||||
import com.itac.mes.datainterface.messaging.EventHandler;
|
||||
|
||||
public class PanaCimParserMessage500Test {
|
||||
|
||||
private static DataInterfaceConfiguration config;
|
||||
private static SmtLineConfiguration smtLine = new SmtLineConfiguration();
|
||||
private static SmtConfiguration smtConfiguration;
|
||||
|
||||
@BeforeClass
|
||||
public static void setUp() throws Exception {
|
||||
// Standard-Werte setzen...
|
||||
StringBuilder text = new StringBuilder(
|
||||
" <line name=\"line1\" activateSetup=\"false\" activateWorkorder=\"false\" adjustContainerQuantity=\"OFF\" " + //
|
||||
" resolveBadmark=\"true\" " + //
|
||||
" checkContainerExpiration=\"true\" checkContainerQuantity=\"true\" checkContainerState=\"true\" " + //
|
||||
" createWorkorder=\"false\" maxLifeSpan=\"00:05:00\" " + //
|
||||
" createContainer=\"true\" setupData=\"true\" setupDetails=\"off\" setupSplices=\"true\" >" + //
|
||||
" <trMachine name=\"machine1\" linePattern=\".*\" machinePattern=\".*\" " + //
|
||||
" lanePattern=\".*\" modulePattern=\".*\">" + //
|
||||
" <smtSettings assignSerialnumbers=\"false\" bomCheck=\"false\" bomCheckState=\"false\" " + //
|
||||
" bomCheckFailureType=\"false\" bookSerialnumbers=\"false\" interlocking=\"CHECK_SN_STATE\" " + //
|
||||
" preBomCheck=\"true\" " + //
|
||||
" processFailureType=\"false\" " + //
|
||||
" materialQuantityReporting=\"false\" " + //
|
||||
" rejectComponents=\"false\" />" + //
|
||||
" </trMachine>" + //
|
||||
" <pmMachine name=\"pmmachine1\" linePattern=\".*\" machinePattern=\".*\" " + //
|
||||
" lanePattern=\".*\" modulePattern=\".*\">" + //
|
||||
" <smtSettings stationConditions=\"false\" stationMessages=\"NONE\" />" + //
|
||||
" </pmMachine>" + //
|
||||
" </line>");
|
||||
|
||||
smtLine.setXmlConfigText(text, false);
|
||||
List<SmtLineConfiguration> smtLineConfigurations = new ArrayList<SmtLineConfiguration>();
|
||||
smtLineConfigurations.add(smtLine);
|
||||
|
||||
config = mock(DataInterfaceConfiguration.class);
|
||||
smtConfiguration = mock(SmtConfiguration.class);
|
||||
when(smtConfiguration.getMachineListPM()).thenReturn(smtLine.getSmtMachineListPM());
|
||||
when(smtConfiguration.getSmtMachineListTR()).thenReturn(smtLine.getSmtMachineListTR());
|
||||
|
||||
when(config.getValue("parser.panacim.defaultStation", String.class)).thenReturn("machine1");
|
||||
when(config.getValue("parser.panacim.modelCodePattern", String.class)).thenReturn("_T");
|
||||
|
||||
when(smtConfiguration.getTransactionTypePlaced()).thenReturn(201);
|
||||
when(smtConfiguration.getProductPattern())
|
||||
.thenReturn(new SearchReplacePattern("productpattern", true, "([0-9]{3})([0-9]{3})([0-9]{2}).*", "$1.$2-$3"));
|
||||
when(smtConfiguration.getContainerPattern()).thenReturn(new SearchReplacePattern("containerPattern", false, "", ""));
|
||||
when(smtConfiguration.getContainerFilter()).thenReturn(new Filter(false, ""));
|
||||
when(smtConfiguration.getComponentPattern()).thenReturn(new SearchReplacePattern("componentPattern", false, "", ""));
|
||||
when(smtConfiguration.getComponentFilter()).thenReturn(new Filter(false, ""));
|
||||
when(smtConfiguration.getDesignatorPattern()).thenReturn(new SearchReplacePattern("designPattern", false, "", ""));
|
||||
when(smtConfiguration.getDesignatorFilter()).thenReturn(new Filter(false, ""));
|
||||
when(smtConfiguration.getConsumptionDataInterval()).thenReturn(new Duration(300000));
|
||||
|
||||
when(smtConfiguration.getPlacementRecipePattern())
|
||||
.thenReturn(new SearchReplacePattern("placementrecipepattern", true, ".*", "$1"));
|
||||
when(smtConfiguration.getDefaultAlarmDuration()).thenReturn(new Duration(3000000l));
|
||||
when(smtConfiguration.getDefaultConditionCode()).thenReturn("4711");
|
||||
when(smtConfiguration.getDefaultContainerQuantity()).thenReturn(1000);
|
||||
when(smtConfiguration.getWorkorderBasedSetupSettings()).thenReturn(new WorkorderBasedSetupSettings());
|
||||
when(smtConfiguration.getWorkorderPattern()).thenReturn(new SearchReplacePattern("woPattern", true, ".*", ""));
|
||||
when(smtConfiguration.getTraceabilityMode()).thenReturn(TraceabilityMode.TRACEDATA_BASED);
|
||||
when(smtConfiguration.getReelPositionWithPattern(anyString(), anyString(), anyString(), anyString(), anyString(), anyString()))
|
||||
.thenReturn("22_1_309");
|
||||
// das erste Zeichen wegnehmen und hinten ein "X" anhaengen
|
||||
when(smtConfiguration.getSerialnumberPattern()).thenReturn(new SearchReplacePattern("serialpattern", true, "^.(.*)", "$1X"));
|
||||
when(smtConfiguration.getSerialnumberPos(anyString(), any(SearchReplacePattern.class), anyString())).thenReturn("1");
|
||||
|
||||
PlacementRecipeCheck placementRecipeCheck = new PlacementRecipeCheck();
|
||||
placementRecipeCheck.setPlacementRecipeCheckMode(PlacementRecipeMode.PROVIDE_BY_PATTERN);
|
||||
when(smtConfiguration.getPlacementRecipeCheck()).thenReturn(placementRecipeCheck);
|
||||
}
|
||||
|
||||
public Toolbox getToolboxMock() {
|
||||
Toolbox mockObject = mock(Toolbox.class);
|
||||
when(mockObject.hasConditionMapping()).thenReturn(true);
|
||||
when(mockObject.hasMessageMapping()).thenReturn(true);
|
||||
when(mockObject.getStatus("PASS")).thenReturn(0);
|
||||
// Fuer Panasonic Standard
|
||||
when(mockObject.getLayer("1")).thenReturn(0);
|
||||
when(mockObject.getLayer("0")).thenReturn(1);
|
||||
when(mockObject.getConditionCode("2")).thenReturn("Fuji2");
|
||||
when(mockObject.getConditionCode("3")).thenReturn("Fuji3");
|
||||
when(mockObject.getMessageCode("1")).thenReturn("Fuji_R1");
|
||||
when(mockObject.getMessageCode("4")).thenReturn("-1");
|
||||
when(mockObject.getMessageCode("5")).thenReturn("Fuji_R5");
|
||||
when(mockObject.getFailcode("0")).thenReturn(0);
|
||||
when(mockObject.getTextcode("0")).thenReturn("0");
|
||||
when(mockObject.getStation("Machine1")).thenReturn(new Station("Machine1", "12012010", false));
|
||||
when(mockObject.getStation("machine1")).thenReturn(new Station("machine1", "12012010", false));
|
||||
when(mockObject.getStation("Machine2")).thenReturn(new Station("Machine2", "12012011", false));
|
||||
when(mockObject.getStation("pmmachine1")).thenReturn(new Station("pmmachine1", "12012011", false));
|
||||
return mockObject;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testApplyBarcodePattern()
|
||||
throws MessageException, SendException, IllegalAccessException, InvocationTargetException, ConfigurationException {
|
||||
PanaCimParser out = new PanaCimParser();
|
||||
out.setHandler(config, DataInterfaceConfiguration.class);
|
||||
out.setHandler(getToolboxMock(), Toolbox.class);
|
||||
out.setHandler(smtConfiguration, SmtConfiguration.class);
|
||||
out.setHandler(mock(EventHandler.class), EventHandler.class);
|
||||
out.configure();
|
||||
out.callAtInit();
|
||||
assertEquals(out.getConfigurationText(), AConfigurableHandler.OK, out.getConfigurationResult());
|
||||
|
||||
PanaCimDataUnit panaCimDataUnit = new PanaCimDataUnit();
|
||||
String msg = //
|
||||
"<message>" + //
|
||||
"<header messageClass=\"500\" transactionID=\"1234567890\" reply=\"1\">" + //
|
||||
" <location routeID=\"1001\" routeName=\"Line\" equipmentID=\"1000\"" + //
|
||||
" equipmentName=\"Station\" zonePos=\"0\" zoneName=\"SMT1\" laneNo=\"0\" />" + //
|
||||
"</header>" + //
|
||||
"<body>" + //
|
||||
" <pcb barcode=\"$serialNumber\" modelCode=\"\" serialNo=\"$serialNumber\" pcbSide=\"1\" scannerMountSide=\"-1\"/>" + //
|
||||
"</body>" + //
|
||||
"</message>";
|
||||
PanaCimMessage panaCimMessage = new PanaCimMessage();
|
||||
panaCimMessage.setContent(msg);
|
||||
out.parse(panaCimMessage, panaCimDataUnit);
|
||||
|
||||
assertNotNull(panaCimDataUnit.uploadUnitList);
|
||||
assertEquals(1, panaCimDataUnit.uploadUnitList.size());
|
||||
assertNotNull(panaCimDataUnit.uploadUnitList.get(0));
|
||||
assertEquals(UploadSmtSerialNumberCheckInUnit.class, panaCimDataUnit.uploadUnitList.get(0).getClass());
|
||||
UploadSmtSerialNumberCheckInUnit smtUnit = (UploadSmtSerialNumberCheckInUnit) panaCimDataUnit.uploadUnitList.get(0);
|
||||
assertNotNull(smtUnit);
|
||||
assertEquals("serialnumber Pattern wurde nicht richtig angewendet", "serialNumberX", smtUnit.getSerialNumber());
|
||||
assertEquals("InterlockingMechanism not parsed correctly", InterlockingMechanism.CHECK_SN_STATE, smtUnit.getInterlocking());
|
||||
assertEquals("AssignSn Flag not parsed correctly", false, smtUnit.isAssignSn());
|
||||
assertEquals("ResolveBadmark Flag not parsed correctly", true, smtUnit.isResolveBadmarks());
|
||||
assertEquals("Pre Bom Check Flag not parsed correctly", true, smtUnit.isPreBomCheck());
|
||||
assertEquals("PlacementRecipeCheck not parsed correctly", PlacementRecipeMode.PROVIDE_BY_PATTERN,
|
||||
smtUnit.getPlacementRecipeCheck().getPlacementRecipeCheckMode());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,173 @@
|
||||
package com.itac.mes.datainterface.parser;
|
||||
|
||||
import static junit.framework.Assert.assertEquals;
|
||||
import static junit.framework.Assert.assertNotNull;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Matchers.anyString;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.itac.mes.datainterface.ConfigurationException;
|
||||
import com.itac.mes.datainterface.DataInterfaceConfiguration;
|
||||
import com.itac.mes.datainterface.data.Duration;
|
||||
import com.itac.mes.datainterface.data.PanaCimDataUnit;
|
||||
import com.itac.mes.datainterface.data.Station;
|
||||
import com.itac.mes.datainterface.data.Toolbox;
|
||||
import com.itac.mes.datainterface.data.UploadSmtSerialNumberCheckInUnit;
|
||||
import com.itac.mes.datainterface.data.panacim.MessageException;
|
||||
import com.itac.mes.datainterface.data.panacim.PanaCimMessage;
|
||||
import com.itac.mes.datainterface.data.panacim.SendException;
|
||||
import com.itac.mes.datainterface.data.smt.Filter;
|
||||
import com.itac.mes.datainterface.data.smt.InterlockingMechanism;
|
||||
import com.itac.mes.datainterface.data.smt.PlacementRecipeCheck;
|
||||
import com.itac.mes.datainterface.data.smt.PlacementRecipeMode;
|
||||
import com.itac.mes.datainterface.data.smt.SearchReplacePattern;
|
||||
import com.itac.mes.datainterface.data.smt.SmtConfiguration;
|
||||
import com.itac.mes.datainterface.data.smt.SmtLineConfiguration;
|
||||
import com.itac.mes.datainterface.data.smt.TraceabilityMode;
|
||||
import com.itac.mes.datainterface.data.smt.WorkorderBasedSetupSettings;
|
||||
import com.itac.mes.datainterface.factories.AConfigurableHandler;
|
||||
import com.itac.mes.datainterface.messaging.EventHandler;
|
||||
|
||||
public class PanaCimParserMessage501Test {
|
||||
|
||||
private static DataInterfaceConfiguration config;
|
||||
private static SmtLineConfiguration smtLine = new SmtLineConfiguration();
|
||||
private static SmtConfiguration smtConfiguration;
|
||||
|
||||
@BeforeClass
|
||||
public static void setUp() throws Exception {
|
||||
// Standard-Werte setzen...
|
||||
StringBuilder text = new StringBuilder(
|
||||
" <line name=\"line1\" activateSetup=\"false\" activateWorkorder=\"false\" adjustContainerQuantity=\"OFF\" " + //
|
||||
" resolveBadmark=\"true\" " + //
|
||||
" checkContainerExpiration=\"true\" checkContainerQuantity=\"true\" checkContainerState=\"true\" " + //
|
||||
" createWorkorder=\"false\" maxLifeSpan=\"00:05:00\" " + //
|
||||
" createContainer=\"true\" setupData=\"true\" setupDetails=\"off\" setupSplices=\"true\" >" + //
|
||||
" <trMachine name=\"machine1\" linePattern=\".*\" machinePattern=\".*\" " + //
|
||||
" lanePattern=\".*\" modulePattern=\".*\">" + //
|
||||
" <smtSettings assignSerialnumbers=\"false\" bomCheck=\"false\" bomCheckState=\"false\" " + //
|
||||
" bomCheckFailureType=\"false\" bookSerialnumbers=\"false\" interlocking=\"CHECK_SN_STATE\" " + //
|
||||
" preBomCheck=\"true\" " + //
|
||||
" processFailureType=\"false\" " + //
|
||||
" materialQuantityReporting=\"false\" " + //
|
||||
" rejectComponents=\"false\" />" + //
|
||||
" </trMachine>" + //
|
||||
" <pmMachine name=\"pmmachine1\" linePattern=\".*\" machinePattern=\".*\" " + //
|
||||
" lanePattern=\".*\" modulePattern=\".*\">" + //
|
||||
" <smtSettings stationConditions=\"false\" stationMessages=\"NONE\" />" + //
|
||||
" </pmMachine>" + //
|
||||
" </line>");
|
||||
|
||||
smtLine.setXmlConfigText(text, false);
|
||||
List<SmtLineConfiguration> smtLineConfigurations = new ArrayList<SmtLineConfiguration>();
|
||||
smtLineConfigurations.add(smtLine);
|
||||
|
||||
config = mock(DataInterfaceConfiguration.class);
|
||||
smtConfiguration = mock(SmtConfiguration.class);
|
||||
when(smtConfiguration.getMachineListPM()).thenReturn(smtLine.getSmtMachineListPM());
|
||||
when(smtConfiguration.getSmtMachineListTR()).thenReturn(smtLine.getSmtMachineListTR());
|
||||
|
||||
when(config.getValue("parser.panacim.defaultStation", String.class)).thenReturn("machine1");
|
||||
when(config.getValue("parser.panacim.modelCodePattern", String.class)).thenReturn("_T");
|
||||
|
||||
when(smtConfiguration.getTransactionTypePlaced()).thenReturn(201);
|
||||
when(smtConfiguration.getProductPattern()).thenReturn(
|
||||
new SearchReplacePattern("productpattern", true, "([0-9]{3})([0-9]{3})([0-9]{2}).*", "$1.$2-$3"));
|
||||
when(smtConfiguration.getContainerPattern()).thenReturn(new SearchReplacePattern("containerPattern", false, "", ""));
|
||||
when(smtConfiguration.getContainerFilter()).thenReturn(new Filter(false, ""));
|
||||
when(smtConfiguration.getComponentPattern()).thenReturn(new SearchReplacePattern("componentPattern", false, "", ""));
|
||||
when(smtConfiguration.getComponentFilter()).thenReturn(new Filter(false, ""));
|
||||
when(smtConfiguration.getDesignatorPattern()).thenReturn(new SearchReplacePattern("designPattern", false, "", ""));
|
||||
when(smtConfiguration.getDesignatorFilter()).thenReturn(new Filter(false, ""));
|
||||
when(smtConfiguration.getConsumptionDataInterval()).thenReturn(new Duration(300000));
|
||||
|
||||
when(smtConfiguration.getPlacementRecipePattern()).thenReturn(
|
||||
new SearchReplacePattern("placementrecipepattern", true, ".*", "$1"));
|
||||
when(smtConfiguration.getDefaultAlarmDuration()).thenReturn(new Duration(3000000l));
|
||||
when(smtConfiguration.getDefaultConditionCode()).thenReturn("4711");
|
||||
when(smtConfiguration.getDefaultContainerQuantity()).thenReturn(1000);
|
||||
when(smtConfiguration.getWorkorderBasedSetupSettings()).thenReturn(new WorkorderBasedSetupSettings());
|
||||
when(smtConfiguration.getWorkorderPattern()).thenReturn(new SearchReplacePattern("woPattern", true, ".*", ""));
|
||||
when(smtConfiguration.getTraceabilityMode()).thenReturn(TraceabilityMode.TRACEDATA_BASED);
|
||||
when(smtConfiguration.getReelPositionWithPattern(anyString(), anyString(), anyString(), anyString(), anyString(), anyString()))
|
||||
.thenReturn("22_1_309");
|
||||
// das erste Zeichen wegnehmen und hinten ein "X" anhaengen
|
||||
when(smtConfiguration.getSerialnumberPattern()).thenReturn(new SearchReplacePattern("serialpattern", true, "^.(.*)", "$1X"));
|
||||
when(smtConfiguration.getSerialnumberPos(anyString(), any(SearchReplacePattern.class), anyString())).thenReturn("1");
|
||||
|
||||
PlacementRecipeCheck placementRecipeCheck = new PlacementRecipeCheck();
|
||||
placementRecipeCheck.setPlacementRecipeCheckMode(PlacementRecipeMode.PROVIDE_BY_PATTERN);
|
||||
when(smtConfiguration.getPlacementRecipeCheck()).thenReturn(placementRecipeCheck);
|
||||
}
|
||||
|
||||
public Toolbox getToolboxMock() {
|
||||
Toolbox mockObject = mock(Toolbox.class);
|
||||
when(mockObject.hasConditionMapping()).thenReturn(true);
|
||||
when(mockObject.hasMessageMapping()).thenReturn(true);
|
||||
when(mockObject.getStatus("PASS")).thenReturn(0);
|
||||
// Fuer Panasonic Standard
|
||||
when(mockObject.getLayer("1")).thenReturn(0);
|
||||
when(mockObject.getLayer("0")).thenReturn(1);
|
||||
when(mockObject.getConditionCode("2")).thenReturn("Fuji2");
|
||||
when(mockObject.getConditionCode("3")).thenReturn("Fuji3");
|
||||
when(mockObject.getMessageCode("1")).thenReturn("Fuji_R1");
|
||||
when(mockObject.getMessageCode("4")).thenReturn("-1");
|
||||
when(mockObject.getMessageCode("5")).thenReturn("Fuji_R5");
|
||||
when(mockObject.getFailcode("0")).thenReturn(0);
|
||||
when(mockObject.getTextcode("0")).thenReturn("0");
|
||||
when(mockObject.getStation("Machine1")).thenReturn(new Station("Machine1", "12012010", false));
|
||||
when(mockObject.getStation("machine1")).thenReturn(new Station("machine1", "12012010", false));
|
||||
when(mockObject.getStation("Machine2")).thenReturn(new Station("Machine2", "12012011", false));
|
||||
when(mockObject.getStation("pmmachine1")).thenReturn(new Station("pmmachine1", "12012011", false));
|
||||
return mockObject;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testApplyBarcodePattern() throws MessageException, SendException, IllegalAccessException, InvocationTargetException, ConfigurationException {
|
||||
PanaCimParser out = new PanaCimParser();
|
||||
out.setHandler(config, DataInterfaceConfiguration.class);
|
||||
out.setHandler(getToolboxMock(), Toolbox.class);
|
||||
out.setHandler(smtConfiguration, SmtConfiguration.class);
|
||||
out.setHandler(mock(EventHandler.class), EventHandler.class);
|
||||
out.configure();
|
||||
out.callAtInit();
|
||||
assertEquals(out.getConfigurationText(), AConfigurableHandler.OK, out.getConfigurationResult());
|
||||
|
||||
PanaCimDataUnit panaCimDataUnit = new PanaCimDataUnit();
|
||||
String msg = //
|
||||
"<message>" + //
|
||||
"<header messageClass=\"501\" transactionID=\"1234567890\" reply=\"1\">" + //
|
||||
" <location routeID=\"1001\" routeName=\"Line\" equipmentID=\"1000\"" + //
|
||||
" equipmentName=\"Station\" zonePos=\"0\" zoneName=\"SMT1\" laneNo=\"0\" />" + //
|
||||
"</header>" + //
|
||||
"<body>" + //
|
||||
" <pcb barcode=\"$serialNumber\" modelCode=\"\" serialNo=\"$serialNumber\" pcbSide=\"1\" scannerMountSide=\"-1\"/>" + //
|
||||
"</body>" + //
|
||||
"</message>";
|
||||
PanaCimMessage panaCimMessage = new PanaCimMessage();
|
||||
panaCimMessage.setContent(msg);
|
||||
out.parse(panaCimMessage, panaCimDataUnit);
|
||||
|
||||
assertNotNull(panaCimDataUnit.uploadUnitList);
|
||||
assertEquals(1, panaCimDataUnit.uploadUnitList.size());
|
||||
assertNotNull(panaCimDataUnit.uploadUnitList.get(0));
|
||||
assertEquals(UploadSmtSerialNumberCheckInUnit.class, panaCimDataUnit.uploadUnitList.get(0).getClass());
|
||||
UploadSmtSerialNumberCheckInUnit smtUnit = (UploadSmtSerialNumberCheckInUnit) panaCimDataUnit.uploadUnitList.get(0);
|
||||
assertNotNull(smtUnit);
|
||||
assertEquals("serialnumber Pattern wurde nicht richtig angewendet", "serialNumberX", smtUnit.getSerialNumber());
|
||||
assertEquals("InterlockingMechanism not parsed correctly", InterlockingMechanism.CHECK_SN_STATE, smtUnit.getInterlocking());
|
||||
assertEquals("AssignSn Flag not parsed correctly", false, smtUnit.isAssignSn());
|
||||
assertEquals("ResolveBadmark Flag not parsed correctly", true, smtUnit.isResolveBadmarks());
|
||||
assertEquals("Pre Bom Check Flag not parsed correctly", true, smtUnit.isPreBomCheck());
|
||||
assertEquals("PlacementRecipeCheck not parsed correctly", PlacementRecipeMode.PROVIDE_BY_PATTERN, smtUnit
|
||||
.getPlacementRecipeCheck().getPlacementRecipeCheckMode());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,310 @@
|
||||
package com.itac.mes.datainterface.parser;
|
||||
|
||||
import static junit.framework.Assert.assertEquals;
|
||||
import static junit.framework.Assert.assertNotNull;
|
||||
import static org.mockito.Matchers.anyString;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.List;
|
||||
|
||||
import javax.xml.datatype.DatatypeConfigurationException;
|
||||
import javax.xml.datatype.DatatypeFactory;
|
||||
import javax.xml.datatype.XMLGregorianCalendar;
|
||||
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.itac.mes.datainterface.ConfigurationException;
|
||||
import com.itac.mes.datainterface.DataInterfaceConfiguration;
|
||||
import com.itac.mes.datainterface.data.Duration;
|
||||
import com.itac.mes.datainterface.data.PanaCimDataUnit;
|
||||
import com.itac.mes.datainterface.data.Station;
|
||||
import com.itac.mes.datainterface.data.Toolbox;
|
||||
import com.itac.mes.datainterface.data.UploadSmtSerialNumberSetupUnit;
|
||||
import com.itac.mes.datainterface.data.panacim.MessageException;
|
||||
import com.itac.mes.datainterface.data.panacim.PanaCimMessage;
|
||||
import com.itac.mes.datainterface.data.panacim.ParseException;
|
||||
import com.itac.mes.datainterface.data.panacim.SendException;
|
||||
import com.itac.mes.datainterface.data.smt.SearchReplacePattern;
|
||||
import com.itac.mes.datainterface.data.smt.SmtConfiguration;
|
||||
import com.itac.mes.datainterface.data.smt.SmtLineConfiguration;
|
||||
import com.itac.mes.datainterface.data.smt.WorkorderBasedSetupSettings;
|
||||
import com.itac.mes.datainterface.factories.AConfigurableHandler;
|
||||
import com.itac.mes.datainterface.parser.IParser.Code;
|
||||
import com.itac.mes.smt.domain.Setup;
|
||||
import com.itac.util.logging.LogHandler;
|
||||
import com.itac.util.logging.LogLevel;
|
||||
|
||||
public class PanaCimParserTest {
|
||||
private static DataInterfaceConfiguration config;
|
||||
private static SmtLineConfiguration smtLine = new SmtLineConfiguration();
|
||||
private static SmtConfiguration smtConfiguration;
|
||||
|
||||
@BeforeClass
|
||||
public static void setUp() throws Exception {
|
||||
// Standard-Werte setzen...
|
||||
StringBuilder text = new StringBuilder(
|
||||
" <line name=\"line1\" activateSetup=\"true\" activateWorkorder=\"true\" adjustContainerQuantity=\"OFF\" " + //
|
||||
" checkContainerExpiration=\"true\" checkContainerQuantity=\"true\" checkContainerState=\"true\" " + //
|
||||
" createWorkorder=\"false\" maxLifeSpan=\"00:05:00\" " + //
|
||||
" createContainer=\"true\" setupData=\"true\" setupDetails=\"off\" setupSplices=\"true\" >" + //
|
||||
" <trMachine name=\"machine1\" linePattern=\".*Ligne-7.*\" machinePattern=\"NPM2.*\" " + //
|
||||
" lanePattern=\"2\" modulePattern=\"3\">" + //
|
||||
" <smtSettings assignSerialnumbers=\"false\" bomCheck=\"true\" bomCheckState=\"true\" " + //
|
||||
" bomCheckFailureType=\"true\" bookSerialnumbers=\"true\" interlocking=\"false\" " + //
|
||||
" preBomCheck=\"true\" " + //
|
||||
" processFailureType=\"true\" " + //
|
||||
" materialQuantityReporting=\"true\" " + //
|
||||
" rejectComponents=\"true\" />" + //
|
||||
" </trMachine>" + //
|
||||
" <pmMachine name=\"pmmachine1\" linePattern=\".*\" machinePattern=\".*\" " + //
|
||||
" lanePattern=\".*\" modulePattern=\".*\">" + //
|
||||
" <smtSettings stationConditions=\"true\" stationMessages=\"ERRORCODE\" />" + //
|
||||
" </pmMachine>" + //
|
||||
" </line>");
|
||||
|
||||
smtLine.setXmlConfigText(text, false);
|
||||
List<SmtLineConfiguration> smtLineConfigurations = new ArrayList<SmtLineConfiguration>();
|
||||
smtLineConfigurations.add(smtLine);
|
||||
|
||||
config = mock(DataInterfaceConfiguration.class);
|
||||
smtConfiguration = mock(SmtConfiguration.class);
|
||||
when(smtConfiguration.getMachineListPM()).thenReturn(smtLine.getSmtMachineListPM());
|
||||
when(smtConfiguration.getSmtMachineListTR()).thenReturn(smtLine.getSmtMachineListTR());
|
||||
when(config.getValue("parser.panacim.modelCodePattern", String.class)).thenReturn("{0}_{1}_F{2}");
|
||||
when(config.getValue("parser.panacim.defaultStation", String.class)).thenReturn("machine1");
|
||||
|
||||
when(smtConfiguration.getTransactionTypePlaced()).thenReturn(201);
|
||||
when(smtConfiguration.getProductPattern())
|
||||
.thenReturn(new SearchReplacePattern("productpattern", true, "([0-9]{3})([0-9]{3})([0-9]{2}).*", "$1.$2-$3"));
|
||||
when(smtConfiguration.getPlacementRecipePattern())
|
||||
.thenReturn(new SearchReplacePattern("placementrecipepattern", true, ".*", "$1"));
|
||||
when(smtConfiguration.getMaxLifeSpan()).thenReturn(new Duration(3000000l));
|
||||
when(smtConfiguration.getDefaultAlarmDuration()).thenReturn(new Duration(3000000l));
|
||||
when(smtConfiguration.getDefaultConditionCode()).thenReturn("4711");
|
||||
when(smtConfiguration.getDefaultContainerQuantity()).thenReturn(1000);
|
||||
when(smtConfiguration.getConsumptionDataInterval()).thenReturn(new Duration(3000000l));
|
||||
when(smtConfiguration.getWorkorderBasedSetupSettings()).thenReturn(new WorkorderBasedSetupSettings());
|
||||
when(smtConfiguration.getWorkorderPattern()).thenReturn(new SearchReplacePattern("woPattern", true, ".*", ""));
|
||||
when(smtConfiguration.getReelPositionWithPattern(anyString(), anyString(), anyString(), anyString(), anyString(), anyString()))
|
||||
.thenReturn("22_1_309");
|
||||
when(smtConfiguration.getSerialnumberPattern()).thenReturn(new SearchReplacePattern("serialpattern", false, "(.*)", "$1"));
|
||||
}
|
||||
|
||||
protected Toolbox getToolbox() throws ConfigurationException {
|
||||
Toolbox toolbox = new Toolbox();
|
||||
toolbox.addStation(new Station("Machine1", "12012010", false));
|
||||
toolbox.addStation(new Station("machine1", "12012010", false));
|
||||
toolbox.addStation(new Station("Machine2", "12012011", false));
|
||||
toolbox.addStation(new Station("pmmachine1", "12012011", false));
|
||||
toolbox.setDateTimePattern("yyyyMMddHHmmss");
|
||||
toolbox.addLayer("1", "0");
|
||||
toolbox.addLayer("0", "1");
|
||||
toolbox.addLayer("_W", "3");
|
||||
toolbox.addFailcode("0", 0);
|
||||
toolbox.addStatus("0", 0);
|
||||
toolbox.addFailcode("1", 1);
|
||||
toolbox.addStatus("1", 1);
|
||||
toolbox.addConditionMapItem("2", "Fuji2");
|
||||
toolbox.addConditionMapItem("3", "Fuji3");
|
||||
toolbox.addMessageMapItem("1", "Fuji_R1");
|
||||
toolbox.addMessageMapItem("4", "-1");
|
||||
toolbox.addMessageMapItem("5", "Fuji_R5");
|
||||
return toolbox;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMessage550()
|
||||
throws MessageException, SendException, IllegalAccessException, InvocationTargetException, ConfigurationException {
|
||||
String noCompsMessage = "<message><header messageClass=\"550\" transactionID=\"cde1e958-d3a5-491b-a828-0b777caae3eb\" reply=\"1\" >"
|
||||
+ "<location routeID=\"1010\" routeName=\"CMS-Ligne-7_12-2012\" equipmentID=\"1077\" equipmentName=\"NPM2-1C6V0467\" zoneID=\"1124\" "
|
||||
+ "zonePos=\"1\" zoneName=\"NPM-1C6V0467\" laneNo=\"2\" controllerGuid=\"\" /></header><body><panel state=\"0\" "
|
||||
+ "pcbID=\"_002222222_04_711_18130670_03_\" productName=\"2222222_04_F1\" productSide=\"1\" timestamp=\"2013-10-01T14:17:24+02:00\" />"
|
||||
+ "<stageNo value=\"3\" />"//
|
||||
+ "<materials></materials><comps></comps></body></message>";
|
||||
|
||||
PanaCimParser out = new PanaCimParser();
|
||||
out.setHandler(config, DataInterfaceConfiguration.class);
|
||||
out.setHandler(getToolbox(), Toolbox.class);
|
||||
out.setHandler(smtConfiguration, SmtConfiguration.class);
|
||||
out.configure();
|
||||
out.callAtInit();
|
||||
assertEquals(out.getConfigurationText(), AConfigurableHandler.OK, out.getConfigurationResult());
|
||||
|
||||
PanaCimMessage pcm = new PanaCimMessage();
|
||||
pcm.setContent(noCompsMessage);
|
||||
|
||||
PanaCimDataUnit pcdu = new PanaCimDataUnit();
|
||||
Code k = out.parse(pcm, pcdu);
|
||||
assertEquals(Code.OK, k);
|
||||
assertEquals("parser generated no uploadUnit", 1, pcdu.uploadUnitList.size());
|
||||
assertEquals("parser generated wrong uploadUnit type", UploadSmtSerialNumberSetupUnit.class,
|
||||
pcdu.uploadUnitList.get(0).getClass());
|
||||
UploadSmtSerialNumberSetupUnit uploadUnit = (UploadSmtSerialNumberSetupUnit) pcdu.uploadUnitList.get(0);
|
||||
assertNotNull("parser did not generated setup", uploadUnit.getSetup());
|
||||
Setup setup = uploadUnit.getSetup();
|
||||
assertNotNull("parser did not generated serial header", setup.getSerialHeader());
|
||||
assertEquals("parser generated wrong number of serialnumbers", 1, setup.getSerialHeader().getSerialNumbers().length);
|
||||
assertEquals("parser generated wrong serialnumber", "_002222222_04_711_18130670_03_",
|
||||
setup.getSerialHeader().getSerialNumbers()[0].getSerialNo());
|
||||
assertEquals("parser generated setup events", 0, setup.getEvents().length);
|
||||
assertEquals("parser generated containerTable", 0, setup.getContainerTable().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTimeStamp() throws IllegalAccessException, InvocationTargetException, ConfigurationException {
|
||||
String time1 = "2014-03-30T01:59:59+01:00";
|
||||
String time2 = "2014-03-30T03:00:00+02:00";
|
||||
|
||||
PanaCimParser out = new PanaCimParser();
|
||||
out.setHandler(config, DataInterfaceConfiguration.class);
|
||||
out.setHandler(getToolbox(), Toolbox.class);
|
||||
out.setHandler(smtConfiguration, SmtConfiguration.class);
|
||||
out.configure();
|
||||
out.callAtInit();
|
||||
assertEquals(out.getConfigurationText(), AConfigurableHandler.OK, out.getConfigurationResult());
|
||||
XMLGregorianCalendar xmlGregCal1 = null;
|
||||
try {
|
||||
xmlGregCal1 = DatatypeFactory.newInstance().newXMLGregorianCalendar(time1);
|
||||
} catch (DatatypeConfigurationException ex) {
|
||||
}
|
||||
Date d1 = out.getDateFromXmlTimeStamp(xmlGregCal1);
|
||||
|
||||
XMLGregorianCalendar xmlGregCal2 = null;
|
||||
try {
|
||||
xmlGregCal2 = DatatypeFactory.newInstance().newXMLGregorianCalendar(time2);
|
||||
} catch (DatatypeConfigurationException ex) {
|
||||
}
|
||||
Date d2 = out.getDateFromXmlTimeStamp(xmlGregCal2);
|
||||
LogHandler.log(getClass().getSimpleName(), LogLevel.INFO, time1 + "--> " + d1 + ": " + d1.getTime());
|
||||
LogHandler.log(getClass().getSimpleName(), LogLevel.INFO, time2 + "--> " + d2 + ": " + d2.getTime());
|
||||
assertEquals("incorrect time converting", 1000, d2.getTime() - d1.getTime());
|
||||
}
|
||||
|
||||
// Umstellung rückwärts
|
||||
// So. 26. Oktober 2014, um 03:00 MESZ
|
||||
|
||||
@Test
|
||||
public void testTimeStamp2() throws IllegalAccessException, InvocationTargetException, ConfigurationException {
|
||||
String time1 = "2014-10-26T02:59:59+02:00";
|
||||
String time2 = "2014-10-26T02:00:00+01:00";
|
||||
|
||||
PanaCimParser out = new PanaCimParser();
|
||||
out.setHandler(config, DataInterfaceConfiguration.class);
|
||||
out.setHandler(getToolbox(), Toolbox.class);
|
||||
out.setHandler(smtConfiguration, SmtConfiguration.class);
|
||||
out.configure();
|
||||
out.callAtInit();
|
||||
assertEquals(out.getConfigurationText(), AConfigurableHandler.OK, out.getConfigurationResult());
|
||||
|
||||
XMLGregorianCalendar xmlGregCal1 = null;
|
||||
try {
|
||||
xmlGregCal1 = DatatypeFactory.newInstance().newXMLGregorianCalendar(time1);
|
||||
} catch (DatatypeConfigurationException ex) {
|
||||
}
|
||||
Date d1 = out.getDateFromXmlTimeStamp(xmlGregCal1);
|
||||
|
||||
XMLGregorianCalendar xmlGregCal2 = null;
|
||||
try {
|
||||
xmlGregCal2 = DatatypeFactory.newInstance().newXMLGregorianCalendar(time2);
|
||||
} catch (DatatypeConfigurationException ex) {
|
||||
}
|
||||
Date d2 = out.getDateFromXmlTimeStamp(xmlGregCal2);
|
||||
LogHandler.log(getClass().getSimpleName(), LogLevel.INFO, time1 + "--> " + d1 + ": " + d1.getTime());
|
||||
LogHandler.log(getClass().getSimpleName(), LogLevel.INFO, time2 + "--> " + d2 + ": " + d2.getTime());
|
||||
assertEquals("incorrect time converting", 1000, d2.getTime() - d1.getTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTimeStampSummertimeToNormalTime() {
|
||||
// Übergang von Sommerzeit in Winterzeit, jeweils eine Sekunde weiter
|
||||
// Startzeitpunkt
|
||||
long d1 = 1414285199000L;
|
||||
|
||||
// erwartete Ergebnisse
|
||||
String[] results = new String[] { "2014-10-26T02:59:59.000+02:00", //
|
||||
"2014-10-26T02:00:00.000+01:00", //
|
||||
"2014-10-26T02:00:01.000+01:00" };
|
||||
|
||||
// weitere erwartete Ergebnisse
|
||||
String[] normalizedResults = new String[] { "2014-10-26T00:59:59.000Z", //
|
||||
"2014-10-26T01:00:00.000Z", //
|
||||
"2014-10-26T01:00:01.000Z" };
|
||||
|
||||
try {
|
||||
for (int i = 0; i < 3; i++) {
|
||||
GregorianCalendar g1 = (GregorianCalendar) GregorianCalendar.getInstance();
|
||||
g1.setTimeInMillis(d1 + (i * 1000));
|
||||
XMLGregorianCalendar xmlCal = DatatypeFactory.newInstance().newXMLGregorianCalendar(g1);
|
||||
LogHandler.log(getClass().getSimpleName(), LogLevel.INFO, xmlCal.toString());
|
||||
assertEquals(results[i], xmlCal.toString());
|
||||
|
||||
xmlCal = xmlCal.normalize();
|
||||
LogHandler.log(getClass().getSimpleName(), LogLevel.INFO, xmlCal.toString() + "(normalized)");
|
||||
assertEquals(normalizedResults[i], xmlCal.toString());
|
||||
}
|
||||
} catch (DatatypeConfigurationException e) {
|
||||
LogHandler.log(getClass().getSimpleName(), LogLevel.ERROR, "parsing date failed", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTimeStampNormalTimeToSummerTime() {
|
||||
// Übergang von Winterzeit in Sommerzeit, jeweils eine Sekunde weiter
|
||||
// Startzeitpunkt
|
||||
long d1 = 1396141199000L;
|
||||
|
||||
// erwartete Ergebnisse
|
||||
String[] results = new String[] { "2014-03-30T01:59:59.000+01:00", //
|
||||
"2014-03-30T03:00:00.000+02:00", //
|
||||
"2014-03-30T03:00:01.000+02:00" };
|
||||
|
||||
// weitere erwartete Ergebnisse
|
||||
String[] normalizedResults = new String[] { "2014-03-30T00:59:59.000Z", //
|
||||
"2014-03-30T01:00:00.000Z", //
|
||||
"2014-03-30T01:00:01.000Z" };
|
||||
|
||||
try {
|
||||
for (int i = 0; i < 3; i++) {
|
||||
GregorianCalendar g1 = (GregorianCalendar) GregorianCalendar.getInstance();
|
||||
g1.setTimeInMillis(d1 + (i * 1000));
|
||||
XMLGregorianCalendar xmlCal = DatatypeFactory.newInstance().newXMLGregorianCalendar(g1);
|
||||
LogHandler.log(getClass().getSimpleName(), LogLevel.INFO, xmlCal.toString());
|
||||
assertEquals(results[i], xmlCal.toString());
|
||||
|
||||
xmlCal = xmlCal.normalize();
|
||||
LogHandler.log(getClass().getSimpleName(), LogLevel.INFO, xmlCal.toString() + "(normalized)");
|
||||
assertEquals(normalizedResults[i], xmlCal.toString());
|
||||
}
|
||||
} catch (DatatypeConfigurationException e) {
|
||||
LogHandler.log(getClass().getSimpleName(), LogLevel.ERROR, "parsing date failed", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetStageNo() throws MessageException, SendException, ConfigurationException, ParseException {
|
||||
// the stage information is in a separate tag
|
||||
String stageInTagMessage = "<message><header messageClass=\"550\" transactionID=\"cde1e958-d3a5-491b-a828-0b777caae3eb\" reply=\"1\" >"
|
||||
+ "<location routeID=\"1010\" routeName=\"CMS-Ligne-7_12-2012\" equipmentID=\"1077\" equipmentName=\"NPM2-1C6V0467\" zoneID=\"1124\" "
|
||||
+ "zonePos=\"1\" zoneName=\"NPM-1C6V0467\" laneNo=\"2\" controllerGuid=\"\" /></header><body><panel state=\"0\" "
|
||||
+ "pcbID=\"_002222222_04_711_18130670_03_\" productName=\"2222222_04_F1\" productSide=\"1\" timestamp=\"2013-10-01T14:17:24+02:00\" />"
|
||||
+ "<stageNo value=\"3\" />"//
|
||||
+ "<materials></materials><comps></comps></body></message>";
|
||||
PanaCimMessage pcm = new PanaCimMessage();
|
||||
pcm.setContent(stageInTagMessage);
|
||||
PanaCimParser out = new PanaCimParser();
|
||||
out.setHandler(config, DataInterfaceConfiguration.class);
|
||||
out.setHandler(getToolbox(), Toolbox.class);
|
||||
out.setHandler(smtConfiguration, SmtConfiguration.class);
|
||||
out.configure();
|
||||
out.callAtInit();
|
||||
assertEquals(out.getConfigurationText(), AConfigurableHandler.OK, out.getConfigurationResult());
|
||||
|
||||
assertEquals("3", out.getStage(pcm.getBody().getStageNo(), pcm.getBody().getPanel().getStageNo()));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user