initialize

This commit is contained in:
Pruefer
2025-06-06 09:15:13 +02:00
commit fa7c2730f1
5817 changed files with 1339670 additions and 0 deletions

View File

@@ -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;
}
}

View File

@@ -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");
}
}
}

View File

@@ -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 = "???";
}

View File

@@ -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;
}
}

View File

@@ -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();
}
}

View File

@@ -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);
}

View File

@@ -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;
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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;
}

View File

@@ -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();
}
}

View File

@@ -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&auml;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();
}
}

View File

@@ -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;
}
}

View File

@@ -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();
}
}

View File

@@ -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();
}
}

View File

@@ -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;
}

View File

@@ -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;
}
}

View File

@@ -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;
}

View File

@@ -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;
}
}

View File

@@ -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 {
}

View File

@@ -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)));
}
}

View File

@@ -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);
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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}));
}
}

View File

@@ -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;
}
}

View File

@@ -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 &uuml;berschrieben werden
*/
@Override
public void startPause() {
application.setPaused(true);
}
/**
* Ende einer Pause. Diese Methode muss von den Datasourcen &uuml;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);
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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&ouml;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());
}
}

View File

@@ -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

View 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>

View File

@@ -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());
}
}

View File

@@ -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());
}
}

View File

@@ -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);
}
}
}

View File

@@ -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());
}
}

View File

@@ -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());
}
}

View File

@@ -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()));
}
}