10 Commits

Author SHA1 Message Date
5c50078c04 Added Work Order and change to left join 2022-10-10 11:49:40 -07:00
5f7450e442 Minor changes for Max RDS 2022-10-07 12:45:58 -07:00
617a4989e2 Ready to test Max RDS 2022-10-03 11:08:24 -07:00
466057022d Ready to test Steps 2022-08-31 09:28:05 -07:00
1e834360ae sjc => auc and switch to code
over reference for MonIn
2022-08-25 10:57:43 -07:00
f36ad1ae5e Add MonIn Send Status 2022-08-24 12:06:41 -07:00
672b439864 Added** extra Route 2022-08-10 10:59:11 -07:00
f9db1ab67c Added* extra Route 2022-08-10 10:48:15 -07:00
be895557d5 Updated readme with Pipeline links 2022-08-10 10:43:18 -07:00
61692f2c48 Added UseFileServer
Removed webApplicationOptions
Added extra Route
2022-08-10 10:38:30 -07:00
49 changed files with 7165 additions and 457 deletions

5162
.Data/RdsMaxRepo.json Normal file

File diff suppressed because it is too large Load Diff

View File

@ -80,9 +80,11 @@ dotnet_diagnostic.CA1825.severity = warning # CA1823: Avoid zero-length array al
dotnet_diagnostic.CA1829.severity = warning # CA1829: Use Length/Count property instead of Count() when available
dotnet_diagnostic.CA1834.severity = warning # CA1834: Consider using 'StringBuilder.Append(char)' when applicable
dotnet_diagnostic.IDE0001.severity = warning # IDE0001: Simplify name
dotnet_diagnostic.IDE0004.severity = warning # IDE0004: Cast is redundant.
dotnet_diagnostic.IDE0002.severity = warning # Simplify (member access) - System.Version.Equals("1", "2"); Version.Equals("1", "2");
dotnet_diagnostic.IDE0005.severity = warning # Using directive is unnecessary
dotnet_diagnostic.IDE0047.severity = warning # IDE0047: Parentheses can be removed
dotnet_diagnostic.IDE0049.severity = warning # Use language keywords instead of framework type names for type references (IDE0049)
dotnet_diagnostic.IDE0060.severity = warning # IDE0060: Remove unused parameter
dotnet_naming_rule.abstract_method_should_be_pascal_case.severity = warning
dotnet_naming_rule.abstract_method_should_be_pascal_case.style = pascal_case
@ -215,7 +217,7 @@ dotnet_style_parentheses_in_other_binary_operators = always_for_clarity
dotnet_style_parentheses_in_other_operators = never_if_unnecessary
dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity
dotnet_style_predefined_type_for_locals_parameters_members = true
dotnet_style_predefined_type_for_member_access = true
dotnet_style_predefined_type_for_member_access = true:warning
dotnet_style_prefer_auto_properties = true:warning
dotnet_style_prefer_compound_assignment = true:warning
dotnet_style_prefer_conditional_expression_over_assignment = false

View File

@ -2,5 +2,6 @@
"cSpell.enabled": false,
"files.exclude": {
"**/.git": false
}
},
"coverage-gutters.coverageBaseDir": "../.vscode/TestResults/*"
}

View File

@ -57,4 +57,12 @@
<ItemGroup>
<None Include="compilerconfig.json" />
</ItemGroup>
<ItemGroup>
<None Include="appsettings.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Include="appsettings.Development.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>

View File

@ -1,4 +1,5 @@
using Microsoft.AspNetCore.Mvc;
using Infineon.Monitoring.MonA;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Logging;
using OI.Metrology.Archive.Models;
@ -17,11 +18,13 @@ public class ExportController : Controller
private readonly ILogger _Logger;
private readonly bool _IsTestDatabase;
private readonly IMetrologyRepo _Repo;
private readonly AppSettings _AppSettings;
public ExportController(AppSettings appSettings, ILogger<ExportController> logger, IMetrologyRepo repo)
{
_Repo = repo;
_Logger = logger;
_AppSettings = appSettings;
_IsTestDatabase = appSettings.ConnectionString.Contains("test", StringComparison.InvariantCultureIgnoreCase);
}
@ -41,6 +44,8 @@ public class ExportController : Controller
StartTime = DateTime.Now.AddMonths(-1),
EndTime = DateTime.Now
};
MonIn monIn = MonIn.GetInstance();
_ = monIn.SendStatus(_AppSettings.MonASite, _AppSettings.MonAResource, "Heartbeat", State.Up);
return View(model);
}
@ -77,6 +82,8 @@ public class ExportController : Controller
ModelState.AddModelError("Exception", ex.Message);
string errorMessage = $"Error exporting: {ex}";
_Logger.LogError(message: errorMessage);
MonIn monIn = MonIn.GetInstance();
_ = monIn.SendStatus(_AppSettings.MonASite, _AppSettings.MonAResource, "Heartbeat", State.Warning);
}
}
return View("Index", model);

View File

@ -4,17 +4,21 @@ using OI.Metrology.Archive.Models;
using OI.Metrology.Shared.Repositories;
using OI.Metrology.Shared.ViewModels;
using System;
using System.Collections.Generic;
using IO = System.IO;
namespace OI.Metrology.Archive.Controllers;
public class PagesController : Controller
{
private readonly IMetrologyRepo _Repo;
private readonly bool _IsTestDatabase;
private readonly IRdsMaxRepo _RdsMaxRepo;
private readonly IMetrologyRepo _MetrologyRepo;
public PagesController(AppSettings appSettings, IMetrologyRepo repo)
public PagesController(AppSettings appSettings, IMetrologyRepo metrologyRepo, IRdsMaxRepo rdsMaxRepo)
{
_Repo = repo;
_RdsMaxRepo = rdsMaxRepo;
_MetrologyRepo = metrologyRepo;
_IsTestDatabase = appSettings.ConnectionString.Contains("test", StringComparison.InvariantCultureIgnoreCase);
}
@ -31,10 +35,13 @@ public class PagesController : Controller
[HttpGet]
[Route("/AwaitingDispo")]
public IActionResult AwaitingDispo() => View();
[Route("/Metrology/AwaitingDispo")]
public IActionResult AwaitingDispo() =>
View();
[HttpGet]
[Route("/RunInfo")]
[Route("/Metrology/RunInfo")]
public IActionResult RunInfo([FromQuery] int tooltypeid = 1, [FromQuery] int headerid = 0)
{
RunInfo m = new()
@ -45,16 +52,74 @@ public class PagesController : Controller
};
if (headerid > 0)
{
m.HeaderAttachmentID = _Repo.GetHeaderAttachmentID(tooltypeid, headerid);
m.HeaderAttachmentID = _MetrologyRepo.GetHeaderAttachmentID(tooltypeid, headerid);
}
return View(m);
}
[HttpGet]
[Route("/RunHeaders")]
public IActionResult RunHeaders() => View();
[Route("/Metrology/RunHeaders")]
public IActionResult RunHeaders() =>
View();
[HttpGet]
[Route("/Crash")]
public IActionResult Crash() => throw new Exception("Test unhandled exception");
public IActionResult Crash() =>
throw new Exception("Test unhandled exception");
[HttpGet]
[Route("/Step1")]
[Route("/Metrology/Step1")]
public IActionResult Step1(string mod = "", string equipment = "", string layer = "", string zone = "", string rds = "", string initials = "")
{
string directory = "D:/Tmp/Metrology";
if (!IO.Directory.Exists(directory))
_ = IO.Directory.CreateDirectory(directory);
string[] model = new string[] { mod, equipment, layer, zone, rds, initials };
if (!string.IsNullOrEmpty(initials))
IO.File.WriteAllLines(IO.Path.Combine(directory, $"{DateTime.Now.Ticks}-{initials}.rsv"), model);
return View(model);
}
[HttpGet]
[Route("/Step2")]
[Route("/Metrology/Step2")]
public IActionResult Step2(string mod) =>
View(new string[] { mod });
[HttpGet]
[Route("/Step3")]
[Route("/Metrology/Step3")]
public IActionResult Step3(string mod, string equipment) =>
View(new string[] { mod, equipment });
[HttpGet]
[Route("/Step4")]
[Route("/Metrology/Step4")]
public IActionResult Step4(string mod, string equipment, string layer) =>
View(new string[] { mod, equipment, layer });
[HttpGet]
[Route("/Step5")]
[Route("/Metrology/Step5")]
public IActionResult Step5(string mod, string equipment, string layer, string zone) =>
View(new string[] { mod, equipment, layer, zone });
[HttpGet]
[Route("/Step6")]
[Route("/Metrology/Step6")]
public IActionResult Step6(string mod, string equipment, string layer, string zone, string rds) =>
View(new string[] { mod, equipment, layer, zone, rds });
[HttpGet]
[Route("/RdsMax")]
[Route("/Metrology/RdsMax")]
public IActionResult RdsMax()
{
Shared.DataModels.RDS.Max[] collection = _RdsMaxRepo.GetMaxRDS();
List<string[]> results = _RdsMaxRepo.Convert(collection);
return View(results);
}
}

View File

@ -6,49 +6,54 @@ namespace OI.Metrology.Archive.Models;
public class AppSettings
{
protected string _ApiLoggingContentTypes;
protected string _ApiLoggingPathPrefixes;
protected string _ApiLogPath;
protected string _AttachmentPath;
protected string _BuildNumber;
protected string _Company;
protected string _ConnectionString;
protected string _GitCommitSeven;
protected string _InboundApiAllowedIPList;
protected string _MonARessource;
protected string _OIExportPath;
protected string _URLs;
protected string _WorkingDirectoryName;
public string ApiLoggingContentTypes => _ApiLoggingContentTypes;
public string ApiLoggingPathPrefixes => _ApiLoggingPathPrefixes;
public string ApiLogPath => _ApiLogPath;
public string AttachmentPath => _AttachmentPath;
public string BuildNumber => _BuildNumber;
public string Company => _Company;
public string ConnectionString => _ConnectionString;
public string GitCommitSeven => _GitCommitSeven;
public string InboundApiAllowedIPList => _InboundApiAllowedIPList;
public string MonARessource => _MonARessource;
public string OIExportPath => _OIExportPath;
public string URLs => _URLs;
public string WorkingDirectoryName => _WorkingDirectoryName;
public string ApiLoggingContentTypes { init; get; }
public string ApiLoggingPathPrefixes { init; get; }
public string ApiLogPath { init; get; }
public string AttachmentPath { init; get; }
public string BuildNumber { init; get; }
public string Company { init; get; }
public string ConnectionString { init; get; }
public string GitCommitSeven { init; get; }
public string InboundApiAllowedIPList { init; get; }
public string MonAResource { init; get; }
public string MonASite { init; get; }
public string OIExportPath { init; get; }
public string Oi2SqlConnectionString { init; get; }
public string URLs { init; get; }
public string WorkingDirectoryName { init; get; }
[JsonConstructor]
public AppSettings(string apiLoggingContentTypes, string apiLoggingPathPrefixes, string apiLogPath, string attachmentPath, string buildNumber, string company, string connectionString, string gitCommitSeven, string inboundApiAllowedIPList, string monARessource, string oiExportPath, string urls, string workingDirectoryName)
public AppSettings(string apiLoggingContentTypes,
string apiLoggingPathPrefixes,
string apiLogPath,
string attachmentPath,
string buildNumber,
string company,
string connectionString,
string gitCommitSeven,
string inboundApiAllowedIPList,
string monAResource,
string monASite,
string oi2SqlConnectionString,
string oiExportPath,
string urls,
string workingDirectoryName)
{
_ApiLoggingContentTypes = apiLoggingContentTypes;
_ApiLoggingPathPrefixes = apiLoggingPathPrefixes;
_ApiLogPath = apiLogPath;
_AttachmentPath = attachmentPath;
_BuildNumber = buildNumber;
_Company = company;
_ConnectionString = connectionString;
_GitCommitSeven = gitCommitSeven;
_InboundApiAllowedIPList = inboundApiAllowedIPList;
_MonARessource = monARessource;
_OIExportPath = oiExportPath;
_URLs = urls;
_WorkingDirectoryName = workingDirectoryName;
ApiLoggingContentTypes = apiLoggingContentTypes;
ApiLoggingPathPrefixes = apiLoggingPathPrefixes;
ApiLogPath = apiLogPath;
AttachmentPath = attachmentPath;
BuildNumber = buildNumber;
Company = company;
ConnectionString = connectionString;
GitCommitSeven = gitCommitSeven;
InboundApiAllowedIPList = inboundApiAllowedIPList;
MonAResource = monAResource;
MonASite = monASite;
Oi2SqlConnectionString = oi2SqlConnectionString;
OIExportPath = oiExportPath;
URLs = urls;
WorkingDirectoryName = workingDirectoryName;
}
public override string ToString()

View File

@ -1,3 +1,4 @@
using Microsoft.Extensions.Configuration;
using System.ComponentModel.DataAnnotations;
using System.Text.Json;
@ -6,6 +7,8 @@ namespace OI.Metrology.Archive.Models.Binder;
public class AppSettings
{
#nullable disable
[Display(Name = "Api Logging Content Types"), Required] public string ApiLoggingContentTypes { get; set; }
[Display(Name = "Api Logging Path Prefixes"), Required] public string ApiLoggingPathPrefixes { get; set; }
[Display(Name = "Api Log Path"), Required] public string ApiLogPath { get; set; }
@ -15,27 +18,14 @@ public class AppSettings
[Display(Name = "Connection String"), Required] public string ConnectionString { get; set; }
[Display(Name = "Git Commit Seven"), Required] public string GitCommitSeven { get; set; }
[Display(Name = "Inbound Api Allowed IP List"), Required] public string InboundApiAllowedIPList { get; set; }
[Display(Name = "MonA Ressource"), Required] public string MonARessource { get; set; }
[Display(Name = "MonA Resource"), Required] public string MonAResource { get; set; }
[Display(Name = "MonA Site"), Required] public string MonASite { get; set; }
[Display(Name = "Oi 2 Sql Connection String"), Required] public string Oi2SqlConnectionString { get; set; }
[Display(Name = "OI Export Path"), Required] public string OIExportPath { get; set; }
[Display(Name = "URLs"), Required] public string URLs { get; set; }
[Display(Name = "Working Directory Name"), Required] public string WorkingDirectoryName { get; set; }
public AppSettings()
{
ApiLoggingContentTypes = string.Empty;
ApiLoggingPathPrefixes = string.Empty;
ApiLogPath = string.Empty;
AttachmentPath = string.Empty;
BuildNumber = string.Empty;
Company = string.Empty;
ConnectionString = string.Empty;
GitCommitSeven = string.Empty;
InboundApiAllowedIPList = string.Empty;
MonARessource = string.Empty;
OIExportPath = string.Empty;
URLs = string.Empty;
WorkingDirectoryName = string.Empty;
}
#nullable restore
public override string ToString()
{
@ -43,4 +33,34 @@ public class AppSettings
return result;
}
private static Models.AppSettings Get(AppSettings appSettings)
{
Models.AppSettings result;
result = new(
appSettings.ApiLoggingContentTypes,
appSettings.ApiLoggingPathPrefixes,
appSettings.ApiLogPath,
appSettings.AttachmentPath,
appSettings.BuildNumber,
appSettings.Company,
appSettings.ConnectionString,
appSettings.GitCommitSeven,
appSettings.InboundApiAllowedIPList,
appSettings.MonAResource,
appSettings.MonASite,
appSettings.Oi2SqlConnectionString,
appSettings.OIExportPath,
appSettings.URLs,
appSettings.WorkingDirectoryName);
return result;
}
public static Models.AppSettings Get(IConfigurationRoot configurationRoot)
{
Models.AppSettings result;
AppSettings appSettings = configurationRoot.Get<AppSettings>();
result = Get(appSettings);
return result;
}
}

View File

@ -0,0 +1,30 @@
namespace OI.Metrology.Archive.Models.Binder;
public class Max
{
#pragma warning disable
public string reactor_type { get; set; }
public int reactor { get; set; }
public string ls_id { get; set; }
public string zone { get; set; }
public string load_lock_side { get; set; }
public int rds_no { get; set; }
public string ps_no { get; set; }
public string recipe_name { get; set; }
public int recipe_no { get; set; }
public string spec_type { get; set; }
public string spec_thick_mtool { get; set; }
public string spec_thick_mrecipe { get; set; }
public string spec_res_mtool { get; set; }
public string spec_res_mrecipe { get; set; }
public string spec_cres_mtool { get; set; }
public string spec_cres_mrecipe { get; set; }
public int ci_no { get; set; }
public int? mv_no { get; set; }
public string scan_tool { get; set; }
public string spec_surfscan_recipe { get; set; }
public int? spec_ss_samp_qty { get; set; }
}

View File

@ -1,44 +0,0 @@
using Microsoft.Extensions.Configuration;
using System;
using System.Linq;
using System.Text.Json;
namespace OI.Metrology.Archive.Models.Stateless;
public abstract class AppSettings
{
#nullable enable
public static Models.AppSettings Get(IConfigurationRoot configurationRoot)
{
Models.AppSettings? result;
Binder.AppSettings appSettings = configurationRoot.Get<Binder.AppSettings>();
string json = JsonSerializer.Serialize(appSettings, new JsonSerializerOptions() { WriteIndented = true });
result = JsonSerializer.Deserialize<Models.AppSettings>(json);
if (result is null)
throw new Exception(json);
if (string.IsNullOrEmpty(result.Company))
throw new Exception(json);
string jsonThis = result.ToString();
if (jsonThis != json)
{
int? check = null;
int min = new int[] { json.Length, jsonThis.Length }.Min();
for (int i = 0; i < min; i++)
{
if (json[i] == jsonThis[i])
continue;
check = i;
break;
}
if (check is null)
throw new Exception();
string a = json[..check.Value].Split(',')[^1];
string b = json[check.Value..].Split(',')[0];
throw new Exception($"{a}{b}");
}
return result;
}
}

View File

@ -47,10 +47,10 @@ public class Program
public static int Main(string[] args)
{
LoggerConfiguration loggerConfiguration = new();
(string assemblyName, WebApplicationOptions webApplicationOptions) = Get(args);
WebApplicationBuilder webApplicationBuilder = WebApplication.CreateBuilder(webApplicationOptions);
(string assemblyName, WebApplicationOptions _) = Get(args);
WebApplicationBuilder webApplicationBuilder = WebApplication.CreateBuilder(args);
_ = webApplicationBuilder.Configuration.AddUserSecrets<Program>();
AppSettings appSettings = Models.Stateless.AppSettings.Get(webApplicationBuilder.Configuration);
AppSettings appSettings = Models.Binder.AppSettings.Get(webApplicationBuilder.Configuration);
if (string.IsNullOrEmpty(appSettings.WorkingDirectoryName))
throw new Exception("Working directory name must have a value!");
string workingDirectory = IWorkingDirectory.GetWorkingDirectory(assemblyName, appSettings.WorkingDirectoryName);
@ -70,6 +70,7 @@ public class Program
_ = webApplicationBuilder.Services.AddScoped<IAttachmentsService, AttachmentsService>();
_ = webApplicationBuilder.Services.AddScoped<IInboundDataService, InboundDataService>();
_ = webApplicationBuilder.Services.AddScoped<IMetrologyRepo, MetrologyRepo>();
_ = webApplicationBuilder.Services.AddScoped<IRdsMaxRepo, RdsMaxRepo>();
_ = webApplicationBuilder.Services.AddSingleton<IDbConnectionFactory, SQLDbConnectionFactory>();
_ = webApplicationBuilder.Services.AddSwaggerGen();
_ = webApplicationBuilder.Services.AddSession(sessionOptions =>
@ -107,6 +108,7 @@ public class Program
_ = webApplication.Lifetime.ApplicationStopped.Register(Log.CloseAndFlush);
_ = ApplicationBuilderSerilogClientExtensions.UseSerilogIngestion(webApplication);
_ = SerilogApplicationBuilderExtensions.UseSerilogRequestLogging(webApplication);
_ = webApplication.UseFileServer(enableDirectoryBrowsing: true);
_ = webApplication.UseStaticFiles();
_ = webApplication.UseSession();
_ = webApplication.UseHttpsRedirection();

View File

@ -25,7 +25,8 @@ public class MetrologyRepo : IMetrologyRepo
private DbConnection GetDbConnection() => _DBConnectionFactory.GetDbConnection();
protected DbProviderFactory GetDbProviderFactory(IDbConnection conn) => DbProviderFactories.GetFactory(conn.GetType().Namespace);
protected DbProviderFactory GetDbProviderFactory(IDbConnection conn) =>
DbProviderFactories.GetFactory(conn.GetType().Namespace);
public bool IsTestDatabase()
{

View File

@ -0,0 +1,294 @@
using Microsoft.Extensions.Caching.Memory;
using OI.Metrology.Shared.DataModels.RDS;
using OI.Metrology.Shared.Repositories;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
namespace OI.Metrology.Archive.Repositories;
public class RdsMaxRepo : IRdsMaxRepo
{
private readonly IMemoryCache _MemoryCache;
private readonly Models.AppSettings _AppSettings;
public RdsMaxRepo(Models.AppSettings appSettings, IMemoryCache memoryCache)
{
_MemoryCache = memoryCache;
_AppSettings = appSettings;
}
public RdsMaxRepo(string json, IMemoryCache memoryCache)
{
_MemoryCache = memoryCache;
Models.AppSettings appSettings = System.Text.Json.JsonSerializer.Deserialize<Models.AppSettings>(json);
_AppSettings = appSettings;
}
protected void CacheItem(string key, object v)
{
System.Diagnostics.Debug.WriteLine("CacheItem: " + key);
_ = _MemoryCache.Set(key, v, new MemoryCacheEntryOptions().SetSlidingExpiration(TimeSpan.FromMinutes(1)));
}
private static string GetMaxRdsSql()
{
StringBuilder result = new();
_ = result.Append(" select ").
Append(" rt.reactor_type ").
Append(" , rr.reactor ").
Append(" , rt.ls_id ").
Append(" , rt.zone ").
Append(" , rr.load_lock_side ").
Append(" , rr.rds_no ").
Append(" , rr.wo_no ").
Append(" , rr.ps_no ").
Append(" , rr.recipe_name ").
Append(" , rr.recipe_no ").
Append(" , rr.spec_type ").
Append(" , rt.spec_thick_mtool ").
Append(" , rt.spec_thick_mrecipe ").
Append(" , rt.spec_res_mtool ").
Append(" , rt.spec_res_mrecipe ").
Append(" , rt.spec_cres_mtool ").
Append(" , rt.spec_cres_mrecipe ").
Append(" , ci.ci_no ").
Append(" , cr.mv_no ").
Append(" , cr.scan_tool ").
Append(" , cr.spec_surfscan_recipe ").
Append(" , cr.spec_ss_samp_qty ").
Append(" from ( ").
Append(" select rds_no ").
Append(" from lsl2sql.dbo.react_run qa ").
Append(" inner join ( ").
Append(" select max(qb.rds_no) max_rds_no, qb.reactor ").
Append(" from lsl2sql.dbo.react_run qb ").
Append(" where qb.load_sig != '' ").
Append(" and qb.load_sig_dtm > @load_sig_dtm ").
Append(" group by qb.reactor ").
Append(" ) qb ").
Append(" on qa.rds_no = qb.max_rds_no ").
Append(" ) as qc ").
Append(" inner join lsl2sql.dbo.react_run rr ").
Append(" on qc.rds_no = rr.rds_no ").
Append(" left join [lsl2sql].[dbo].[rds_test] rt ").
Append(" on rr.rds_no = rt.rds_no ").
Append(" and rr.ps_no = rt.ps_no ").
Append(" left join [lsl2sql].[dbo].[clean_insp] ci ").
Append(" on rr.rds_no = ci.rds_no ").
Append(" and ci.stage = 'LWI' ").
Append(" left join [lsl2sql].[dbo].[clean_insp_scan_results] cr ").
Append(" on ci.ci_no = cr.ci_no ").
Append(" order by ").
Append(" rr.reactor ").
Append(" , rt.ls_id ").
Append(" , rt.zone ").
Append(" for json path ");
return result.ToString();
}
private string GetMaxRDSJson(string commandText)
{
StringBuilder result = new();
try
{
using DbConnection dbConnection = SqlClientFactory.Instance.CreateConnection();
dbConnection.ConnectionString = _AppSettings.Oi2SqlConnectionString;
dbConnection.Open();
using DbCommand dbCommand = dbConnection.CreateCommand();
dbCommand.CommandText = commandText;
using DbDataReader reader = dbCommand.ExecuteReader(CommandBehavior.SequentialAccess);
while (reader.Read())
_ = result.Append(reader.GetString(0));
dbConnection.Close();
}
catch (Exception)
{ }
return result.ToString();
}
public Max[] GetMaxRDS()
{
Max[] cached;
string cacheKey = "GetMaxRDS";
if (_MemoryCache.TryGetValue(cacheKey, out cached))
return cached;
string loadSigDTM = DateTime.Now.AddDays(-90).ToString("yyyy-MM-dd 00:00:00.000");
string sql = GetMaxRdsSql();
string commandText = sql.Replace("@load_sig_dtm", $"'{loadSigDTM}'");
string json = GetMaxRDSJson(commandText);
Max[] r = System.Text.Json.JsonSerializer.Deserialize<Max[]>(json);
CacheItem(cacheKey, r);
return r;
}
private static Dictionary<int, List<Max>> GetReactorToRecords(Max[] collection)
{
Dictionary<int, List<Max>> results = new();
foreach (Max max in collection)
{
if (!results.ContainsKey(max.Reactor))
results.Add(max.Reactor, new());
results[max.Reactor].Add(max);
}
return results;
}
private static (string[], int[], int[], int[]) GetDistinct(Max[] collection)
{
List<string> layerCollection = new();
List<int> comboCollection = new();
List<int> zoneCollection = new();
List<int> cleanCollection = new();
foreach (Max max in collection)
{
if (!string.IsNullOrEmpty(max.LsId) && max.LsId[0] == 'L' && !layerCollection.Contains(max.LsId))
layerCollection.Add(max.LsId);
if (!string.IsNullOrEmpty(max.LsId) && max.LsId[0] != 'L' && int.TryParse(max.LsId, out int comboCheck) && !comboCollection.Contains(comboCheck))
comboCollection.Add(comboCheck);
if (!string.IsNullOrEmpty(max.Zone) && int.TryParse(max.Zone, out int zoneCheck) && !zoneCollection.Contains(zoneCheck))
zoneCollection.Add(zoneCheck);
if (max.MvNo.HasValue && !cleanCollection.Contains(max.MvNo.Value))
cleanCollection.Add(max.MvNo.Value);
}
return new(layerCollection.OrderBy(l => l).ToArray(), comboCollection.OrderBy(l => l).ToArray(), zoneCollection.OrderBy(l => l).ToArray(), cleanCollection.OrderBy(l => l).ToArray());
}
private static Max[] GetLayerZoneCollection(Dictionary<string, List<(string, Max)>> layerZoneToCollection)
{
Max[] results;
List<(string Sort, Max Max)> collection = new();
foreach (KeyValuePair<string, List<(string, Max)>> keyValuePair in layerZoneToCollection)
collection.AddRange(keyValuePair.Value);
results = (from l in collection orderby l.Sort select l.Max).ToArray();
return results;
}
private static Max[] GetLayerZoneCollection(string[] layerCollection, int[] comboCollection, int[] zoneCollection, List<Max> collection)
{
Max[] results;
string key;
string sort;
string distinct;
List<string> distinctCollection = new();
Dictionary<string, List<(string, Max)>> layerZoneToCollection = new();
foreach (string layer in layerCollection)
{
layerZoneToCollection.Add(string.Concat(layer, '.'), new());
foreach (int zone in zoneCollection)
layerZoneToCollection.Add(string.Concat(layer, '.', zone), new());
}
foreach (int combo in comboCollection)
{
layerZoneToCollection.Add(string.Concat(combo, '.'), new());
foreach (int zone in zoneCollection)
layerZoneToCollection.Add(string.Concat(combo, '.', zone), new());
}
foreach (Max max in collection)
{
if (string.IsNullOrEmpty(max.LsId))
continue;
sort = string.Concat(max.LsId.PadLeft(2, 'Z'), '.', max.Zone);
key = string.Concat(max.LsId, '.', max.Zone);
distinct = string.Concat(max.LsId, '\t', max.Zone, '\t', max.LoadLockSide, '\t', max.RdsNo, '\t', max.PsNo, '\t', max.RecipeName, '\t', max.SpecType, '\t', max.SpecThickMtool, '\t', max.SpecThickMrecipe, '\t', max.SpecResMtool, '\t', max.SpecResMrecipe, '\t', max.SpecCresMtool, '\t', max.SpecCresMrecipe);
if (distinctCollection.Contains(distinct))
continue;
distinctCollection.Add(distinct);
layerZoneToCollection[key].Add(new(sort, max));
}
results = GetLayerZoneCollection(layerZoneToCollection);
return results;
}
private static Max[] GetCleanCollection(Dictionary<int, List<(int, Max)>> layerZoneToCollection)
{
Max[] results;
List<(int Sort, Max Max)> collection = new();
foreach (KeyValuePair<int, List<(int, Max)>> keyValuePair in layerZoneToCollection)
collection.AddRange(keyValuePair.Value);
results = (from l in collection orderby l.Sort select l.Max).ToArray();
return results;
}
private static Max[] GetCleanCollection(int[] cleanCollection, List<Max> collection)
{
Max[] results;
int key;
string distinct;
List<string> distinctCollection = new();
Dictionary<int, List<(int, Max)>> cleanToCollection = new();
foreach (int clean in cleanCollection)
cleanToCollection.Add(clean, new());
foreach (Max max in collection)
{
if (max.MvNo is null)
continue;
key = max.MvNo.Value;
distinct = string.Concat(max.MvNo, '\t', max.ScanTool, '\t', max.SpecSurfscanRecipe, '\t', max.SpecSsSampQty);
if (distinctCollection.Contains(distinct))
continue;
distinctCollection.Add(distinct);
cleanToCollection[key].Add(new(key, max));
}
results = GetCleanCollection(cleanToCollection);
return results;
}
public List<string[]> Convert(Max[] collection)
{
List<string[]> results = new();
string[] row;
Max[] cleanCollectionB;
List<string> res = new();
Max[] layerZoneCollection;
List<string> clean = new();
List<string> thick = new();
List<string> centerRes = new();
StringBuilder stringBuilder = new();
_ = stringBuilder.Append($"Reactor\tReactorType\tWO\tRDS\tPSN\tName\tSpecType\tRes\tThick\tCenter Res\tScan");
row = stringBuilder.ToString().Split('\t');
results.Add(row);
Dictionary<int, List<Max>> reactorToRecords = GetReactorToRecords(collection);
(string[] layerCollection, int[] comboCollection, int[] zoneCollection, int[] cleanCollection) = GetDistinct(collection);
foreach (KeyValuePair<int, List<Max>> reactorToRecord in reactorToRecords)
{
res.Clear();
clean.Clear();
thick.Clear();
centerRes.Clear();
_ = stringBuilder.Clear();
foreach (Max max in reactorToRecord.Value)
{
_ = stringBuilder.Append($"R{max.Reactor}\t{max.ReactorType}\t{max.WoNo}\t{max.RdsNo}\t{max.PsNo}\t{max.RecipeName}\t{max.SpecType}\t");
break;
}
layerZoneCollection = GetLayerZoneCollection(layerCollection, comboCollection, zoneCollection, reactorToRecord.Value);
foreach (Max max in layerZoneCollection)
{
res.Add(string.Concat(max.LsId, '.', max.Zone, " - ", max.SpecResMtool, " {", max.SpecResMrecipe, '}'));
thick.Add(string.Concat(max.LsId, '.', max.Zone, " - ", max.SpecThickMtool, " {", max.SpecThickMrecipe, '}'));
centerRes.Add(string.Concat(max.LsId, '.', max.Zone, " - ", max.SpecCresMtool, " {", max.SpecCresMrecipe, '}'));
}
_ = stringBuilder.Append($"{string.Join("<br />", res.ToArray())}\t");
_ = stringBuilder.Append($"{string.Join("<br />", thick.ToArray())}\t");
_ = stringBuilder.Append($"{string.Join("<br />", centerRes.ToArray())}\t");
cleanCollectionB = GetCleanCollection(cleanCollection, reactorToRecord.Value);
foreach (Max max in cleanCollectionB)
clean.Add(string.Concat(max.MvNo, " - {", max.SpecSurfscanRecipe, "} [", max.SpecSsSampQty, "] ", max.ScanTool));
_ = stringBuilder.Append($"{string.Join("<br />", clean.ToArray())}");
row = stringBuilder.ToString().Split('\t');
results.Add(row);
}
return results;
}
}

View File

@ -0,0 +1,43 @@
@model System.Collections.Generic.List<string[]>
@{
ViewData["Title"] = "Max RDS per Reactor with Recipes";
}
<style>
html,
body {
height: 100%;
}
div.container-fluid {
height: 90%;
}
#HeaderGrid,
#FieldsGrid {
font-size: 12px;
}
.FieldTitle {
font-weight: bold;
}
</style>
<h4>Max RDS per Reactor with Recipes</h4>
<table border="1" style="width:100%">
@foreach (string[] row in Model)
{
<tr>
@foreach (string column in row)
{
<td>@Html.Raw(column)</td>
}
</tr>
}
</table>
<script>
$(document).ready(function () {
});
</script>

View File

@ -0,0 +1,96 @@
@model string[]
@{
ViewData["Title"] = "Step 1";
string side = Model[0] == "0" ? "Even" : "Odd";
}
<style>
html,
body {
height: 100%;
}
div.container-fluid {
height: 90%;
}
#HeaderGrid,
#FieldsGrid {
font-size: 12px;
}
.FieldTitle {
font-weight: bold;
}
</style>
@if (!string.IsNullOrEmpty(Model[5]))
{
<h3>@(side) - @(Model[1])</h3><br />
<h3>__-@(Model[4])-____.@(Model[2])-@(Model[3])</h3><br />
<h3>@(Model[5])</h3><br />
}
<h4>Step 1</h4>
<table>
<tr>
<td>
<label for="Side">Side:</label>
</td>
<td>
<span>&nbsp;</span>
</td>
<td>
<span>&nbsp;</span>
</td>
</tr>
<tr>
<td>
<span>&nbsp;</span>
</td>
<td>
<div class="form-group">
<input class="btn btn-primary" type="button" value="Even" id="EvenButton" />
</div>
</td>
<td>
<div class="form-group">
<input class="btn btn-primary" type="button" value="Odd" id="OddButton" />
</div>
</td>
</tr>
<tr>
<td>
<span>&nbsp;</span>
</td>
<td>
<span>&nbsp;</span>
</td>
<td>
<div class="form-group">
<input class="btn btn-warning" type="button" value="Restart" id="RestartButton" />
</div>
</td>
</tr>
</table>
<script>
function Submit(mod) {
if (mod === 9) {
window.location.href = '\Step1';
}
else {
window.location.href = '\Step2?mod=' + mod;
}
}
$(document).ready(function () {
$("#EvenButton").click(function () { Submit(0); });
$("#OddButton").click(function () { Submit(1); });
$("#RestartButton").click(function () { Submit(9); });
});
</script>

View File

@ -0,0 +1,167 @@
@model string[]
@{
ViewData["Title"] = "Step 2";
}
<style>
html,
body {
height: 100%;
}
div.container-fluid {
height: 90%;
}
#HeaderGrid,
#FieldsGrid {
font-size: 12px;
}
.FieldTitle {
font-weight: bold;
}
</style>
<h4>Step 2</h4>
<table>
<tr>
<td>
<label for="Equipment">Equipment:</label>
</td>
<td>
<span>&nbsp;</span>
</td>
<td>
<span>&nbsp;</span>
</td>
</tr>
<tr>
<td>
<span>&nbsp;</span>
</td>
<td>
<div class="form-group">
<input class="btn btn-primary" type="button" value="Tencor 1" id="Tencor1Button" />
</div>
</td>
<td>
<div class="form-group">
<input class="btn btn-primary" type="button" value="Tencor 2" id="Tencor2Button" />
</div>
</td>
<td>
<div class="form-group">
<input class="btn btn-primary" type="button" value="Tencor 3" id="Tencor3Button" />
</div>
</td>
</tr>
<tr>
<td>
<span>&nbsp;</span>
</td>
<td>
<div class="form-group">
<input class="btn btn-primary" type="button" value="HgCV 1" id="HgCV1Button" />
</div>
</td>
<td>
<div class="form-group">
<input class="btn btn-primary" type="button" value="HgCV 2" id="HgCV2Button" />
</div>
</td>
<td>
<div class="form-group">
<input class="btn btn-primary" type="button" value="HgCV 3" id="HgCV3Button" />
</div>
</td>
</tr>
<tr>
<td>
<span>&nbsp;</span>
</td>
<td>
<div class="form-group">
<input class="btn btn-primary" type="button" value="BioRad 2" id="BioRad2Button" />
</div>
</td>
<td>
<div class="form-group">
<input class="btn btn-primary" type="button" value="BioRad 3" id="BioRad3Button" />
</div>
</td>
<td>
<div class="form-group">
<input class="btn btn-primary" type="button" value="BioRad 4" id="BioRad4Button" />
</div>
</td>
</tr>
<tr>
<td>
<span>&nbsp;</span>
</td>
<td>
<div class="form-group">
<input class="btn btn-primary" type="button" value="CDE 2" id="CDE2Button" />
</div>
</td>
<td>
<div class="form-group">
<input class="btn btn-primary" type="button" value="CDE 4" id="CDE4Button" />
</div>
</td>
<td>
<div class="form-group">
<input class="btn btn-primary" type="button" value="CDE 5" id="CDE5Button" />
</div>
</td>
</tr>
<tr>
<td>
<span>&nbsp;</span>
</td>
<td>
<span>&nbsp;</span>
</td>
<td>
<div class="form-group">
<input class="btn btn-primary" type="button" value="Restart" id="RestartButton" />
</div>
</td>
</tr>
</table>
<script>
function Submit(equipment) {
if (equipment === 'RestartButton') {
window.location.href = '\Step1';
}
else {
window.location.href = '\Step3?mod=@(Model[0])&equipment=' + equipment;
}
}
$(document).ready(function () {
$("#Tencor1Button").click(function () { Submit('Tencor1'); });
$("#Tencor2Button").click(function () { Submit('Tencor2'); });
$("#Tencor3Button").click(function () { Submit('Tencor3'); });
$("#HgCV1Button").click(function () { Submit('HgCV1'); });
$("#HgCV2Button").click(function () { Submit('HgCV2'); });
$("#HgCV3Button").click(function () { Submit('HgCV3'); });
$("#BioRad2Button").click(function () { Submit('BioRad2'); });
$("#BioRad3Button").click(function () { Submit('BioRad3'); });
$("#BioRad4Button").click(function () { Submit('BioRad4'); });
$("#CDE2Button").click(function () { Submit('CDE2'); });
$("#CDE4Button").click(function () { Submit('CDE4'); });
$("#CDE5Button").click(function () { Submit('CDE5'); });
$("#RestartButton").click(function () { Submit('RestartButton'); });
});
</script>

View File

@ -0,0 +1,95 @@
@model string[]
@{
ViewData["Title"] = "Step 3";
}
<style>
html,
body {
height: 100%;
}
div.container-fluid {
height: 90%;
}
#HeaderGrid,
#FieldsGrid {
font-size: 12px;
}
.FieldTitle {
font-weight: bold;
}
</style>
<h4>Step 3</h4>
<table>
<tr>
<td>
<label for="Layer">Layer:</label>
</td>
<td>
<span>&nbsp;</span>
</td>
<td>
<span>&nbsp;</span>
</td>
</tr>
<tr>
<td>
<span>&nbsp;</span>
</td>
<td>
<div class="form-group">
<input class="btn btn-primary" type="button" value="Layer 1" id="Layer1Button" />
</div>
</td>
<td>
<div class="form-group">
<input class="btn btn-primary" type="button" value="Layer 2" id="Layer2Button" />
</div>
</td>
<td>
<div class="form-group">
<input class="btn btn-primary" type="button" value="Layer 3" id="Layer3Button" />
</div>
</td>
</tr>
<tr>
<td>
<span>&nbsp;</span>
</td>
<td>
<span>&nbsp;</span>
</td>
<td>
<div class="form-group">
<input class="btn btn-warning" type="button" value="Restart" id="RestartButton" />
</div>
</td>
</tr>
</table>
<script>
function Submit(layer) {
if (layer === 'RestartButton') {
window.location.href = '\Step1';
}
else {
window.location.href = '\Step4?mod=@(Model[0])&equipment=@(Model[1])&layer=' + layer;
}
}
$(document).ready(function () {
$("#Layer1Button").click(function () { Submit('1'); });
$("#Layer2Button").click(function () { Submit('2'); });
$("#Layer3Button").click(function () { Submit('3'); });
$("#RestartButton").click(function () { Submit('RestartButton'); });
});
</script>

View File

@ -0,0 +1,115 @@
@model string[]
@{
ViewData["Title"] = "Step 4";
}
<style>
html,
body {
height: 100%;
}
div.container-fluid {
height: 90%;
}
#HeaderGrid,
#FieldsGrid {
font-size: 12px;
}
.FieldTitle {
font-weight: bold;
}
</style>
<h4>Step 4</h4>
<table>
<tr>
<td>
<label for="Zone">Zone:</label>
</td>
<td>
<span>&nbsp;</span>
</td>
<td>
<span>&nbsp;</span>
</td>
</tr>
<tr>
<td>
<div class="form-group">
<input class="btn btn-primary" type="button" value="Zone 1" id="Zone1Button" />
</div>
</td>
<td>
<div class="form-group">
<input class="btn btn-primary" type="button" value="Zone 2" id="Zone2Button" />
</div>
</td>
<td>
<div class="form-group">
<input class="btn btn-primary" type="button" value="Zone 3" id="Zone3Button" />
</div>
</td>
</tr>
<tr>
<td>
<span>&nbsp;</span>
</td>
<td>
<span>&nbsp;</span>
</td>
<td>
<label for="NoZone">No Zone - RDS:</label>
</td>
<td>
<div class="form-group">
<input class="txt txt-primary" type="input" value="" id="RDSInput" /><br />
<input class="btn btn-warning" type="button" value="Next" id="RDSButton" />
</div>
</td>
</tr>
<tr>
<td>
<span>&nbsp;</span>
</td>
<td>
<span>&nbsp;</span>
</td>
<td>
<div class="form-group">
<input class="btn btn-warning" type="button" value="Restart" id="RestartButton" />
</div>
</td>
</tr>
</table>
<script>
function Submit(zone) {
if (zone === 9) {
window.location.href = '\Step1';
}
else if (zone > 9) {
var rds = $("#RDSInput").val();
window.location.href = '\Step6?mod=@(Model[0])&equipment=@(Model[1])&layer=@(Model[2])&zone=0&rds=' + rds;
}
else {
window.location.href = '\Step5?mod=@(Model[0])&equipment=@(Model[1])&layer=@(Model[2])&zone=' + zone;
}
}
$(document).ready(function () {
$("#Zone1Button").click(function () { Submit(1); });
$("#Zone2Button").click(function () { Submit(2); });
$("#Zone3Button").click(function () { Submit(3); });
$("#RDSButton").click(function () { Submit(123456); });
$("#RestartButton").click(function () { Submit(9); });
});
</script>

View File

@ -0,0 +1,89 @@
@model string[]
@{
ViewData["Title"] = "Step 5";
}
<style>
html,
body {
height: 100%;
}
div.container-fluid {
height: 90%;
}
#HeaderGrid,
#FieldsGrid {
font-size: 12px;
}
.FieldTitle {
font-weight: bold;
}
</style>
<h4>Step 5</h4>
<table>
<tr>
<td>
<label for="RDS">RDS:</label>
</td>
<td>
<span>&nbsp;</span>
</td>
<td>
<span>&nbsp;</span>
</td>
</tr>
<tr>
<td>
<span>&nbsp;</span>
</td>
<td>
<div class="form-group">
<input class="txt txt-primary" type="input" value="" id="RDSInput" />
</div>
</td>
<td>
<div class="form-group">
<input class="btn btn-primary" type="button" value="Next" id="RDSButton" />
</div>
</td>
</tr>
<tr>
<td>
<span>&nbsp;</span>
</td>
<td>
<span>&nbsp;</span>
</td>
<td>
<div class="form-group">
<input class="btn btn-warning" type="button" value="Restart" id="RestartButton" />
</div>
</td>
</tr>
</table>
<script>
function Submit(zone) {
if (zone === 9) {
window.location.href = '\Step1';
}
else {
var rds = $("#RDSInput").val();
window.location.href = '\Step6?mod=@(Model[0])&equipment=@(Model[1])&layer=@(Model[2])&zone=@(Model[3])&rds=' + rds;
}
}
$(document).ready(function () {
$("#RDSButton").click(function () { Submit(123456); });
$("#RestartButton").click(function () { Submit(9); });
});
</script>

View File

@ -0,0 +1,89 @@
@model string[]
@{
ViewData["Title"] = "Step 6";
}
<style>
html,
body {
height: 100%;
}
div.container-fluid {
height: 90%;
}
#HeaderGrid,
#FieldsGrid {
font-size: 12px;
}
.FieldTitle {
font-weight: bold;
}
</style>
<h4>Step 6</h4>
<table>
<tr>
<td>
<label for="Initials">Initials:</label>
</td>
<td>
<span>&nbsp;</span>
</td>
<td>
<span>&nbsp;</span>
</td>
</tr>
<tr>
<td>
<span>&nbsp;</span>
</td>
<td>
<div class="form-group">
<input class="txt txt-primary" type="input" value="" id="InitialsInput" />
</div>
</td>
<td>
<div class="form-group">
<input class="btn btn-primary" type="button" value="Next" id="InitialsButton" />
</div>
</td>
</tr>
<tr>
<td>
<span>&nbsp;</span>
</td>
<td>
<span>&nbsp;</span>
</td>
<td>
<div class="form-group">
<input class="btn btn-warning" type="button" value="Restart" id="RestartButton" />
</div>
</td>
</tr>
</table>
<script>
function Submit(initials) {
if (initials === 'RestartButton') {
window.location.href = '\Step1';
}
else {
var initials = $("#InitialsInput").val();
window.location.href = '\Step1?mod=@(Model[0])&equipment=@(Model[1])&layer=@(Model[2])&zone=@(Model[3])&rds=@(Model[4])&initials=' + initials;
}
}
$(document).ready(function () {
$("#InitialsButton").click(function () { Submit('MP'); });
$("#RestartButton").click(function () { Submit('RestartButton'); });
});
</script>

View File

@ -17,6 +17,9 @@
}
},
"InboundApiAllowedIPList": "",
"MonAResource": "OI_Metrology_Archive_IFX",
"MonASite": "auc",
"Oi2SqlConnectionString": "Data Source=messv01ec.ec.local\\PROD1,53959;Initial Catalog=LSL2SQL;Persist Security Info=True;User ID=srpadmin;Password=0okm9ijn;",
"OIExportPath": "\\\\openinsight-db-srv.na.infineon.com\\apps\\Metrology\\Data",
"Serilog": {
"Using": [

View File

@ -17,6 +17,9 @@
}
},
"InboundApiAllowedIPList": "",
"MonAResource": "OI_Metrology_Archive_EC",
"MonASite": "auc",
"Oi2SqlConnectionString": "Data Source=messv01ec.ec.local\\PROD1,53959;Initial Catalog=LSL2SQL;Persist Security Info=True;User ID=srpadmin;Password=0okm9ijn;",
"OIExportPath": "\\\\openinsight-db-srv.na.infineon.com\\apps\\Metrology\\Data",
"Serilog": {
"Using": [

View File

@ -23,3 +23,13 @@ Ouellette Jonathan (IFAM IT FI MES) created #315807, 7/25/2022
## Git
* git@tfs.intra.infineon.com:22/tfs/ManufacturingIT/Mesa_FI/_git/APC-Viewer
## TFS / Azure DevOps - Pipelines
* https://tfs.intra.infineon.com/tfs/manufacturingit/Mesa_FI/_build?definitionId=5439&_a=summary
* https://tfs.intra.infineon.com/tfs/manufacturingit/Mesa_FI/_release?_a=releases&view=mine&definitionId=1
4c07c49f3b9daa69fecd9d5be64e047d0ad6be1d
343ff2d792149c9eef1216f44dbdb73935cf6041
https://oi-metrology-viewer-prod.mes.infineon.com/
https://oi-metrology-viewer-archive.mes.infineon.com/

View File

@ -0,0 +1,28 @@
using System.Text.Json.Serialization;
namespace OI.Metrology.Shared.DataModels.RDS;
public record Max(
[property: JsonPropertyName("reactor_type")] string ReactorType,
[property: JsonPropertyName("reactor")] int Reactor,
[property: JsonPropertyName("ls_id")] string LsId,
[property: JsonPropertyName("zone")] string Zone,
[property: JsonPropertyName("load_lock_side")] string LoadLockSide,
[property: JsonPropertyName("rds_no")] int RdsNo,
[property: JsonPropertyName("wo_no")] int WoNo,
[property: JsonPropertyName("ps_no")] string PsNo,
[property: JsonPropertyName("recipe_name")] string RecipeName,
[property: JsonPropertyName("recipe_no")] int RecipeNo,
[property: JsonPropertyName("spec_type")] string SpecType,
[property: JsonPropertyName("spec_thick_mtool")] string SpecThickMtool,
[property: JsonPropertyName("spec_thick_mrecipe")] string SpecThickMrecipe,
[property: JsonPropertyName("spec_res_mtool")] string SpecResMtool,
[property: JsonPropertyName("spec_res_mrecipe")] string SpecResMrecipe,
[property: JsonPropertyName("spec_cres_mtool")] string SpecCresMtool,
[property: JsonPropertyName("spec_cres_mrecipe")] string SpecCresMrecipe,
[property: JsonPropertyName("ci_no")] int CiNo,
[property: JsonPropertyName("mv_no")] int? MvNo,
[property: JsonPropertyName("scan_tool")] string ScanTool,
[property: JsonPropertyName("spec_surfscan_recipe")] string SpecSurfscanRecipe,
[property: JsonPropertyName("spec_ss_samp_qty")] int? SpecSsSampQty
);

View File

@ -0,0 +1,19 @@
using System.Net;
namespace Infineon.Monitoring.MonA;
#nullable disable
#pragma warning disable SYSLIB0014
public class ExtWebClient : WebClient
{
protected override WebRequest GetWebRequest(Uri address)
{
WebRequest webRequest = base.GetWebRequest(address);
if (webRequest != null)
webRequest.PreAuthenticate = PreAuthenticate;
return webRequest;
}
public bool PreAuthenticate { get; set; }
}

View File

@ -0,0 +1,165 @@
namespace Infineon.Monitoring.MonA;
public interface IMonIn
{
string SendStatus(string site, string resource, string stateName, State state);
string SendStatus(
string site,
DateTime timeStamp,
string resource,
string stateName,
State state);
string SendStatus(
string site,
string resource,
string stateName,
State state,
string description);
string SendStatus(
string site,
DateTime timeStamp,
string resource,
string stateName,
State state,
string description);
string SendStatus(
string site,
string resource,
string subresource,
string stateName,
State state);
string SendStatus(
string site,
DateTime timeStamp,
string resource,
string subresource,
string stateName,
State state);
string SendStatus(
string site,
string resource,
string subresource,
string stateName,
State state,
string description);
string SendStatus(
string site,
DateTime? timeStamp,
string resource,
string subresource,
string stateName,
State state,
string description);
string SendPerformanceMessage(
string site,
string resource,
string performanceName,
double value);
string SendPerformanceMessage(
string site,
DateTime? timeStamp,
string resource,
string performanceName,
double value);
string SendPerformanceMessage(
string site,
string resource,
string performanceName,
double value,
string description);
string SendPerformanceMessage(
string site,
DateTime? timeStamp,
string resource,
string performanceName,
double value,
string description);
string SendPerformanceMessage(
string site,
DateTime? timeStamp,
string resource,
string performanceName,
double value,
int? interval);
string SendPerformanceMessage(
string site,
string resource,
DateTime? timeStamp,
string performanceName,
double value,
string unit);
string SendPerformanceMessage(
string site,
DateTime? timeStamp,
string resource,
string performanceName,
double value,
string unit,
int? interval);
string SendPerformanceMessage(
string site,
string resource,
string subresource,
string performanceName,
double value);
string SendPerformanceMessage(
string site,
DateTime? timeStamp,
string resource,
string subresource,
string performanceName,
double value);
string SendPerformanceMessage(
string site,
string resource,
string subresource,
string performanceName,
double value,
string description);
string SendPerformanceMessage(
string site,
DateTime? timeStamp,
string resource,
string subresource,
string performanceName,
double value,
int? interval);
string SendPerformanceMessage(
string site,
DateTime? timeStamp,
string resource,
string subresource,
string performanceName,
double value,
string unit);
string SendPerformanceMessage(
string site,
DateTime? timeStamp,
string resource,
string subresource,
string performanceName,
double value,
string description,
string unit,
int? interval);
}

View File

@ -0,0 +1,309 @@
using System.Globalization;
using System.Net;
using System.Text;
namespace Infineon.Monitoring.MonA;
public class MonIn : IMonIn, IDisposable
{
private static readonly DateTime _Utc1970DateTime = new(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
public const string MonInUrl = "http://moninhttp.{0}.infineon.com/input/text";
private static readonly Dictionary<string, MonIn> _Instances = new();
private readonly ExtWebClient _WebClient;
private readonly string _MonInUrl;
private static CultureInfo? _CultureInfo;
public static MonIn GetInstance(string url = "http://moninhttp.{0}.infineon.com/input/text")
{
MonIn instance;
if (_Instances.ContainsKey(url))
{
instance = _Instances[url];
}
else
{
lock (_Instances)
{
if (!_Instances.ContainsKey(url))
{
instance = new MonIn(url);
_Instances.Add(url, instance);
}
else
instance = _Instances[url];
}
}
return instance;
}
private MonIn(string url)
{
_WebClient = new ExtWebClient();
_WebClient.Headers[HttpRequestHeader.ContentType] = "application/text";
_WebClient.Encoding = Encoding.UTF8;
_CultureInfo = new CultureInfo("en-US");
_MonInUrl = url;
}
public void SetBasicAuthentication(string username, string password)
{
_WebClient.PreAuthenticate = true;
_WebClient.Headers[HttpRequestHeader.Authorization] = "Basic " + Convert.ToBase64String(Encoding.ASCII.GetBytes(username + ":" + password));
}
public string SendStatus(string site, string resource, string stateName, State state) =>
SendStatus(site, new DateTime?(), resource, string.Empty, stateName, state, string.Empty);
public string SendStatus(
string site,
DateTime timeStamp,
string resource,
string stateName,
State state) =>
SendStatus(site, new DateTime?(timeStamp), resource, string.Empty, stateName, state, string.Empty);
public string SendStatus(
string site,
string resource,
string stateName,
State state,
string description) =>
SendStatus(site, new DateTime?(), resource, string.Empty, stateName, state, description);
public string SendStatus(
string site,
DateTime timeStamp,
string resource,
string stateName,
State state,
string description) =>
SendStatus(site, new DateTime?(timeStamp), resource, string.Empty, stateName, state, description);
public string SendStatus(
string site,
string resource,
string subresource,
string stateName,
State state) =>
SendStatus(site, new DateTime?(), resource, subresource, stateName, state, string.Empty);
public string SendStatus(
string site,
DateTime timeStamp,
string resource,
string subresource,
string stateName,
State state) =>
SendStatus(site, new DateTime?(timeStamp), resource, subresource, stateName, state, string.Empty);
public string SendStatus(
string site,
string resource,
string subresource,
string stateName,
State state,
string description) =>
SendStatus(site, new DateTime?(), resource, subresource, stateName, state, description);
public string SendStatus(
string site,
DateTime? timeStamp,
string resource,
string subresource,
string stateName,
State state,
string description)
{
string statusMessage = CreateStatusMessage(site, timeStamp, resource, subresource, stateName, state.ToString(), description);
lock (_WebClient)
return _WebClient.UploadString(string.Format(_MonInUrl, site), statusMessage);
}
public string SendPerformanceMessage(
string site,
string resource,
string performanceName,
double value) =>
SendPerformanceMessage(site, new DateTime?(), resource, string.Empty, performanceName, value, string.Empty, string.Empty, new int?());
public string SendPerformanceMessage(
string site,
DateTime? timeStamp,
string resource,
string performanceName,
double value) =>
SendPerformanceMessage(site, timeStamp, resource, string.Empty, performanceName, value, string.Empty, string.Empty, new int?());
public string SendPerformanceMessage(
string site,
string resource,
string performanceName,
double value,
string description) =>
SendPerformanceMessage(site, new DateTime?(), resource, string.Empty, performanceName, value, description, string.Empty, new int?());
public string SendPerformanceMessage(
string site,
DateTime? timeStamp,
string resource,
string performanceName,
double value,
string description) =>
SendPerformanceMessage(site, timeStamp, resource, string.Empty, performanceName, value, description, string.Empty, new int?());
public string SendPerformanceMessage(
string site,
DateTime? timeStamp,
string resource,
string performanceName,
double value,
int? interval) =>
SendPerformanceMessage(site, timeStamp, resource, string.Empty, performanceName, value, string.Empty, string.Empty, interval);
public string SendPerformanceMessage(
string site,
string resource,
DateTime? timeStamp,
string performanceName,
double value,
string unit) =>
SendPerformanceMessage(site, timeStamp, resource, string.Empty, performanceName, value, string.Empty, unit, new int?());
public string SendPerformanceMessage(
string site,
DateTime? timeStamp,
string resource,
string performanceName,
double value,
string unit,
int? interval) =>
SendPerformanceMessage(site, timeStamp, resource, string.Empty, performanceName, value, string.Empty, unit, interval);
public string SendPerformanceMessage(
string site,
string resource,
string subresource,
string performanceName,
double value) =>
SendPerformanceMessage(site, new DateTime?(), resource, subresource, performanceName, value, string.Empty, string.Empty, new int?());
public string SendPerformanceMessage(
string site,
DateTime? timeStamp,
string resource,
string subresource,
string performanceName,
double value) =>
SendPerformanceMessage(site, timeStamp, resource, subresource, performanceName, value, string.Empty, string.Empty, new int?());
public string SendPerformanceMessage(
string site,
string resource,
string subresource,
string performanceName,
double value,
string description) =>
SendPerformanceMessage(site, new DateTime?(), resource, subresource, performanceName, value, description, string.Empty, new int?());
public string SendPerformanceMessage(
string site,
DateTime? timeStamp,
string resource,
string subresource,
string performanceName,
double value,
int? interval) =>
SendPerformanceMessage(site, timeStamp, resource, subresource, performanceName, value, string.Empty, string.Empty, interval);
public string SendPerformanceMessage(
string site,
DateTime? timeStamp,
string resource,
string subresource,
string performanceName,
double value,
string unit) =>
SendPerformanceMessage(site, timeStamp, resource, subresource, performanceName, value, string.Empty, unit, new int?());
public string SendPerformanceMessage(
string site,
DateTime? timeStamp,
string resource,
string subresource,
string performanceName,
double value,
string description,
string unit,
int? interval)
{
string performanceMessage = CreatePerformanceMessage(site, timeStamp, resource, subresource, performanceName, value, description, unit, interval);
lock (_WebClient)
return _WebClient.UploadString(string.Format(_MonInUrl, site), performanceMessage);
}
private static string CreateStatusMessage(
string site,
DateTime? timeStamp,
string resource,
string subresource,
string stateName,
string state,
string description)
{
StringBuilder stringBuilder = new();
if (string.IsNullOrEmpty(subresource))
_ = stringBuilder.AppendFormat(_CultureInfo, "> {0} {1} \"{2}\" \"{3}\" {4} \n{5}", site.Trim(), timeStamp.HasValue ? GetDateTimeNowAsPosix(timeStamp.Value) : (object)"now", resource.Trim(), stateName.Trim(), state.Trim(), description.Trim());
else
_ = stringBuilder.AppendFormat(_CultureInfo, "> {0} {1} \"{2}\" \"{3}\" \"{4}\" {5} \n{6}", site.Trim(), timeStamp.HasValue ? GetDateTimeNowAsPosix(timeStamp.Value) : (object)"now", resource.Trim(), subresource.Trim(), stateName.Trim(), state.Trim(), description.Trim());
return stringBuilder.ToString();
}
private static string CreatePerformanceMessage(
string site,
DateTime? timeStamp,
string resource,
string subresource,
string performanceName,
double value,
string description,
string unit,
int? interval)
{
StringBuilder stringBuilder = new();
if (string.IsNullOrEmpty(subresource))
{
if (unit.Equals(string.Empty) && !interval.HasValue)
_ = stringBuilder.AppendFormat(_CultureInfo, "> {0} {1} \"{2}\" \"{3}\" {4} \n{5}", site.Trim(), timeStamp.HasValue ? GetDateTimeNowAsPosix(timeStamp.Value) : (object)"now", resource.Trim(), performanceName.Trim(), value, description.Trim());
else
_ = stringBuilder.AppendFormat(_CultureInfo, "> {0} {1} \"{2}\" \"{3}\" {4} {5} {{interval={6}, unit={7}}}\n", site.Trim(), timeStamp.HasValue ? GetDateTimeNowAsPosix(timeStamp.Value) : (object)"now", resource.Trim(), performanceName.Trim(), value, description.Trim(), interval.HasValue ? interval.Value.ToString() : (object)string.Empty, unit.Trim());
}
else if (unit.Equals(string.Empty) && !interval.HasValue)
_ = stringBuilder.AppendFormat(_CultureInfo, "> {0} {1} \"{2}\" \"{3}\" \"{4}\" {5} \n{6}", site.Trim(), timeStamp.HasValue ? GetDateTimeNowAsPosix(timeStamp.Value) : (object)"now", resource.Trim(), subresource.Trim(), performanceName.Trim(), value, description.Trim());
else
_ = stringBuilder.AppendFormat(_CultureInfo, "> {0} {1} \"{2}\" \"{3}\" \"{4}\" {5} {6} {{interval={7}, unit={8}}}\n", site.Trim(), timeStamp.HasValue ? GetDateTimeNowAsPosix(timeStamp.Value) : (object)"now", resource.Trim(), subresource.Trim(), performanceName.Trim(), value, description.Trim(), interval.HasValue ? interval.Value.ToString() : (object)string.Empty, unit.Trim());
return stringBuilder.ToString();
}
private static string GetDateTimeNowAsPosix(DateTime timeStamp)
{
if (timeStamp > DateTime.Now)
timeStamp = DateTime.Now;
return ((int)timeStamp.ToUniversalTime().Subtract(_Utc1970DateTime).TotalSeconds).ToString(CultureInfo.InvariantCulture);
}
public void Dispose()
{
KeyValuePair<string, MonIn> keyValuePair = new();
foreach (KeyValuePair<string, MonIn> instance in _Instances)
{
if (instance.Value == this)
{
keyValuePair = instance;
break;
}
}
_ = _Instances.Remove(keyValuePair.Key);
_WebClient?.Dispose();
}
}

View File

@ -0,0 +1,11 @@
namespace Infineon.Monitoring.MonA;
public enum State
{
Up,
Ok,
Warning,
Critical,
Down,
Unknown,
}

View File

@ -3,6 +3,7 @@ namespace OI.Metrology.Shared.Models;
public interface IWorkingDirectory
{
static string GetWorkingDirectory(string? executingAssemblyName, string subDirectoryName) => WorkingDirectory.GetWorkingDirectory(executingAssemblyName, subDirectoryName);
static string GetWorkingDirectory(string? executingAssemblyName, string subDirectoryName) =>
WorkingDirectory.GetWorkingDirectory(executingAssemblyName, subDirectoryName);
}

View File

@ -0,0 +1,11 @@
namespace OI.Metrology.Shared.Repositories;
using DataModels.RDS;
using System.Collections.Generic;
public interface IRdsMaxRepo
{
Max[] GetMaxRDS();
List<string[]> Convert(Max[] collection);
}

View File

@ -6,49 +6,54 @@ namespace OI.Metrology.Tests.Models;
public class AppSettings
{
protected string _ApiLoggingContentTypes;
protected string _ApiLoggingPathPrefixes;
protected string _ApiLogPath;
protected string _AttachmentPath;
protected string _BuildNumber;
protected string _Company;
protected string _ConnectionString;
protected string _GitCommitSeven;
protected string _InboundApiAllowedIPList;
protected string _MonARessource;
protected string _OIExportPath;
protected string _URLs;
protected string _WorkingDirectoryName;
public string ApiLoggingContentTypes => _ApiLoggingContentTypes;
public string ApiLoggingPathPrefixes => _ApiLoggingPathPrefixes;
public string ApiLogPath => _ApiLogPath;
public string AttachmentPath => _AttachmentPath;
public string BuildNumber => _BuildNumber;
public string Company => _Company;
public string ConnectionString => _ConnectionString;
public string GitCommitSeven => _GitCommitSeven;
public string InboundApiAllowedIPList => _InboundApiAllowedIPList;
public string MonARessource => _MonARessource;
public string OIExportPath => _OIExportPath;
public string URLs => _URLs;
public string WorkingDirectoryName => _WorkingDirectoryName;
public string ApiLoggingContentTypes { init; get; }
public string ApiLoggingPathPrefixes { init; get; }
public string ApiLogPath { init; get; }
public string AttachmentPath { init; get; }
public string BuildNumber { init; get; }
public string Company { init; get; }
public string ConnectionString { init; get; }
public string GitCommitSeven { init; get; }
public string InboundApiAllowedIPList { init; get; }
public string MonAResource { init; get; }
public string MonASite { init; get; }
public string Oi2SqlConnectionString { init; get; }
public string OIExportPath { init; get; }
public string URLs { init; get; }
public string WorkingDirectoryName { init; get; }
[JsonConstructor]
public AppSettings(string apiLoggingContentTypes, string apiLoggingPathPrefixes, string apiLogPath, string attachmentPath, string buildNumber, string company, string connectionString, string gitCommitSeven, string inboundApiAllowedIPList, string monARessource, string oiExportPath, string urls, string workingDirectoryName)
public AppSettings(string apiLoggingContentTypes,
string apiLoggingPathPrefixes,
string apiLogPath,
string attachmentPath,
string buildNumber,
string company,
string connectionString,
string gitCommitSeven,
string inboundApiAllowedIPList,
string monAResource,
string monASite,
string oi2SqlConnectionString,
string oiExportPath,
string urls,
string workingDirectoryName)
{
_ApiLoggingContentTypes = apiLoggingContentTypes;
_ApiLoggingPathPrefixes = apiLoggingPathPrefixes;
_ApiLogPath = apiLogPath;
_AttachmentPath = attachmentPath;
_BuildNumber = buildNumber;
_Company = company;
_ConnectionString = connectionString;
_GitCommitSeven = gitCommitSeven;
_InboundApiAllowedIPList = inboundApiAllowedIPList;
_MonARessource = monARessource;
_OIExportPath = oiExportPath;
_URLs = urls;
_WorkingDirectoryName = workingDirectoryName;
ApiLoggingContentTypes = apiLoggingContentTypes;
ApiLoggingPathPrefixes = apiLoggingPathPrefixes;
ApiLogPath = apiLogPath;
AttachmentPath = attachmentPath;
BuildNumber = buildNumber;
Company = company;
ConnectionString = connectionString;
GitCommitSeven = gitCommitSeven;
InboundApiAllowedIPList = inboundApiAllowedIPList;
MonAResource = monAResource;
MonASite = monASite;
Oi2SqlConnectionString = oi2SqlConnectionString;
OIExportPath = oiExportPath;
URLs = urls;
WorkingDirectoryName = workingDirectoryName;
}
public override string ToString()

View File

@ -1,3 +1,4 @@
using Microsoft.Extensions.Configuration;
using System.ComponentModel.DataAnnotations;
using System.Text.Json;
@ -6,6 +7,8 @@ namespace OI.Metrology.Tests.Models.Binder;
public class AppSettings
{
#nullable disable
[Display(Name = "Api Logging Content Types"), Required] public string ApiLoggingContentTypes { get; set; }
[Display(Name = "Api Logging Path Prefixes"), Required] public string ApiLoggingPathPrefixes { get; set; }
[Display(Name = "Api Log Path"), Required] public string ApiLogPath { get; set; }
@ -15,27 +18,14 @@ public class AppSettings
[Display(Name = "Connection String"), Required] public string ConnectionString { get; set; }
[Display(Name = "Git Commit Seven"), Required] public string GitCommitSeven { get; set; }
[Display(Name = "Inbound Api Allowed IP List"), Required] public string InboundApiAllowedIPList { get; set; }
[Display(Name = "MonA Ressource"), Required] public string MonARessource { get; set; }
[Display(Name = "MonA Resource"), Required] public string MonAResource { get; set; }
[Display(Name = "MonA Site"), Required] public string MonASite { get; set; }
[Display(Name = "Oi 2 Sql Connection String"), Required] public string Oi2SqlConnectionString { get; set; }
[Display(Name = "OI Export Path"), Required] public string OIExportPath { get; set; }
[Display(Name = "URLs"), Required] public string URLs { get; set; }
[Display(Name = "Working Directory Name"), Required] public string WorkingDirectoryName { get; set; }
public AppSettings()
{
ApiLoggingContentTypes = string.Empty;
ApiLoggingPathPrefixes = string.Empty;
ApiLogPath = string.Empty;
AttachmentPath = string.Empty;
BuildNumber = string.Empty;
Company = string.Empty;
ConnectionString = string.Empty;
GitCommitSeven = string.Empty;
InboundApiAllowedIPList = string.Empty;
MonARessource = string.Empty;
OIExportPath = string.Empty;
URLs = string.Empty;
WorkingDirectoryName = string.Empty;
}
#nullable restore
public override string ToString()
{
@ -43,4 +33,34 @@ public class AppSettings
return result;
}
private static Models.AppSettings Get(AppSettings appSettings)
{
Models.AppSettings result;
result = new(
appSettings.ApiLoggingContentTypes,
appSettings.ApiLoggingPathPrefixes,
appSettings.ApiLogPath,
appSettings.AttachmentPath,
appSettings.BuildNumber,
appSettings.Company,
appSettings.ConnectionString,
appSettings.GitCommitSeven,
appSettings.InboundApiAllowedIPList,
appSettings.MonAResource,
appSettings.MonASite,
appSettings.Oi2SqlConnectionString,
appSettings.OIExportPath,
appSettings.URLs,
appSettings.WorkingDirectoryName);
return result;
}
public static Models.AppSettings Get(IConfigurationRoot configurationRoot)
{
Models.AppSettings result;
AppSettings appSettings = configurationRoot.Get<AppSettings>();
result = Get(appSettings);
return result;
}
}

View File

@ -1,44 +0,0 @@
using Microsoft.Extensions.Configuration;
using System;
using System.Linq;
using System.Text.Json;
namespace OI.Metrology.Tests.Models.Stateless;
public abstract class AppSettings
{
#nullable enable
public static Models.AppSettings Get(IConfigurationRoot configurationRoot)
{
Models.AppSettings? result;
Binder.AppSettings appSettings = configurationRoot.Get<Binder.AppSettings>();
string json = JsonSerializer.Serialize(appSettings, new JsonSerializerOptions() { WriteIndented = true });
result = JsonSerializer.Deserialize<Models.AppSettings>(json);
if (result is null)
throw new Exception(json);
if (string.IsNullOrEmpty(result.Company))
throw new Exception(json);
string jsonThis = result.ToString();
if (jsonThis != json)
{
int? check = null;
int min = new int[] { json.Length, jsonThis.Length }.Min();
for (int i = 0; i < min; i++)
{
if (json[i] == jsonThis[i])
continue;
check = i;
break;
}
if (check is null)
throw new Exception();
string a = json[..check.Value].Split(',')[^1];
string b = json[check.Value..].Split(',')[0];
throw new Exception($"{a}{b}");
}
return result;
}
}

View File

@ -7,6 +7,11 @@
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
<TargetFramework>net6.0</TargetFramework>
</PropertyGroup>
<PropertyGroup>
<VSTestLogger>trx</VSTestLogger>
<VSTestCollect>XPlat Code Coverage</VSTestCollect>
<VSTestResultsDirectory>../.vscode/TestResults</VSTestResultsDirectory>
</PropertyGroup>
<PropertyGroup>
<IsWindows Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Windows)))' == 'true'">true</IsWindows>
<IsOSX Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::OSX)))' == 'true'">true</IsOSX>
@ -39,10 +44,13 @@
<ProjectReference Include="..\Archive\Archive.csproj" />
</ItemGroup>
<ItemGroup>
<None Include="appsettings.json">
<None Include="..\Archive\appsettings.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Include="appsettings.Development.json">
<None Include="..\Archive\appsettings.Development.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Include="..\.Data\RdsMaxRepo.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>

View File

@ -1,10 +1,15 @@
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using OI.Metrology.Archive.Repositories;
using OI.Metrology.Shared.Models;
using OI.Metrology.Shared.Repositories;
using OI.Metrology.Tests.Models;
using Serilog;
using System.Reflection;
using OI.Metrology.Tests.Models;
using OI.Metrology.Shared.Models;
using System.Text.Json;
namespace View_by_Distance.Tests;
namespace OI.Metrology.Tests;
[TestClass]
public class UnitTestArchive
@ -13,6 +18,7 @@ public class UnitTestArchive
private readonly ILogger _Logger;
private readonly AppSettings _AppSettings;
private readonly string _WorkingDirectory;
private readonly IMemoryCache? _MemoryCache;
private readonly IConfigurationRoot _ConfigurationRoot;
public UnitTestArchive()
@ -27,13 +33,17 @@ public class UnitTestArchive
.AddEnvironmentVariables()
.AddJsonFile("appsettings.Development.json");
configurationRoot = configurationBuilder.Build();
appSettings = OI.Metrology.Tests.Models.Stateless.AppSettings.Get(configurationRoot);
appSettings = Models.Binder.AppSettings.Get(configurationRoot);
workingDirectory = IWorkingDirectory.GetWorkingDirectory(assembly.GetName().Name, appSettings.WorkingDirectoryName);
Environment.SetEnvironmentVariable(nameof(workingDirectory), workingDirectory);
_ = ConfigurationLoggerConfigurationExtensions.Configuration(loggerConfiguration.ReadFrom, configurationRoot);
Log.Logger = loggerConfiguration.CreateLogger();
logger = Log.ForContext<UnitTestArchive>();
logger.Information("Complete");
ServiceCollection services = new();
ServiceProvider serviceProvider = services.BuildServiceProvider();
_ = services.AddMemoryCache();
_MemoryCache = serviceProvider.GetService<IMemoryCache>();
_Logger = logger;
_AppSettings = appSettings;
_WorkingDirectory = workingDirectory;
@ -56,7 +66,22 @@ public class UnitTestArchive
Assert.IsFalse(_AppSettings is null);
Assert.IsFalse(_WorkingDirectory is null);
Assert.IsFalse(_ConfigurationRoot is null);
}
[TestMethod]
public void TestMethodArchiveJson()
{
string json;
string jsonFile = Path.Combine(AppContext.BaseDirectory, "RdsMaxRepo.json");
Assert.IsTrue(File.Exists(jsonFile));
json = JsonSerializer.Serialize(_AppSettings);
IRdsMaxRepo rdsMaxRepo = new RdsMaxRepo(json, _MemoryCache);
json = File.ReadAllText(jsonFile);
Shared.DataModels.RDS.Max[]? collection = JsonSerializer.Deserialize<Shared.DataModels.RDS.Max[]>(json);
if (collection is null)
throw new NullReferenceException(nameof(collection));
List<string[]> data = rdsMaxRepo.Convert(collection);
Assert.IsTrue(data.Any());
}
}

View File

@ -1,10 +1,10 @@
using Microsoft.Extensions.Configuration;
using OI.Metrology.Shared.Models;
using OI.Metrology.Tests.Models;
using Serilog;
using System.Reflection;
using OI.Metrology.Tests.Models;
using OI.Metrology.Shared.Models;
namespace View_by_Distance.Tests;
namespace OI.Metrology.Tests;
[TestClass]
public class UnitTestExample
@ -27,7 +27,7 @@ public class UnitTestExample
.AddEnvironmentVariables()
.AddJsonFile("appsettings.Development.json");
configurationRoot = configurationBuilder.Build();
appSettings = OI.Metrology.Tests.Models.Stateless.AppSettings.Get(configurationRoot);
appSettings = OI.Metrology.Tests.Models.Binder.AppSettings.Get(configurationRoot);
workingDirectory = IWorkingDirectory.GetWorkingDirectory(assembly.GetName().Name, appSettings.WorkingDirectoryName);
Environment.SetEnvironmentVariable(nameof(workingDirectory), workingDirectory);
_ = ConfigurationLoggerConfigurationExtensions.Configuration(loggerConfiguration.ReadFrom, configurationRoot);

View File

@ -1,60 +0,0 @@
{
"AllowedHosts": "*",
"ApiLoggingContentTypes": "application/json",
"ApiLoggingPathPrefixes": "/api/inbound",
"ApiLogPath": "D:\\Metrology\\MetrologyAPILogs",
"AttachmentPath": "\\\\messv02ecc1.ec.local\\EC_Metrology_Si\\MetrologyAttachments",
"BuildNumber": "1",
"Company": "Infineon Technologies Americas Corp.",
"ConnectionString": "Data Source=messv01ec.ec.local\\PROD1,53959;Integrated Security=True;Initial Catalog=Metrology_Archive;",
"GitCommitSeven": "1234567",
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Log4netProvider": "Debug",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"InboundApiAllowedIPList": "",
"OIExportPath": "\\\\openinsight-db-srv.na.infineon.com\\apps\\Metrology\\Data",
"Serilog": {
"Using": [
"Serilog.Sinks.Console",
"Serilog.Sinks.File"
],
"MinimumLevel": "Debug",
"WriteTo": [
{
"Name": "Debug",
"Args": {
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] ({SourceContext}.{MethodName}) ({InstanceId}) ({RemoteIpAddress}) {Message}{NewLine}{Exception}"
}
},
{
"Name": "Console",
"Args": {
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] ({SourceContext}.{MethodName}) ({InstanceId}) ({RemoteIpAddress}) {Message}{NewLine}{Exception}"
}
},
{
"Name": "File",
"Args": {
"path": "%workingDirectory% - Log/log-.txt",
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] ({SourceContext}.{MethodName}) ({InstanceId}) ({RemoteIpAddress}) {Message}{NewLine}{Exception}",
"rollingInterval": "Hour"
}
}
],
"Enrich": [
"FromLogContext",
"WithMachineName",
"WithThreadId"
],
"Properties": {
"Application": "Sample"
}
},
"URLs": "https://localhost:7130;http://localhost:5126",
"WorkingDirectoryName": "IFXApps"
}

View File

@ -1,60 +0,0 @@
{
"AllowedHosts": "*",
"ApiLoggingContentTypes": "application/json",
"ApiLoggingPathPrefixes": "/api/inbound",
"ApiLogPath": "D:\\Metrology\\MetrologyAPILogs",
"AttachmentPath": "\\\\messv02ecc1.ec.local\\EC_Metrology_Si\\MetrologyAttachments",
"BuildNumber": "1",
"Company": "Infineon Technologies Americas Corp.",
"ConnectionString": "Data Source=messv01ec.ec.local\\PROD1,53959;Integrated Security=True;Initial Catalog=Metrology_Archive;",
"GitCommitSeven": "1234567",
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Log4netProvider": "Debug",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"InboundApiAllowedIPList": "",
"OIExportPath": "\\\\openinsight-db-srv.na.infineon.com\\apps\\Metrology\\Data",
"Serilog": {
"Using": [
"Serilog.Sinks.Console",
"Serilog.Sinks.File"
],
"MinimumLevel": "Debug",
"WriteTo": [
{
"Name": "Debug",
"Args": {
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] ({SourceContext}.{MethodName}) ({InstanceId}) ({RemoteIpAddress}) {Message}{NewLine}{Exception}"
}
},
{
"Name": "Console",
"Args": {
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] ({SourceContext}.{MethodName}) ({InstanceId}) ({RemoteIpAddress}) {Message}{NewLine}{Exception}"
}
},
{
"Name": "File",
"Args": {
"path": "%workingDirectory% - Log/log-.txt",
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] ({SourceContext}.{MethodName}) ({InstanceId}) ({RemoteIpAddress}) {Message}{NewLine}{Exception}",
"rollingInterval": "Hour"
}
}
],
"Enrich": [
"FromLogContext",
"WithMachineName",
"WithThreadId"
],
"Properties": {
"Application": "Sample"
}
},
"URLs": "http://localhost:5002;",
"WorkingDirectoryName": "IFXApps"
}

View File

@ -1,4 +1,5 @@
using Microsoft.AspNetCore.Mvc;
using Infineon.Monitoring.MonA;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Logging;
using OI.Metrology.Shared.DataModels;
@ -17,11 +18,13 @@ public class ExportController : Controller
private readonly ILogger _Logger;
private readonly bool _IsTestDatabase;
private readonly IMetrologyRepo _Repo;
private readonly AppSettings _AppSettings;
public ExportController(AppSettings appSettings, ILogger<ExportController> logger, IMetrologyRepo repo)
{
_Repo = repo;
_Logger = logger;
_AppSettings = appSettings;
_IsTestDatabase = appSettings.ConnectionString.Contains("test", StringComparison.InvariantCultureIgnoreCase);
}
@ -40,6 +43,8 @@ public class ExportController : Controller
StartTime = DateTime.Now.AddMonths(-1),
EndTime = DateTime.Now
};
MonIn monIn = MonIn.GetInstance();
_ = monIn.SendStatus(_AppSettings.MonASite, _AppSettings.MonAResource, "Heartbeat", State.Up);
return View(model);
}

View File

@ -31,10 +31,13 @@ public class PagesController : Controller
[HttpGet]
[Route("/AwaitingDispo")]
public IActionResult AwaitingDispo() => View();
[Route("/Metrology/AwaitingDispo")]
public IActionResult AwaitingDispo() =>
View();
[HttpGet]
[Route("/RunInfo")]
[Route("/Metrology/RunInfo")]
public IActionResult RunInfo([FromQuery] int tooltypeid = 1, [FromQuery] int headerid = 0)
{
RunInfo m = new()
@ -52,7 +55,9 @@ public class PagesController : Controller
[HttpGet]
[Route("/RunHeaders")]
public IActionResult RunHeaders() => View();
[Route("/Metrology/RunHeaders")]
public IActionResult RunHeaders() =>
View();
[HttpGet]
[Route("/Crash")]

View File

@ -6,49 +6,54 @@ namespace OI.Metrology.Viewer.Models;
public class AppSettings
{
protected string _ApiLoggingContentTypes;
protected string _ApiLoggingPathPrefixes;
protected string _ApiLogPath;
protected string _AttachmentPath;
protected string _BuildNumber;
protected string _Company;
protected string _ConnectionString;
protected string _GitCommitSeven;
protected string _InboundApiAllowedIPList;
protected string _MonARessource;
protected string _OIExportPath;
protected string _URLs;
protected string _WorkingDirectoryName;
public string ApiLoggingContentTypes => _ApiLoggingContentTypes;
public string ApiLoggingPathPrefixes => _ApiLoggingPathPrefixes;
public string ApiLogPath => _ApiLogPath;
public string AttachmentPath => _AttachmentPath;
public string BuildNumber => _BuildNumber;
public string Company => _Company;
public string ConnectionString => _ConnectionString;
public string GitCommitSeven => _GitCommitSeven;
public string InboundApiAllowedIPList => _InboundApiAllowedIPList;
public string MonARessource => _MonARessource;
public string OIExportPath => _OIExportPath;
public string URLs => _URLs;
public string WorkingDirectoryName => _WorkingDirectoryName;
public string ApiLoggingContentTypes { init; get; }
public string ApiLoggingPathPrefixes { init; get; }
public string ApiLogPath { init; get; }
public string AttachmentPath { init; get; }
public string BuildNumber { init; get; }
public string Company { init; get; }
public string ConnectionString { init; get; }
public string GitCommitSeven { init; get; }
public string InboundApiAllowedIPList { init; get; }
public string MonAResource { init; get; }
public string MonASite { init; get; }
public string Oi2SqlConnectionString { init; get; }
public string OIExportPath { init; get; }
public string URLs { init; get; }
public string WorkingDirectoryName { init; get; }
[JsonConstructor]
public AppSettings(string apiLoggingContentTypes, string apiLoggingPathPrefixes, string apiLogPath, string attachmentPath, string buildNumber, string company, string connectionString, string gitCommitSeven, string inboundApiAllowedIPList, string monARessource, string oiExportPath, string urls, string workingDirectoryName)
public AppSettings(string apiLoggingContentTypes,
string apiLoggingPathPrefixes,
string apiLogPath,
string attachmentPath,
string buildNumber,
string company,
string connectionString,
string gitCommitSeven,
string inboundApiAllowedIPList,
string monAResource,
string monASite,
string oi2SqlConnectionString,
string oiExportPath,
string urls,
string workingDirectoryName)
{
_ApiLoggingContentTypes = apiLoggingContentTypes;
_ApiLoggingPathPrefixes = apiLoggingPathPrefixes;
_ApiLogPath = apiLogPath;
_AttachmentPath = attachmentPath;
_BuildNumber = buildNumber;
_Company = company;
_ConnectionString = connectionString;
_GitCommitSeven = gitCommitSeven;
_InboundApiAllowedIPList = inboundApiAllowedIPList;
_MonARessource = monARessource;
_OIExportPath = oiExportPath;
_URLs = urls;
_WorkingDirectoryName = workingDirectoryName;
ApiLoggingContentTypes = apiLoggingContentTypes;
ApiLoggingPathPrefixes = apiLoggingPathPrefixes;
ApiLogPath = apiLogPath;
AttachmentPath = attachmentPath;
BuildNumber = buildNumber;
Company = company;
ConnectionString = connectionString;
GitCommitSeven = gitCommitSeven;
InboundApiAllowedIPList = inboundApiAllowedIPList;
MonAResource = monAResource;
MonASite = monASite;
Oi2SqlConnectionString = oi2SqlConnectionString;
OIExportPath = oiExportPath;
URLs = urls;
WorkingDirectoryName = workingDirectoryName;
}
public override string ToString()

View File

@ -1,3 +1,4 @@
using Microsoft.Extensions.Configuration;
using System.ComponentModel.DataAnnotations;
using System.Text.Json;
@ -6,6 +7,8 @@ namespace OI.Metrology.Viewer.Models.Binder;
public class AppSettings
{
#nullable disable
[Display(Name = "Api Logging Content Types"), Required] public string ApiLoggingContentTypes { get; set; }
[Display(Name = "Api Logging Path Prefixes"), Required] public string ApiLoggingPathPrefixes { get; set; }
[Display(Name = "Api Log Path"), Required] public string ApiLogPath { get; set; }
@ -15,27 +18,14 @@ public class AppSettings
[Display(Name = "Connection String"), Required] public string ConnectionString { get; set; }
[Display(Name = "Git Commit Seven"), Required] public string GitCommitSeven { get; set; }
[Display(Name = "Inbound Api Allowed IP List"), Required] public string InboundApiAllowedIPList { get; set; }
[Display(Name = "MonA Ressource"), Required] public string MonARessource { get; set; }
[Display(Name = "MonA Resource"), Required] public string MonAResource { get; set; }
[Display(Name = "MonA Site"), Required] public string MonASite { get; set; }
[Display(Name = "Oi 2 Sql Connection String"), Required] public string Oi2SqlConnectionString { get; set; }
[Display(Name = "OI Export Path"), Required] public string OIExportPath { get; set; }
[Display(Name = "URLs"), Required] public string URLs { get; set; }
[Display(Name = "Working Directory Name"), Required] public string WorkingDirectoryName { get; set; }
public AppSettings()
{
ApiLoggingContentTypes = string.Empty;
ApiLoggingPathPrefixes = string.Empty;
ApiLogPath = string.Empty;
AttachmentPath = string.Empty;
BuildNumber = string.Empty;
Company = string.Empty;
ConnectionString = string.Empty;
GitCommitSeven = string.Empty;
InboundApiAllowedIPList = string.Empty;
MonARessource = string.Empty;
OIExportPath = string.Empty;
URLs = string.Empty;
WorkingDirectoryName = string.Empty;
}
#nullable restore
public override string ToString()
{
@ -43,4 +33,34 @@ public class AppSettings
return result;
}
private static Models.AppSettings Get(AppSettings appSettings)
{
Models.AppSettings result;
result = new(
appSettings.ApiLoggingContentTypes,
appSettings.ApiLoggingPathPrefixes,
appSettings.ApiLogPath,
appSettings.AttachmentPath,
appSettings.BuildNumber,
appSettings.Company,
appSettings.ConnectionString,
appSettings.GitCommitSeven,
appSettings.InboundApiAllowedIPList,
appSettings.MonAResource,
appSettings.MonASite,
appSettings.Oi2SqlConnectionString,
appSettings.OIExportPath,
appSettings.URLs,
appSettings.WorkingDirectoryName);
return result;
}
public static Models.AppSettings Get(IConfigurationRoot configurationRoot)
{
Models.AppSettings result;
AppSettings appSettings = configurationRoot.Get<AppSettings>();
result = Get(appSettings);
return result;
}
}

View File

@ -1,44 +0,0 @@
using Microsoft.Extensions.Configuration;
using System;
using System.Linq;
using System.Text.Json;
namespace OI.Metrology.Viewer.Models.Stateless;
public abstract class AppSettings
{
#nullable enable
public static Models.AppSettings Get(IConfigurationRoot configurationRoot)
{
Models.AppSettings? result;
Binder.AppSettings appSettings = configurationRoot.Get<Binder.AppSettings>();
string json = JsonSerializer.Serialize(appSettings, new JsonSerializerOptions() { WriteIndented = true });
result = JsonSerializer.Deserialize<Models.AppSettings>(json);
if (result is null)
throw new Exception(json);
if (string.IsNullOrEmpty(result.Company))
throw new Exception(json);
string jsonThis = result.ToString();
if (jsonThis != json)
{
int? check = null;
int min = new int[] { json.Length, jsonThis.Length }.Min();
for (int i = 0; i < min; i++)
{
if (json[i] == jsonThis[i])
continue;
check = i;
break;
}
if (check is null)
throw new Exception();
string a = json[..check.Value].Split(',')[^1];
string b = json[check.Value..].Split(',')[0];
throw new Exception($"{a}{b}");
}
return result;
}
}

View File

@ -47,10 +47,10 @@ public class Program
public static int Main(string[] args)
{
LoggerConfiguration loggerConfiguration = new();
(string assemblyName, WebApplicationOptions webApplicationOptions) = Get(args);
WebApplicationBuilder webApplicationBuilder = WebApplication.CreateBuilder(webApplicationOptions);
(string assemblyName, WebApplicationOptions _) = Get(args);
WebApplicationBuilder webApplicationBuilder = WebApplication.CreateBuilder(args);
_ = webApplicationBuilder.Configuration.AddUserSecrets<Program>();
AppSettings appSettings = Models.Stateless.AppSettings.Get(webApplicationBuilder.Configuration);
AppSettings appSettings = Models.Binder.AppSettings.Get(webApplicationBuilder.Configuration);
if (string.IsNullOrEmpty(appSettings.WorkingDirectoryName))
throw new Exception("Working directory name must have a value!");
string workingDirectory = IWorkingDirectory.GetWorkingDirectory(assemblyName, appSettings.WorkingDirectoryName);
@ -107,6 +107,7 @@ public class Program
_ = webApplication.Lifetime.ApplicationStopped.Register(Log.CloseAndFlush);
_ = ApplicationBuilderSerilogClientExtensions.UseSerilogIngestion(webApplication);
_ = SerilogApplicationBuilderExtensions.UseSerilogRequestLogging(webApplication);
_ = webApplication.UseFileServer(enableDirectoryBrowsing: true);
_ = webApplication.UseStaticFiles();
_ = webApplication.UseSession();
_ = webApplication.UseHttpsRedirection();

View File

@ -25,7 +25,8 @@ public class MetrologyRepo : IMetrologyRepo
private DbConnection GetDbConnection() => _DBConnectionFactory.GetDbConnection();
protected DbProviderFactory GetDbProviderFactory(IDbConnection conn) => DbProviderFactories.GetFactory(conn.GetType().Namespace);
protected DbProviderFactory GetDbProviderFactory(IDbConnection conn) =>
DbProviderFactories.GetFactory(conn.GetType().Namespace);
public bool IsTestDatabase()
{

View File

@ -57,4 +57,12 @@
<ItemGroup>
<None Include="compilerconfig.json" />
</ItemGroup>
<ItemGroup>
<None Include="appsettings.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Include="appsettings.Development.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>

View File

@ -70,7 +70,7 @@
<li>@Html.ActionLink("Run Information", "RunInfo", "Pages", new { area = "" }, null)</li>
<li>@Html.ActionLink("Run Headers", "RunHeaders", "Pages", new { area = "" }, null)</li>
<li>@Html.ActionLink("Export", "Index", "Export", new { area = "" }, null)</li>
<li><a href="http://oi-metrology-viewer-archive.mes.infineon.com/" target="_blank">Archive</a></li>
<li><a href="https://oi-metrology-viewer-archive.mes.infineon.com/" target="_blank">Archive</a></li>
</ul>
<p class="navbar-text navbar-right">
@User.Identity.Name

View File

@ -17,6 +17,9 @@
}
},
"InboundApiAllowedIPList": "",
"MonAResource": "OI_Metrology_Viewer_IFX",
"MonASite": "auc",
"Oi2SqlConnectionString": "Data Source=messv01ec.ec.local\\PROD1,53959;Initial Catalog=LSL2SQL;Persist Security Info=True;User ID=srpadmin;Password=0okm9ijn;",
"OIExportPath": "\\\\openinsight-db-srv.na.infineon.com\\apps\\Metrology\\Data",
"Serilog": {
"Using": [

View File

@ -17,6 +17,9 @@
}
},
"InboundApiAllowedIPList": "",
"MonAResource": "OI_Metrology_Viewer_EC",
"MonASite": "auc",
"Oi2SqlConnectionString": "Data Source=messv01ec.ec.local\\PROD1,53959;Initial Catalog=LSL2SQL;Persist Security Info=True;User ID=srpadmin;Password=0okm9ijn;",
"OIExportPath": "\\\\openinsight-db-srv.na.infineon.com\\apps\\Metrology\\Data",
"Serilog": {
"Using": [