4 Commits

Author SHA1 Message Date
5603d01412 national-instruments-helper 2025-08-18 12:52:48 -07:00
9b61eceb80 Updated to Phares 8.0.118.14751 for Shared and Metadata 2025-07-20 08:28:52 -07:00
97797fc440 disk-info-helper
selenium-helper (Not fully tested)

sync-helper (Not fully tested)
2025-06-23 11:16:17 -07:00
e50a90f0fc decryptedPassword 2025-04-29 14:33:00 -07:00
46 changed files with 1948 additions and 64 deletions

View File

@ -118,7 +118,7 @@ dotnet_diagnostic.CA2254.severity = none # CA2254: The logging message template
dotnet_diagnostic.IDE0001.severity = warning # IDE0001: Simplify name dotnet_diagnostic.IDE0001.severity = warning # IDE0001: Simplify name
dotnet_diagnostic.IDE0002.severity = warning # Simplify (member access) - System.Version.Equals("1", "2"); Version.Equals("1", "2"); dotnet_diagnostic.IDE0002.severity = warning # Simplify (member access) - System.Version.Equals("1", "2"); Version.Equals("1", "2");
dotnet_diagnostic.IDE0004.severity = warning # IDE0004: Cast is redundant. dotnet_diagnostic.IDE0004.severity = warning # IDE0004: Cast is redundant.
dotnet_diagnostic.IDE0005.severity = warning # Using directive is unnecessary dotnet_diagnostic.IDE0005.severity = none # Using directive is unnecessary
dotnet_diagnostic.IDE0010.severity = none # Add missing cases to switch statement (IDE0010) dotnet_diagnostic.IDE0010.severity = none # Add missing cases to switch statement (IDE0010)
dotnet_diagnostic.IDE0028.severity = error # IDE0028: Collection initialization can be simplified dotnet_diagnostic.IDE0028.severity = error # IDE0028: Collection initialization can be simplified
dotnet_diagnostic.IDE0031.severity = warning # Use null propagation (IDE0031) dotnet_diagnostic.IDE0031.severity = warning # Use null propagation (IDE0031)

23
.vscode/.http vendored Normal file
View File

@ -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/

2
.vscode/launch.json vendored
View File

@ -8,7 +8,7 @@
"name": ".NET Core Launch (console)", "name": ".NET Core Launch (console)",
"type": "coreclr", "type": "coreclr",
"request": "launch", "request": "launch",
"preLaunchTask": "build", "preLaunchTask": "Build",
"program": "${workspaceFolder}/bin/Debug/net8.0/win-x64/File-Watcher.dll", "program": "${workspaceFolder}/bin/Debug/net8.0/win-x64/File-Watcher.dll",
"args": [ "args": [
"s" "s"

View File

@ -42,6 +42,7 @@
"PDSF", "PDSF",
"pged", "pged",
"Phares", "Phares",
"Pinnable",
"Rijndael", "Rijndael",
"Serilog", "Serilog",
"SUBM", "SUBM",

18
.vscode/tasks.json vendored
View File

@ -7,8 +7,6 @@
"type": "process", "type": "process",
"args": [ "args": [
"user-secrets", "user-secrets",
"-p",
"${workspaceFolder}/File-Watcher.csproj",
"init" "init"
], ],
"problemMatcher": "$msCompile" "problemMatcher": "$msCompile"
@ -19,8 +17,6 @@
"type": "process", "type": "process",
"args": [ "args": [
"user-secrets", "user-secrets",
"-p",
"${workspaceFolder}/File-Watcher.csproj",
"set", "set",
"_UserSecretsId", "_UserSecretsId",
"6516d19d6569" "6516d19d6569"
@ -43,19 +39,16 @@
"problemMatcher": "$msCompile" "problemMatcher": "$msCompile"
}, },
{ {
"label": "build", "label": "Build",
"command": "dotnet", "command": "dotnet",
"type": "process", "type": "process",
"args": [ "args": [
"build", "build"
"${workspaceFolder}/File-Watcher.csproj",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
], ],
"problemMatcher": "$msCompile" "problemMatcher": "$msCompile"
}, },
{ {
"label": "Format-Whitespaces", "label": "Format Whitespaces",
"command": "dotnet", "command": "dotnet",
"type": "process", "type": "process",
"args": [ "args": [
@ -74,10 +67,7 @@
"win-x64", "win-x64",
"-c", "-c",
"Release", "Release",
"-p:PublishAot=true", "-p:PublishAot=true"
"${workspaceFolder}/File-Watcher.csproj",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
], ],
"problemMatcher": "$msCompile" "problemMatcher": "$msCompile"
}, },

View File

@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk.Worker"> <Project Sdk="Microsoft.NET.Sdk.Worker">
<PropertyGroup> <PropertyGroup>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
@ -12,7 +12,7 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="CliWrap" Version="3.8.2" /> <PackageReference Include="CliWrap" Version="3.8.2" />
<PackageReference Include="DiscUtils.Iso9660" Version="0.16.13" /> <PackageReference Include="DiscUtils.Iso9660" Version="0.16.13" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="8.0.14" /> <PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="8.0.16" />
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="8.0.1" /> <PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="8.0.1" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.1" /> <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.1" />
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="8.0.1" /> <PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="8.0.1" />
@ -20,13 +20,20 @@
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="8.0.1" /> <PackageReference Include="Microsoft.Extensions.Logging.Console" Version="8.0.1" />
<PackageReference Include="Microsoft.Extensions.Logging.EventLog" Version="8.0.1" /> <PackageReference Include="Microsoft.Extensions.Logging.EventLog" Version="8.0.1" />
<PackageReference Include="Oracle.ManagedDataAccess.Core" Version="23.7.0" /> <PackageReference Include="Oracle.ManagedDataAccess.Core" Version="23.7.0" />
<PackageReference Include="runtime.win-x64.Microsoft.DotNet.ILCompiler" Version="8.0.14" /> <PackageReference Include="runtime.win-x64.Microsoft.DotNet.ILCompiler" Version="8.0.16" />
<PackageReference Include="ShellProgressBar" Version="5.2.0" />
<PackageReference Include="System.Data.SqlClient" Version="4.8.6" /> <PackageReference Include="System.Data.SqlClient" Version="4.8.6" />
<PackageReference Include="System.Drawing.Common" Version="8.0.14" /> <PackageReference Include="System.Drawing.Common" Version="8.0.16" />
<PackageReference Include="System.IO.Ports" Version="8.0.0" /> <PackageReference Include="System.IO.Ports" Version="8.0.0" />
<PackageReference Include="System.Text.Json" Version="9.0.3" /> <PackageReference Include="System.Text.Json" Version="9.0.5" />
<PackageReference Include="Phares.AA.Shared" Version="8.0.114.12235" /> <PackageReference Include="Phares.Shared" Version="8.0.118.14751" />
<PackageReference Include="Phares.AA.Metadata" Version="8.0.114.12235" /> <PackageReference Include="Phares.Metadata" Version="8.0.118.14751" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Nancy.Owin" Version="2.0.0" />
<PackageReference Include="Microsoft.Owin" Version="4.2.2" />
<PackageReference Include="Microsoft.Owin.Cors" Version="4.2.2" />
<PackageReference Include="Microsoft.Owin.Hosting" Version="4.2.2" />
<PackageReference Include="Microsoft.Owin.Host.HttpListener" Version="4.2.2" />
<PackageReference Include="ShellProgressBar" Version="5.2.0" />
</ItemGroup> </ItemGroup>
</Project> </Project>

12
Helpers/DAQmx/CSVTime.cs Normal file
View File

@ -0,0 +1,12 @@
namespace Helpers.DAQmx;
#pragma warning disable IDE1006 // Naming Styles
#pragma warning disable IDE0044 // Add readonly modifier
#pragma warning disable IDE0051 // Remove unused private members
#pragma warning disable CS0169 // Field is never assigned to, and will always have its default value
public struct CSVTime
{
private ulong lsb;
private long msb;
}

View File

@ -0,0 +1,17 @@
using System.Runtime.InteropServices;
namespace Helpers.DAQmx;
#pragma warning disable IDE0044 // Add readonly modifier
#pragma warning disable IDE0051 // Remove unused private members
#pragma warning disable IDE1006 // Naming Styles
#pragma warning disable CS0169 // Field is never assigned to, and will always have its default value
[StructLayout(LayoutKind.Explicit)]
public struct CVIAbsoluteTime
{
[FieldOffset(0)]
private CSVTime cviTime;
[FieldOffset(0)]
private uint[] u32Data;
}

13
Helpers/DAQmx/DAQmx.cs Normal file
View File

@ -0,0 +1,13 @@
using System.Text;
namespace Helpers.DAQmx;
public static class DAQmx
{
public static string GetErrorString(int errorCode)
{
StringBuilder errorString = new(256);
_ = Interop.DAQmxGetErrorString(errorCode, errorString, (uint)(errorString.Capacity + 1));
return errorString.ToString();
}
}

View File

@ -0,0 +1,7 @@
namespace Helpers.DAQmx;
public enum DAQmxActiveEdge
{
Falling = 10171, // 0x000027BB
Rising = 10280, // 0x00002828
}

View File

@ -0,0 +1,7 @@
namespace Helpers.DAQmx;
public enum DAQmxDataLayout
{
GroupByChannel,
GroupByScanNumber,
}

View File

@ -0,0 +1,7 @@
namespace Helpers.DAQmx;
public enum DAQmxDigitalPatternTriggerWhen
{
PatternDoesNotMatch = 10253, // 0x0000280D
PatternMatches = 10254, // 0x0000280E
}

View File

@ -0,0 +1,7 @@
namespace Helpers.DAQmx;
public enum DAQmxEdge
{
Falling = 10171, // 0x000027BB
Rising = 10280, // 0x00002828
}

View File

@ -0,0 +1,14 @@
namespace Helpers.DAQmx;
public class DAQmxException : Exception
{
public DAQmxException(string message)
: base(message)
{
}
public DAQmxException(int errorCode, string message)
: base(errorCode.ToString() + " - " + message + " (" + DAQmx.GetErrorString(errorCode) + ")")
{
}
}

View File

@ -0,0 +1,7 @@
namespace Helpers.DAQmx;
public enum DAQmxFillMode
{
GroupByChannel,
GroupByScanNumber,
}

View File

@ -0,0 +1,10 @@
namespace Helpers.DAQmx;
public enum DAQmxInputTerminalConfiguration
{
Default = -1, // 0xFFFFFFFF
NonReferencedSingleEnded = 10078, // 0x0000275E
ReferencedSingleEnded = 10083, // 0x00002763
Differential = 10106, // 0x0000277A
Pseudodifferential = 12529, // 0x000030F1
}

View File

@ -0,0 +1,7 @@
namespace Helpers.DAQmx;
public enum DAQmxLevel
{
High = 10192, // 0x000027D0
Low = 10214, // 0x000027E6
}

View File

@ -0,0 +1,7 @@
namespace Helpers.DAQmx;
public enum DAQmxLineGrouping
{
OneChannelForEachLine,
OneChannelForAllLines,
}

View File

@ -0,0 +1,8 @@
namespace Helpers.DAQmx;
public enum DAQmxLoggingMode
{
Off = 10231, // 0x000027F7
LogAndRead = 15842, // 0x00003DE2
Log = 15844, // 0x00003DE4
}

View File

@ -0,0 +1,9 @@
namespace Helpers.DAQmx;
public enum DAQmxLoggingTDMSOperation
{
Open = 10437, // 0x000028C5
OpenOrCreate = 15846, // 0x00003DE6
CreateOrReplace = 15847, // 0x00003DE7
Create = 15848, // 0x00003DE8
}

View File

@ -0,0 +1,5 @@
namespace Helpers.DAQmx;
public class DAQmxMemoryException(string message) : Exception(message)
{
}

View File

@ -0,0 +1,7 @@
namespace Helpers.DAQmx;
public enum DAQmxPolarity
{
ActiveHigh = 10095, // 0x0000276F
ActiveLow = 10096, // 0x00002770
}

View File

@ -0,0 +1,8 @@
namespace Helpers.DAQmx;
public enum DAQmxSampleMode
{
ContinuousSamples = 10123, // 0x0000278B
FiniteSamples = 10178, // 0x000027C2
HardwareTimedSinglePoint = 12522, // 0x000030EA
}

348
Helpers/DAQmx/DAQmxTask.cs Normal file
View File

@ -0,0 +1,348 @@
namespace Helpers.DAQmx;
#pragma warning disable IDE1006 // Naming Styles
#pragma warning disable IDE0044 // Add readonly modifier
#pragma warning disable IDE0051 // Remove unused private members
#pragma warning disable CS0169 // Field is never assigned to, and will always have its default value
public class DAQmxTask
{
private IntPtr taskHandle;
private DAQmxTask()
{
}
public double DT { get; private set; }
public int Channels { get; private set; }
public ulong TotalSamplesRead { get; private set; }
public DateTime TaskStartedUtc { get; private set; }
public ulong TotalSamplesWrite { get; private set; }
public ulong TotalSamplesPerChanRead { get; private set; }
public ulong TotalSamplesPerChanWrite { get; private set; }
public static DAQmxTask Create(string taskName)
{
DAQmxTask result;
IntPtr taskHandle;
int task = Interop.DAQmxCreateTask(taskName, out taskHandle);
if (task < 0)
throw new DAQmxException(task, "Could not create Task");
result = new() { taskHandle = taskHandle, Channels = 0 };
return result;
}
public void ConfigureLoggingTechnicalDataManagementStreaming(string filePath, DAQmxLoggingMode loggingMode, string groupName, DAQmxLoggingTDMSOperation operation)
{
int errorCode = Interop.DAQmxConfigureLogging(taskHandle, filePath, (int)loggingMode, groupName, (int)operation);
if (errorCode < 0)
throw new DAQmxException(errorCode, "Could not configure technical data management streaming logging");
}
public void CreateAnalogInputVoltageChannel(string physicalChannel, string nameToAssignToChannel, DAQmxInputTerminalConfiguration terminalConfig, double minVal, double maxVal, DAQmxUnits units, string customScaleName)
{
int analogInputVoltageChan = Interop.DAQmxCreateAIVoltageChan(taskHandle, physicalChannel, nameToAssignToChannel, (int)terminalConfig, minVal, maxVal, (int)units, customScaleName);
if (analogInputVoltageChan < 0)
throw new DAQmxException(analogInputVoltageChan, "Could not create analog input voltage channel");
++Channels;
}
public void CreateAnalogOutputVoltageChan(string physicalChannel, string nameToAssignToChannel, double minVal, double maxVal, DAQmxUnits units, string customScaleName)
{
int analogOutputVoltageChan = Interop.DAQmxCreateAOVoltageChan(taskHandle, physicalChannel, nameToAssignToChannel, minVal, maxVal, (int)units, customScaleName);
if (analogOutputVoltageChan < 0)
throw new DAQmxException(analogOutputVoltageChan, "Could not create analog output voltage channel");
++Channels;
}
public void CreateDigitalOutputChanel(string lines, string nameToAssignToLines, DAQmxLineGrouping lineGrouping)
{
int doChan = Interop.DAQmxCreateDOChan(taskHandle, lines, nameToAssignToLines, (int)lineGrouping);
if (doChan < 0)
throw new DAQmxException(doChan, "Could not create digital output channel");
++Channels;
}
#if unsafe
public unsafe void ReadAnalogF64(int numSamplesPerChan, double timeout, DAQmxFillMode fillMode, Span<double> data)
{
int arraySizeInSamples = numSamplesPerChan * Channels;
if (data.Length < arraySizeInSamples)
throw new DAQmxMemoryException("Span length too short. (Span length: " + data.Length.ToString() + ", required length: " + arraySizeInSamples.ToString() + ")");
fixed (double* readArray = &data.GetPinnableReference())
{
IntPtr samplesPerChanRead;
int errorCode = Interop.DAQmxReadAnalogF64(taskHandle, numSamplesPerChan, timeout, (int)fillMode, readArray, (uint)arraySizeInSamples, out samplesPerChanRead, IntPtr.Zero);
if (errorCode < 0)
throw new DAQmxException(errorCode, "Could not read samples");
int int32 = samplesPerChanRead.ToInt32();
if (int32 != numSamplesPerChan)
throw new DAQmxException("Could not read requested number of samples");
TotalSamplesPerChanRead += (ulong)int32;
TotalSamplesRead += (ulong)arraySizeInSamples;
}
}
#endif
public double ReadAnalogScalarF64(double timeout)
{
double result;
int errorCode = Interop.DAQmxReadAnalogScalarF64(taskHandle, timeout, out result, IntPtr.Zero);
if (errorCode < 0)
throw new DAQmxException(errorCode, "Could not read samples");
++TotalSamplesRead;
return result;
}
#if unsafe
public double ReadAnalogF64(double timeout)
{
double result = DAQmxReadAnalogF64(timeout);
++TotalSamplesRead;
return result;
}
#endif
#if unsafe
private unsafe double DAQmxReadAnalogF64(double timeout)
{
double results;
int numSamplesPerChan = 1;
uint arraySizeInSamples = 1;
IntPtr samplesPerChanRead = IntPtr.Zero;
double* readArray = stackalloc double[1];
int fillMode = (int)DAQmxFillMode.GroupByChannel;
int errorCode = Interop.DAQmxReadAnalogF64(taskHandle,
numSamplesPerChan,
timeout,
fillMode,
readArray,
arraySizeInSamples,
out samplesPerChanRead,
IntPtr.Zero);
if (errorCode < 0)
throw new DAQmxException(errorCode, "Could not read samples");
results = *readArray;
return results;
}
#endif
public void Start()
{
int errorCode = Interop.DAQmxStartTask(taskHandle);
if (errorCode < 0)
throw new DAQmxException(errorCode, "Could not start Task");
TaskStartedUtc = DateTime.UtcNow;
}
public void Stop()
{
int errorCode = Interop.DAQmxStopTask(taskHandle);
if (errorCode < 0)
throw new DAQmxException(errorCode, "Could not stop Task");
}
public void Clear()
{
int errorCode = Interop.DAQmxClearTask(taskHandle);
if (errorCode < 0)
throw new DAQmxException(errorCode, "Could not clear Task");
}
public void CfgSampleClkTiming(string source, double rate, DAQmxActiveEdge activeEdge, DAQmxSampleMode sampleMode, ulong samplesPerChan)
{
int errorCode = Interop.DAQmxCfgSampClkTiming(taskHandle, source, rate, (int)activeEdge, (int)sampleMode, samplesPerChan);
if (errorCode < 0)
throw new DAQmxException(errorCode, "CfgSampleClkTiming failed.");
DT = 1.0 / SampleClockRate;
}
public void DAQmxCfgHandshakingTiming(DAQmxSampleMode sampleMode, ulong samplesPerChan)
{
int errorCode = Interop.DAQmxCfgHandshakingTiming(taskHandle, (int)sampleMode, samplesPerChan);
if (errorCode < 0)
throw new DAQmxException(errorCode, "DAQmxCfgHandshakingTiming failed.");
}
public void DAQmxCfgBurstHandshakingTimingImportClock(DAQmxSampleMode sampleMode, ulong samplesPerChan, double sampleClkRate, string sampleClkSrc, DAQmxPolarity sampleClkActiveEdge, DAQmxLevel pauseWhen, DAQmxPolarity readyEventActiveLevel)
{
int errorCode = Interop.DAQmxCfgBurstHandshakingTimingImportClock(taskHandle, (int)sampleMode, samplesPerChan, sampleClkRate, sampleClkSrc, (int)sampleClkActiveEdge, (int)pauseWhen, (int)readyEventActiveLevel);
if (errorCode < 0)
throw new DAQmxException(errorCode, "DAQmxCfgBurstHandshakingTimingImportClock failed.");
}
public void DAQmxCfgBurstHandshakingTimingExportClock(DAQmxSampleMode sampleMode, ulong samplesPerChan, double sampleClkRate, string sampleClkOutputTerm, DAQmxPolarity sampleClkPulsePolarity, DAQmxLevel pauseWhen, DAQmxPolarity readyEventActiveLevel)
{
int errorCode = Interop.DAQmxCfgBurstHandshakingTimingExportClock(taskHandle, (int)sampleMode, samplesPerChan, sampleClkRate, sampleClkOutputTerm, (int)sampleClkPulsePolarity, (int)pauseWhen, (int)readyEventActiveLevel);
if (errorCode < 0)
throw new DAQmxException(errorCode, "DAQmxCfgBurstHandshakingTimingExportClock failed.");
}
public void DAQmxCfgChangeDetectionTiming(string risingEdgeChan, string fallingEdgeChan, DAQmxSampleMode sampleMode, ulong samplesPerChan)
{
int errorCode = Interop.DAQmxCfgChangeDetectionTiming(taskHandle, risingEdgeChan, fallingEdgeChan, (int)sampleMode, samplesPerChan);
if (errorCode < 0)
throw new DAQmxException(errorCode, "DAQmxCfgChangeDetectionTiming failed.");
}
public void DAQmxCfgImplicitTiming(DAQmxSampleMode sampleMode, ulong samplesPerChan)
{
int errorCode = Interop.DAQmxCfgImplicitTiming(taskHandle, (int)sampleMode, samplesPerChan);
if (errorCode < 0)
throw new DAQmxException(errorCode, "DAQmxCfgImplicitTiming failed.");
}
public void DAQmxCfgPipelinedSampleClkTiming(string source, double rate, DAQmxActiveEdge activeEdge, DAQmxSampleMode sampleMode, ulong samplesPerChan)
{
int errorCode = Interop.DAQmxCfgPipelinedSampClkTiming(taskHandle, source, rate, (int)activeEdge, (int)sampleMode, samplesPerChan);
if (errorCode < 0)
throw new DAQmxException(errorCode, "DAQmxCfgPipelinedSampleClkTiming failed.");
}
public double SampleClockRate
{
get
{
double result = 0.0;
int sampleClkRate = Interop.DAQmxGetSampClkRate(taskHandle, ref result);
if (sampleClkRate < 0)
throw new DAQmxException(sampleClkRate, "Could not get SampleClockRate");
return result;
}
set
{
int errorCode = Interop.DAQmxSetSampClkRate(taskHandle, value);
if (errorCode < 0)
throw new DAQmxException(errorCode, "Could not set SampleClockRate");
}
}
public double SampleClockMaxRate
{
get
{
double result = 0.0;
int sampleClkMaxRate = Interop.DAQmxGetSampClkMaxRate(taskHandle, ref result);
if (sampleClkMaxRate < 0)
throw new DAQmxException(sampleClkMaxRate, "Could not get SampleClockMaxRate");
return result;
}
}
public void DisableStartTrig()
{
int errorCode = Interop.DAQmxDisableStartTrig(taskHandle);
if (errorCode < 0)
throw new DAQmxException(errorCode, "DisableStartTrig failed.");
}
public void CfgDigEdgeStartTrig(string triggerSource, DAQmxEdge triggerEdge)
{
int errorCode = Interop.DAQmxCfgDigEdgeStartTrig(taskHandle, triggerSource, (int)triggerEdge);
if (errorCode < 0)
throw new DAQmxException(errorCode, "CfgDigEdgeStartTrig failed.");
}
public void CfgAnalogEdgeStartTrig(string triggerSource, DAQmxEdge triggerSlope, double triggerLevel)
{
int errorCode = Interop.DAQmxCfgAnlgEdgeStartTrig(taskHandle, triggerSource, (int)triggerSlope, triggerLevel);
if (errorCode < 0)
throw new DAQmxException(errorCode, "CfgAnalogEdgeStartTrig failed.");
}
public void CfgAnalogMultiEdgeStartTrig(string triggerSources, DAQmxEdge[] triggerSlopes, double[] triggerLevels) =>
throw new NotImplementedException("CfgAnalogMultiEdgeStartTrig is not implemented in this version.");
public void CfgAnalogWindowStartTrig(string triggerSource, DAQmxWindowTriggerWhen triggerWhen, double windowTop, double windowBottom)
{
int errorCode = Interop.DAQmxCfgAnlgWindowStartTrig(taskHandle, triggerSource, (int)triggerWhen, windowTop, windowBottom);
if (errorCode < 0)
throw new DAQmxException(errorCode, "CfgAnalogWindowStartTrig failed.");
}
public void CfgTimeStartTrig(CVIAbsoluteTime when, DAQmxTimescale timescale)
{
int errorCode = Interop.DAQmxCfgTimeStartTrig(taskHandle, when, (int)timescale);
if (errorCode < 0)
throw new DAQmxException(errorCode, "CfgTimeStartTrig failed.");
}
public void CfgDigPatternStartTrig(string triggerSource, string triggerPattern, DAQmxDigitalPatternTriggerWhen triggerWhen)
{
int errorCode = Interop.DAQmxCfgDigPatternStartTrig(taskHandle, triggerSource, triggerPattern, (int)triggerWhen);
if (errorCode < 0)
throw new DAQmxException(errorCode, "CfgDigPatternStartTrig failed.");
}
public void DisableRefTrig()
{
int errorCode = Interop.DAQmxDisableRefTrig(taskHandle);
if (errorCode < 0)
throw new DAQmxException(errorCode, "DisableRefTrig failed.");
}
public void CfgDigEdgeRefTrig(string triggerSource, DAQmxEdge triggerEdge, uint pretriggerSamples)
{
int errorCode = Interop.DAQmxCfgDigEdgeRefTrig(taskHandle, triggerSource, (int)triggerEdge, pretriggerSamples);
if (errorCode < 0)
throw new DAQmxException(errorCode, "CfgDigEdgeRefTrig failed.");
}
public void CfgAnalogEdgeRefTrig(string triggerSource, DAQmxEdge triggerSlope, double triggerLevel, uint pretriggerSamples)
{
int errorCode = Interop.DAQmxCfgAnlgEdgeRefTrig(taskHandle, triggerSource, (int)triggerSlope, triggerLevel, pretriggerSamples);
if (errorCode < 0)
throw new DAQmxException(errorCode, "CfgAnalogEdgeRefTrig failed.");
}
public void CfgAnalogMultiEdgeRefTrig(string triggerSources, DAQmxEdge[] triggerSlopes, double[] triggerLevels, uint pretriggerSamples) =>
throw new NotImplementedException("CfgAnalogMultiEdgeRefTrig is not implemented in this version.");
public void CfgAnalogWindowRefTrig(string triggerSource, DAQmxWindowTriggerWhen triggerWhen, double windowTop, double windowBottom, uint pretriggerSamples)
{
int errorCode = Interop.DAQmxCfgAnlgWindowRefTrig(taskHandle, triggerSource, (int)triggerWhen, windowTop, windowBottom, pretriggerSamples);
if (errorCode < 0)
throw new DAQmxException(errorCode, "CfgAnalogWindowRefTrig failed.");
}
public void CfgDigPatternRefTrig(string triggerSource, string triggerPattern, DAQmxDigitalPatternTriggerWhen triggerWhen, uint pretriggerSamples)
{
int errorCode = Interop.DAQmxCfgDigPatternRefTrig(taskHandle, triggerSource, triggerPattern, (int)triggerWhen, pretriggerSamples);
if (errorCode < 0)
throw new DAQmxException(errorCode, "CfgDigPatternRefTrig failed.");
}
public void WriteAnalogF64(int numSamplesPerChan, bool autoStart, double timeout, DAQmxDataLayout dataLayout, Span<double> data)
{
int num = numSamplesPerChan * Channels;
if (data.Length < num)
throw new DAQmxMemoryException("Span length too short. (Span length: " + data.Length.ToString() + ", required length: " + num.ToString() + ")");
IntPtr samplesPerChanWritten;
int errorCode = Interop.DAQmxWriteAnalogF64(taskHandle, numSamplesPerChan, autoStart, timeout, dataLayout > DAQmxDataLayout.GroupByChannel, data.ToArray(), out samplesPerChanWritten, IntPtr.Zero);
if (errorCode < 0)
throw new DAQmxException(errorCode, "Could not write samples");
int int32 = samplesPerChanWritten.ToInt32();
if (int32 != numSamplesPerChan)
throw new DAQmxException("Could not write requested number of samples");
TotalSamplesPerChanWrite += (ulong)int32;
TotalSamplesWrite += (ulong)num;
}
public void WriteDigitalLines(int numSamplesPerChan, bool autoStart, double timeout, DAQmxDataLayout dataLayout, Span<byte> data)
{
int num = numSamplesPerChan * Channels;
if (data.Length < num)
throw new DAQmxMemoryException("Span length too short. (Span length: " + data.Length.ToString() + ", required length: " + num.ToString() + ")");
IntPtr samplesPerChanWritten;
int errorCode = Interop.DAQmxWriteDigitalLines(taskHandle, numSamplesPerChan, autoStart, timeout, dataLayout > DAQmxDataLayout.GroupByChannel, data.ToArray(), out samplesPerChanWritten, IntPtr.Zero);
if (errorCode < 0)
throw new DAQmxException(errorCode, "Could not write samples");
int int32 = samplesPerChanWritten.ToInt32();
if (int32 != numSamplesPerChan)
throw new DAQmxException("Could not write requested number of samples");
TotalSamplesPerChanWrite += (ulong)int32;
TotalSamplesWrite += (ulong)num;
}
}

View File

@ -0,0 +1,7 @@
namespace Helpers.DAQmx;
public enum DAQmxTimescale
{
HostTime = 16126, // 0x00003EFE
IODeviceTime = 16127, // 0x00003EFF
}

View File

@ -0,0 +1,7 @@
namespace Helpers.DAQmx;
public enum DAQmxUnits
{
FromCustomScale = 10065, // 0x00002751
Volts = 10348, // 0x0000286C
}

View File

@ -0,0 +1,7 @@
namespace Helpers.DAQmx;
public enum DAQmxWindowTriggerWhen
{
EnteringWindow = 10163, // 0x000027B3
LeavingWindow = 10208, // 0x000027E0
}

View File

@ -0,0 +1,7 @@
namespace Helpers.DAQmx;
public enum DAQmxWriteRegenMode
{
AllowRegen = 10097, // 0x00002771
DoNotAllowRegen = 10158, // 0x000027AE
}

431
Helpers/DAQmx/Interop.cs Normal file
View File

@ -0,0 +1,431 @@
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
#pragma warning disable IDE1006 // Naming Styles
#pragma warning disable SYSLIB1054 // Type or member is obsolete
namespace Helpers.DAQmx;
internal class Interop
{ // cSpell:disable
private const string lib = "DAQmx";
private static IntPtr libHandle = IntPtr.Zero;
static Interop() =>
NativeLibrary.SetDllImportResolver(typeof(Interop).Assembly, ImportResolver);
private static IntPtr ImportResolver(string libraryName, Assembly assembly, DllImportSearchPath? searchPath)
{
if (libraryName == "DAQmx" && !(libHandle != IntPtr.Zero))
{
bool loaded;
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
loaded = NativeLibrary.TryLoad("C:/Windows/System32/nicaiu.dll", assembly, searchPath, out libHandle);
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
loaded = NativeLibrary.TryLoad("/usr/local/lib64/libnidaqmxbase.so", assembly, searchPath, out libHandle);
if (!loaded)
loaded = NativeLibrary.TryLoad("/usr/local/lib/libnidaqmxbase.so", assembly, searchPath, out libHandle);
if (!loaded)
loaded = NativeLibrary.TryLoad("/usr/local/natinst/lib/libnidaqmx.so", assembly, searchPath, out libHandle);
if (!loaded)
loaded = NativeLibrary.TryLoad("/usr/lib/x86_64-linux-gnu/libnidaqmx.so", assembly, searchPath, out libHandle);
}
else
throw new PlatformNotSupportedException("Unsupported platform for DAQmx library.");
if (!loaded)
throw new DllNotFoundException($"Failed to load {lib} library.");
}
return libHandle;
}
[DllImport("DAQmx", CallingConvention = CallingConvention.StdCall)]
internal static extern int DAQmxGetSampClkRate(IntPtr taskHandle, ref double data);
[DllImport("DAQmx", CallingConvention = CallingConvention.StdCall)]
internal static extern int DAQmxSetSampClkRate(IntPtr taskHandle, double data);
[DllImport("DAQmx", CallingConvention = CallingConvention.StdCall)]
internal static extern int DAQmxGetSampClkMaxRate(IntPtr taskHandle, ref double data);
[DllImport("DAQmx", CallingConvention = CallingConvention.StdCall)]
internal static extern int DAQmxSetWriteRegenMode(IntPtr taskHandle, int data);
[DllImport("DAQmx", CallingConvention = CallingConvention.StdCall)]
internal static extern int DAQmxCreateAIVoltageChan(
IntPtr taskHandle,
string physicalChannel,
string nameToAssignToChannel,
int terminalConfig,
double minVal,
double maxVal,
int units,
string customScaleName);
[DllImport("DAQmx", CallingConvention = CallingConvention.StdCall)]
internal static extern int DAQmxCreateAOVoltageChan(
IntPtr taskHandle,
string physicalChannel,
string nameToAssignToChannel,
double minVal,
double maxVal,
int units,
string customScaleName);
[DllImport("DAQmx", CallingConvention = CallingConvention.StdCall)]
internal static extern int DAQmxCreateDOChan(
IntPtr taskHandle,
string lines,
string nameToAssignToLines,
int lineGrouping);
[DllImport("DAQmx", CallingConvention = CallingConvention.StdCall)]
public static extern int DAQmxGetErrorString(
int errorCode,
StringBuilder errorString,
uint buffersize);
#if unsafe
[DllImport("DAQmx", CallingConvention = CallingConvention.StdCall)]
public static extern unsafe int DAQmxReadAnalogF64(
IntPtr taskHandle,
int numSampsPerChan,
double timeout,
int fillMode,
double* readArray,
uint arraySizeInSamps,
out IntPtr sampsPerChanRead,
IntPtr reserved);
#endif
[DllImport("DAQmx", CallingConvention = CallingConvention.StdCall)]
public static extern int DAQmxReadAnalogScalarF64(
IntPtr taskHandle,
double timeout,
out double value,
IntPtr reserved);
#if unsafe
[DllImport("DAQmx", CallingConvention = CallingConvention.StdCall)]
public static extern unsafe int DAQmxReadBinaryI16(
IntPtr taskHandle,
int numSampsPerChan,
double timeout,
int fillMode,
bool* readArray,
uint arraySizeInSamps,
out IntPtr sampsPerChanRead,
IntPtr reserved);
#endif
#if unsafe
[DllImport("DAQmx", CallingConvention = CallingConvention.StdCall)]
public static extern unsafe int DAQmxReadBinaryU16(
IntPtr taskHandle,
int numSampsPerChan,
double timeout,
int fillMode,
ushort* readArray,
uint arraySizeInSamps,
out IntPtr sampsPerChanRead,
IntPtr reserved);
#endif
#if unsafe
[DllImport("DAQmx", CallingConvention = CallingConvention.StdCall)]
public static extern unsafe int DAQmxReadBinaryI32(
IntPtr taskHandle,
int numSampsPerChan,
double timeout,
int fillMode,
int* readArray,
uint arraySizeInSamps,
out IntPtr sampsPerChanRead,
IntPtr reserved);
#endif
#if unsafe
[DllImport("DAQmx", CallingConvention = CallingConvention.StdCall)]
public static extern unsafe int DAQmxReadBinaryU32(
IntPtr taskHandle,
int numSampsPerChan,
double timeout,
int fillMode,
uint* readArray,
uint arraySizeInSamps,
out IntPtr sampsPerChanRead,
IntPtr reserved);
#endif
[DllImport("DAQmx", CallingConvention = CallingConvention.StdCall)]
public static extern int DAQmxConfigureLogging(
IntPtr taskHandle,
string filePath,
int loggingMode,
string groupName,
int operation);
[DllImport("DAQmx", CallingConvention = CallingConvention.StdCall)]
internal static extern int DAQmxLoadTask(string taskName, out IntPtr taskHandle);
[DllImport("DAQmx", CallingConvention = CallingConvention.StdCall)]
internal static extern int DAQmxCreateTask(string taskName, out IntPtr taskHandle);
[DllImport("DAQmx", CallingConvention = CallingConvention.StdCall)]
internal static extern int DAQmxAddGlobalChansToTask(IntPtr taskHandle, string[] channelNames);
[DllImport("DAQmx", CallingConvention = CallingConvention.StdCall)]
internal static extern int DAQmxStartTask(IntPtr taskHandle);
[DllImport("DAQmx", CallingConvention = CallingConvention.StdCall)]
internal static extern int DAQmxStopTask(IntPtr taskHandle);
[DllImport("DAQmx", CallingConvention = CallingConvention.StdCall)]
internal static extern int DAQmxClearTask(IntPtr taskHandle);
[DllImport("DAQmx", CallingConvention = CallingConvention.StdCall)]
internal static extern int DAQmxWaitUntilTaskDone(IntPtr taskHandle, double timeToWait);
[DllImport("DAQmx", CallingConvention = CallingConvention.StdCall)]
internal static extern int DAQmxWaitForValidTimestamp(
IntPtr taskHandle,
int timestampEvent,
double timeout,
CVIAbsoluteTime timestamp);
[DllImport("DAQmx", CallingConvention = CallingConvention.StdCall)]
internal static extern int DAQmxIsTaskDone(IntPtr taskHandle, out uint isTaskDone);
[DllImport("DAQmx", CallingConvention = CallingConvention.StdCall)]
internal static extern int DAQmxTaskControl(IntPtr taskHandle);
[DllImport("DAQmx", CallingConvention = CallingConvention.StdCall)]
internal static extern int DAQmxGetNthTaskChannel(IntPtr taskHandle);
[DllImport("DAQmx", CallingConvention = CallingConvention.StdCall)]
internal static extern int DAQmxGetNthTaskDevice(IntPtr taskHandle);
[DllImport("DAQmx", CallingConvention = CallingConvention.StdCall)]
internal static extern int DAQmxGetTaskAttribute(IntPtr taskHandle);
[DllImport("DAQmx", CallingConvention = CallingConvention.StdCall)]
internal static extern int DAQmxCfgSampClkTiming(
IntPtr taskHandle,
string source,
double rate,
int activeEdge,
int sampleMode,
ulong sampsPerChan);
[DllImport("DAQmx", CallingConvention = CallingConvention.StdCall)]
internal static extern int DAQmxCfgHandshakingTiming(
IntPtr taskHandle,
int sampleMode,
ulong sampsPerChan);
[DllImport("DAQmx", CallingConvention = CallingConvention.StdCall)]
internal static extern int DAQmxCfgBurstHandshakingTimingImportClock(
IntPtr taskHandle,
int sampleMode,
ulong sampsPerChan,
double sampleClkRate,
string sampleClkSrc,
int sampleClkActiveEdge,
int pauseWhen,
int readyEventActiveLevel);
[DllImport("DAQmx", CallingConvention = CallingConvention.StdCall)]
internal static extern int DAQmxCfgBurstHandshakingTimingExportClock(
IntPtr taskHandle,
int sampleMode,
ulong sampsPerChan,
double sampleClkRate,
string sampleClkOutpTerm,
int sampleClkPulsePolarity,
int pauseWhen,
int readyEventActiveLevel);
[DllImport("DAQmx", CallingConvention = CallingConvention.StdCall)]
internal static extern int DAQmxCfgChangeDetectionTiming(
IntPtr taskHandle,
string risingEdgeChan,
string fallingEdgeChan,
int sampleMode,
ulong sampsPerChan);
[DllImport("DAQmx", CallingConvention = CallingConvention.StdCall)]
internal static extern int DAQmxCfgImplicitTiming(
IntPtr taskHandle,
int sampleMode,
ulong sampsPerChan);
[DllImport("DAQmx", CallingConvention = CallingConvention.StdCall)]
internal static extern int DAQmxCfgPipelinedSampClkTiming(
IntPtr taskHandle,
string source,
double rate,
int activeEdge,
int sampleMode,
ulong sampsPerChan);
[DllImport("DAQmx", CallingConvention = CallingConvention.StdCall)]
internal static extern int DAQmxGetTimingAttribute(
IntPtr taskHandle,
int attribute,
out object value);
[DllImport("DAQmx", CallingConvention = CallingConvention.StdCall)]
internal static extern int DAQmxSetTimingAttribute(
IntPtr taskHandle,
int attribute,
object value);
[DllImport("DAQmx", CallingConvention = CallingConvention.StdCall)]
internal static extern int DAQmxResetTimingAttribute(IntPtr taskHandle, int attribute);
[DllImport("DAQmx", CallingConvention = CallingConvention.StdCall)]
internal static extern int DAQmxGetTimingAttributeEx(
IntPtr taskHandle,
string deviceNames,
int attribute,
out object value);
[DllImport("DAQmx", CallingConvention = CallingConvention.StdCall)]
internal static extern int DAQmxSetTimingAttributeEx(
IntPtr taskHandle,
string deviceNames,
int attribute,
object value);
[DllImport("DAQmx", CallingConvention = CallingConvention.StdCall)]
internal static extern int DAQmxResetTimingAttributeEx(
IntPtr taskHandle,
string deviceNames,
int attribute);
[DllImport("DAQmx", CallingConvention = CallingConvention.StdCall)]
public static extern int DAQmxDisableStartTrig(IntPtr taskHandle);
[DllImport("DAQmx", CallingConvention = CallingConvention.StdCall)]
public static extern int DAQmxCfgDigEdgeStartTrig(
IntPtr taskHandle,
string triggerSource,
int triggerEdge);
[DllImport("DAQmx", CallingConvention = CallingConvention.StdCall)]
public static extern int DAQmxCfgAnlgEdgeStartTrig(
IntPtr taskHandle,
string triggerSource,
int triggerSlope,
double triggerLevel);
[DllImport("DAQmx", CallingConvention = CallingConvention.StdCall)]
public static extern int DAQmxCfgAnlgMultiEdgeStartTrig(
IntPtr taskHandle,
string triggerSources,
int[] triggerSlopeArray,
double[] triggerLevelArray,
uint arraySize);
[DllImport("DAQmx", CallingConvention = CallingConvention.StdCall)]
public static extern int DAQmxCfgAnlgWindowStartTrig(
IntPtr taskHandle,
string triggerSource,
int triggerWhen,
double windowTop,
double windowBottom);
[DllImport("DAQmx", CallingConvention = CallingConvention.StdCall)]
public static extern int DAQmxCfgTimeStartTrig(
IntPtr taskHandle,
CVIAbsoluteTime when,
int timescale);
[DllImport("DAQmx", CallingConvention = CallingConvention.StdCall)]
public static extern int DAQmxCfgDigPatternStartTrig(
IntPtr taskHandle,
string triggerSource,
string triggerPattern,
int triggerWhen);
[DllImport("DAQmx", CallingConvention = CallingConvention.StdCall)]
public static extern int DAQmxDisableRefTrig(IntPtr taskHandle);
[DllImport("DAQmx", CallingConvention = CallingConvention.StdCall)]
public static extern int DAQmxCfgDigEdgeRefTrig(
IntPtr taskHandle,
string triggerSource,
int triggerEdge,
uint pretriggerSamples);
[DllImport("DAQmx", CallingConvention = CallingConvention.StdCall)]
public static extern int DAQmxCfgAnlgEdgeRefTrig(
IntPtr taskHandle,
string triggerSource,
int triggerSlope,
double triggerLevel,
uint pretriggerSamples);
[DllImport("DAQmx", CallingConvention = CallingConvention.StdCall)]
public static extern int DAQmxCfgAnlgMultiEdgeRefTrig(
IntPtr taskHandle,
string triggerSources,
int[] triggerSlopeArray,
double[] triggerLevelArray,
uint pretriggerSamples,
uint arraySize);
[DllImport("DAQmx", CallingConvention = CallingConvention.StdCall)]
public static extern int DAQmxCfgAnlgWindowRefTrig(
IntPtr taskHandle,
string triggerSource,
int triggerWhen,
double windowTop,
double windowBottom,
uint pretriggerSamples);
[DllImport("DAQmx", CallingConvention = CallingConvention.StdCall)]
public static extern int DAQmxCfgDigPatternRefTrig(
IntPtr taskHandle,
string triggerSource,
string triggerPattern,
int triggerWhen,
uint pretriggerSamples);
[DllImport("DAQmx", CallingConvention = CallingConvention.StdCall)]
public static extern int DAQmxGetTrigAttribute(
IntPtr taskHandle,
int attribute,
out object value);
[DllImport("DAQmx", CallingConvention = CallingConvention.StdCall)]
public static extern int DAQmxSetTrigAttribute(IntPtr taskHandle, int attribute, object value);
[DllImport("DAQmx", CallingConvention = CallingConvention.StdCall)]
public static extern int DAQmxResetTrigAttribute(IntPtr taskHandle, int attribute);
[DllImport("DAQmx", CallingConvention = CallingConvention.StdCall)]
public static extern int DAQmxWriteAnalogF64(
IntPtr taskHandle,
int numSampsPerChan,
bool autoStart,
double timeout,
bool dataLayout,
double[] writeArray,
out IntPtr sampsPerChanWritten,
IntPtr reserved);
[DllImport("DAQmx", CallingConvention = CallingConvention.StdCall)]
public static extern int DAQmxWriteDigitalLines(
IntPtr taskHandle,
int numSampsPerChan,
bool autoStart,
double timeout,
bool dataLayout,
byte[] writeArray,
out IntPtr sampsPerChanWritten,
IntPtr reserved);
}

View File

@ -1,16 +1,22 @@
using CliWrap; using CliWrap;
using File_Watcher.Models; using File_Watcher.Models;
#if ShellProgressBar
using ShellProgressBar; using ShellProgressBar;
#endif
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Drawing; using System.Drawing;
using System.Drawing.Imaging; using System.Drawing.Imaging;
using System.IO.Compression; using System.IO.Compression;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Text.Json; using System.Text.Json;
using View_by_Distance.Metadata.Models; using Phares.Metadata.Models;
using View_by_Distance.Metadata.Models.Stateless; using Phares.Metadata.Models.Stateless;
using View_by_Distance.Shared.Models; using Phares.Shared.Models;
using View_by_Distance.Shared.Models.Stateless; using Phares.Shared.Models.Stateless;
namespace File_Watcher.Helpers; namespace File_Watcher.Helpers;
@ -20,13 +26,25 @@ internal static partial class DeterministicHashCodeHelper
private class Windows : IWindows, IDisposable private class Windows : IWindows, IDisposable
{ {
public long Ticks { get; init; }
public int? CurrentTick =>
#if ShellProgressBar
_ProgressBar?.CurrentTick;
#else
throw new NotSupportedException("ShellProgressBar is not supported in this context.");
#endif
#if ShellProgressBar
private ProgressBar? _ProgressBar; private ProgressBar? _ProgressBar;
private readonly ProgressBarOptions _ProgressBarOptions; private readonly ProgressBarOptions _ProgressBarOptions;
#endif
public int CurrentTick { get; internal set; }
public Windows() => public Windows() =>
#if ShellProgressBar
_ProgressBarOptions = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true }; _ProgressBarOptions = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true };
#else
throw new NotSupportedException("ShellProgressBar is not supported in this context.");
#endif
DeterministicHashCode IWindows.GetDeterministicHashCode(HttpClient httpClient, Uri uri) => DeterministicHashCode IWindows.GetDeterministicHashCode(HttpClient httpClient, Uri uri) =>
GetDeterministicHashCode(httpClient, uri); GetDeterministicHashCode(httpClient, uri);
@ -97,18 +115,26 @@ internal static partial class DeterministicHashCodeHelper
} }
void IWindows.Tick() => void IWindows.Tick() =>
#if ShellProgressBar
_ProgressBar?.Tick(); _ProgressBar?.Tick();
#else
throw new NotSupportedException("ShellProgressBar is not supported in this context.");
#endif
void IDisposable.Dispose() void IDisposable.Dispose()
{ {
#if ShellProgressBar
_ProgressBar?.Dispose(); _ProgressBar?.Dispose();
#endif
GC.SuppressFinalize(this); GC.SuppressFinalize(this);
} }
void IWindows.ConstructProgressBar(int maxTicks, string message) void IWindows.ConstructProgressBar(int maxTicks, string message)
{ {
#if ShellProgressBar
_ProgressBar?.Dispose(); _ProgressBar?.Dispose();
_ProgressBar = new(maxTicks, message, _ProgressBarOptions); _ProgressBar = new(maxTicks, message, _ProgressBarOptions);
#endif
} }
ReadOnlyCollection<string> IWindows.ConvertAndGetFastForwardMovingPictureExpertsGroupFiles(ResultSettings resultSettings, HttpClient? httpClient, FilePath filePath) ReadOnlyCollection<string> IWindows.ConvertAndGetFastForwardMovingPictureExpertsGroupFiles(ResultSettings resultSettings, HttpClient? httpClient, FilePath filePath)
@ -164,7 +190,7 @@ internal static partial class DeterministicHashCodeHelper
string sourceDirectory; string sourceDirectory;
List<string> check = []; List<string> check = [];
string archiveEntryFile; string archiveEntryFile;
long ticks = DateTime.Now.Ticks; Windows windows = new();
ReadOnlyCollection<FirstPass> collection; ReadOnlyCollection<FirstPass> collection;
string rootDirectory = Path.GetFullPath(appSettings.ResultSettings.RootDirectory); string rootDirectory = Path.GetFullPath(appSettings.ResultSettings.RootDirectory);
if (!Directory.Exists(rootDirectory)) if (!Directory.Exists(rootDirectory))
@ -187,7 +213,7 @@ internal static partial class DeterministicHashCodeHelper
archiveEntryFile = Path.Combine(sourceDirectory, zipArchiveEntry.Name); archiveEntryFile = Path.Combine(sourceDirectory, zipArchiveEntry.Name);
zipArchiveEntry.ExtractToFile(archiveEntryFile); zipArchiveEntry.ExtractToFile(archiveEntryFile);
} }
collection = WindowsWork(logger, appSettings, ticks, sourceDirectory); collection = WindowsWork(windows, logger, appSettings, sourceDirectory);
if (check.Count == collection.Count) if (check.Count == collection.Count)
{ {
json = JsonSerializer.Serialize(collection.ToList(), FirstPassCollectionSourceGenerationContext.Default.ListFirstPass); json = JsonSerializer.Serialize(collection.ToList(), FirstPassCollectionSourceGenerationContext.Default.ListFirstPass);
@ -198,12 +224,11 @@ internal static partial class DeterministicHashCodeHelper
return true; return true;
} }
private static ReadOnlyCollection<FirstPass> WindowsWork(ILogger<Worker>? logger, AppSettings appSettings, long ticks, string sourceDirectory) private static ReadOnlyCollection<FirstPass> WindowsWork(IWindows windows, ILogger<Worker>? logger, AppSettings appSettings, string sourceDirectory)
{ {
ReadOnlyCollection<FirstPass> results; ReadOnlyCollection<FirstPass> results;
Windows windows = new();
IWindows windowsInterface = windows; IWindows windowsInterface = windows;
logger?.LogInformation("{Ticks} {RootDirectory}", ticks, sourceDirectory); logger?.LogInformation("{Ticks} {RootDirectory}", windows.Ticks, sourceDirectory);
A_Metadata metadata = new(appSettings.ResultSettings, appSettings.MetadataSettings); A_Metadata metadata = new(appSettings.ResultSettings, appSettings.MetadataSettings);
int appSettingsMaxDegreeOfParallelism = appSettings.DeterministicHashCodeConfiguration.MaxDegreeOfParallelism; int appSettingsMaxDegreeOfParallelism = appSettings.DeterministicHashCodeConfiguration.MaxDegreeOfParallelism;
ReadOnlyCollection<string> files = Directory.GetFiles(sourceDirectory, "*", SearchOption.AllDirectories).AsReadOnly(); ReadOnlyCollection<string> files = Directory.GetFiles(sourceDirectory, "*", SearchOption.AllDirectories).AsReadOnly();
@ -299,7 +324,7 @@ internal static partial class DeterministicHashCodeHelper
return result; return result;
} }
private static ReadOnlyCollection<FirstPass> WindowsAsynchronousWork(AppSettings appSettings, Windows windows, ReadOnlyCollection<string> files, A_Metadata metadata, int appSettingsMaxDegreeOfParallelism) private static ReadOnlyCollection<FirstPass> WindowsAsynchronousWork(AppSettings appSettings, IWindows windows, ReadOnlyCollection<string> files, A_Metadata metadata, int appSettingsMaxDegreeOfParallelism)
{ {
List<FirstPass> results = []; List<FirstPass> results = [];
FirstPass firstPass; FirstPass firstPass;

503
Helpers/DiskInfoHelper.cs Normal file
View File

@ -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<string, object>))]
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<DiskPartition> 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<Worker> logger)
{
string? json = WriteRecord();
ReadOnlyCollection<DiskDrive> devices = GetDrives(appSettings, logger);
string yaml = GetYetAnotherMarkupLanguage(devices);
ReadOnlyCollection<string> normalized = GetNormalized(appSettings, logger, devices);
string text = string.Join(Environment.NewLine, normalized);
string markdown = string.Concat("# ",
Environment.MachineName.ToLower(),
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.ToLower()}.md"), markdown);
return true;
}
private static string WriteRecord()
{
string result;
Record record;
List<Record> 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<DiskDrive> GetDrives(AppSettings appSettings, ILogger<Worker> logger)
{
#pragma warning disable CA1416
List<DiskDrive> 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<Worker> 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.ToLower()}-{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<string, object> DeserializeAndFlatten(string json, char? remove)
{
Dictionary<string, object> results = [];
JsonElement jsonElement = JsonSerializer.Deserialize(json, JsonElementSourceGenerationContext.Default.JsonElement);
FillDictionaryFromJToken(results, jsonElement, string.Empty, remove);
return results;
}
private static void FillDictionaryFromJToken(Dictionary<string, object> 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<DiskDrive> devices)
{
string result;
List<string> results = [];
string json = JsonSerializer.Serialize(devices.ToArray(), DiskDriveArraySourceGenerationContext.Default.DiskDriveArray);
Dictionary<string, object> 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<string> GetNormalized(AppSettings appSettings, ILogger<Worker> logger, ReadOnlyCollection<DiskDrive> drives)
{
List<string> 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();
}
}

View File

@ -68,7 +68,7 @@ internal static partial class HelperCamstarOracle
return results; return results;
} }
internal static bool Check(AppSettings appSettings, ILogger<Worker> logger, CancellationToken cancellationToken) internal static bool Check(AppSettings appSettings, IHttpClientFactory httpClientFactory, ILogger<Worker> logger, CancellationToken cancellationToken)
{ {
if (_MonIn is null) if (_MonIn is null)
throw new NullReferenceException(nameof(_MonIn)); throw new NullReferenceException(nameof(_MonIn));
@ -100,6 +100,7 @@ internal static partial class HelperCamstarOracle
File.WriteAllLines(Path.Combine(directory, $"{dateTime.Ticks}.tsv"), lines); 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) 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> httpResponseMessage = _MonIn.SendPerformanceMessage(camstarOracleConfiguration.MonitorApplicationSite, camstarOracleConfiguration.MonitorApplicationResource, performanceName, value: lines.Count, description: string.Empty); Task<HttpResponseMessage> httpResponseMessage = _MonIn.SendPerformanceMessage(camstarOracleConfiguration.MonitorApplicationSite, camstarOracleConfiguration.MonitorApplicationResource, performanceName, value: lines.Count, description: string.Empty);
httpResponseMessage.Wait(cancellationToken); httpResponseMessage.Wait(cancellationToken);
if (httpResponseMessage.Result.StatusCode != System.Net.HttpStatusCode.OK) if (httpResponseMessage.Result.StatusCode != System.Net.HttpStatusCode.OK)

View File

@ -17,7 +17,7 @@ internal static partial class HelperInfinityQS
} }
} }
private static void RunMI() private static void RunMI(string decryptedPassword)
{ {
#pragma warning disable CA1416 #pragma warning disable CA1416
string processName = "iispcmi.exe"; string processName = "iispcmi.exe";
@ -27,7 +27,7 @@ internal static partial class HelperInfinityQS
Domain = "Infineon", Domain = "Infineon",
UseShellExecute = false, UseShellExecute = false,
UserName = "ecfisysadmin", UserName = "ecfisysadmin",
PasswordInClearText = "j(1(P%xB=g}3w9db", PasswordInClearText = decryptedPassword,
WorkingDirectory = "C:/Program Files (x86)/InfinityQS International/ProFicient/Applications" WorkingDirectory = "C:/Program Files (x86)/InfinityQS International/ProFicient/Applications"
}; };
TimeSpan timeSpan = new(DateTime.Now.AddDays(7).Ticks - DateTime.Now.Ticks); TimeSpan timeSpan = new(DateTime.Now.AddDays(7).Ticks - DateTime.Now.Ticks);
@ -36,10 +36,11 @@ internal static partial class HelperInfinityQS
#pragma warning restore CA1416 #pragma warning restore CA1416
} }
internal static bool Select(AppSettings appSettings, ILogger<Worker> logger) internal static bool ProcessStart(AppSettings appSettings, ILogger<Worker> logger)
{ {
logger.LogInformation(appSettings.FileWatcherConfiguration.Company); logger.LogInformation(appSettings.FileWatcherConfiguration.Company);
RunMI(); string decrypted = RijndaelEncryption.Decrypt(appSettings.InfinityQSConfiguration.EncryptedPassword, appSettings.FileWatcherConfiguration.Company);
RunMI(decrypted);
return true; return true;
} }
} }

View File

@ -0,0 +1,75 @@
using File_Watcher.Models;
using Helpers.DAQmx;
namespace File_Watcher.Helpers;
internal static partial class NationalInstrumentsHelper
{
private static Dictionary<string, DAQmxTask>? _DataAcquisitionTasks = null;
internal static bool WriteData(AppSettings appSettings, ILogger<Worker> logger)
{
double value;
LogNetToHoursSince(logger);
if (_DataAcquisitionTasks is null)
{
string name;
_DataAcquisitionTasks = [];
DAQmxTask dataAcquisitionTask;
const DAQmxUnits volts = DAQmxUnits.Volts;
NationalInstrumentsConfiguration ni = appSettings.NationalInstrumentsConfiguration;
const DAQmxInputTerminalConfiguration differential = DAQmxInputTerminalConfiguration.Differential;
const DAQmxInputTerminalConfiguration referencedSingleEnded = DAQmxInputTerminalConfiguration.ReferencedSingleEnded;
foreach (string physicalChannel in appSettings.NationalInstrumentsConfiguration.DifferentialPhysicalChannels.Distinct())
{
name = !physicalChannel.Contains('/') ? physicalChannel : physicalChannel.Split('/')[1];
dataAcquisitionTask = DAQmxTask.Create(name);
dataAcquisitionTask.CreateAnalogInputVoltageChannel(physicalChannel, name, differential, ni.MiniumValue, ni.MaximumValue, volts, ni.CustomScaleName);
_DataAcquisitionTasks.Add(name, dataAcquisitionTask);
}
foreach (string physicalChannel in appSettings.NationalInstrumentsConfiguration.ReferencedSingleEndedPhysicalChannels.Distinct())
{
name = !physicalChannel.Contains('/') ? physicalChannel : physicalChannel.Split('/')[1];
dataAcquisitionTask = DAQmxTask.Create(name);
dataAcquisitionTask.CreateAnalogInputVoltageChannel(physicalChannel, name, referencedSingleEnded, ni.MiniumValue, ni.MaximumValue, volts, ni.CustomScaleName);
_DataAcquisitionTasks.Add(name, dataAcquisitionTask);
}
}
foreach (KeyValuePair<string, DAQmxTask> keyValuePair in _DataAcquisitionTasks)
{
if (appSettings.NationalInstrumentsConfiguration.UsePointerMethod)
throw new NotSupportedException("Pointer method is not supported in this implementation.");
value = keyValuePair.Value.ReadAnalogScalarF64(appSettings.NationalInstrumentsConfiguration.ReadTimeout);
logger.LogInformation("{key}-{read}: {value}", keyValuePair.Key, keyValuePair.Value.TotalSamplesRead, value);
}
return true;
}
private static void LogNetToHoursSince(ILogger<Worker>? logger)
{
double secondsInAHour = 3600f;
long epoch = new DateTime(1970, 1, 1).Ticks;
long net8ReleaseDate = new DateTime(2023, 11, 14).Ticks;
long net9ReleaseDate = new DateTime(2024, 11, 12).Ticks;
long net10ReleaseDate = new DateTime(2026, 01, 01).Ticks;
long framework48ReleaseDate = new DateTime(2019, 04, 18).Ticks;
double net8TotalSeconds = new TimeSpan(net8ReleaseDate - epoch).TotalSeconds;
double net9TotalSeconds = new TimeSpan(net9ReleaseDate - epoch).TotalSeconds;
double net10TotalSeconds = new TimeSpan(net10ReleaseDate - epoch).TotalSeconds;
double framework48TotalSeconds = new TimeSpan(framework48ReleaseDate - epoch).TotalSeconds;
logger?.LogInformation("It has been {net8TotalSeconds} seconds since net8 was released", net8TotalSeconds);
logger?.LogInformation("It has been {net9TotalSeconds} seconds since net9 was released", net9TotalSeconds);
logger?.LogInformation("It has been {net10TotalSeconds} seconds since net10 was released", net10TotalSeconds);
logger?.LogInformation("It has been {framework48TotalSeconds} seconds since framework48 was released", framework48TotalSeconds);
double net8TotalHours = Math.Floor((DateTimeOffset.UtcNow.ToUnixTimeSeconds() - net8TotalSeconds) / secondsInAHour);
double net9TotalHours = Math.Floor((DateTimeOffset.UtcNow.ToUnixTimeSeconds() - net9TotalSeconds) / secondsInAHour);
double net10TotalHours = Math.Floor((DateTimeOffset.UtcNow.ToUnixTimeSeconds() - net10TotalSeconds) / secondsInAHour);
double framework48TotalHours = Math.Floor((DateTimeOffset.UtcNow.ToUnixTimeSeconds() - framework48TotalSeconds) / secondsInAHour);
logger?.LogInformation("It has been {net8TotalHours} hours since net8 was released", net8TotalHours);
logger?.LogInformation("It has been {net9TotalHours} hours since net9 was released", net9TotalHours);
logger?.LogInformation("It has been {net10TotalHours} hours since net10 was released", net10TotalHours);
logger?.LogInformation("It has been {framework48TotalHours} hours since framework48 was released", framework48TotalHours);
}
}

45
Helpers/SeleniumHelper.cs Normal file
View File

@ -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
{
// <PackageReference Include="Selenium.WebDriver" Version="4.31.0" />
// <PackageReference Include="Selenium.WebDriver.MSEdgeDriver" Version="135.0.3179.85" />
internal static bool HyperTextMarkupLanguageToPortableNetworkGraphics(AppSettings appSettings, ILogger<Worker> 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;
}
}

51
Helpers/SyncHelper.cs Normal file
View File

@ -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<string, object>))]
private partial class DictionaryStringObjectBSourceGenerationContext : JsonSerializerContext
{
}
internal static bool Check(AppSettings _, ILogger<Worker> __) =>
true;
internal static string GetReply(string body, Dictionary<string, object> 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}";
}
}

View File

@ -1,12 +1,13 @@
using System.Text.Json; using System.Text.Json;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
using View_by_Distance.Shared.Models; using Phares.Shared.Models;
namespace File_Watcher.Models; namespace File_Watcher.Models;
public record AppSettings(CamstarOracleConfiguration CamstarOracleConfiguration, public record AppSettings(CamstarOracleConfiguration CamstarOracleConfiguration,
CompassConfiguration CompassConfiguration, CompassConfiguration CompassConfiguration,
DeterministicHashCodeConfiguration DeterministicHashCodeConfiguration, DeterministicHashCodeConfiguration DeterministicHashCodeConfiguration,
DiskInfoConfiguration DiskInfoConfiguration,
DriveConfiguration DriveConfiguration, DriveConfiguration DriveConfiguration,
EAFLogConfiguration EAFLogConfiguration, EAFLogConfiguration EAFLogConfiguration,
EDADatabaseConfiguration EDADatabaseConfiguration, EDADatabaseConfiguration EDADatabaseConfiguration,
@ -15,10 +16,13 @@ public record AppSettings(CamstarOracleConfiguration CamstarOracleConfiguration,
IsoConfiguration IsoConfiguration, IsoConfiguration IsoConfiguration,
MetadataSettings MetadataSettings, MetadataSettings MetadataSettings,
MetrologyConfiguration MetrologyConfiguration, MetrologyConfiguration MetrologyConfiguration,
NationalInstrumentsConfiguration NationalInstrumentsConfiguration,
NugetConfiguration NugetConfiguration, NugetConfiguration NugetConfiguration,
ResultSettings ResultSettings, ResultSettings ResultSettings,
SeleniumConfiguration SeleniumConfiguration,
SerialConfiguration SerialConfiguration, SerialConfiguration SerialConfiguration,
StratusConfiguration StratusConfiguration, StratusConfiguration StratusConfiguration,
SyncConfiguration SyncConfiguration,
TransmissionControlProtocolConfiguration TransmissionControlProtocolConfiguration, TransmissionControlProtocolConfiguration TransmissionControlProtocolConfiguration,
WaferCounterConfiguration WaferCounterConfiguration) WaferCounterConfiguration WaferCounterConfiguration)
{ {
@ -29,6 +33,7 @@ public record AppSettings(CamstarOracleConfiguration CamstarOracleConfiguration,
#pragma warning disable IL3050, IL2026 #pragma warning disable IL3050, IL2026
CamstarOracleConfiguration? camstarOracleConfiguration = configurationRoot.GetSection(nameof(CamstarOracleConfiguration)).Get<CamstarOracleConfiguration>(); CamstarOracleConfiguration? camstarOracleConfiguration = configurationRoot.GetSection(nameof(CamstarOracleConfiguration)).Get<CamstarOracleConfiguration>();
CompassConfiguration? compassConfiguration = configurationRoot.GetSection(nameof(CompassConfiguration)).Get<CompassConfiguration>(); CompassConfiguration? compassConfiguration = configurationRoot.GetSection(nameof(CompassConfiguration)).Get<CompassConfiguration>();
DiskInfoConfiguration? diskInfoConfiguration = configurationRoot.GetSection(nameof(DiskInfoConfiguration)).Get<DiskInfoConfiguration>();
DeterministicHashCodeConfiguration? deterministicHashCodeConfiguration = configurationRoot.GetSection(nameof(DeterministicHashCodeConfiguration)).Get<DeterministicHashCodeConfiguration>(); DeterministicHashCodeConfiguration? deterministicHashCodeConfiguration = configurationRoot.GetSection(nameof(DeterministicHashCodeConfiguration)).Get<DeterministicHashCodeConfiguration>();
DriveConfiguration? driveConfiguration = configurationRoot.GetSection(nameof(DriveConfiguration)).Get<DriveConfiguration>(); DriveConfiguration? driveConfiguration = configurationRoot.GetSection(nameof(DriveConfiguration)).Get<DriveConfiguration>();
EAFLogConfiguration? eafLogConfiguration = configurationRoot.GetSection(nameof(EAFLogConfiguration)).Get<EAFLogConfiguration>(); EAFLogConfiguration? eafLogConfiguration = configurationRoot.GetSection(nameof(EAFLogConfiguration)).Get<EAFLogConfiguration>();
@ -38,16 +43,20 @@ public record AppSettings(CamstarOracleConfiguration CamstarOracleConfiguration,
IsoConfiguration? isoConfiguration = configurationRoot.GetSection(nameof(IsoConfiguration)).Get<IsoConfiguration>(); IsoConfiguration? isoConfiguration = configurationRoot.GetSection(nameof(IsoConfiguration)).Get<IsoConfiguration>();
MetadataSettings? metadataSettings = configurationRoot.GetSection(nameof(MetadataSettings)).Get<MetadataSettings>(); MetadataSettings? metadataSettings = configurationRoot.GetSection(nameof(MetadataSettings)).Get<MetadataSettings>();
MetrologyConfiguration? metrologyConfiguration = configurationRoot.GetSection(nameof(MetrologyConfiguration)).Get<MetrologyConfiguration>(); MetrologyConfiguration? metrologyConfiguration = configurationRoot.GetSection(nameof(MetrologyConfiguration)).Get<MetrologyConfiguration>();
NationalInstrumentsConfiguration? nationalInstrumentsConfiguration = configurationRoot.GetSection(nameof(NationalInstrumentsConfiguration)).Get<NationalInstrumentsConfiguration>();
NugetConfiguration? nugetConfiguration = configurationRoot.GetSection(nameof(NugetConfiguration)).Get<NugetConfiguration>(); NugetConfiguration? nugetConfiguration = configurationRoot.GetSection(nameof(NugetConfiguration)).Get<NugetConfiguration>();
ResultSettings? resultSettings = configurationRoot.GetSection(nameof(ResultSettings)).Get<ResultSettings>(); ResultSettings? resultSettings = configurationRoot.GetSection(nameof(ResultSettings)).Get<ResultSettings>();
SeleniumConfiguration? seleniumConfiguration = configurationRoot.GetSection(nameof(SeleniumConfiguration)).Get<SeleniumConfiguration>();
SerialConfiguration? serialConfiguration = configurationRoot.GetSection(nameof(SerialConfiguration)).Get<SerialConfiguration>(); SerialConfiguration? serialConfiguration = configurationRoot.GetSection(nameof(SerialConfiguration)).Get<SerialConfiguration>();
StratusConfiguration? stratusConfiguration = configurationRoot.GetSection(nameof(StratusConfiguration)).Get<StratusConfiguration>(); StratusConfiguration? stratusConfiguration = configurationRoot.GetSection(nameof(StratusConfiguration)).Get<StratusConfiguration>();
SyncConfiguration? syncConfiguration = configurationRoot.GetSection(nameof(SyncConfiguration)).Get<SyncConfiguration>();
TransmissionControlProtocolConfiguration? transmissionControlProtocolConfiguration = configurationRoot.GetSection(nameof(TransmissionControlProtocolConfiguration)).Get<TransmissionControlProtocolConfiguration>(); TransmissionControlProtocolConfiguration? transmissionControlProtocolConfiguration = configurationRoot.GetSection(nameof(TransmissionControlProtocolConfiguration)).Get<TransmissionControlProtocolConfiguration>();
WaferCounterConfiguration? waferCounterConfiguration = configurationRoot.GetSection(nameof(WaferCounterConfiguration)).Get<WaferCounterConfiguration>(); WaferCounterConfiguration? waferCounterConfiguration = configurationRoot.GetSection(nameof(WaferCounterConfiguration)).Get<WaferCounterConfiguration>();
#pragma warning restore IL3050, IL2026 #pragma warning restore IL3050, IL2026
if (camstarOracleConfiguration is null if (camstarOracleConfiguration is null
|| compassConfiguration is null || compassConfiguration is null
|| deterministicHashCodeConfiguration is null || deterministicHashCodeConfiguration is null
|| diskInfoConfiguration is null
|| driveConfiguration is null || driveConfiguration is null
|| eafLogConfiguration is null || eafLogConfiguration is null
|| edaDatabaseConfiguration is null || edaDatabaseConfiguration is null
@ -56,10 +65,13 @@ public record AppSettings(CamstarOracleConfiguration CamstarOracleConfiguration,
|| isoConfiguration is null || isoConfiguration is null
|| metadataSettings is null || metadataSettings is null
|| metrologyConfiguration is null || metrologyConfiguration is null
|| nationalInstrumentsConfiguration is null
|| nugetConfiguration is null || nugetConfiguration is null
|| resultSettings is null || resultSettings is null
|| seleniumConfiguration is null
|| serialConfiguration is null || serialConfiguration is null
|| stratusConfiguration is null || stratusConfiguration is null
|| syncConfiguration is null
|| transmissionControlProtocolConfiguration is null || transmissionControlProtocolConfiguration is null
|| waferCounterConfiguration is null || waferCounterConfiguration is null
|| fileWatcherConfiguration?.Company is null) || fileWatcherConfiguration?.Company is null)
@ -78,6 +90,7 @@ public record AppSettings(CamstarOracleConfiguration CamstarOracleConfiguration,
result = new(camstarOracleConfiguration, result = new(camstarOracleConfiguration,
compassConfiguration, compassConfiguration,
deterministicHashCodeConfiguration, deterministicHashCodeConfiguration,
diskInfoConfiguration,
driveConfiguration, driveConfiguration,
eafLogConfiguration, eafLogConfiguration,
edaDatabaseConfiguration, edaDatabaseConfiguration,
@ -86,10 +99,13 @@ public record AppSettings(CamstarOracleConfiguration CamstarOracleConfiguration,
isoConfiguration, isoConfiguration,
metadataSettings, metadataSettings,
metrologyConfiguration, metrologyConfiguration,
nationalInstrumentsConfiguration,
nugetConfiguration, nugetConfiguration,
resultSettings, resultSettings,
seleniumConfiguration,
serialConfiguration, serialConfiguration,
stratusConfiguration, stratusConfiguration,
syncConfiguration,
transmissionControlProtocolConfiguration, transmissionControlProtocolConfiguration,
waferCounterConfiguration); waferCounterConfiguration);
Verify(result); Verify(result);

View File

@ -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
{
}

View File

@ -3,17 +3,9 @@ using System.Text.Json.Serialization;
namespace File_Watcher.Models; 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, public record InfinityQSConfiguration(string ConnectionString,
string DestinationDirectory, string DestinationDirectory,
string EncryptedPassword,
long SubGroupTime, long SubGroupTime,
string TestsFile, string TestsFile,
Test[] Tests) Test[] Tests)

View File

@ -0,0 +1,27 @@
using System.Text.Json;
using System.Text.Json.Serialization;
namespace File_Watcher.Models;
public record NationalInstrumentsConfiguration(string CustomScaleName,
string[] DifferentialPhysicalChannels,
int MaximumValue,
int MiniumValue,
string[] ReferencedSingleEndedPhysicalChannels,
int ReadTimeout,
bool UsePointerMethod)
{
public override string ToString()
{
string result = JsonSerializer.Serialize(this, NationalInstrumentsConfigurationSourceGenerationContext.Default.NationalInstrumentsConfiguration);
return result;
}
}
[JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSerializable(typeof(NationalInstrumentsConfiguration))]
internal partial class NationalInstrumentsConfigurationSourceGenerationContext : JsonSerializerContext
{
}

View File

@ -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
{
}

View File

@ -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
{
}

12
Models/Test.cs Normal file
View File

@ -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
{
}

View File

@ -0,0 +1,55 @@
#if Nancy
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<string, IEnumerable<string>> 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<string, object> 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;
});
}
}
#endif

23
Startup.cs Normal file
View File

@ -0,0 +1,23 @@
#if Nancy
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();
}
}
#endif

View File

@ -1,4 +1,4 @@
using File_Watcher.Models; using File_Watcher.Models;
using Microsoft.Extensions.Hosting.WindowsServices; using Microsoft.Extensions.Hosting.WindowsServices;
using System.Data; using System.Data;
@ -7,7 +7,6 @@ namespace File_Watcher;
public partial class Worker : BackgroundService public partial class Worker : BackgroundService
{ {
private bool? _First;
private readonly bool _IsWindowsService; private readonly bool _IsWindowsService;
private readonly ILogger<Worker> _Logger; private readonly ILogger<Worker> _Logger;
private readonly AppSettings _AppSettings; private readonly AppSettings _AppSettings;
@ -22,8 +21,14 @@ public partial class Worker : BackgroundService
try try
{ logger.LogInformation("<{folder}>", Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)); } { logger.LogInformation("<{folder}>", Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)); }
catch (Exception) { } catch (Exception) { }
_First = null;
_IsWindowsService = collection.Contains(nameof(WindowsServiceLifetime)); _IsWindowsService = collection.Contains(nameof(WindowsServiceLifetime));
if (appSettings.FileWatcherConfiguration.Helper == nameof(Helpers.SyncHelper))
{
#if Nancy
_ = Microsoft.Owin.Hosting.WebApp.Start<Startup>(appSettings.SyncConfiguration.UniformResourceLocator);
#endif
logger.LogInformation("Server running on {url}", appSettings.SyncConfiguration.UniformResourceLocator);
}
} }
public override Task StopAsync(CancellationToken cancellationToken) public override Task StopAsync(CancellationToken cancellationToken)
@ -35,6 +40,7 @@ public partial class Worker : BackgroundService
protected override async Task ExecuteAsync(CancellationToken cancellationToken) => protected override async Task ExecuteAsync(CancellationToken cancellationToken) =>
await Body(cancellationToken); await Body(cancellationToken);
private async Task Body(CancellationToken cancellationToken) private async Task Body(CancellationToken cancellationToken)
{ {
if (!_IsWindowsService) if (!_IsWindowsService)
@ -52,40 +58,44 @@ public partial class Worker : BackgroundService
} }
while (_IsWindowsService && !cancellationToken.IsCancellationRequested) while (_IsWindowsService && !cancellationToken.IsCancellationRequested)
{ {
BodyInner(cancellationToken); try
await Task.Delay(_AppSettings.FileWatcherConfiguration.MillisecondsDelay, cancellationToken); {
BodyInner(cancellationToken);
await Task.Delay(_AppSettings.FileWatcherConfiguration.MillisecondsDelay, cancellationToken);
}
catch (Exception ex) { _Logger.LogError(ex, "Unexpected Error!"); }
} }
} }
private void BodyInner(CancellationToken cancellationToken) 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")); _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 is null || _First.Value)
{
_First = false;
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)) if (!Directory.Exists(_AppSettings.FileWatcherConfiguration.WatchDirectory))
_ = Directory.CreateDirectory(_AppSettings.FileWatcherConfiguration.WatchDirectory); _ = Directory.CreateDirectory(_AppSettings.FileWatcherConfiguration.WatchDirectory);
else else
{ {
_ = _AppSettings.FileWatcherConfiguration.Helper switch _ = _AppSettings.FileWatcherConfiguration.Helper switch
{ {
nameof(Helpers.SyncHelper) => Helpers.SyncHelper.Check(_AppSettings, _Logger),
nameof(Helpers.HelperNuget) => Helpers.HelperNuget.Sync(_AppSettings, _Logger), nameof(Helpers.HelperNuget) => Helpers.HelperNuget.Sync(_AppSettings, _Logger),
nameof(Helpers.HelperTCP) => Helpers.HelperTCP.ReadWrite(_AppSettings, _Logger), nameof(Helpers.HelperTCP) => Helpers.HelperTCP.ReadWrite(_AppSettings, _Logger),
nameof(Helpers.HelperISO) => Helpers.HelperISO.DirectoryToISO(_AppSettings, _Logger), nameof(Helpers.HelperISO) => Helpers.HelperISO.DirectoryToISO(_AppSettings, _Logger),
nameof(Helpers.HelperCompass) => Helpers.HelperCompass.CopyFile(_AppSettings, _Logger), nameof(Helpers.HelperCompass) => Helpers.HelperCompass.CopyFile(_AppSettings, _Logger),
nameof(Helpers.HelperStratus) => Helpers.HelperStratus.MoveFile(_AppSettings, _Logger), nameof(Helpers.HelperStratus) => Helpers.HelperStratus.MoveFile(_AppSettings, _Logger),
nameof(Helpers.HelperEAFLog) => Helpers.HelperEAFLog.DeleteFiles(_AppSettings, _Logger), nameof(Helpers.HelperEAFLog) => Helpers.HelperEAFLog.DeleteFiles(_AppSettings, _Logger),
nameof(Helpers.HelperInfinityQS) => Helpers.HelperInfinityQS.Select(_AppSettings, _Logger), nameof(Helpers.DiskInfoHelper) => Helpers.DiskInfoHelper.WriteDiskInfo(_AppSettings, _Logger),
nameof(Helpers.HelperEventLog) => Helpers.HelperEventLog.ClearEventLogs(_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.HelperWaferCounter) => Helpers.HelperWaferCounter.MoveFile(_AppSettings, _Logger),
nameof(Helpers.HelperSerial) => Helpers.HelperSerial.ReadWrite(_AppSettings, _Logger, cancellationToken), nameof(Helpers.HelperSerial) => Helpers.HelperSerial.ReadWrite(_AppSettings, _Logger, cancellationToken),
nameof(Helpers.HelperMetrologyFiles) => Helpers.HelperMetrologyFiles.SortAndDelete(_AppSettings, _Logger), nameof(Helpers.HelperMetrologyFiles) => Helpers.HelperMetrologyFiles.SortAndDelete(_AppSettings, _Logger),
nameof(Helpers.HelperCamstarOracle) => Helpers.HelperCamstarOracle.Check(_AppSettings, _Logger, cancellationToken), nameof(Helpers.NationalInstrumentsHelper) => Helpers.NationalInstrumentsHelper.WriteData(_AppSettings, _Logger),
nameof(Helpers.DeterministicHashCodeHelper) => Helpers.DeterministicHashCodeHelper.WindowsWork(_AppSettings, _Logger), 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.HelperEDADatabase) => Helpers.HelperEDADatabase.SaveDataCollectionPlans(_AppSettings, _Logger, cancellationToken),
nameof(Helpers.HelperCamstarOracle) => Helpers.HelperCamstarOracle.Check(_AppSettings, _HttpClientFactory, _Logger, cancellationToken),
_ => throw new NotSupportedException() _ => throw new NotSupportedException()
}; };
} }