From 21aaf804ee6c4a6f85ae7e7bfdb2e2c503f65b24 Mon Sep 17 00:00:00 2001 From: Mike Phares Date: Thu, 29 May 2025 14:43:08 -0700 Subject: [PATCH] R29 and R36 --- .../CellInstanceConnectionName.cs | 2 + Adaptation/FileHandlers/R29/FileRead.cs | 238 ++++++++++++++++++ Adaptation/FileHandlers/R36/FileRead.cs | 238 ++++++++++++++++++ DEP08CEPIEPSILON.csproj | 2 + 4 files changed, 480 insertions(+) create mode 100644 Adaptation/FileHandlers/R29/FileRead.cs create mode 100644 Adaptation/FileHandlers/R36/FileRead.cs diff --git a/Adaptation/FileHandlers/CellInstanceConnectionName.cs b/Adaptation/FileHandlers/CellInstanceConnectionName.cs index 1551e83..ab21929 100644 --- a/Adaptation/FileHandlers/CellInstanceConnectionName.cs +++ b/Adaptation/FileHandlers/CellInstanceConnectionName.cs @@ -13,7 +13,9 @@ public class CellInstanceConnectionName { IFileRead result = cellInstanceConnectionName switch { + nameof(R29) => new R29.FileRead(smtp, fileParameter, cellInstanceName, connectionCount, cellInstanceConnectionName, fileConnectorConfiguration, equipmentTypeName, parameterizedModelObjectDefinitionType, modelObjectParameters, equipmentDictionaryName, dummyRuns, staticRuns, useCyclicalForDescription, isEAFHosted: connectionCount is null), nameof(R32) => new R32.FileRead(smtp, fileParameter, cellInstanceName, connectionCount, cellInstanceConnectionName, fileConnectorConfiguration, equipmentTypeName, parameterizedModelObjectDefinitionType, modelObjectParameters, equipmentDictionaryName, dummyRuns, staticRuns, useCyclicalForDescription, isEAFHosted: connectionCount is null), + nameof(R36) => new R36.FileRead(smtp, fileParameter, cellInstanceName, connectionCount, cellInstanceConnectionName, fileConnectorConfiguration, equipmentTypeName, parameterizedModelObjectDefinitionType, modelObjectParameters, equipmentDictionaryName, dummyRuns, staticRuns, useCyclicalForDescription, isEAFHosted: connectionCount is null), nameof(R55) => new R55.FileRead(smtp, fileParameter, cellInstanceName, connectionCount, cellInstanceConnectionName, fileConnectorConfiguration, equipmentTypeName, parameterizedModelObjectDefinitionType, modelObjectParameters, equipmentDictionaryName, dummyRuns, staticRuns, useCyclicalForDescription, isEAFHosted: connectionCount is null), nameof(R57) => new R57.FileRead(smtp, fileParameter, cellInstanceName, connectionCount, cellInstanceConnectionName, fileConnectorConfiguration, equipmentTypeName, parameterizedModelObjectDefinitionType, modelObjectParameters, equipmentDictionaryName, dummyRuns, staticRuns, useCyclicalForDescription, isEAFHosted: connectionCount is null), nameof(R61) => new R61.FileRead(smtp, fileParameter, cellInstanceName, connectionCount, cellInstanceConnectionName, fileConnectorConfiguration, equipmentTypeName, parameterizedModelObjectDefinitionType, modelObjectParameters, equipmentDictionaryName, dummyRuns, staticRuns, useCyclicalForDescription, isEAFHosted: connectionCount is null), diff --git a/Adaptation/FileHandlers/R29/FileRead.cs b/Adaptation/FileHandlers/R29/FileRead.cs new file mode 100644 index 0000000..5e51f74 --- /dev/null +++ b/Adaptation/FileHandlers/R29/FileRead.cs @@ -0,0 +1,238 @@ +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.Collections.ObjectModel; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Text.Json; + +namespace Adaptation.FileHandlers.R29; + +public class FileRead : Shared.FileRead, IFileRead +{ + + private readonly string _KeyColumn; + private readonly string _TimestampFormat; + private readonly ReadOnlyDictionary _SystemStateToNames; + + public FileRead(ISMTP smtp, Dictionary fileParameter, string cellInstanceName, int? connectionCount, string cellInstanceConnectionName, FileConnectorConfiguration fileConnectorConfiguration, string equipmentTypeName, string parameterizedModelObjectDefinitionType, IList modelObjectParameters, string equipmentDictionaryName, Dictionary> dummyRuns, Dictionary> 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); + string[] segments; + Dictionary systemStateToNames = new(); + _KeyColumn = GetPropertyValue(cellInstanceConnectionName, modelObjectParameters, "ProcessDataStandardFormat.KeyColumn"); + _TimestampFormat = GetPropertyValue(cellInstanceConnectionName, modelObjectParameters, "ProcessDataStandardFormat.TimestampFormat"); + ModelObjectParameterDefinition[] systemStates = GetProperties(cellInstanceConnectionName, modelObjectParameters, "ProcessDataStandardFormat.SystemState"); + foreach (ModelObjectParameterDefinition modelObjectParameterDefinition in systemStates) + { + segments = modelObjectParameterDefinition.Value.Split('|'); + if (segments.Length != 2) + continue; + systemStateToNames.Add(segments[0], segments[1]); + } + _SystemStateToNames = new(systemStateToNames); + } + + void IFileRead.Move(Tuple> extractResults, Exception exception) + { + bool isErrorFile = exception is not null; + if (!isErrorFile && !string.IsNullOrEmpty(_Logistics.ReportFullPath)) + { + FileInfo fileInfo = new(_Logistics.ReportFullPath); + if (fileInfo.Exists && fileInfo.LastWriteTime < fileInfo.CreationTime) + File.SetLastWriteTime(_Logistics.ReportFullPath, fileInfo.CreationTime); + } + Move(extractResults); + } + + void IFileRead.WaitForThread() => WaitForThread(thread: null, threadExceptions: null); + + string IFileRead.GetEventDescription() + { + string result = _Description.GetEventDescription(); + return result; + } + + List IFileRead.GetHeaderNames() + { + List results = _Description.GetHeaderNames(); + return results; + } + + string[] IFileRead.Move(Tuple> 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 IFileRead.GetDisplayNamesJsonElement() + { + Dictionary results = _Description.GetDisplayNamesJsonElement(this); + return results; + } + + List IFileRead.GetDescriptions(IFileRead fileRead, List tests, IProcessData processData) + { + List results = _Description.GetDescriptions(fileRead, _Logistics, tests, processData); + return results; + } + + Tuple> IFileRead.GetExtractResult(string reportFullPath, string eventName) + { + Tuple> results; + if (string.IsNullOrEmpty(eventName)) + throw new Exception(); + _ReportFullPath = reportFullPath; + DateTime dateTime = DateTime.Now; + results = GetExtractResult(reportFullPath, dateTime); + if (results.Item3 is null) + results = new Tuple>(results.Item1, Array.Empty(), JsonSerializer.Deserialize("[]"), results.Item4); + if (results.Item3.Length > 0 && _IsEAFHosted) + WritePDSF(this, results.Item3); + UpdateLastTicksDuration(DateTime.Now.Ticks - dateTime.Ticks); + return results; + } + + Tuple> IFileRead.ReExtract() + { + Tuple> results; + List headerNames = _Description.GetHeaderNames(); + Dictionary keyValuePairs = _Description.GetDisplayNamesJsonElement(this); + results = ReExtract(this, headerNames, keyValuePairs); + return results; + } + + private static int? GetKeyColumnIndex(string[] columns, string keyColumn) + { +#nullable enable + int? result = null; + for (int i = 0; i < columns.Length; i++) + { + if (columns[i] != keyColumn) + continue; + result = i; + break; + } + return result; + } + + private ReadOnlyCollection GetSystemStateValues(List lines, string[] columns, int keyColumnIndex) + { + List results = new(); + string[] values; + string? systemState; + string keyColumnValue; + for (int i = 7; i < lines.Count; i++) + { + values = lines[i].Split('\t'); + if (values.Length != columns.Length) + continue; + keyColumnValue = values[keyColumnIndex]; + if (string.IsNullOrEmpty(keyColumnValue)) + continue; + if (!_SystemStateToNames.TryGetValue(keyColumnValue, out systemState)) + continue; + if (results.Contains(systemState)) + continue; + results.Add(systemState); + } + return new(results); + } + + private void MoveFile(string reportFullPath) + { + string equipment; + string timestamp; + string[] columns; + DateTime dateTime; + List lines; + string systemState; + int? keyColumnIndex; + string checkFileName; + List headerLines = new(); + ReadOnlyCollection systemStateValues; + string missingKeyDirectory = Path.Combine(_FileConnectorConfiguration.AlternateTargetFolder, "Missing-Key"); + if (!Directory.Exists(missingKeyDirectory)) + _ = Directory.CreateDirectory(missingKeyDirectory); + string fileName = Path.GetFileName(reportFullPath); + string[] segments = fileName.Split('_'); + for (int z = 0; z < 1; z++) + { + if (segments.Length != 2) + continue; + equipment = segments[0]; + timestamp = segments[1].Split('.')[0]; + if (timestamp.Length != _TimestampFormat.Length) + continue; + headerLines.Clear(); + lines = File.ReadAllLines(reportFullPath).ToList(); + if (lines.Count < 8) + continue; + for (int i = 0; i < 6; i++) + { + headerLines.Add(lines[0]); + lines.RemoveAt(0); + } + if (lines[0].Length < 1 || lines[0][0] != '"' || !lines[0].StartsWith("\"Time\"")) + continue; + columns = lines[0].Split('\t'); + if (columns.Length < 3) + continue; + keyColumnIndex = GetKeyColumnIndex(columns, _KeyColumn); + if (keyColumnIndex is null) + { + File.Move(reportFullPath, Path.Combine(_FileConnectorConfiguration.AlternateTargetFolder, missingKeyDirectory, fileName)); + continue; + } + systemStateValues = GetSystemStateValues(lines, columns, keyColumnIndex.Value); + if (systemStateValues.Count == 0) + { + File.Move(reportFullPath, Path.Combine(_FileConnectorConfiguration.AlternateTargetFolder, missingKeyDirectory, fileName)); + continue; + } + lines.AddRange(headerLines); + systemState = string.Join("-", systemStateValues); + checkFileName = Path.Combine(_FileConnectorConfiguration.AlternateTargetFolder, $"{equipment}-{timestamp}-{systemState}.pdsf"); + File.WriteAllLines(checkFileName, lines); + // File.Delete(reportFullPath); + if (DateTime.TryParseExact(timestamp, _TimestampFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out dateTime)) + File.SetLastWriteTime(checkFileName, dateTime); + } + } + + private Tuple> GetExtractResult(string reportFullPath, DateTime _) + { + Tuple> results; + ProcessDataStandardFormat processDataStandardFormat = ProcessDataStandardFormat.GetProcessDataStandardFormat(reportFullPath); + _Logistics = new Logistics(reportFullPath, processDataStandardFormat); + SetFileParameterLotIDToLogisticsMID(); + JsonElement[] jsonElements = ProcessDataStandardFormat.GetArray(processDataStandardFormat); + List descriptions = GetDuplicatorDescriptions(jsonElements); + Test[] tests = (from l in descriptions select (Test)l.Test).ToArray(); + if (_IsEAFHosted && _FileConnectorConfiguration.FileScanningIntervalInSeconds > 0) + MoveFile(reportFullPath); + results = new Tuple>(string.Join(Environment.NewLine, processDataStandardFormat.Logistics[0]), tests, jsonElements, new List()); + return results; + } + +} \ No newline at end of file diff --git a/Adaptation/FileHandlers/R36/FileRead.cs b/Adaptation/FileHandlers/R36/FileRead.cs new file mode 100644 index 0000000..a5b7b53 --- /dev/null +++ b/Adaptation/FileHandlers/R36/FileRead.cs @@ -0,0 +1,238 @@ +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.Collections.ObjectModel; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Text.Json; + +namespace Adaptation.FileHandlers.R36; + +public class FileRead : Shared.FileRead, IFileRead +{ + + private readonly string _KeyColumn; + private readonly string _TimestampFormat; + private readonly ReadOnlyDictionary _SystemStateToNames; + + public FileRead(ISMTP smtp, Dictionary fileParameter, string cellInstanceName, int? connectionCount, string cellInstanceConnectionName, FileConnectorConfiguration fileConnectorConfiguration, string equipmentTypeName, string parameterizedModelObjectDefinitionType, IList modelObjectParameters, string equipmentDictionaryName, Dictionary> dummyRuns, Dictionary> 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); + string[] segments; + Dictionary systemStateToNames = new(); + _KeyColumn = GetPropertyValue(cellInstanceConnectionName, modelObjectParameters, "ProcessDataStandardFormat.KeyColumn"); + _TimestampFormat = GetPropertyValue(cellInstanceConnectionName, modelObjectParameters, "ProcessDataStandardFormat.TimestampFormat"); + ModelObjectParameterDefinition[] systemStates = GetProperties(cellInstanceConnectionName, modelObjectParameters, "ProcessDataStandardFormat.SystemState"); + foreach (ModelObjectParameterDefinition modelObjectParameterDefinition in systemStates) + { + segments = modelObjectParameterDefinition.Value.Split('|'); + if (segments.Length != 2) + continue; + systemStateToNames.Add(segments[0], segments[1]); + } + _SystemStateToNames = new(systemStateToNames); + } + + void IFileRead.Move(Tuple> extractResults, Exception exception) + { + bool isErrorFile = exception is not null; + if (!isErrorFile && !string.IsNullOrEmpty(_Logistics.ReportFullPath)) + { + FileInfo fileInfo = new(_Logistics.ReportFullPath); + if (fileInfo.Exists && fileInfo.LastWriteTime < fileInfo.CreationTime) + File.SetLastWriteTime(_Logistics.ReportFullPath, fileInfo.CreationTime); + } + Move(extractResults); + } + + void IFileRead.WaitForThread() => WaitForThread(thread: null, threadExceptions: null); + + string IFileRead.GetEventDescription() + { + string result = _Description.GetEventDescription(); + return result; + } + + List IFileRead.GetHeaderNames() + { + List results = _Description.GetHeaderNames(); + return results; + } + + string[] IFileRead.Move(Tuple> 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 IFileRead.GetDisplayNamesJsonElement() + { + Dictionary results = _Description.GetDisplayNamesJsonElement(this); + return results; + } + + List IFileRead.GetDescriptions(IFileRead fileRead, List tests, IProcessData processData) + { + List results = _Description.GetDescriptions(fileRead, _Logistics, tests, processData); + return results; + } + + Tuple> IFileRead.GetExtractResult(string reportFullPath, string eventName) + { + Tuple> results; + if (string.IsNullOrEmpty(eventName)) + throw new Exception(); + _ReportFullPath = reportFullPath; + DateTime dateTime = DateTime.Now; + results = GetExtractResult(reportFullPath, dateTime); + if (results.Item3 is null) + results = new Tuple>(results.Item1, Array.Empty(), JsonSerializer.Deserialize("[]"), results.Item4); + if (results.Item3.Length > 0 && _IsEAFHosted) + WritePDSF(this, results.Item3); + UpdateLastTicksDuration(DateTime.Now.Ticks - dateTime.Ticks); + return results; + } + + Tuple> IFileRead.ReExtract() + { + Tuple> results; + List headerNames = _Description.GetHeaderNames(); + Dictionary keyValuePairs = _Description.GetDisplayNamesJsonElement(this); + results = ReExtract(this, headerNames, keyValuePairs); + return results; + } + + private static int? GetKeyColumnIndex(string[] columns, string keyColumn) + { +#nullable enable + int? result = null; + for (int i = 0; i < columns.Length; i++) + { + if (columns[i] != keyColumn) + continue; + result = i; + break; + } + return result; + } + + private ReadOnlyCollection GetSystemStateValues(List lines, string[] columns, int keyColumnIndex) + { + List results = new(); + string[] values; + string? systemState; + string keyColumnValue; + for (int i = 7; i < lines.Count; i++) + { + values = lines[i].Split('\t'); + if (values.Length != columns.Length) + continue; + keyColumnValue = values[keyColumnIndex]; + if (string.IsNullOrEmpty(keyColumnValue)) + continue; + if (!_SystemStateToNames.TryGetValue(keyColumnValue, out systemState)) + continue; + if (results.Contains(systemState)) + continue; + results.Add(systemState); + } + return new(results); + } + + private void MoveFile(string reportFullPath) + { + string equipment; + string timestamp; + string[] columns; + DateTime dateTime; + List lines; + string systemState; + int? keyColumnIndex; + string checkFileName; + List headerLines = new(); + ReadOnlyCollection systemStateValues; + string missingKeyDirectory = Path.Combine(_FileConnectorConfiguration.AlternateTargetFolder, "Missing-Key"); + if (!Directory.Exists(missingKeyDirectory)) + _ = Directory.CreateDirectory(missingKeyDirectory); + string fileName = Path.GetFileName(reportFullPath); + string[] segments = fileName.Split('_'); + for (int z = 0; z < 1; z++) + { + if (segments.Length != 2) + continue; + equipment = segments[0]; + timestamp = segments[1].Split('.')[0]; + if (timestamp.Length != _TimestampFormat.Length) + continue; + headerLines.Clear(); + lines = File.ReadAllLines(reportFullPath).ToList(); + if (lines.Count < 8) + continue; + for (int i = 0; i < 6; i++) + { + headerLines.Add(lines[0]); + lines.RemoveAt(0); + } + if (lines[0].Length < 1 || lines[0][0] != '"' || !lines[0].StartsWith("\"Time\"")) + continue; + columns = lines[0].Split('\t'); + if (columns.Length < 3) + continue; + keyColumnIndex = GetKeyColumnIndex(columns, _KeyColumn); + if (keyColumnIndex is null) + { + File.Move(reportFullPath, Path.Combine(_FileConnectorConfiguration.AlternateTargetFolder, missingKeyDirectory, fileName)); + continue; + } + systemStateValues = GetSystemStateValues(lines, columns, keyColumnIndex.Value); + if (systemStateValues.Count == 0) + { + File.Move(reportFullPath, Path.Combine(_FileConnectorConfiguration.AlternateTargetFolder, missingKeyDirectory, fileName)); + continue; + } + lines.AddRange(headerLines); + systemState = string.Join("-", systemStateValues); + checkFileName = Path.Combine(_FileConnectorConfiguration.AlternateTargetFolder, $"{equipment}-{timestamp}-{systemState}.pdsf"); + File.WriteAllLines(checkFileName, lines); + // File.Delete(reportFullPath); + if (DateTime.TryParseExact(timestamp, _TimestampFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out dateTime)) + File.SetLastWriteTime(checkFileName, dateTime); + } + } + + private Tuple> GetExtractResult(string reportFullPath, DateTime _) + { + Tuple> results; + ProcessDataStandardFormat processDataStandardFormat = ProcessDataStandardFormat.GetProcessDataStandardFormat(reportFullPath); + _Logistics = new Logistics(reportFullPath, processDataStandardFormat); + SetFileParameterLotIDToLogisticsMID(); + JsonElement[] jsonElements = ProcessDataStandardFormat.GetArray(processDataStandardFormat); + List descriptions = GetDuplicatorDescriptions(jsonElements); + Test[] tests = (from l in descriptions select (Test)l.Test).ToArray(); + if (_IsEAFHosted && _FileConnectorConfiguration.FileScanningIntervalInSeconds > 0) + MoveFile(reportFullPath); + results = new Tuple>(string.Join(Environment.NewLine, processDataStandardFormat.Logistics[0]), tests, jsonElements, new List()); + return results; + } + +} \ No newline at end of file diff --git a/DEP08CEPIEPSILON.csproj b/DEP08CEPIEPSILON.csproj index ede87d7..efdcd4e 100644 --- a/DEP08CEPIEPSILON.csproj +++ b/DEP08CEPIEPSILON.csproj @@ -105,7 +105,9 @@ + +