Not Tested

This commit is contained in:
2024-04-02 10:39:16 -07:00
commit 09d2d904c6
123 changed files with 14694 additions and 0 deletions

View File

@ -0,0 +1,52 @@
#if NETFRAMEWORK && NET48
using System.Web.Http;
using System.Web.Http.Results;
namespace Adaptation.FileHandlers.Archive.ApiController;
[Route("api/[controller]")]
public class WaferCounterController : System.Web.Http.ApiController
{
#nullable enable
[HttpGet]
#pragma warning disable CA1822
public OkNegotiatedContentResult<string[]> Get()
#pragma warning restore CA1822
{
string[] results = WaferCounterHelper.Review();
return Ok(results);
}
[HttpPut]
#pragma warning disable CA1822
public OkNegotiatedContentResult<string> Put(string callbackUrl)
#pragma warning restore CA1822
{
WaferCounterHelper.Subscribe(callbackUrl);
return Ok(callbackUrl);
}
[HttpDelete]
#pragma warning disable CA1822
public OkNegotiatedContentResult<string> Delete(string callbackUrl)
#pragma warning restore CA1822
{
WaferCounterHelper.Unsubscribe(callbackUrl);
return Ok(callbackUrl);
}
[HttpGet]
#pragma warning disable CA1822
public OkNegotiatedContentResult<string> Get(string area, string waferSize)
#pragma warning restore CA1822
{
string result = WaferCounterHelper.GetLastQuantityAndSlotMap(area, waferSize);
return Ok(result);
}
}
#endif

View File

@ -0,0 +1,226 @@
using Adaptation.Eaf.Management.ConfigurationData.CellAutomation;
using Adaptation.Ifx.Eaf.EquipmentConnector.File.Configuration;
using Adaptation.Shared;
using Adaptation.Shared.Duplicator;
using Adaptation.Shared.Methods;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Reflection;
using System.Text;
using System.Text.Json;
using System.Threading;
namespace Adaptation.FileHandlers.Archive;
public class FileRead : Shared.FileRead, IFileRead
{
#nullable enable
private readonly Timer _Timer;
private static PropertyInfo? _PropertyInfo;
private static NetworkStream? _NetworkStream;
public FileRead(ISMTP smtp, Dictionary<string, string> fileParameter, string cellInstanceName, int? connectionCount, string cellInstanceConnectionName, FileConnectorConfiguration fileConnectorConfiguration, string equipmentTypeName, string parameterizedModelObjectDefinitionType, IList<ModelObjectParameterDefinition> modelObjectParameters, string equipmentDictionaryName, Dictionary<string, List<long>> dummyRuns, Dictionary<long, List<string>> staticRuns, bool useCyclicalForDescription, bool isEAFHosted) :
base(new Description(), false, smtp, fileParameter, cellInstanceName, connectionCount, cellInstanceConnectionName, fileConnectorConfiguration, equipmentTypeName, parameterizedModelObjectDefinitionType, modelObjectParameters, equipmentDictionaryName, dummyRuns, staticRuns, useCyclicalForDescription, isEAFHosted: connectionCount is null)
{
if (_FileConnectorConfiguration.FileScanningIntervalInSeconds is null)
throw new NullReferenceException(nameof(_FileConnectorConfiguration.FileScanningIntervalInSeconds));
_MinFileLength = 10;
_NetworkStream = null;
_Logistics = new(this);
_NullData = string.Empty;
if (_FileParameter is null)
throw new Exception(cellInstanceConnectionName);
if (_ModelObjectParameterDefinitions is null)
throw new Exception(cellInstanceConnectionName);
if (_IsDuplicator)
throw new Exception(cellInstanceConnectionName);
// https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_server
TcpListener tcpListener = new(IPAddress.Parse("127.0.0.1"), 8087);
tcpListener.Start();
_ = tcpListener.BeginAcceptTcpClient(OnAccept, tcpListener);
Type type = typeof(NetworkStream);
PropertyInfo? propertyInfo = type.GetProperty("Socket", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.GetProperty);
if (propertyInfo is null)
throw new NotSupportedException();
_PropertyInfo = propertyInfo;
_Timer = new Timer(Callback, null, Timeout.Infinite, Timeout.Infinite);
if (Debugger.IsAttached || fileConnectorConfiguration.PreProcessingMode == FileConnectorConfiguration.PreProcessingModeEnum.Process)
Callback(null);
else
{
TimeSpan timeSpan = new(DateTime.Now.AddSeconds(_FileConnectorConfiguration.FileScanningIntervalInSeconds.Value).Ticks - DateTime.Now.Ticks);
_ = _Timer.Change((long)timeSpan.TotalMilliseconds, Timeout.Infinite);
}
}
void IFileRead.Move(Tuple<string, Test[], JsonElement[], List<FileInfo>> extractResults, Exception exception) => Move(extractResults);
void IFileRead.WaitForThread() => WaitForThread(thread: null, threadExceptions: null);
string IFileRead.GetEventDescription()
{
string result = _Description.GetEventDescription();
return result;
}
List<string> IFileRead.GetHeaderNames()
{
List<string> results = _Description.GetHeaderNames();
return results;
}
string[] IFileRead.Move(Tuple<string, Test[], JsonElement[], List<FileInfo>> extractResults, string to, string from, string resolvedFileLocation, Exception exception)
{
string[] results = Move(extractResults, to, from, resolvedFileLocation, exception);
return results;
}
JsonProperty[] IFileRead.GetDefault()
{
JsonProperty[] results = _Description.GetDefault(this, _Logistics);
return results;
}
Dictionary<string, string> IFileRead.GetDisplayNamesJsonElement()
{
Dictionary<string, string> results = _Description.GetDisplayNamesJsonElement(this);
return results;
}
List<IDescription> IFileRead.GetDescriptions(IFileRead fileRead, List<Test> tests, IProcessData processData)
{
List<IDescription> results = _Description.GetDescriptions(fileRead, _Logistics, tests, processData);
return results;
}
Tuple<string, Test[], JsonElement[], List<FileInfo>> IFileRead.GetExtractResult(string reportFullPath, string eventName) => throw new Exception(string.Concat("See ", nameof(Callback)));
Tuple<string, Test[], JsonElement[], List<FileInfo>> IFileRead.ReExtract() => throw new Exception(string.Concat("See ", nameof(Callback)));
private static void Archive(FileConnectorConfiguration fileConnectorConfiguration, Calendar calendar, DateTime dateTime, string fileName, string fullFileName)
{
string weekOfYear = $"{dateTime:yyyy}_Week_{calendar.GetWeekOfYear(dateTime, CalendarWeekRule.FirstDay, DayOfWeek.Sunday):00}";
string archiveDirectory = Path.Combine(fileConnectorConfiguration.TargetFileLocation, "Archive", weekOfYear);
if (!Directory.Exists(archiveDirectory))
_ = Directory.CreateDirectory(archiveDirectory);
string to = Path.Combine(archiveDirectory, fileName);
File.Move(fullFileName, to);
}
internal static void Notify(FileConnectorConfiguration fileConnectorConfiguration, Calendar calendar, DateTime dateTime, string fileName, string fullFileName, string json)
{
if (_NetworkStream is not null)
{
if (!_NetworkStream.CanWrite)
{
TcpListener tcpListener = new(IPAddress.Parse("127.0.0.1"), 8087);
tcpListener.Start();
_ = tcpListener.BeginAcceptTcpClient(OnAccept, tcpListener);
}
else
{
if (_PropertyInfo is null)
throw new NullReferenceException(nameof(_PropertyInfo));
if (_PropertyInfo.GetValue(_NetworkStream) is not Socket socket)
throw new NotSupportedException();
if (!socket.Connected)
{
TcpListener tcpListener = new(IPAddress.Parse("127.0.0.1"), 8087);
tcpListener.Start();
_ = tcpListener.BeginAcceptTcpClient(OnAccept, tcpListener);
}
else
{
BinaryWriter binaryWriter = new(_NetworkStream);
binaryWriter.Write(json);
binaryWriter.Flush();
binaryWriter.Dispose();
Archive(fileConnectorConfiguration, calendar, dateTime, fileName, fullFileName);
}
}
}
}
private static void NetworkStreamDataAvailable(string cellInstanceName, FileConnectorConfiguration fileConnectorConfiguration, Calendar calendar, NetworkStream networkStream)
{
int length;
string read;
byte[] bytes = new byte[1024];
StringBuilder stringBuilder = new();
do
{
length = networkStream.Read(bytes, 0, bytes.Length);
read = Encoding.ASCII.GetString(bytes, 0, length);
foreach (char item in read)
{
if (item is '\0')
continue;
_ = stringBuilder.Append(item);
}
}
while (networkStream.DataAvailable);
if (stringBuilder.Length > 0)
throw new NotImplementedException();
}
private void Callback()
{
if (_NetworkStream is not null && _NetworkStream.CanRead)
{
if (_PropertyInfo is null)
throw new NullReferenceException(nameof(_PropertyInfo));
if (_PropertyInfo.GetValue(_NetworkStream) is not Socket socket)
throw new NotSupportedException();
if (socket.Connected && _NetworkStream.DataAvailable)
NetworkStreamDataAvailable(_CellInstanceName, _FileConnectorConfiguration, _Calendar, _NetworkStream);
}
}
private void Callback(object? state)
{
if (_FileConnectorConfiguration.FileScanningIntervalInSeconds is null)
throw new NullReferenceException(nameof(_FileConnectorConfiguration.FileScanningIntervalInSeconds));
try
{
Callback();
}
catch (Exception exception)
{
string subject = string.Concat("Exception:", _CellInstanceConnectionName);
string body = string.Concat(exception.Message, Environment.NewLine, Environment.NewLine, exception.StackTrace);
try
{ _SMTP.SendHighPriorityEmailMessage(subject, body); }
catch (Exception) { }
}
try
{
TimeSpan timeSpan = new(DateTime.Now.AddSeconds(_FileConnectorConfiguration.FileScanningIntervalInSeconds.Value).Ticks - DateTime.Now.Ticks);
_ = _Timer.Change((long)timeSpan.TotalMilliseconds, Timeout.Infinite);
}
catch (Exception exception)
{
string subject = string.Concat("Exception:", _CellInstanceConnectionName);
string body = string.Concat(exception.Message, Environment.NewLine, Environment.NewLine, exception.StackTrace);
try
{ _SMTP.SendHighPriorityEmailMessage(subject, body); }
catch (Exception) { }
}
}
private static void OnAccept(IAsyncResult asyncResult)
{
if (asyncResult.AsyncState is TcpListener tcpListener)
{
TcpClient tcpClient = tcpListener.EndAcceptTcpClient(asyncResult);
_NetworkStream = tcpClient.GetStream();
}
}
}

View File

@ -0,0 +1,24 @@
using Adaptation.Eaf.Management.ConfigurationData.CellAutomation;
using Adaptation.Ifx.Eaf.EquipmentConnector.File.Configuration;
using Adaptation.Shared.Methods;
using System;
using System.Collections.Generic;
namespace Adaptation.FileHandlers;
public class CellInstanceConnectionName
{
internal static IFileRead Get(ISMTP smtp, Dictionary<string, string> fileParameter, string cellInstanceName, string cellInstanceConnectionName, FileConnectorConfiguration fileConnectorConfiguration, string equipmentTypeName, string parameterizedModelObjectDefinitionType, IList<ModelObjectParameterDefinition> modelObjectParameters, string equipmentDictionaryName, Dictionary<string, List<long>> dummyRuns, Dictionary<long, List<string>> staticRuns, bool useCyclicalForDescription, int? connectionCount)
{
IFileRead result = cellInstanceConnectionName switch
{
nameof(Archive) => new Archive.FileRead(smtp, fileParameter, cellInstanceName, connectionCount, cellInstanceConnectionName, fileConnectorConfiguration, equipmentTypeName, parameterizedModelObjectDefinitionType, modelObjectParameters, equipmentDictionaryName, dummyRuns, staticRuns, useCyclicalForDescription, isEAFHosted: connectionCount is null),
nameof(wc) => new wc.FileRead(smtp, fileParameter, cellInstanceName, connectionCount, cellInstanceConnectionName, fileConnectorConfiguration, equipmentTypeName, parameterizedModelObjectDefinitionType, modelObjectParameters, equipmentDictionaryName, dummyRuns, staticRuns, useCyclicalForDescription, isEAFHosted: connectionCount is null),
nameof(Dummy) => new Dummy.FileRead(smtp, fileParameter, cellInstanceName, connectionCount, cellInstanceConnectionName, fileConnectorConfiguration, equipmentTypeName, parameterizedModelObjectDefinitionType, modelObjectParameters, equipmentDictionaryName, dummyRuns, staticRuns, useCyclicalForDescription, isEAFHosted: connectionCount is null),
_ => throw new Exception($"\"{cellInstanceConnectionName}\" not mapped")
};
return result;
}
}

View File

@ -0,0 +1,286 @@
using Adaptation.Eaf.Management.ConfigurationData.CellAutomation;
using Adaptation.Ifx.Eaf.EquipmentConnector.File.Configuration;
using Adaptation.Shared;
using Adaptation.Shared.Duplicator;
using Adaptation.Shared.Methods;
using Infineon.Monitoring.MonA;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Text.Json;
using System.Threading;
namespace Adaptation.FileHandlers.Dummy;
public class FileRead : Shared.FileRead, IFileRead
{
private readonly Timer _Timer;
private int _LastDummyRunIndex;
private readonly string[] _CellNames;
public FileRead(ISMTP smtp, Dictionary<string, string> fileParameter, string cellInstanceName, int? connectionCount, string cellInstanceConnectionName, FileConnectorConfiguration fileConnectorConfiguration, string equipmentTypeName, string parameterizedModelObjectDefinitionType, IList<ModelObjectParameterDefinition> modelObjectParameters, string equipmentDictionaryName, Dictionary<string, List<long>> dummyRuns, Dictionary<long, List<string>> staticRuns, bool useCyclicalForDescription, bool isEAFHosted) :
base(new Description(), false, smtp, fileParameter, cellInstanceName, connectionCount, cellInstanceConnectionName, fileConnectorConfiguration, equipmentTypeName, parameterizedModelObjectDefinitionType, modelObjectParameters, equipmentDictionaryName, dummyRuns, staticRuns, useCyclicalForDescription, isEAFHosted: connectionCount is null)
{
_MinFileLength = 10;
_NullData = string.Empty;
_Logistics = new(this);
if (_FileParameter is null)
throw new Exception(cellInstanceConnectionName);
if (_ModelObjectParameterDefinitions is null)
throw new Exception(cellInstanceConnectionName);
if (!_IsDuplicator)
throw new Exception(cellInstanceConnectionName);
_LastDummyRunIndex = -1;
List<string> cellNames = new();
_Timer = new Timer(Callback, null, Timeout.Infinite, Timeout.Infinite);
ModelObjectParameterDefinition[] cellInstanceCollection = GetProperties(cellInstanceConnectionName, modelObjectParameters, "CellInstance.", ".Alias");
foreach (ModelObjectParameterDefinition modelObjectParameterDefinition in cellInstanceCollection)
cellNames.Add(modelObjectParameterDefinition.Name.Split('.')[1]);
_CellNames = cellNames.ToArray();
if (Debugger.IsAttached || fileConnectorConfiguration.PreProcessingMode == FileConnectorConfiguration.PreProcessingModeEnum.Process)
Callback(null);
else
{
TimeSpan timeSpan = new(DateTime.Now.AddSeconds(_FileConnectorConfiguration.FileScanningIntervalInSeconds.Value).Ticks - DateTime.Now.Ticks);
_ = _Timer.Change((long)timeSpan.TotalMilliseconds, Timeout.Infinite);
}
}
void IFileRead.Move(Tuple<string, Test[], JsonElement[], List<FileInfo>> extractResults, Exception exception) => Move(extractResults);
void IFileRead.WaitForThread() => WaitForThread(thread: null, threadExceptions: null);
string IFileRead.GetEventDescription()
{
string result = _Description.GetEventDescription();
return result;
}
List<string> IFileRead.GetHeaderNames()
{
List<string> results = _Description.GetHeaderNames();
return results;
}
string[] IFileRead.Move(Tuple<string, Test[], JsonElement[], List<FileInfo>> extractResults, string to, string from, string resolvedFileLocation, Exception exception)
{
string[] results = Move(extractResults, to, from, resolvedFileLocation, exception);
return results;
}
JsonProperty[] IFileRead.GetDefault()
{
JsonProperty[] results = _Description.GetDefault(this, _Logistics);
return results;
}
Dictionary<string, string> IFileRead.GetDisplayNamesJsonElement()
{
Dictionary<string, string> results = _Description.GetDisplayNamesJsonElement(this);
return results;
}
List<IDescription> IFileRead.GetDescriptions(IFileRead fileRead, List<Test> tests, IProcessData processData)
{
List<IDescription> results = _Description.GetDescriptions(fileRead, _Logistics, tests, processData);
return results;
}
Tuple<string, Test[], JsonElement[], List<FileInfo>> IFileRead.GetExtractResult(string reportFullPath, string eventName) => throw new Exception(string.Concat("See ", nameof(CallbackFileExists)));
Tuple<string, Test[], JsonElement[], List<FileInfo>> IFileRead.ReExtract() => throw new Exception(string.Concat("See ", nameof(CallbackFileExists)));
private void CallbackInProcessCleared(string sourceArchiveFile, string traceDummyFile, string targetFileLocation, string monARessource, string inProcessDirectory, long sequence, bool warning)
{
const string site = "sjc";
string stateName = string.Concat("Dummy_", _EventName);
const string monInURL = "http://moninhttp.sjc.infineon.com/input/text";
MonIn monIn = MonIn.GetInstance(monInURL);
try
{
if (warning)
{
File.AppendAllLines(traceDummyFile, new string[] { site, monARessource, stateName, State.Warning.ToString() });
_ = monIn.SendStatus(site, monARessource, stateName, State.Warning);
for (int i = 1; i < 12; i++)
Thread.Sleep(500);
}
ZipFile.ExtractToDirectory(sourceArchiveFile, inProcessDirectory);
string[] files = Directory.GetFiles(inProcessDirectory, "*", SearchOption.TopDirectoryOnly);
if (files.Length > 250)
throw new Exception("Safety net!");
foreach (string file in files)
File.SetLastWriteTime(file, new DateTime(sequence));
if (!_FileConnectorConfiguration.IncludeSubDirectories.Value)
{
foreach (string file in files)
File.Move(file, Path.Combine(targetFileLocation, Path.GetFileName(file)));
}
else
{
string[] directories = Directory.GetDirectories(inProcessDirectory, "*", SearchOption.AllDirectories);
foreach (string directory in directories)
_ = Directory.CreateDirectory(string.Concat(targetFileLocation, directory.Substring(inProcessDirectory.Length)));
foreach (string file in files)
File.Move(file, string.Concat(targetFileLocation, file.Substring(inProcessDirectory.Length)));
}
File.AppendAllLines(traceDummyFile, new string[] { site, monARessource, stateName, State.Ok.ToString() });
_ = monIn.SendStatus(site, monARessource, stateName, State.Ok);
}
catch (Exception exception)
{
string subject = string.Concat("Exception:", _CellInstanceConnectionName);
string body = string.Concat(exception.Message, Environment.NewLine, Environment.NewLine, exception.StackTrace);
try
{ _SMTP.SendHighPriorityEmailMessage(subject, body); }
catch (Exception) { }
File.AppendAllLines(traceDummyFile, new string[] { site, monARessource, stateName, State.Critical.ToString(), exception.Message, exception.StackTrace });
_ = monIn.SendStatus(site, monARessource, stateName, State.Critical);
}
}
private void CallbackFileExists(string sourceArchiveFile, string traceDummyFile, string targetFileLocation, string monARessource, long sequence)
{
string[] files;
bool warning = false;
if (!_DummyRuns.ContainsKey(monARessource))
_DummyRuns.Add(monARessource, new List<long>());
if (!_DummyRuns[monARessource].Contains(sequence))
_DummyRuns[monARessource].Add(sequence);
File.AppendAllLines(traceDummyFile, new string[] { sourceArchiveFile });
string inProcessDirectory = Path.Combine("_ProgressPath", "Dummy In-Process", sequence.ToString());
if (!Directory.Exists(inProcessDirectory))
_ = Directory.CreateDirectory(inProcessDirectory);
files = Directory.GetFiles(inProcessDirectory, "*", SearchOption.AllDirectories);
if (files.Length != 0)
{
if (files.Length > 250)
throw new Exception("Safety net!");
try
{
foreach (string file in files)
File.Delete(file);
}
catch (Exception) { }
}
if (_FileConnectorConfiguration.IncludeSubDirectories.Value)
files = Directory.GetFiles(targetFileLocation, "*", SearchOption.AllDirectories);
else
files = Directory.GetFiles(targetFileLocation, "*", SearchOption.TopDirectoryOnly);
foreach (string file in files)
{
if (new FileInfo(file).LastWriteTime.Ticks == sequence)
{
warning = true;
break;
}
}
CallbackInProcessCleared(sourceArchiveFile, traceDummyFile, targetFileLocation, monARessource, inProcessDirectory, sequence, warning);
}
private string GetCellName(string pathSegment)
{
string result = string.Empty;
foreach (string cellName in _CellNames)
{
if (pathSegment.ToLower().Contains(cellName.ToLower()))
{
result = cellName;
break;
}
}
if (string.IsNullOrEmpty(result))
{
int count;
List<(string CellName, int Count)> cellNames = new();
foreach (string cellName in _CellNames)
{
count = 0;
foreach (char @char in cellName.ToLower())
count += pathSegment.Length - pathSegment.ToLower().Replace(@char.ToString(), string.Empty).Length;
cellNames.Add(new(cellName, count));
}
result = (from l in cellNames orderby l.CellName.Length, l.Count descending select l.CellName).First();
}
return result;
}
private void Callback(object state)
{
try
{
string sourceParentDirectory;
string targetParentDirectory;
DateTime dateTime = DateTime.Now;
if (!string.IsNullOrEmpty(Path.GetFileName(_FileConnectorConfiguration.SourceFileLocation)))
sourceParentDirectory = Path.GetDirectoryName(_FileConnectorConfiguration.SourceFileLocation);
else
sourceParentDirectory = GetParentParent(_FileConnectorConfiguration.SourceFileLocation);
if (!string.IsNullOrEmpty(Path.GetFileName(_FileConnectorConfiguration.TargetFileLocation)))
targetParentDirectory = Path.GetDirectoryName(_FileConnectorConfiguration.TargetFileLocation);
else
targetParentDirectory = GetParentParent(_FileConnectorConfiguration.TargetFileLocation);
if (sourceParentDirectory != targetParentDirectory)
throw new Exception("Target and source must have the same parent for Si Dummy FileConnectorConfiguration!");
bool check = dateTime.Hour > 7 && dateTime.Hour < 18 && dateTime.DayOfWeek != DayOfWeek.Sunday && dateTime.DayOfWeek != DayOfWeek.Saturday;
if (!_IsEAFHosted || check)
{
string monARessource;
string sourceFileFilter;
string sourceArchiveFile;
string weekOfYear = _Calendar.GetWeekOfYear(dateTime, CalendarWeekRule.FirstDay, DayOfWeek.Sunday).ToString("00");
string traceDummyDirectory = Path.Combine(Path.GetPathRoot(_TracePath), "TracesDummy", _CellInstanceName, "Source", $"{dateTime:yyyy}___Week_{weekOfYear}");
if (!Directory.Exists(traceDummyDirectory))
_ = Directory.CreateDirectory(traceDummyDirectory);
string traceDummyFile = Path.Combine(traceDummyDirectory, $"{dateTime.Ticks} - {_CellInstanceName}.txt");
File.AppendAllText(traceDummyFile, string.Empty);
for (int i = 0; i < _FileConnectorConfiguration.SourceFileFilters.Count; i++)
{
_LastDummyRunIndex += 1;
if (_LastDummyRunIndex >= _FileConnectorConfiguration.SourceFileFilters.Count)
_LastDummyRunIndex = 0;
sourceFileFilter = _FileConnectorConfiguration.SourceFileFilters[_LastDummyRunIndex];
sourceArchiveFile = Path.Combine(_FileConnectorConfiguration.SourceFileLocation, sourceFileFilter);
if (File.Exists(sourceArchiveFile))
{
if (!long.TryParse(Path.GetFileNameWithoutExtension(sourceArchiveFile).Replace("x", string.Empty), out long sequence))
throw new Exception("Invalid file name for source archive file!");
monARessource = GetCellName(sourceArchiveFile);
if (string.IsNullOrEmpty(monARessource))
throw new Exception("Could not determine which cell archive file is associated with!");
if (_IsEAFHosted)
CallbackFileExists(sourceArchiveFile, traceDummyFile, _FileConnectorConfiguration.TargetFileLocation, monARessource, sequence);
break;
}
}
}
}
catch (Exception exception)
{
string subject = string.Concat("Exception:", _CellInstanceConnectionName);
string body = string.Concat(exception.Message, Environment.NewLine, Environment.NewLine, exception.StackTrace);
try
{ _SMTP.SendHighPriorityEmailMessage(subject, body); }
catch (Exception) { }
}
try
{
TimeSpan timeSpan = new(DateTime.Now.AddSeconds(_FileConnectorConfiguration.FileScanningIntervalInSeconds.Value).Ticks - DateTime.Now.Ticks);
_ = _Timer.Change((long)timeSpan.TotalMilliseconds, Timeout.Infinite);
}
catch (Exception exception)
{
string subject = string.Concat("Exception:", _CellInstanceConnectionName);
string body = string.Concat(exception.Message, Environment.NewLine, Environment.NewLine, exception.StackTrace);
try
{ _SMTP.SendHighPriorityEmailMessage(subject, body); }
catch (Exception) { }
}
}
}

View File

@ -0,0 +1,201 @@
using Adaptation.Eaf.Management.ConfigurationData.CellAutomation;
using Adaptation.Ifx.Eaf.EquipmentConnector.File.Configuration;
using Adaptation.Shared;
using Adaptation.Shared.Duplicator;
using Adaptation.Shared.Methods;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Net.Sockets;
using System.Reflection;
using System.Text;
using System.Text.Json;
using System.Threading;
namespace Adaptation.FileHandlers.wc;
public class FileRead : Shared.FileRead, IFileRead
{
#nullable enable
private readonly int _Port;
private readonly Timer _Timer;
private readonly string _Hostname;
private static PropertyInfo? _PropertyInfo;
private static NetworkStream? _NetworkStream;
public FileRead(ISMTP smtp, Dictionary<string, string> fileParameter, string cellInstanceName, int? connectionCount, string cellInstanceConnectionName, FileConnectorConfiguration fileConnectorConfiguration, string equipmentTypeName, string parameterizedModelObjectDefinitionType, IList<ModelObjectParameterDefinition> modelObjectParameters, string equipmentDictionaryName, Dictionary<string, List<long>> dummyRuns, Dictionary<long, List<string>> staticRuns, bool useCyclicalForDescription, bool isEAFHosted) :
base(new Description(), false, smtp, fileParameter, cellInstanceName, connectionCount, cellInstanceConnectionName, fileConnectorConfiguration, equipmentTypeName, parameterizedModelObjectDefinitionType, modelObjectParameters, equipmentDictionaryName, dummyRuns, staticRuns, useCyclicalForDescription, isEAFHosted: connectionCount is null)
{
if (_FileConnectorConfiguration.FileScanningIntervalInSeconds is null)
throw new NullReferenceException(nameof(_FileConnectorConfiguration.FileScanningIntervalInSeconds));
_MinFileLength = 10;
_NetworkStream = null;
_Logistics = new(this);
_NullData = string.Empty;
if (_FileParameter is null)
throw new Exception(cellInstanceConnectionName);
if (_ModelObjectParameterDefinitions is null)
throw new Exception(cellInstanceConnectionName);
if (_IsDuplicator)
throw new Exception(cellInstanceConnectionName);
Type type = typeof(NetworkStream);
PropertyInfo? propertyInfo = type.GetProperty("Socket", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.GetProperty);
if (propertyInfo is null)
throw new NullReferenceException(nameof(propertyInfo));
_PropertyInfo = propertyInfo;
_Timer = new Timer(Callback, null, Timeout.Infinite, Timeout.Infinite);
string port = GetPropertyValue(cellInstanceConnectionName, modelObjectParameters, "TCP.Port");
_Hostname = GetPropertyValue(cellInstanceConnectionName, modelObjectParameters, string.Concat("CellInstance.", cellInstanceName, ".TCP.Hostname"));
_Port = int.Parse(port);
WaferCounterHelper.Initialize(fileConnectorConfiguration);
if (Debugger.IsAttached || fileConnectorConfiguration.PreProcessingMode == FileConnectorConfiguration.PreProcessingModeEnum.Process)
Callback(null);
else
{
TimeSpan timeSpan = new(DateTime.Now.AddSeconds(_FileConnectorConfiguration.FileScanningIntervalInSeconds.Value).Ticks - DateTime.Now.Ticks);
_ = _Timer.Change((long)timeSpan.TotalMilliseconds, Timeout.Infinite);
}
}
void IFileRead.Move(Tuple<string, Test[], JsonElement[], List<FileInfo>> extractResults, Exception exception) => Move(extractResults);
void IFileRead.WaitForThread() => WaitForThread(thread: null, threadExceptions: null);
string IFileRead.GetEventDescription()
{
string result = _Description.GetEventDescription();
return result;
}
List<string> IFileRead.GetHeaderNames()
{
List<string> results = _Description.GetHeaderNames();
return results;
}
string[] IFileRead.Move(Tuple<string, Test[], JsonElement[], List<FileInfo>> extractResults, string to, string from, string resolvedFileLocation, Exception exception)
{
string[] results = Move(extractResults, to, from, resolvedFileLocation, exception);
return results;
}
JsonProperty[] IFileRead.GetDefault()
{
JsonProperty[] results = _Description.GetDefault(this, _Logistics);
return results;
}
Dictionary<string, string> IFileRead.GetDisplayNamesJsonElement()
{
Dictionary<string, string> results = _Description.GetDisplayNamesJsonElement(this);
return results;
}
List<IDescription> IFileRead.GetDescriptions(IFileRead fileRead, List<Test> tests, IProcessData processData)
{
List<IDescription> results = _Description.GetDescriptions(fileRead, _Logistics, tests, processData);
return results;
}
Tuple<string, Test[], JsonElement[], List<FileInfo>> IFileRead.GetExtractResult(string reportFullPath, string eventName) => throw new Exception(string.Concat("See ", nameof(Callback)));
Tuple<string, Test[], JsonElement[], List<FileInfo>> IFileRead.ReExtract() => throw new Exception(string.Concat("See ", nameof(Callback)));
private static void NetworkStreamDataAvailable(string cellInstanceName, FileConnectorConfiguration fileConnectorConfiguration, Calendar calendar, NetworkStream networkStream)
{
int length;
string read;
byte[] bytes = new byte[1024];
StringBuilder stringBuilder = new();
do
{
length = networkStream.Read(bytes, 0, bytes.Length);
read = Encoding.ASCII.GetString(bytes, 0, length);
foreach (char item in read)
{
if (item is '\0')
continue;
_ = stringBuilder.Append(item);
}
}
while (networkStream.DataAvailable);
if (stringBuilder.Length > 0)
{
DateTime dateTime = DateTime.Now;
string contents = stringBuilder.ToString();
string fileName = $"{dateTime.Ticks}{fileConnectorConfiguration.TargetFileName}";
string fullFileName = Path.Combine(fileConnectorConfiguration.TargetFileLocation, fileName);
if (contents[0] != 'T')
File.WriteAllText(fullFileName, contents);
else
{
string json = WaferCounterHelper.GetJson(cellInstanceName, dateTime, contents);
File.WriteAllText(fullFileName, contents);
Archive.FileRead.Notify(fileConnectorConfiguration, calendar, dateTime, fileName, fullFileName, json);
}
}
}
private void Callback()
{
if (_NetworkStream is null)
{
TcpClient tcpClient = new(_Hostname, _Port);
_NetworkStream = tcpClient.GetStream();
}
if (_PropertyInfo is null)
throw new NullReferenceException(nameof(_PropertyInfo));
if (_PropertyInfo.GetValue(_NetworkStream) is not Socket socket)
throw new NotSupportedException();
if (!socket.Connected)
{
TcpClient tcpClient = new(_Hostname, _Port);
_NetworkStream = tcpClient.GetStream();
}
if (_NetworkStream is null)
throw new NullReferenceException(nameof(_NetworkStream));
if (_NetworkStream.CanRead && _NetworkStream.DataAvailable)
NetworkStreamDataAvailable(_CellInstanceName, _FileConnectorConfiguration, _Calendar, _NetworkStream);
if (File.Exists(""))
{
DateTime dateTime = DateTime.Now;
Archive.FileRead.Notify(_FileConnectorConfiguration, _Calendar, dateTime, ".json", "D:/EAF/EAF Deployment Storage/Adaptation_MET08AWCT/.json", "json");
}
}
private void Callback(object? state)
{
if (_FileConnectorConfiguration.FileScanningIntervalInSeconds is null)
throw new NullReferenceException(nameof(_FileConnectorConfiguration.FileScanningIntervalInSeconds));
try
{
Callback();
}
catch (Exception exception)
{
string subject = string.Concat("Exception:", _CellInstanceConnectionName);
string body = string.Concat(exception.Message, Environment.NewLine, Environment.NewLine, exception.StackTrace);
try
{ _SMTP.SendHighPriorityEmailMessage(subject, body); }
catch (Exception) { }
}
try
{
TimeSpan timeSpan = new(DateTime.Now.AddSeconds(_FileConnectorConfiguration.FileScanningIntervalInSeconds.Value).Ticks - DateTime.Now.Ticks);
_ = _Timer.Change((long)timeSpan.TotalMilliseconds, Timeout.Infinite);
}
catch (Exception exception)
{
string subject = string.Concat("Exception:", _CellInstanceConnectionName);
string body = string.Concat(exception.Message, Environment.NewLine, Environment.NewLine, exception.StackTrace);
try
{ _SMTP.SendHighPriorityEmailMessage(subject, body); }
catch (Exception) { }
}
}
}

View File

@ -0,0 +1,332 @@
using Adaptation.Ifx.Eaf.EquipmentConnector.File.Configuration;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Net.WebSockets;
using System.Text;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
namespace Adaptation.FileHandlers.wc;
public class WaferCounterHelper
{
#nullable enable
private class Record
{
public int Check { get; set; }
public int Total { get; set; }
public string? SlotMap { get; set; }
}
private class WaferCounter
{
public DateTime DateTime { get; set; }
public string? DateTimeFormatted { get; set; }
public string? EquipmentId { get; set; }
public string? Text { get; set; }
public int Total { get; set; }
public string? SlotMap { get; set; }
}
private static long? _Wait;
private static string? _Directory;
private static readonly Dictionary<string, ClientWebSocket> _ClientWebSockets = new();
internal static void Initialize(FileConnectorConfiguration fileConnectorConfiguration)
{
_Directory = fileConnectorConfiguration.TargetFileLocation;
_Wait = fileConnectorConfiguration.IdleEventWaitTimeInSeconds;
}
internal static string[] Review()
{
List<string> results = new();
lock (_ClientWebSockets)
{
foreach (KeyValuePair<string, ClientWebSocket> keyValuePair in _ClientWebSockets)
{
if (results.Contains(keyValuePair.Key))
continue;
results.Add(keyValuePair.Key);
}
}
return results.ToArray();
}
internal static void Subscribe(string callbackUrl)
{
if (!_ClientWebSockets.ContainsKey(callbackUrl))
{
ClientWebSocket clientWebSocket = new();
Task task = clientWebSocket.ConnectAsync(new Uri(callbackUrl), CancellationToken.None);
task.Wait();
lock (_ClientWebSockets)
_ClientWebSockets.Add(callbackUrl, clientWebSocket);
}
}
private static void CloseAndDispose(string callbackUrl, ClientWebSocket clientWebSocket)
{
Task task = clientWebSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None);
task.Wait();
clientWebSocket.Dispose();
lock (_ClientWebSockets)
_ = _ClientWebSockets.Remove(callbackUrl);
}
internal static void Unsubscribe(string callbackUrl)
{
if (_ClientWebSockets.TryGetValue(callbackUrl, out ClientWebSocket? clientWebSocket))
CloseAndDispose(callbackUrl, clientWebSocket);
}
private static Record GetRecord(string line1, string line2)
{
Record result;
string? slotMap = string.IsNullOrEmpty(line2) || line2.Length != 8 ? null : line2.Substring(1, 1);
int check = slotMap == "1" ? 1 : 0;
int total = int.Parse(line1.Substring(1));
foreach (char item in line2.Substring(2))
{
switch (item)
{
case '0':
check += 0;
slotMap += "0000";
break;
case '1':
check += 1;
slotMap += "0001";
break;
case '2':
check += 1;
slotMap += "0010";
break;
case '3':
check += 2;
slotMap += "0011";
break;
case '4':
check += 1;
slotMap += "0100";
break;
case '5':
check += 2;
slotMap += "0101";
break;
case '6':
check += 2;
slotMap += "0110";
break;
case '7':
check += 3;
slotMap += "0111";
break;
case '8':
check += 1;
slotMap += "1000";
break;
case '9':
check += 2;
slotMap += "1001";
break;
case 'A':
check += 2;
slotMap += "1010";
break;
case 'B':
check += 3;
slotMap += "1011";
break;
case 'C':
check += 2;
slotMap += "1100";
break;
case 'D':
check += 3;
slotMap += "1101";
break;
case 'E':
check += 3;
slotMap += "1110";
break;
case 'F':
check += 4;
slotMap += "1111";
break;
default:
break;
}
}
result = new Record { Check = check, Total = total, SlotMap = slotMap };
return result;
}
internal static void TestSlotMap(string line1, string line2, string expectedSlotMap)
{
Record record = GetRecord(line1, line2);
if (record.SlotMap != expectedSlotMap)
throw new NotSupportedException($"{line1}{line2}{expectedSlotMap}");
}
internal static string GetJson(string cellInstanceName, DateTime dateTime, string contents)
{
string result;
string[] separator = new string[] { "\r\n" };
string[] lines = contents.Split(separator, StringSplitOptions.None);
if (lines.Length <= 1)
throw new Exception("Incomplete file length!");
Record record = GetRecord(lines[0], lines[1]);
if (string.IsNullOrEmpty(record.SlotMap) || record.SlotMap.Length != 25)
throw new Exception("Wrong length!");
if (record.Total != record.Check)
throw new Exception("Invalid!");
WaferCounter waferCounter = new()
{
DateTime = dateTime,
DateTimeFormatted = dateTime.ToString("yyyy-MM-dd hh:mm tt"),
EquipmentId = cellInstanceName,
Text = contents,
Total = record.Total,
SlotMap = record.SlotMap
};
result = JsonSerializer.Serialize(waferCounter);
return result;
}
private static void Notify(string json, List<KeyValuePair<string, ClientWebSocket>> clientWebSockets)
{
List<KeyValuePair<string, ClientWebSocket>> removeClientWebSockets = new();
ArraySegment<byte> bytes = new(Encoding.Default.GetBytes(json));
foreach (KeyValuePair<string, ClientWebSocket> clientWebSocket in clientWebSockets)
{
try
{
Task task = clientWebSocket.Value.SendAsync(bytes, WebSocketMessageType.Binary, false, CancellationToken.None);
task.Wait();
}
catch (Exception)
{
removeClientWebSockets.Add(clientWebSocket);
}
}
if (removeClientWebSockets.Count > 0)
{
lock (_ClientWebSockets)
{
foreach (KeyValuePair<string, ClientWebSocket> clientWebSocket in removeClientWebSockets)
CloseAndDispose(clientWebSocket.Key, clientWebSocket.Value);
}
}
}
private static void Archive(FileConnectorConfiguration fileConnectorConfiguration, Calendar calendar, DateTime dateTime, string fileName, string fullFileName)
{
string weekOfYear = $"{dateTime:yyyy}_Week_{calendar.GetWeekOfYear(dateTime, CalendarWeekRule.FirstDay, DayOfWeek.Sunday):00}";
string archiveDirectory = Path.Combine(fileConnectorConfiguration.TargetFileLocation, "Archive", weekOfYear);
if (!Directory.Exists(archiveDirectory))
_ = Directory.CreateDirectory(archiveDirectory);
string to = Path.Combine(archiveDirectory, fileName);
File.Move(fullFileName, to);
}
private static void MoveFile(string waferSizeDirectory, FileInfo fileInfo)
{
Calendar calendar = new CultureInfo("en-US").Calendar;
string weekOfYear = $"{fileInfo.LastWriteTime:yyyy}_Week_{calendar.GetWeekOfYear(fileInfo.LastWriteTime, CalendarWeekRule.FirstDay, DayOfWeek.Sunday):00}";
string checkDirectory = Path.Combine(waferSizeDirectory, "Archive", weekOfYear);
if (!Directory.Exists(checkDirectory))
_ = Directory.CreateDirectory(checkDirectory);
string checkFile = Path.Combine(checkDirectory, fileInfo.Name);
if (!File.Exists(checkFile))
File.Move(fileInfo.FullName, checkFile);
}
internal static void Notify(FileConnectorConfiguration fileConnectorConfiguration, Calendar calendar, DateTime dateTime, string fileName, string fullFileName, string json)
{
List<KeyValuePair<string, ClientWebSocket>> clientWebSockets = new();
lock (_ClientWebSockets)
{
foreach (KeyValuePair<string, ClientWebSocket> keyValuePair in _ClientWebSockets)
clientWebSockets.Add(keyValuePair);
}
if (clientWebSockets.Count > 0)
{
Notify(json, clientWebSockets);
Archive(fileConnectorConfiguration, calendar, dateTime, fileName, fullFileName);
}
}
private static FileInfo[] GetFileInfoCollection(string waferSizeDirectory)
{
List<FileInfo> results = new();
List<string> files = new();
FileInfo[] fileInfoCollection;
DateTime dateTime = DateTime.Now;
long ticks = dateTime.AddSeconds(1).Ticks;
for (int i = 0; i < int.MaxValue; i++)
{
files.AddRange(!Directory.Exists(waferSizeDirectory) ? Array.Empty<string>() : Directory.GetFiles(waferSizeDirectory, "*.wc", SearchOption.TopDirectoryOnly));
if (results.Count > 0 || DateTime.Now.Ticks > ticks)
break;
Thread.Sleep(250);
}
fileInfoCollection = (from l in files select new FileInfo(l)).OrderByDescending(l => l.LastWriteTime).ToArray();
if (fileInfoCollection.Length > 0)
results.Add(fileInfoCollection[0]);
for (int i = 0; i < fileInfoCollection.Length; i++)
MoveFile(waferSizeDirectory, fileInfoCollection[i]);
return fileInfoCollection;
}
private static WaferCounter GetLastQuantityAndSlotMapWithText(string waferSize, string text, FileInfo fileInfo)
{
WaferCounter result;
string[] lines = File.ReadAllLines(fileInfo.FullName);
if (lines.Length <= 1)
throw new Exception("Incomplete file length!");
string[] segments = fileInfo.Name.Split('-');
Record record = GetRecord(lines[0], lines[1]);
string equipmentId = segments.Length < 2 ? fileInfo.Name : segments[1].Split('.')[0];
if (string.IsNullOrEmpty(record.SlotMap) || record.SlotMap.Length != 25)
throw new Exception("Wrong length!");
if (record.Total != record.Check)
throw new Exception("Invalid!");
result = new()
{
DateTime = fileInfo.LastWriteTime,
DateTimeFormatted = fileInfo.LastWriteTime.ToString("yyyy-MM-dd hh:mm tt"),
EquipmentId = $"WC{waferSize}{equipmentId}",
Text = text,
Total = record.Total,
SlotMap = record.SlotMap
};
return result;
}
private static string GetWaferSizeDirectory(string area, string waferSize) =>
Path.Combine(_Directory, area, waferSize);
internal static string GetLastQuantityAndSlotMap(string area, string waferSize)
{
string result;
WaferCounter waferCounter;
string waferSizeDirectory = GetWaferSizeDirectory(area, waferSize);
FileInfo[] fileInfoCollection = GetFileInfoCollection(waferSizeDirectory);
if (fileInfoCollection.Length == 0)
throw new Exception("No files!");
string text = string.Empty;
waferCounter = GetLastQuantityAndSlotMapWithText(waferSize, text, fileInfoCollection[0]);
result = JsonSerializer.Serialize(waferCounter);
return result;
}
}