Files
2025-06-06 09:15:13 +02:00

838 lines
29 KiB
C#

/*
* Copyright (c) 2015 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.
*/
using com.itac.mes.tools;
using System;
using System.Diagnostics;
using System.IO;
using com.itac.mes.commonsmt.data;
using System.Runtime.CompilerServices;
using System.Threading;
namespace com.itac.mes.commonsmt
{
/// <summary>
/// documentation for the namespace
/// </summary>
[System.Runtime.CompilerServices.CompilerGenerated]
class NamespaceDoc
{
}
public class MyEventArgs : EventArgs
{
public TraceEventType traceEventType;
public String message;
}
/// <summary>
///
/// </summary>
public delegate void MyEventHandler(Object sender, MyEventArgs e);
/// <summary>
/// Class level summary documentation goes here.</summary>
/// <remarks>
/// Longer comments can be associated with a type or member through
/// the remarks tag.</remarks>
public class MesServices : IMesServices
{
/// <summary>
///
/// </summary>
public event MyEventHandler OnLog;
/// <summary>
/// return this value in {@link MesResponse#setTotalResult(int)}
/// {@link MesResponse#getTotalResult()} for any request
/// which was processed successfully.
/// All returned values are be valid.</summary>
public static int MES_RESULT_OK = 0;
/// <summary>
/// return this value in {@link MesResponse#setTotalResult(int)}/{@link MesResponse#getTotalResult()} for any request
/// which was NOT processed successfully. Not all returned values must be valid, depends on the request.
///
/// @see separate calls in {@link IMesServices#} for detailled information.
/// </summary>
public static int MES_RESULT_NOT_OK = 1;
// allowed port range
private static int MIN_PORT = 1023;
private static int MAX_PORT = 49150;
// 10 minutes default
private static int DEFAULT_REFRESH_INTERVAL = 600000;
// some bool flags for operation
private Boolean configured;
private Boolean active;
// every call to a mes host needs an own id; the id does not change when a call is completed on a failover host
private RequestIdGenerator idGenerator = new RequestIdGenerator();
// the invocation handler accepts all calls from the failoverProxy
private FailoverInvocationHandler failoverInvocationHandler;
// this proxy delegates the calls to all known failover hosts
private IMesServices failoverProxy;
// update Thread counter
private int runCounter;
/// <summary>
/// do not marshal objects but print as xml
/// </summary>
private ItacXmlSerializer serializer = new ItacXmlSerializer();
//// failover detection
private static int updateThreadCount;
private Thread failoverUpdateThread;
private int refreshFailoverhostsInterval;
/// <summary>
///
/// </summary>
public MesServices(String hostname, int port, int refreshFailoverhostsInterval)
{
setConfigured(false);
setActive(false);
//// create and initialize the failover proxy
failoverInvocationHandler = new FailoverInvocationHandler(OnLog);
// create the proxy and set the delegate
failoverProxy = (IMesServices)new FailoverProxy(typeof(IMesServices), failoverInvocationHandler).GetTransparentProxy();
// check hostname
if (!isHostNameValid(hostname))
{
log(TraceEventType.Error, "hostname must not be null or empty");
return;
}
// check port range
if (!isPortValid(port))
{
log(TraceEventType.Error, String.Format("value {0} is out of range {1}..{2}", port, MIN_PORT, MAX_PORT));
return;
}
// check refresh interval
if (!isRefreshIntervalValid(refreshFailoverhostsInterval))
{
log(TraceEventType.Error, "value {0} is out of valid values [-1], [0], [>60000]");
return;
}
setRefreshFailoverhostsInterval(refreshFailoverhostsInterval);
setConfigured(true);
FailoverHost failoverHost = new FailoverHost();
failoverHost.setHostname(hostname);
failoverHost.setPort(port);
failoverInvocationHandler.setFailover(new FailoverHost[] { failoverHost });
}
protected void setRefreshFailoverhostsInterval(int refreshFailoverhostsInterval)
{
this.refreshFailoverhostsInterval = refreshFailoverhostsInterval;
}
protected Boolean isPortValid(int newPort)
{
Boolean result = newPort >= MIN_PORT && newPort <= MAX_PORT;
return result;
}
protected Boolean isHostNameValid(String hostname)
{
return hostname != null && hostname.Length != 0;
}
protected Boolean isRefreshIntervalValid(long refreshFailoverhostsInterval)
{
return refreshFailoverhostsInterval == -1 || refreshFailoverhostsInterval == 0 || refreshFailoverhostsInterval > 60000;
}
protected void setActive(Boolean active)
{
if (!this.active && active)
{
log(TraceEventType.Information, "setting MesServices active");
}
else if (this.active && !active)
{
log(TraceEventType.Information, "setting MesServices inactive");
}
this.active = active;
}
protected Boolean isActive()
{
return active;
}
protected Boolean isConfigured()
{
return configured;
}
protected void setConfigured(Boolean configured)
{
if (!this.configured && configured)
{
log(TraceEventType.Information, "setting MesServices configured");
}
else if (this.configured && !configured)
{
log(TraceEventType.Information, "setting MesServices unconfigured");
}
this.configured = configured;
}
/// <summary>
/// Vorbedingungen sind dass der Request gesetzt ist, sowie die Konfiguration und die aktivierung des Plugin
/// </summary>
/// <param name="mesResponse"> Parameter description for s goes here.</param>
/// <param name="mesRequest"> Parameter description for s goes here.</param>
/// <seealso cref="System.String">
/// You can use the cref attribute on any tag to reference a type or member
/// and the compiler will check that the reference exists. </seealso>
private void checkPreconditions(MesResponse mesResponse, MesRequest mesRequest) /* throws CogiscanException */{
checkRequestPreconditons(mesRequest);
if (mesResponse == null)
{
throw new PluginException(ResponseDetail.RESPONSE_IS_NULL, "response is null");
}
// requestId aus Request in den Response uebernehmen
mesResponse.setRequestId(mesRequest.getRequestId());
// Konfigurationsprobleme checken
if (!isConfigured())
{
throw new PluginException(ResponseDetail.PLUGIN_NOT_CONFIGURED, "plugin is not yet configured");
}
if (!isActive())
{
throw new PluginException(ResponseDetail.PLUGIN_NOT_ACTIVE, "plugin is not yet active");
}
setResponseValues(mesResponse, new ResponseDetail("", ResponseDetail.OK));
}
private void checkRequestPreconditons(MesRequest mesRequest)
{
if (mesRequest == null)
{
throw new PluginException(ResponseDetail.REQUEST_IS_NULL, "the request is null");
}
if (mesRequest.getRequestId() <= 0)
{
mesRequest.setRequestId(idGenerator.getNextId());
}
if (mesRequest.getEventDate() == null || mesRequest.getEventDate().Ticks == 0)
{
mesRequest.setEventDate(DateTime.Now);
}
// Request ausgeben
logRequest(mesRequest);
}
/**
* finalizing means closing communication channel and loggin response Object
*
* @param connection
* the used connection
* @param responseObject
* the responseObject
*/
private void finalizeRequest(MesResponse responseObject)
{
logResponse(responseObject);
}
// * gets a new communication cahnnel with specified name
// *
// * @param channelName
// * the name for the channel
// * @param connectionListener
// * @return
// * @throws IOException
// eine neue socket zum DataInterface als Client aufmachen. ?ber diese Verbindung werden alle Events zum
// Datainterface ?bertragen
// Returned nie einen Null-Wert
/// <summary>
/// Description for SomeMethod.</summary>
/// You can use the cref attribute on any tag to reference a type or member
/// and the compiler will check that the reference exists.
private void log(TraceEventType traceEventType, string message)
{
if (OnLog == null) { return; }
MyEventArgs myEventArgs = new MyEventArgs();
myEventArgs.message = "iTAC.MES.Suite SMT-Plugin:" + message;
myEventArgs.traceEventType = traceEventType;
OnLog(this, myEventArgs);
}
// convenient method
private ErrorDetail getErrorDetail(String detail, int code)
{
ErrorDetail errorDetail = new ErrorDetail();
errorDetail.setCode(code);
errorDetail.setDetail(detail);
return errorDetail;
}
private void handleThrowable(MesResponse response, Exception throwable)
{
response.setTotalResult(MesServices.MES_RESULT_NOT_OK);
if (throwable is PluginException)
{
setResponseValues(response, ((PluginException)throwable).getResponseDetail());
}
else if (throwable is IOException)
{
ErrorDetail[] details = response.getErrorDetails();
addError(ref details, getErrorDetail(throwable.Message, ResponseDetail.COMMUNICATION_FAILURE));
response.setErrorDetails(details);
}
else
{
ErrorDetail[] details = response.getErrorDetails();
addError(ref details, getErrorDetail(throwable.Message, ResponseDetail.PROCESSED_WITH_EXCEPTION));
response.setErrorDetails(details);
}
}
private void logResponse(MesResponse mesResponse)
{
if (mesResponse == null)
{
log(TraceEventType.Information, "finish empty response");
return;
}
try
{
String v = serializer.serialize(mesResponse).ToString();
log(TraceEventType.Verbose, "finish response " + mesResponse.getRequestId() + " (" + mesResponse.GetType().Name + ")"
+ " with code " + mesResponse.getTotalResult() + "\n" + v);
}
catch (Exception)
{
log(TraceEventType.Verbose, "finish request " + mesResponse.getRequestId() + " with code " + mesResponse.getTotalResult() + "\ncannot log response message");
}
}
private void logRequest(MesRequest mesRequest)
{
if (mesRequest == null)
{
log(TraceEventType.Information, "finish empty request");
return;
}
try
{
String v = serializer.serialize(mesRequest).ToString();
log(TraceEventType.Verbose, "finish request " + mesRequest.getRequestId() + " (" + mesRequest.GetType().Name + ")" + "\n" + v);
}
catch (Exception)
{
log(TraceEventType.Verbose, "finish request " + mesRequest.getRequestId() + "\ncannot log request message");
}
}
private void setResponseValues(MesResponse response, ResponseDetail responseDetail)
{
if (responseDetail.getCode() == ResponseDetail.OK)
{
response.setTotalResult(MesServices.MES_RESULT_OK);
return;
}
response.setTotalResult(MesServices.MES_RESULT_NOT_OK);
ErrorDetail[] details = response.getErrorDetails();
addError(ref details, getErrorDetail(responseDetail.getText(), responseDetail.getCode()));
response.setErrorDetails(details);
}
protected IMesServices getFailoverProxy()
{
return failoverProxy;
}
#region IMesServices_Member
/// <summary>
///
/// </summary>
/// <param name="createContainerRequest"></param>
/// <returns></returns>
public CreateContainerResponse mesCreateContainer(CreateContainerRequest createContainerRequest)
{
CreateContainerResponse responseObject = new CreateContainerResponse();
try
{
checkPreconditions(responseObject, createContainerRequest);
responseObject = getFailoverProxy().mesCreateContainer(createContainerRequest);
}
catch (Exception throwable)
{
handleThrowable(responseObject, throwable);
}
finally
{
finalizeRequest(responseObject);
}
return responseObject;
}
public CreateMslContainerResponse mesCreateMslContainer(CreateMslContainerRequest createMslContainerRequest)
{
CreateMslContainerResponse responseObject = new CreateMslContainerResponse();
try
{
checkPreconditions(responseObject, createMslContainerRequest);
responseObject = getFailoverProxy().mesCreateMslContainer(createMslContainerRequest);
}
catch (Exception throwable)
{
handleThrowable(responseObject, throwable);
}
finally
{
finalizeRequest(responseObject);
}
return responseObject;
}
/// <summary>
///
/// </summary>
public CheckContainerResponse mesCheckContainer(CheckContainerRequest checkContainerRequest)
{
CheckContainerResponse responseObject = new CheckContainerResponse();
try
{
checkPreconditions(responseObject, checkContainerRequest);
responseObject = getFailoverProxy().mesCheckContainer(checkContainerRequest);
}
catch (Exception throwable)
{
handleThrowable(responseObject, throwable);
}
finally
{
finalizeRequest(responseObject);
}
return responseObject;
}
public CheckMslContainerResponse mesCheckMslContainer(CheckMslContainerRequest checkMslContainerRequest)
{
CheckMslContainerResponse responseObject = new CheckMslContainerResponse();
try
{
checkPreconditions(responseObject, checkMslContainerRequest);
responseObject = getFailoverProxy().mesCheckMslContainer(checkMslContainerRequest);
}
catch (Exception throwable)
{
handleThrowable(responseObject, throwable);
}
finally
{
finalizeRequest(responseObject);
}
return responseObject;
}
/// <summary>
///
/// </summary>
public PlacementRecipeCheckResponse mesCheckPlacementRecipe(PlacementRecipeCheckRequest placementRecipeCheckRequest)
{
PlacementRecipeCheckResponse responseObject = new PlacementRecipeCheckResponse();
try
{
checkPreconditions(responseObject, placementRecipeCheckRequest);
responseObject = getFailoverProxy().mesCheckPlacementRecipe(placementRecipeCheckRequest);
}
catch (Exception throwable)
{
handleThrowable(responseObject, throwable);
}
finally
{
finalizeRequest(responseObject);
}
return responseObject;
}
/// <summary>
///
/// </summary>
public InterlockingResponse mesInterlocking(InterlockingRequest interlockingRequest)
{
InterlockingResponse responseObject = new InterlockingResponse();
try
{
checkPreconditions(responseObject, interlockingRequest);
responseObject = getFailoverProxy().mesInterlocking(interlockingRequest);
}
catch (Exception throwable)
{
handleThrowable(responseObject, throwable);
}
finally
{
finalizeRequest(responseObject);
}
return responseObject;
}
/// <summary>
///
/// <param name="name">description</param>
/// <returns>description</returns>
/// <seealso cref="MesRequest"/>
/// </summary>
public PanelInfoResponse mesPanelInformation(PanelInfoRequest infoRequest)
{
PanelInfoResponse responseObject = new PanelInfoResponse();
try
{
checkPreconditions(responseObject, infoRequest);
responseObject = getFailoverProxy().mesPanelInformation(infoRequest);
}
catch (Exception throwable)
{
handleThrowable(responseObject, throwable);
}
finally
{
finalizeRequest(responseObject);
}
return responseObject;
}
/// <summary>
///
/// </summary>
public MesResponse mesItemProduced(ItemProducedRequest itemProducedRequest)
{
MesResponse responseObject = new MesResponse();
try
{
checkPreconditions(responseObject, itemProducedRequest);
responseObject = getFailoverProxy().mesItemProduced(itemProducedRequest);
}
catch (Exception throwable)
{
handleThrowable(responseObject, throwable);
}
finally
{
finalizeRequest(responseObject);
}
return responseObject;
}
/// <summary>
///
/// </summary>
public MesResponse mesMachineState(MachineStatusRequest machineStatus)
{
MesResponse responseObject = new MesResponse();
try
{
checkPreconditions(responseObject, machineStatus);
responseObject = getFailoverProxy().mesMachineState(machineStatus);
}
catch (Exception throwable)
{
handleThrowable(responseObject, throwable);
}
finally
{
finalizeRequest(responseObject);
}
return responseObject;
}
/// <summary>
///
/// </summary>
public MesResponse mesMachineMessage(MachineMessageRequest machineMessage)
{
MesResponse responseObject = new MesResponse();
try
{
checkPreconditions(responseObject, machineMessage);
responseObject = getFailoverProxy().mesMachineMessage(machineMessage);
}
catch (Exception throwable)
{
handleThrowable(responseObject, throwable);
}
finally
{
finalizeRequest(responseObject);
}
return responseObject;
}
/// <summary>
///
/// </summary>
public MesFailoverResponse mesGetFailoverList(MesRequest mesRequest)
{
MesFailoverResponse responseObject = new MesFailoverResponse();
try
{
checkPreconditions(responseObject, mesRequest);
responseObject = getFailoverProxy().mesGetFailoverList(mesRequest);
}
catch (Exception throwable)
{
handleThrowable(responseObject, throwable);
}
finally
{
finalizeRequest(responseObject);
}
return responseObject;
}
/// <summary>
///
/// </summary>
public MesResponse mesMaterialConsumed(MaterialConsumedRequest materialConsumedRequest)
{
MesResponse responseObject = new MesResponse();
try
{
checkPreconditions(responseObject, materialConsumedRequest);
responseObject = getFailoverProxy().mesMaterialConsumed(materialConsumedRequest);
}
catch (Exception throwable)
{
handleThrowable(responseObject, throwable);
}
finally
{
finalizeRequest(responseObject);
}
return responseObject;
}
/// <summary>
///
/// </summary>
public MesConfigurationResponse mesGetConfiguration(MesRequest mesRequest)
{
MesConfigurationResponse responseObject = new MesConfigurationResponse();
try
{
checkPreconditions(responseObject, mesRequest);
responseObject = getFailoverProxy().mesGetConfiguration(mesRequest);
}
catch (Exception throwable)
{
handleThrowable(responseObject, throwable);
}
finally
{
finalizeRequest(responseObject);
}
return responseObject;
}
/// <summary>
///
/// </summary>
public MesResponse mesStart(MesStartRequest mesRequest)
{
checkRequestPreconditons(mesRequest);
MesResponse responseObject = new MesResponse();
responseObject.setRequestId(mesRequest.getRequestId());
try
{
if (!isConfigured())
{
throw new PluginException(ResponseDetail.MES_NOT_CONFIGURED_PROPERLY, "");
}
if (isActive())
{
setResponseValues(responseObject, new ResponseDetail("", ResponseDetail.OK));
return responseObject;
}
// append own assembly vresion to mesStart message
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
responseObject = getFailoverProxy().mesStart(mesRequest);
stopWatch.Stop();
long millies = stopWatch.ElapsedMilliseconds;
log(TraceEventType.Information, "roundtrip = " + (millies) + " milliseconds");
if (responseObject.getTotalResult() == MES_RESULT_OK)
{
setActive(true);
startUpdateThread();
}
}
catch (PluginException cse)
{
handleThrowable(responseObject, cse);
}
finally
{
logResponse(responseObject);
}
return responseObject;
}
/// <summary>
///
/// </summary>
public MesResponse mesGetStatus(MesRequest mesRequest)
{
MesResponse responseObject = new MesResponse();
try
{
checkPreconditions(responseObject, mesRequest);
responseObject = getFailoverProxy().mesGetStatus(mesRequest);
}
catch (Exception throwable)
{
handleThrowable(responseObject, throwable);
}
finally
{
logResponse(responseObject);
}
return responseObject;
}
/// <summary>
///
/// </summary>
public MesResponse mesStop(MesRequest mesRequest)
{
MesResponse responseObject = new MesResponse();
try
{
checkPreconditions(responseObject, mesRequest);
responseObject = getFailoverProxy().mesStop(mesRequest);
}
catch (Exception throwable)
{
handleThrowable(responseObject, throwable);
}
finally
{
logResponse(responseObject);
}
setActive(false);
stopUpdateThread();
return responseObject;
}
#endregion IMesServices_Member
#region UpdateThread
public void failoverThreadProc()
{
log(TraceEventType.Information, Thread.CurrentThread.Name + "renew failoverHost list thread started, call #" + (++runCounter));
while (true)
{
try
{
mesGetFailoverList(new MesRequest());
log(TraceEventType.Information, Thread.CurrentThread.Name + "renew failoverHost list finished");
int millies = refreshFailoverhostsInterval;
if (millies == -1)
{
millies = DEFAULT_REFRESH_INTERVAL;
}
TimeSpan ts = TimeSpan.FromMilliseconds(millies);
log(TraceEventType.Information, Thread.CurrentThread.Name + "next failover resolving in " + ts.ToString());
Thread.Sleep(millies);
}
catch (ThreadAbortException)
{
log(TraceEventType.Error, Thread.CurrentThread.Name + "interrupted or failed");
break;
}
catch (ThreadInterruptedException)
{
log(TraceEventType.Error, Thread.CurrentThread.Name + "interrupted");
break;
}
}
log(TraceEventType.Information, Thread.CurrentThread.Name + "closed");
}
[MethodImpl(MethodImplOptions.Synchronized)]
protected Thread getUpdateThread()
{
String threadName = "failoverUpdateThread#" + (updateThreadCount++);
Thread failoverUpdateThread = new Thread(new ThreadStart(failoverThreadProc));
// threadName) {
//};
log(TraceEventType.Error, Thread.CurrentThread.Name + "created");
return failoverUpdateThread;
}
protected void startUpdateThread()
{
// if connection is established and OK start observation thread
if (failoverUpdateThread == null)
{
failoverUpdateThread = getUpdateThread();
failoverUpdateThread.Start();
}
}
/**
* the current active channel was closed (port closed on DataInterface)
*
* @param channelName
*/
protected void stopUpdateThread()
{
log(TraceEventType.Information, " was closed by iTAC.MES.Suite DataInterface");
// den Ueberwachungsthread stoppen
if (failoverUpdateThread != null)
{
log(TraceEventType.Information, " stop " + failoverUpdateThread.Name + " now");
failoverUpdateThread.Interrupt();
failoverUpdateThread = null;
}
}
private void addError(ref ErrorDetail[] errorDetail1, ErrorDetail errorDetail2)
{
if (errorDetail1 == null)
{
errorDetail1 = new ErrorDetail[0];
}
int newArrSize = errorDetail1.Length + 1;
Array.Resize<ErrorDetail>(ref errorDetail1, newArrSize);
errorDetail1[newArrSize - 1] = errorDetail2;
}
#endregion UpdateThread
}
}