From e6df9ae54e67c6ebf049c95d64df9953b1a5475b Mon Sep 17 00:00:00 2001 From: Mike Phares Date: Mon, 19 May 2025 09:59:09 -0700 Subject: [PATCH] disk-info-helper selenium-helper (Not fully tested) sync-helper (Not fully tested) --- .vscode/.http | 23 ++ File-Watcher.csproj | 13 +- Helpers/DiskInfoHelper.cs | 503 ++++++++++++++++++++++++++++++ Helpers/HelperCamstarOracle.cs | 3 +- Helpers/SeleniumHelper.cs | 45 +++ Helpers/SyncHelper.cs | 51 +++ Models/AppSettings.cs | 12 + Models/DiskInfoConfiguration.cs | 24 ++ Models/InfinityQSConfiguration.cs | 9 - Models/SeleniumConfiguration.cs | 23 ++ Models/SyncConfiguration.cs | 21 ++ Models/Test.cs | 12 + NancyModules/SyncModule.cs | 51 +++ Startup.cs | 19 ++ Worker.cs | 21 +- 15 files changed, 807 insertions(+), 23 deletions(-) create mode 100644 .vscode/.http create mode 100644 Helpers/DiskInfoHelper.cs create mode 100644 Helpers/SeleniumHelper.cs create mode 100644 Helpers/SyncHelper.cs create mode 100644 Models/DiskInfoConfiguration.cs create mode 100644 Models/SeleniumConfiguration.cs create mode 100644 Models/SyncConfiguration.cs create mode 100644 Models/Test.cs create mode 100644 NancyModules/SyncModule.cs create mode 100644 Startup.cs diff --git a/.vscode/.http b/.vscode/.http new file mode 100644 index 0000000..ab0a9a9 --- /dev/null +++ b/.vscode/.http @@ -0,0 +1,23 @@ + +### + +GET https://eaf-dev.mes.infineon.com/bob/v1/sync/ + +### + +POST https://eaf-dev.mes.infineon.com/bob/v1/sync/ +Accept: application/json + +{ + "id": "110738", + "machineId": "30ef1b54e075c5370ce74eea2042cb750be659696b170f8758d219a8f9a88e10", + "page": "time", + "site": "MES", + "time": "1744339499677", + "username": "phares", + "value": "3" +} + +### + +https://eaf-dev.mes.infineon.com/api/v1/ado/ \ No newline at end of file diff --git a/File-Watcher.csproj b/File-Watcher.csproj index 5a61b98..d2c0d57 100644 --- a/File-Watcher.csproj +++ b/File-Watcher.csproj @@ -12,7 +12,12 @@ - + + + + + + @@ -20,12 +25,12 @@ - + - + - + diff --git a/Helpers/DiskInfoHelper.cs b/Helpers/DiskInfoHelper.cs new file mode 100644 index 0000000..6268650 --- /dev/null +++ b/Helpers/DiskInfoHelper.cs @@ -0,0 +1,503 @@ +using File_Watcher.Models; +using System.Collections.ObjectModel; +using System.Diagnostics; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace File_Watcher.Helpers; + +internal static partial class DiskInfoHelper +{ + + public record DiskDrive(string? Caption, + string? DeviceID, + string? FirmwareRevision, + uint? Index, + string? Model, + string? Name, + uint? Partitions, + DiskPartition[]? PartitionCollection, + string? SerialNumber, + ulong? Size, + string? Status, + string? SystemName, + ulong? TotalCylinders, + ulong? TotalHeads) + { + + internal static DiskDrive Get(DiskDrive diskDrive, DiskPartition[] diskPartitions, LogicalDrive[] logicalDrives) + { + DiskDrive result; + DiskPartition[] collection = DiskPartition.Get((from l in diskPartitions where l.DiskIndex == diskDrive.Index select l).ToArray(), logicalDrives); + result = new(Caption: diskDrive.Caption, + DeviceID: diskDrive.DeviceID, + FirmwareRevision: diskDrive.FirmwareRevision, + Index: diskDrive.Index, + Model: diskDrive.Model, + Name: diskDrive.Name, + Partitions: diskDrive.Partitions, + PartitionCollection: collection, + SerialNumber: diskDrive.SerialNumber, + Size: diskDrive.Size, + Status: diskDrive.Status, + SystemName: diskDrive.SystemName, + TotalCylinders: diskDrive.TotalCylinders, + TotalHeads: diskDrive.TotalHeads); + return result; + } + + } + + [JsonSourceGenerationOptions(WriteIndented = true)] + [JsonSerializable(typeof(DiskDrive[]))] + private partial class DiskDriveArraySourceGenerationContext : JsonSerializerContext + { + } + + [JsonSourceGenerationOptions(WriteIndented = true)] + [JsonSerializable(typeof(Dictionary))] + private partial class DictionaryStringObjectSourceGenerationContext : JsonSerializerContext + { + } + + [JsonSourceGenerationOptions(WriteIndented = true)] + [JsonSerializable(typeof(JsonElement))] + private partial class JsonElementSourceGenerationContext : JsonSerializerContext + { + } + + public record DiskPartition(bool? BootPartition, + string? Caption, + string? Description, + string? DeviceID, + uint? DiskIndex, + uint? Index, + LogicalDrive[]? LogicalDrives, + ulong? Size, + ulong? StartingOffset, + string? SystemName, + string? Type) + { + + internal static DiskPartition[] Get(DiskPartition[] diskPartitions, LogicalDrive[] logicalDrives) + { + List results = []; + ulong lowerMatch; + ulong upperMatch; + LogicalDrive[] collection; + DiskPartition diskPartition; + foreach (DiskPartition p in diskPartitions) + { + if (p.Size is null) + continue; + lowerMatch = p.Size.Value - 10240; + upperMatch = p.Size.Value + 10240; + collection = (from l in logicalDrives where l.DriveType != 4 && l.Size > lowerMatch && l.Size < upperMatch select l).ToArray(); + diskPartition = new(BootPartition: p.BootPartition, + Caption: p.Caption, + Description: p.Description, + DeviceID: p.DeviceID, + DiskIndex: p.DiskIndex, + Index: p.Index, + LogicalDrives: collection, + Size: p.Size, + StartingOffset: p.StartingOffset, + SystemName: p.SystemName, + Type: p.Type); + results.Add(diskPartition); + } + return results.ToArray(); + } + + } + + [JsonSourceGenerationOptions(WriteIndented = true)] + [JsonSerializable(typeof(DiskPartition[]))] + private partial class DiskPartitionSourceGenerationContext : JsonSerializerContext + { + } + + public record LogicalDrive(string? Caption, + string? DeviceID, + uint? DriveType, + string? FileSystem, + ulong? FreeSpace, + string? Name, + ulong? PercentageFree, + ulong? PercentageUsed, + string? ProviderName, + ulong? Size, + string? SystemName, + string? VolumeName, + string? VolumeSerialNumber); + + [JsonSourceGenerationOptions(WriteIndented = true)] + [JsonSerializable(typeof(LogicalDrive[]))] + private partial class LogicalDriveSourceGenerationContext : JsonSerializerContext + { + } + + public record Record(long AvailableFreeSpace, + string DriveFormat, + string DriveType, + bool IsReady, + char Name, + ulong PercentageFree, + ulong PercentageUsed, + long TotalFreeSpace, + long TotalSize, + string VolumeLabel) + { + + public static Record Get(DriveInfo driveInfo) => + new(AvailableFreeSpace: driveInfo.AvailableFreeSpace, + DriveFormat: driveInfo.DriveFormat, + DriveType: driveInfo.DriveType.ToString(), + IsReady: driveInfo.IsReady, + Name: driveInfo.Name.ToUpper()[0], + PercentageUsed: (ulong)(Math.Round(driveInfo.AvailableFreeSpace / (double)driveInfo.TotalSize, 2) * 100), + PercentageFree: (ulong)(Math.Round((driveInfo.TotalSize - driveInfo.AvailableFreeSpace) / (double)driveInfo.TotalSize, 2) * 100), + TotalFreeSpace: driveInfo.TotalFreeSpace, + TotalSize: driveInfo.TotalSize, + VolumeLabel: driveInfo.VolumeLabel); + } + + [JsonSourceGenerationOptions(WriteIndented = true)] + [JsonSerializable(typeof(Record[]))] + private partial class RecordSourceGenerationContext : JsonSerializerContext + { + } + + private record Win32(string? DiskDrive, + string? Processor, + string? LogicalDisk, + string? DiskPartition, + string? NetworkAdapter); + + internal static bool WriteDiskInfo(AppSettings appSettings, ILogger logger) + { + string? json = WriteRecord(); + ReadOnlyCollection devices = GetDrives(appSettings, logger); + string yaml = GetYetAnotherMarkupLanguage(devices); + ReadOnlyCollection normalized = GetNormalized(appSettings, logger, devices); + string text = string.Join(Environment.NewLine, normalized); + string markdown = string.Concat("# ", + Environment.MachineName.ToUpper(), + Environment.NewLine, + Environment.NewLine, + "## Normalized", + Environment.NewLine, + Environment.NewLine, + "```log", + Environment.NewLine, + text, + Environment.NewLine, + "```", + Environment.NewLine, + Environment.NewLine, + "## json", + Environment.NewLine, + Environment.NewLine, + "```json", + Environment.NewLine, + json, + Environment.NewLine, + "```", + Environment.NewLine, + Environment.NewLine, + "## yaml", + Environment.NewLine, + Environment.NewLine, + "```yaml", + Environment.NewLine, + yaml, + Environment.NewLine, + "```", + Environment.NewLine); + WriteAllText(Path.Combine(appSettings.DiskInfoConfiguration.Destination, $"{Environment.MachineName.ToUpper()}.md"), markdown); + return true; + } + + private static string WriteRecord() + { + string result; + Record record; + List records = []; + DriveInfo[] drives = DriveInfo.GetDrives(); + foreach (DriveInfo driveInfo in drives) + { + record = Record.Get(driveInfo); + records.Add(record); + } + result = JsonSerializer.Serialize(records.ToArray(), RecordSourceGenerationContext.Default.RecordArray); + return result; + } + + private static ReadOnlyCollection GetDrives(AppSettings appSettings, ILogger logger) + { +#pragma warning disable CA1416 + List results = []; + Win32 win32 = GetWin32(appSettings, logger); + if (win32.DiskDrive is not null && win32.DiskPartition is not null && win32.LogicalDisk is not null) + { + DiskDrive diskDrive; + string diskDriveJson = win32.DiskDrive[0] == '[' ? win32.DiskDrive : $"[{win32.DiskDrive}]"; + string logicalDiskJson = win32.LogicalDisk[0] == '[' ? win32.LogicalDisk : $"[{win32.LogicalDisk}]"; + string diskPartitionJson = win32.DiskPartition[0] == '[' ? win32.DiskPartition : $"[{win32.DiskPartition}]"; + DiskDrive[] diskDrives = JsonSerializer.Deserialize(diskDriveJson, DiskDriveArraySourceGenerationContext.Default.DiskDriveArray) ?? + throw new NullReferenceException(nameof(DiskDrive)); + LogicalDrive[] logicalDrives = JsonSerializer.Deserialize(logicalDiskJson, LogicalDriveSourceGenerationContext.Default.LogicalDriveArray) ?? + throw new NullReferenceException(nameof(LogicalDrive)); + DiskPartition[] diskPartitions = JsonSerializer.Deserialize(diskPartitionJson, DiskPartitionSourceGenerationContext.Default.DiskPartitionArray) ?? + throw new NullReferenceException(nameof(DiskPartition)); + foreach (DiskDrive d in diskDrives) + { + diskDrive = DiskDrive.Get(d, diskPartitions, logicalDrives); + results.Add(diskDrive); + } + } + return results.AsReadOnly(); +#pragma warning restore + } + + private static Win32 GetWin32(AppSettings appSettings, ILogger logger) + { + Win32 win32; + Process? process; + string[] segments; + string standardError; + string standardOutput; + string? diskDrive = null; + string? processor = null; + string? logicalDisk = null; + string? diskPartition = null; + string? networkAdapter = null; + ProcessStartInfo processStartInfo; + string fileName = "powershell.exe"; + string date = DateTime.Now.ToString("yyyy-MM-dd"); + foreach (string className in appSettings.DiskInfoConfiguration.Classes) + { + segments = className.Split(' '); + if (segments[0].Length < 3) + continue; + processStartInfo = new(fileName, $"-NoProfile -ExecutionPolicy ByPass Get-WmiObject {className} | ConvertTo-JSON") + { + RedirectStandardError = true, + RedirectStandardOutput = true, + UseShellExecute = false + }; + try + { + process = Process.Start(processStartInfo); + if (process is not null) + { + for (int j = 1; j < 45; j++) + { + _ = process.WaitForExit(1000); + if (process.HasExited) + break; + } + if (!process.HasExited) + { + logger.LogWarning($"// {segments[0]} Never exited!"); + if (segments[0] is "Win32_DiskDrive" or "Win32_DiskPartition" or "Win32_LogicalDisk") + break; + } + else + { + standardError = process.StandardError.ReadToEnd(); + standardOutput = process.StandardOutput.ReadToEnd(); + logger.LogInformation("// {className}{line}{error}{line}{line}// {output}", segments[0], Environment.NewLine, standardError, Environment.NewLine, Environment.NewLine, standardOutput); + if (string.IsNullOrEmpty(standardError)) + { + if (segments[0] == "Win32_DiskDrive") + diskDrive = standardOutput; + else if (segments[0] == "Win32_DiskPartition") + diskPartition = standardOutput; + else if (segments[0] == "Win32_LogicalDisk") + logicalDisk = standardOutput; + else if (segments[0] == "Win32_NetworkAdapter") + networkAdapter = standardOutput; + else if (segments[0] == "Win32_Processor") + processor = standardOutput; + WriteAllText(Path.Combine(appSettings.DiskInfoConfiguration.Destination, $"{Environment.MachineName.ToUpper()}-{segments[0]}-{date}.json"), standardOutput); + } + } + } + process?.Dispose(); + } + catch (Exception ex) + { + logger.LogError(ex, "Error:"); + } + } + win32 = new(DiskDrive: diskDrive, + Processor: processor, + LogicalDisk: logicalDisk, + DiskPartition: diskPartition, + NetworkAdapter: networkAdapter); + return win32; + } + + public static Dictionary DeserializeAndFlatten(string json, char? remove) + { + Dictionary results = []; + JsonElement jsonElement = JsonSerializer.Deserialize(json, JsonElementSourceGenerationContext.Default.JsonElement); + FillDictionaryFromJToken(results, jsonElement, string.Empty, remove); + return results; + } + + private static void FillDictionaryFromJToken(Dictionary results, JsonElement jsonElement, string prefix, char? remove) + { + switch (jsonElement.ValueKind) + { + case JsonValueKind.Object: + foreach (JsonProperty jsonProperty in jsonElement.EnumerateObject()) + { + FillDictionaryFromJToken(results, jsonProperty.Value, Join(prefix, jsonProperty.Name), remove); + } + break; + + case JsonValueKind.Array: + int index = 0; + foreach (JsonElement value in jsonElement.EnumerateArray()) + { + FillDictionaryFromJToken(results, value, Join(prefix, index.ToString()), remove); + index++; + } + break; + + case JsonValueKind.String: + if (remove is null) + { + results.Add(prefix, jsonElement.ToString()); + } + else + { + results.Add(prefix, jsonElement.ToString().Replace(remove.Value, '_')); + } + break; + + case JsonValueKind.True: + case JsonValueKind.False: + case JsonValueKind.Number: + results.Add(prefix, jsonElement.ToString()); + break; + } + } + + private static string Join(string prefix, string name) => + string.IsNullOrEmpty(prefix) ? name : prefix + "." + name; + + private static string GetYetAnotherMarkupLanguage(ReadOnlyCollection devices) + { + string result; + List results = []; + string json = JsonSerializer.Serialize(devices.ToArray(), DiskDriveArraySourceGenerationContext.Default.DiskDriveArray); + Dictionary keyValuePairs = DeserializeAndFlatten(json, ':'); + string[] lines = JsonSerializer.Serialize(keyValuePairs, DictionaryStringObjectSourceGenerationContext.Default.DictionaryStringObject).Split(Environment.NewLine); + for (int i = 1; i < lines.Length - 1; i++) + { + results.Add(lines[i].Trim() + .Trim(',') + .Trim('"') + .Replace("\": \"", ": ") + .Replace("\": ", ": ")); + } + result = string.Join(Environment.NewLine, results); + return result; + } + + private static string GetSizeWithSuffix(ulong value) + { + string result; + int i = 0; + double displayValue = value * 1f; + string[] SizeSuffixes = ["bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"]; + while (Math.Round(displayValue / 1024f) >= 1) + { + displayValue /= 1024; + i++; + } + result = string.Format("{0:n1} {1}", displayValue, SizeSuffixes[i]); + return result; + } + + private static void WriteAllText(string path, string text) + { + string check = !File.Exists(path) ? string.Empty : File.ReadAllText(path); + if (check != text) + File.WriteAllText(path, text); + } + + private static ReadOnlyCollection GetNormalized(AppSettings appSettings, ILogger logger, ReadOnlyCollection drives) + { + List results = []; + decimal free; + decimal used; + string display; + int deviceCount; + int offsetCount; + string deviceSize; + int partitionCount; + results.Add("Max"); + string offsetDisplay; + string partitionSize; + decimal devicePercent; + string logicalDriveUsed; + string logicalDriveSize; + decimal partitionPercent; + int logicalDriveFreeCount; + int logicalDriveUsedCount; + decimal partitionDecimalSize; + string logicalDriveFreeSpace; + decimal logicalDriveDecimalFreeSpace; + DiskInfoConfiguration diskInfoConfiguration = appSettings.DiskInfoConfiguration; + results.Add($"{new string('-', diskInfoConfiguration.Bars)} Value of Max Argument"); + foreach (DiskDrive drive in drives.OrderBy(l => l.Index)) + { + if (drive.Size is null || drive.PartitionCollection is null) + continue; + devicePercent = drive.Size.Value / diskInfoConfiguration.Max; + deviceSize = GetSizeWithSuffix(drive.Size.Value); + results.Add($"{drive.DeviceID} - Cylinders: {drive.TotalCylinders} - {drive.Model}"); + deviceCount = (int)Math.Round(devicePercent * diskInfoConfiguration.Bars); + results.Add($"{new string('-', deviceCount)} {Math.Round(devicePercent, 2) * 100:000}% of Max Argument {deviceSize}"); + foreach (DiskPartition partition in drive.PartitionCollection.OrderBy(l => l.Index)) + { + if (partition.Size is null || partition.StartingOffset is null || partition.LogicalDrives is null) + continue; + partitionPercent = partition.Size.Value / diskInfoConfiguration.Max; + partitionSize = GetSizeWithSuffix(partition.Size.Value); + partitionCount = (int)Math.Round(partitionPercent * diskInfoConfiguration.Bars); + offsetCount = (int)Math.Round(partition.StartingOffset.Value / diskInfoConfiguration.Max * diskInfoConfiguration.Bars); + offsetDisplay = new string('_', offsetCount); + results.Add($"{partition.DeviceID} - {string.Join(", ", partition.LogicalDrives.Select(l => l.DeviceID))}"); + results.Add($"{offsetDisplay}{new string('-', partitionCount)}{new string('_', diskInfoConfiguration.Bars - offsetCount - partitionCount)} {Math.Round(partitionPercent, 2) * 100:000}% of Disk {partitionSize}"); + foreach (LogicalDrive logicalDrive in partition.LogicalDrives) + { + if (logicalDrive.Size is null || logicalDrive.FreeSpace is null) + continue; + if ((int)Math.Round(logicalDrive.Size.Value / diskInfoConfiguration.Max * diskInfoConfiguration.Bars) != (int)Math.Round(partition.Size.Value / diskInfoConfiguration.Max * diskInfoConfiguration.Bars)) + { + logger.LogWarning("logicalDrive.Size !~ partition.Size"); + break; + } + partitionDecimalSize = partition.Size.Value; + logicalDriveDecimalFreeSpace = logicalDrive.FreeSpace.Value; + logicalDriveSize = GetSizeWithSuffix(logicalDrive.Size.Value); + logicalDriveFreeSpace = GetSizeWithSuffix(logicalDrive.FreeSpace.Value); + logicalDriveUsed = GetSizeWithSuffix(logicalDrive.Size.Value - logicalDrive.FreeSpace.Value); + logicalDriveFreeCount = (int)Math.Round(logicalDriveDecimalFreeSpace / diskInfoConfiguration.Max * diskInfoConfiguration.Bars); + display = string.IsNullOrEmpty(logicalDrive.DeviceID) ? "Partition" : logicalDrive.DeviceID; + logicalDriveUsedCount = (int)Math.Round((partitionDecimalSize - logicalDriveDecimalFreeSpace) / diskInfoConfiguration.Max * diskInfoConfiguration.Bars); + free = (int)(Math.Round(logicalDriveDecimalFreeSpace / partitionDecimalSize, 2) * 100); + used = (int)(Math.Round((partitionDecimalSize - logicalDriveDecimalFreeSpace) / partitionDecimalSize, 2) * 100); + results.Add($"{offsetDisplay}{new string('-', logicalDriveUsedCount)}{new string('*', logicalDriveFreeCount)}{new string('_', diskInfoConfiguration.Bars - offsetCount - logicalDriveUsedCount - logicalDriveFreeCount)} {used:000}% of [{display}] {logicalDriveUsed} ({free:000}% {logicalDriveFreeSpace} free)"); + } + } + } + return results.AsReadOnly(); + } + +} \ No newline at end of file diff --git a/Helpers/HelperCamstarOracle.cs b/Helpers/HelperCamstarOracle.cs index a33e0a2..b2f53a1 100644 --- a/Helpers/HelperCamstarOracle.cs +++ b/Helpers/HelperCamstarOracle.cs @@ -68,7 +68,7 @@ internal static partial class HelperCamstarOracle return results; } - internal static bool Check(AppSettings appSettings, ILogger logger, CancellationToken cancellationToken) + internal static bool Check(AppSettings appSettings, IHttpClientFactory httpClientFactory, ILogger logger, CancellationToken cancellationToken) { if (_MonIn is null) throw new NullReferenceException(nameof(_MonIn)); @@ -100,6 +100,7 @@ internal static partial class HelperCamstarOracle File.WriteAllLines(Path.Combine(directory, $"{dateTime.Ticks}.tsv"), lines); if (_LastValue is null || _LastUpload is null || _LastValue.Value != lines.Count || new TimeSpan(dateTime.Ticks - _LastUpload.Value.Ticks).TotalMinutes > 5) { + Heartbeat(appSettings, httpClientFactory, logger, State.Up, cancellationToken); Task httpResponseMessage = _MonIn.SendPerformanceMessage(camstarOracleConfiguration.MonitorApplicationSite, camstarOracleConfiguration.MonitorApplicationResource, performanceName, value: lines.Count, description: string.Empty); httpResponseMessage.Wait(cancellationToken); if (httpResponseMessage.Result.StatusCode != System.Net.HttpStatusCode.OK) diff --git a/Helpers/SeleniumHelper.cs b/Helpers/SeleniumHelper.cs new file mode 100644 index 0000000..424702b --- /dev/null +++ b/Helpers/SeleniumHelper.cs @@ -0,0 +1,45 @@ +using File_Watcher.Models; +#if Selenium +using OpenQA.Selenium; +using OpenQA.Selenium.Edge; +#endif + +namespace File_Watcher.Helpers; + +internal static partial class SeleniumHelper +{ + + // + // + + internal static bool HyperTextMarkupLanguageToPortableNetworkGraphics(AppSettings appSettings, ILogger logger) + { + if (!string.IsNullOrEmpty(appSettings.SeleniumConfiguration.UniformResourceLocator)) + logger.LogInformation("This helper is disabled!"); +#if Selenium + EdgeOptions edgeOptions = new(); + foreach (string edgeOption in appSettings.SeleniumConfiguration.EdgeOptions) + edgeOptions.AddArgument(edgeOption); + EdgeDriver edgeDriver = new(edgeOptions); + string outputFile = Path.Combine(appSettings.SeleniumConfiguration.DestinationDirectory, $"{DateTime.Now:yyyy-MM-dd;HH-mi-ss-fff}.png"); + try + { + edgeDriver.Navigate().GoToUrl(appSettings.SeleniumConfiguration.UniformResourceLocator); +#pragma warning disable CS8602, CS8604 + int fullWidth = int.Parse(edgeDriver.ExecuteScript("return document.body.parentNode.scrollWidth").ToString()); + int fullHeight = int.Parse(edgeDriver.ExecuteScript("return document.body.parentNode.scrollHeight").ToString()); +#pragma warning restore CS8602, CS8604 + edgeDriver.Manage().Window.Size = new(fullWidth, fullHeight); + Screenshot screenshot = edgeDriver.GetScreenshot(); + screenshot.SaveAsFile(outputFile); + } + catch (Exception ex) + { + logger.LogError(ex, ex.Message); + } + edgeDriver.Close(); +#endif + return true; + } + +} diff --git a/Helpers/SyncHelper.cs b/Helpers/SyncHelper.cs new file mode 100644 index 0000000..c7431f6 --- /dev/null +++ b/Helpers/SyncHelper.cs @@ -0,0 +1,51 @@ +using File_Watcher.Models; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace File_Watcher.Helpers; + +internal static partial class SyncHelper +{ + + private record Record(string RelativePath, + long Size, + long Ticks); + + private record RelativePath(string Path, + Record[] Records); + + [JsonSourceGenerationOptions(WriteIndented = true)] + [JsonSerializable(typeof(RelativePath))] + private partial class RelativePathSourceGenerationContext : JsonSerializerContext + { + } + + [JsonSourceGenerationOptions(WriteIndented = true)] + [JsonSerializable(typeof(Dictionary))] + private partial class DictionaryStringObjectBSourceGenerationContext : JsonSerializerContext + { + } + + internal static bool Check(AppSettings _, ILogger __) => + true; + + internal static string GetReply(string body, Dictionary keyValuePairs) + { + string? json; + RelativePath? relativePath; + if (!string.IsNullOrEmpty(body) && body[0] == '{') + { + File.WriteAllText(".json", body); + relativePath = JsonSerializer.Deserialize(body, RelativePathSourceGenerationContext.Default.RelativePath) ?? throw new NullReferenceException(); + } + else + { + json = JsonSerializer.Serialize(keyValuePairs, DictionaryStringObjectBSourceGenerationContext.Default.DictionaryStringObject); + File.WriteAllText(".json", json); + relativePath = JsonSerializer.Deserialize(json, RelativePathSourceGenerationContext.Default.RelativePath) ?? throw new NullReferenceException(); + } + if (relativePath is null) + { } + return $"wait-{relativePath?.Records.Length}"; + } +} \ No newline at end of file diff --git a/Models/AppSettings.cs b/Models/AppSettings.cs index 781e502..c08c6eb 100644 --- a/Models/AppSettings.cs +++ b/Models/AppSettings.cs @@ -7,6 +7,7 @@ namespace File_Watcher.Models; public record AppSettings(CamstarOracleConfiguration CamstarOracleConfiguration, CompassConfiguration CompassConfiguration, DeterministicHashCodeConfiguration DeterministicHashCodeConfiguration, + DiskInfoConfiguration DiskInfoConfiguration, DriveConfiguration DriveConfiguration, EAFLogConfiguration EAFLogConfiguration, EDADatabaseConfiguration EDADatabaseConfiguration, @@ -17,8 +18,10 @@ public record AppSettings(CamstarOracleConfiguration CamstarOracleConfiguration, MetrologyConfiguration MetrologyConfiguration, NugetConfiguration NugetConfiguration, ResultSettings ResultSettings, + SeleniumConfiguration SeleniumConfiguration, SerialConfiguration SerialConfiguration, StratusConfiguration StratusConfiguration, + SyncConfiguration SyncConfiguration, TransmissionControlProtocolConfiguration TransmissionControlProtocolConfiguration, WaferCounterConfiguration WaferCounterConfiguration) { @@ -29,6 +32,7 @@ public record AppSettings(CamstarOracleConfiguration CamstarOracleConfiguration, #pragma warning disable IL3050, IL2026 CamstarOracleConfiguration? camstarOracleConfiguration = configurationRoot.GetSection(nameof(CamstarOracleConfiguration)).Get(); CompassConfiguration? compassConfiguration = configurationRoot.GetSection(nameof(CompassConfiguration)).Get(); + DiskInfoConfiguration? diskInfoConfiguration = configurationRoot.GetSection(nameof(DiskInfoConfiguration)).Get(); DeterministicHashCodeConfiguration? deterministicHashCodeConfiguration = configurationRoot.GetSection(nameof(DeterministicHashCodeConfiguration)).Get(); DriveConfiguration? driveConfiguration = configurationRoot.GetSection(nameof(DriveConfiguration)).Get(); EAFLogConfiguration? eafLogConfiguration = configurationRoot.GetSection(nameof(EAFLogConfiguration)).Get(); @@ -40,14 +44,17 @@ public record AppSettings(CamstarOracleConfiguration CamstarOracleConfiguration, MetrologyConfiguration? metrologyConfiguration = configurationRoot.GetSection(nameof(MetrologyConfiguration)).Get(); NugetConfiguration? nugetConfiguration = configurationRoot.GetSection(nameof(NugetConfiguration)).Get(); ResultSettings? resultSettings = configurationRoot.GetSection(nameof(ResultSettings)).Get(); + SeleniumConfiguration? seleniumConfiguration = configurationRoot.GetSection(nameof(SeleniumConfiguration)).Get(); SerialConfiguration? serialConfiguration = configurationRoot.GetSection(nameof(SerialConfiguration)).Get(); StratusConfiguration? stratusConfiguration = configurationRoot.GetSection(nameof(StratusConfiguration)).Get(); + SyncConfiguration? syncConfiguration = configurationRoot.GetSection(nameof(SyncConfiguration)).Get(); TransmissionControlProtocolConfiguration? transmissionControlProtocolConfiguration = configurationRoot.GetSection(nameof(TransmissionControlProtocolConfiguration)).Get(); WaferCounterConfiguration? waferCounterConfiguration = configurationRoot.GetSection(nameof(WaferCounterConfiguration)).Get(); #pragma warning restore IL3050, IL2026 if (camstarOracleConfiguration is null || compassConfiguration is null || deterministicHashCodeConfiguration is null + || diskInfoConfiguration is null || driveConfiguration is null || eafLogConfiguration is null || edaDatabaseConfiguration is null @@ -58,8 +65,10 @@ public record AppSettings(CamstarOracleConfiguration CamstarOracleConfiguration, || metrologyConfiguration is null || nugetConfiguration is null || resultSettings is null + || seleniumConfiguration is null || serialConfiguration is null || stratusConfiguration is null + || syncConfiguration is null || transmissionControlProtocolConfiguration is null || waferCounterConfiguration is null || fileWatcherConfiguration?.Company is null) @@ -78,6 +87,7 @@ public record AppSettings(CamstarOracleConfiguration CamstarOracleConfiguration, result = new(camstarOracleConfiguration, compassConfiguration, deterministicHashCodeConfiguration, + diskInfoConfiguration, driveConfiguration, eafLogConfiguration, edaDatabaseConfiguration, @@ -88,8 +98,10 @@ public record AppSettings(CamstarOracleConfiguration CamstarOracleConfiguration, metrologyConfiguration, nugetConfiguration, resultSettings, + seleniumConfiguration, serialConfiguration, stratusConfiguration, + syncConfiguration, transmissionControlProtocolConfiguration, waferCounterConfiguration); Verify(result); diff --git a/Models/DiskInfoConfiguration.cs b/Models/DiskInfoConfiguration.cs new file mode 100644 index 0000000..d9bf5b1 --- /dev/null +++ b/Models/DiskInfoConfiguration.cs @@ -0,0 +1,24 @@ +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace File_Watcher.Models; + +public record DiskInfoConfiguration(int Bars, + string[] Classes, + string Destination, + decimal Max) +{ + + public override string ToString() + { + string result = JsonSerializer.Serialize(this, DiskInfoConfigurationSourceGenerationContext.Default.DiskInfoConfiguration); + return result; + } + +} + +[JsonSourceGenerationOptions(WriteIndented = true)] +[JsonSerializable(typeof(DiskInfoConfiguration))] +internal partial class DiskInfoConfigurationSourceGenerationContext : JsonSerializerContext +{ +} \ No newline at end of file diff --git a/Models/InfinityQSConfiguration.cs b/Models/InfinityQSConfiguration.cs index 4e2ec5b..7b856ec 100644 --- a/Models/InfinityQSConfiguration.cs +++ b/Models/InfinityQSConfiguration.cs @@ -3,15 +3,6 @@ using System.Text.Json.Serialization; namespace File_Watcher.Models; -public record Test(string Name, - long Value); - -[JsonSourceGenerationOptions(WriteIndented = true)] -[JsonSerializable(typeof(Test[]))] -internal partial class TestCollectionSourceGenerationContext : JsonSerializerContext -{ -} - public record InfinityQSConfiguration(string ConnectionString, string DestinationDirectory, string EncryptedPassword, diff --git a/Models/SeleniumConfiguration.cs b/Models/SeleniumConfiguration.cs new file mode 100644 index 0000000..94f0b1f --- /dev/null +++ b/Models/SeleniumConfiguration.cs @@ -0,0 +1,23 @@ +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace File_Watcher.Models; + +public record SeleniumConfiguration(string DestinationDirectory, + string[] EdgeOptions, + string UniformResourceLocator) +{ + + public override string ToString() + { + string result = JsonSerializer.Serialize(this, SeleniumConfigurationSourceGenerationContext.Default.SeleniumConfiguration); + return result; + } + +} + +[JsonSourceGenerationOptions(WriteIndented = true)] +[JsonSerializable(typeof(SeleniumConfiguration))] +internal partial class SeleniumConfigurationSourceGenerationContext : JsonSerializerContext +{ +} \ No newline at end of file diff --git a/Models/SyncConfiguration.cs b/Models/SyncConfiguration.cs new file mode 100644 index 0000000..b078bc1 --- /dev/null +++ b/Models/SyncConfiguration.cs @@ -0,0 +1,21 @@ +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace File_Watcher.Models; + +public record SyncConfiguration(string UniformResourceLocator) +{ + + public override string ToString() + { + string result = JsonSerializer.Serialize(this, SyncConfigurationSourceGenerationContext.Default.SyncConfiguration); + return result; + } + +} + +[JsonSourceGenerationOptions(WriteIndented = true)] +[JsonSerializable(typeof(SyncConfiguration))] +internal partial class SyncConfigurationSourceGenerationContext : JsonSerializerContext +{ +} \ No newline at end of file diff --git a/Models/Test.cs b/Models/Test.cs new file mode 100644 index 0000000..370c85c --- /dev/null +++ b/Models/Test.cs @@ -0,0 +1,12 @@ +using System.Text.Json.Serialization; + +namespace File_Watcher.Models; + +public record Test(string Name, + long Value); + +[JsonSourceGenerationOptions(WriteIndented = true)] +[JsonSerializable(typeof(Test[]))] +internal partial class TestCollectionSourceGenerationContext : JsonSerializerContext +{ +} diff --git a/NancyModules/SyncModule.cs b/NancyModules/SyncModule.cs new file mode 100644 index 0000000..6ecffa3 --- /dev/null +++ b/NancyModules/SyncModule.cs @@ -0,0 +1,51 @@ +using Nancy; +using Nancy.Extensions; + +namespace File_Watcher.NancyModules; + +public class SyncModule : NancyModule +{ + + public SyncModule() + { + Get("/bob/v1/sync/", _ => + { + string? result; + try + { + string query = Request.Url.Query; + IDictionary> collection = Nancy.Helpers.HttpUtility.ParseQueryString(query).ToDictionary(); + result = collection is null ? "null" : collection.ToString(); + } + catch (Exception ex) + { + result = ex.Message; + } + return result; + }); + Post("/bob/v1/sync/", _ => + { + string result; + // Notification notification; + // ILog log = LogManager.GetLogger(typeof(SyncModule)); + // log.Info($"Enter-{nameof(Post)}"); + try + { + string body = Request.Body.AsString(); + DynamicDictionary form = Request.Form; + Dictionary keyValuePairs = form.ToDictionary(); + string reply = Helpers.SyncHelper.GetReply(body, keyValuePairs); + result = reply; + } + catch (Exception ex) + { + // log.Fatal($"Exception-{nameof(Post)}{Environment.NewLine}{ex.Message}{Environment.NewLine}{Environment.NewLine}{ex.StackTrace}"); + result = ex.Message; + throw; + } + // log.Info($"Return-{nameof(Post)}"); + return result; + }); + } + +} \ No newline at end of file diff --git a/Startup.cs b/Startup.cs new file mode 100644 index 0000000..0d81aff --- /dev/null +++ b/Startup.cs @@ -0,0 +1,19 @@ +using Microsoft.Owin.Cors; +using Nancy.Owin; +using Owin; + +namespace File_Watcher; + +public class Startup +{ + + public Startup() + { } + + public void Configuration(IAppBuilder app) + { + _ = app.UseCors(CorsOptions.AllowAll); + _ = app.UseNancy(); + } + +} \ No newline at end of file diff --git a/Worker.cs b/Worker.cs index d01bb42..0c2e1b2 100644 --- a/Worker.cs +++ b/Worker.cs @@ -7,7 +7,6 @@ namespace File_Watcher; public partial class Worker : BackgroundService { - private int _First; private readonly bool _IsWindowsService; private readonly ILogger _Logger; private readonly AppSettings _AppSettings; @@ -23,6 +22,11 @@ public partial class Worker : BackgroundService { logger.LogInformation("<{folder}>", Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)); } catch (Exception) { } _IsWindowsService = collection.Contains(nameof(WindowsServiceLifetime)); + if (appSettings.FileWatcherConfiguration.Helper == nameof(Helpers.SyncHelper)) + { + _ = Microsoft.Owin.Hosting.WebApp.Start(appSettings.SyncConfiguration.UniformResourceLocator); + logger.LogInformation("Server running on {url}", appSettings.SyncConfiguration.UniformResourceLocator); + } } public override Task StopAsync(CancellationToken cancellationToken) @@ -64,32 +68,31 @@ public partial class Worker : BackgroundService private void BodyInner(CancellationToken cancellationToken) { _Logger.LogInformation("A) Next execute will be at {date}", DateTime.Now.AddMilliseconds(_AppSettings.FileWatcherConfiguration.MillisecondsDelay).ToString("yyyy-MM-dd hh:mm:ss.fff tt")); - if (_First < 9) - { - _First += 1; - if (_AppSettings.FileWatcherConfiguration.Helper == nameof(Helpers.HelperCamstarOracle)) - Helpers.HelperCamstarOracle.Heartbeat(_AppSettings, _HttpClientFactory, _Logger, Infineon.Monitoring.MonA.State.Up, cancellationToken); - } if (!Directory.Exists(_AppSettings.FileWatcherConfiguration.WatchDirectory)) _ = Directory.CreateDirectory(_AppSettings.FileWatcherConfiguration.WatchDirectory); else { _ = _AppSettings.FileWatcherConfiguration.Helper switch { + nameof(Helpers.SyncHelper) => Helpers.SyncHelper.Check(_AppSettings, _Logger), nameof(Helpers.HelperNuget) => Helpers.HelperNuget.Sync(_AppSettings, _Logger), nameof(Helpers.HelperTCP) => Helpers.HelperTCP.ReadWrite(_AppSettings, _Logger), nameof(Helpers.HelperISO) => Helpers.HelperISO.DirectoryToISO(_AppSettings, _Logger), nameof(Helpers.HelperCompass) => Helpers.HelperCompass.CopyFile(_AppSettings, _Logger), nameof(Helpers.HelperStratus) => Helpers.HelperStratus.MoveFile(_AppSettings, _Logger), nameof(Helpers.HelperEAFLog) => Helpers.HelperEAFLog.DeleteFiles(_AppSettings, _Logger), - nameof(Helpers.HelperInfinityQS) => Helpers.HelperInfinityQS.ProcessStart(_AppSettings, _Logger), + nameof(Helpers.DiskInfoHelper) => Helpers.DiskInfoHelper.WriteDiskInfo(_AppSettings, _Logger), nameof(Helpers.HelperEventLog) => Helpers.HelperEventLog.ClearEventLogs(_AppSettings, _Logger), + nameof(Helpers.HelperInfinityQS) => Helpers.HelperInfinityQS.ProcessStart(_AppSettings, _Logger), nameof(Helpers.HelperWaferCounter) => Helpers.HelperWaferCounter.MoveFile(_AppSettings, _Logger), nameof(Helpers.HelperSerial) => Helpers.HelperSerial.ReadWrite(_AppSettings, _Logger, cancellationToken), nameof(Helpers.HelperMetrologyFiles) => Helpers.HelperMetrologyFiles.SortAndDelete(_AppSettings, _Logger), - nameof(Helpers.HelperCamstarOracle) => Helpers.HelperCamstarOracle.Check(_AppSettings, _Logger, cancellationToken), nameof(Helpers.DeterministicHashCodeHelper) => Helpers.DeterministicHashCodeHelper.WindowsWork(_AppSettings, _Logger), +#if Selenium + nameof(Helpers.SeleniumHelper) => Helpers.SeleniumHelper.HyperTextMarkupLanguageToPortableNetworkGraphics(_AppSettings, _Logger), +#endif nameof(Helpers.HelperEDADatabase) => Helpers.HelperEDADatabase.SaveDataCollectionPlans(_AppSettings, _Logger, cancellationToken), + nameof(Helpers.HelperCamstarOracle) => Helpers.HelperCamstarOracle.Check(_AppSettings, _HttpClientFactory, _Logger, cancellationToken), _ => throw new NotSupportedException() }; }