Compare commits
7 Commits
Author | SHA1 | Date | |
---|---|---|---|
5045133cf8 | |||
a5b224cee1 | |||
1dffe235ff | |||
5603d01412 | |||
9b61eceb80 | |||
97797fc440 | |||
e50a90f0fc |
@ -118,7 +118,7 @@ dotnet_diagnostic.CA2254.severity = none # CA2254: The logging message template
|
||||
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.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.IDE0028.severity = error # IDE0028: Collection initialization can be simplified
|
||||
dotnet_diagnostic.IDE0031.severity = warning # Use null propagation (IDE0031)
|
||||
|
23
.vscode/.http
vendored
Normal file
23
.vscode/.http
vendored
Normal 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
2
.vscode/launch.json
vendored
@ -8,7 +8,7 @@
|
||||
"name": ".NET Core Launch (console)",
|
||||
"type": "coreclr",
|
||||
"request": "launch",
|
||||
"preLaunchTask": "build",
|
||||
"preLaunchTask": "Build",
|
||||
"program": "${workspaceFolder}/bin/Debug/net8.0/win-x64/File-Watcher.dll",
|
||||
"args": [
|
||||
"s"
|
||||
|
2
.vscode/settings.json
vendored
2
.vscode/settings.json
vendored
@ -33,6 +33,7 @@
|
||||
"Kofax",
|
||||
"linc",
|
||||
"Linc",
|
||||
"Modbus",
|
||||
"NOPAUSE",
|
||||
"NSFX",
|
||||
"OBJE",
|
||||
@ -42,6 +43,7 @@
|
||||
"PDSF",
|
||||
"pged",
|
||||
"Phares",
|
||||
"Pinnable",
|
||||
"Rijndael",
|
||||
"Serilog",
|
||||
"SUBM",
|
||||
|
18
.vscode/tasks.json
vendored
18
.vscode/tasks.json
vendored
@ -7,8 +7,6 @@
|
||||
"type": "process",
|
||||
"args": [
|
||||
"user-secrets",
|
||||
"-p",
|
||||
"${workspaceFolder}/File-Watcher.csproj",
|
||||
"init"
|
||||
],
|
||||
"problemMatcher": "$msCompile"
|
||||
@ -19,8 +17,6 @@
|
||||
"type": "process",
|
||||
"args": [
|
||||
"user-secrets",
|
||||
"-p",
|
||||
"${workspaceFolder}/File-Watcher.csproj",
|
||||
"set",
|
||||
"_UserSecretsId",
|
||||
"6516d19d6569"
|
||||
@ -43,19 +39,16 @@
|
||||
"problemMatcher": "$msCompile"
|
||||
},
|
||||
{
|
||||
"label": "build",
|
||||
"label": "Build",
|
||||
"command": "dotnet",
|
||||
"type": "process",
|
||||
"args": [
|
||||
"build",
|
||||
"${workspaceFolder}/File-Watcher.csproj",
|
||||
"/property:GenerateFullPaths=true",
|
||||
"/consoleloggerparameters:NoSummary"
|
||||
"build"
|
||||
],
|
||||
"problemMatcher": "$msCompile"
|
||||
},
|
||||
{
|
||||
"label": "Format-Whitespaces",
|
||||
"label": "Format Whitespaces",
|
||||
"command": "dotnet",
|
||||
"type": "process",
|
||||
"args": [
|
||||
@ -74,10 +67,7 @@
|
||||
"win-x64",
|
||||
"-c",
|
||||
"Release",
|
||||
"-p:PublishAot=true",
|
||||
"${workspaceFolder}/File-Watcher.csproj",
|
||||
"/property:GenerateFullPaths=true",
|
||||
"/consoleloggerparameters:NoSummary"
|
||||
"-p:PublishAot=true"
|
||||
],
|
||||
"problemMatcher": "$msCompile"
|
||||
},
|
||||
|
@ -1,4 +1,4 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Worker">
|
||||
<Project Sdk="Microsoft.NET.Sdk.Worker">
|
||||
<PropertyGroup>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
@ -12,7 +12,7 @@
|
||||
<ItemGroup>
|
||||
<PackageReference Include="CliWrap" Version="3.8.2" />
|
||||
<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.DependencyInjection" 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.EventLog" Version="8.0.1" />
|
||||
<PackageReference Include="Oracle.ManagedDataAccess.Core" Version="23.7.0" />
|
||||
<PackageReference Include="runtime.win-x64.Microsoft.DotNet.ILCompiler" Version="8.0.14" />
|
||||
<PackageReference Include="ShellProgressBar" Version="5.2.0" />
|
||||
<PackageReference Include="runtime.win-x64.Microsoft.DotNet.ILCompiler" Version="8.0.20" />
|
||||
<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.Text.Json" Version="9.0.3" />
|
||||
<PackageReference Include="Phares.AA.Shared" Version="8.0.114.12235" />
|
||||
<PackageReference Include="Phares.AA.Metadata" Version="8.0.114.12235" />
|
||||
<PackageReference Include="System.Text.Json" Version="9.0.5" />
|
||||
<PackageReference Include="Phares.Shared" Version="8.0.118.14751" />
|
||||
<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>
|
||||
</Project>
|
12
Helpers/DAQmx/CSVTime.cs
Normal file
12
Helpers/DAQmx/CSVTime.cs
Normal 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;
|
||||
}
|
17
Helpers/DAQmx/CVIAbsoluteTime.cs
Normal file
17
Helpers/DAQmx/CVIAbsoluteTime.cs
Normal 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
13
Helpers/DAQmx/DAQmx.cs
Normal 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();
|
||||
}
|
||||
}
|
7
Helpers/DAQmx/DAQmxActiveEdge.cs
Normal file
7
Helpers/DAQmx/DAQmxActiveEdge.cs
Normal file
@ -0,0 +1,7 @@
|
||||
namespace Helpers.DAQmx;
|
||||
|
||||
public enum DAQmxActiveEdge
|
||||
{
|
||||
Falling = 10171, // 0x000027BB
|
||||
Rising = 10280, // 0x00002828
|
||||
}
|
7
Helpers/DAQmx/DAQmxDataLayout.cs
Normal file
7
Helpers/DAQmx/DAQmxDataLayout.cs
Normal file
@ -0,0 +1,7 @@
|
||||
namespace Helpers.DAQmx;
|
||||
|
||||
public enum DAQmxDataLayout
|
||||
{
|
||||
GroupByChannel,
|
||||
GroupByScanNumber,
|
||||
}
|
7
Helpers/DAQmx/DAQmxDigitalPatternTriggerWhen.cs
Normal file
7
Helpers/DAQmx/DAQmxDigitalPatternTriggerWhen.cs
Normal file
@ -0,0 +1,7 @@
|
||||
namespace Helpers.DAQmx;
|
||||
|
||||
public enum DAQmxDigitalPatternTriggerWhen
|
||||
{
|
||||
PatternDoesNotMatch = 10253, // 0x0000280D
|
||||
PatternMatches = 10254, // 0x0000280E
|
||||
}
|
7
Helpers/DAQmx/DAQmxEdge.cs
Normal file
7
Helpers/DAQmx/DAQmxEdge.cs
Normal file
@ -0,0 +1,7 @@
|
||||
namespace Helpers.DAQmx;
|
||||
|
||||
public enum DAQmxEdge
|
||||
{
|
||||
Falling = 10171, // 0x000027BB
|
||||
Rising = 10280, // 0x00002828
|
||||
}
|
14
Helpers/DAQmx/DAQmxException.cs
Normal file
14
Helpers/DAQmx/DAQmxException.cs
Normal 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) + ")")
|
||||
{
|
||||
}
|
||||
}
|
7
Helpers/DAQmx/DAQmxFillMode.cs
Normal file
7
Helpers/DAQmx/DAQmxFillMode.cs
Normal file
@ -0,0 +1,7 @@
|
||||
namespace Helpers.DAQmx;
|
||||
|
||||
public enum DAQmxFillMode
|
||||
{
|
||||
GroupByChannel,
|
||||
GroupByScanNumber,
|
||||
}
|
10
Helpers/DAQmx/DAQmxInputTerminalConfiguration.cs
Normal file
10
Helpers/DAQmx/DAQmxInputTerminalConfiguration.cs
Normal 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
|
||||
}
|
7
Helpers/DAQmx/DAQmxLevel.cs
Normal file
7
Helpers/DAQmx/DAQmxLevel.cs
Normal file
@ -0,0 +1,7 @@
|
||||
namespace Helpers.DAQmx;
|
||||
|
||||
public enum DAQmxLevel
|
||||
{
|
||||
High = 10192, // 0x000027D0
|
||||
Low = 10214, // 0x000027E6
|
||||
}
|
7
Helpers/DAQmx/DAQmxLineGrouping.cs
Normal file
7
Helpers/DAQmx/DAQmxLineGrouping.cs
Normal file
@ -0,0 +1,7 @@
|
||||
namespace Helpers.DAQmx;
|
||||
|
||||
public enum DAQmxLineGrouping
|
||||
{
|
||||
OneChannelForEachLine,
|
||||
OneChannelForAllLines,
|
||||
}
|
8
Helpers/DAQmx/DAQmxLoggingMode.cs
Normal file
8
Helpers/DAQmx/DAQmxLoggingMode.cs
Normal file
@ -0,0 +1,8 @@
|
||||
namespace Helpers.DAQmx;
|
||||
|
||||
public enum DAQmxLoggingMode
|
||||
{
|
||||
Off = 10231, // 0x000027F7
|
||||
LogAndRead = 15842, // 0x00003DE2
|
||||
Log = 15844, // 0x00003DE4
|
||||
}
|
9
Helpers/DAQmx/DAQmxLoggingTDMSOperation.cs
Normal file
9
Helpers/DAQmx/DAQmxLoggingTDMSOperation.cs
Normal file
@ -0,0 +1,9 @@
|
||||
namespace Helpers.DAQmx;
|
||||
|
||||
public enum DAQmxLoggingTDMSOperation
|
||||
{
|
||||
Open = 10437, // 0x000028C5
|
||||
OpenOrCreate = 15846, // 0x00003DE6
|
||||
CreateOrReplace = 15847, // 0x00003DE7
|
||||
Create = 15848, // 0x00003DE8
|
||||
}
|
5
Helpers/DAQmx/DAQmxMemoryException.cs
Normal file
5
Helpers/DAQmx/DAQmxMemoryException.cs
Normal file
@ -0,0 +1,5 @@
|
||||
namespace Helpers.DAQmx;
|
||||
|
||||
public class DAQmxMemoryException(string message) : Exception(message)
|
||||
{
|
||||
}
|
7
Helpers/DAQmx/DAQmxPolarity.cs
Normal file
7
Helpers/DAQmx/DAQmxPolarity.cs
Normal file
@ -0,0 +1,7 @@
|
||||
namespace Helpers.DAQmx;
|
||||
|
||||
public enum DAQmxPolarity
|
||||
{
|
||||
ActiveHigh = 10095, // 0x0000276F
|
||||
ActiveLow = 10096, // 0x00002770
|
||||
}
|
8
Helpers/DAQmx/DAQmxSampleMode.cs
Normal file
8
Helpers/DAQmx/DAQmxSampleMode.cs
Normal 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
348
Helpers/DAQmx/DAQmxTask.cs
Normal 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;
|
||||
}
|
||||
|
||||
}
|
7
Helpers/DAQmx/DAQmxTimescale.cs
Normal file
7
Helpers/DAQmx/DAQmxTimescale.cs
Normal file
@ -0,0 +1,7 @@
|
||||
namespace Helpers.DAQmx;
|
||||
|
||||
public enum DAQmxTimescale
|
||||
{
|
||||
HostTime = 16126, // 0x00003EFE
|
||||
IODeviceTime = 16127, // 0x00003EFF
|
||||
}
|
7
Helpers/DAQmx/DAQmxUnits.cs
Normal file
7
Helpers/DAQmx/DAQmxUnits.cs
Normal file
@ -0,0 +1,7 @@
|
||||
namespace Helpers.DAQmx;
|
||||
|
||||
public enum DAQmxUnits
|
||||
{
|
||||
FromCustomScale = 10065, // 0x00002751
|
||||
Volts = 10348, // 0x0000286C
|
||||
}
|
7
Helpers/DAQmx/DAQmxWindowTriggerWhen.cs
Normal file
7
Helpers/DAQmx/DAQmxWindowTriggerWhen.cs
Normal file
@ -0,0 +1,7 @@
|
||||
namespace Helpers.DAQmx;
|
||||
|
||||
public enum DAQmxWindowTriggerWhen
|
||||
{
|
||||
EnteringWindow = 10163, // 0x000027B3
|
||||
LeavingWindow = 10208, // 0x000027E0
|
||||
}
|
7
Helpers/DAQmx/DAQmxWriteRegenMode.cs
Normal file
7
Helpers/DAQmx/DAQmxWriteRegenMode.cs
Normal file
@ -0,0 +1,7 @@
|
||||
namespace Helpers.DAQmx;
|
||||
|
||||
public enum DAQmxWriteRegenMode
|
||||
{
|
||||
AllowRegen = 10097, // 0x00002771
|
||||
DoNotAllowRegen = 10158, // 0x000027AE
|
||||
}
|
431
Helpers/DAQmx/Interop.cs
Normal file
431
Helpers/DAQmx/Interop.cs
Normal 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);
|
||||
|
||||
}
|
@ -1,16 +1,22 @@
|
||||
using CliWrap;
|
||||
using File_Watcher.Models;
|
||||
|
||||
#if ShellProgressBar
|
||||
|
||||
using ShellProgressBar;
|
||||
|
||||
#endif
|
||||
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
using System.IO.Compression;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text.Json;
|
||||
using View_by_Distance.Metadata.Models;
|
||||
using View_by_Distance.Metadata.Models.Stateless;
|
||||
using View_by_Distance.Shared.Models;
|
||||
using View_by_Distance.Shared.Models.Stateless;
|
||||
using Phares.Metadata.Models;
|
||||
using Phares.Metadata.Models.Stateless;
|
||||
using Phares.Shared.Models;
|
||||
using Phares.Shared.Models.Stateless;
|
||||
|
||||
namespace File_Watcher.Helpers;
|
||||
|
||||
@ -20,13 +26,25 @@ internal static partial class DeterministicHashCodeHelper
|
||||
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 readonly ProgressBarOptions _ProgressBarOptions;
|
||||
|
||||
public int CurrentTick { get; internal set; }
|
||||
#endif
|
||||
|
||||
public Windows() =>
|
||||
#if ShellProgressBar
|
||||
_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) =>
|
||||
GetDeterministicHashCode(httpClient, uri);
|
||||
@ -97,18 +115,26 @@ internal static partial class DeterministicHashCodeHelper
|
||||
}
|
||||
|
||||
void IWindows.Tick() =>
|
||||
#if ShellProgressBar
|
||||
_ProgressBar?.Tick();
|
||||
#else
|
||||
throw new NotSupportedException("ShellProgressBar is not supported in this context.");
|
||||
#endif
|
||||
|
||||
void IDisposable.Dispose()
|
||||
{
|
||||
#if ShellProgressBar
|
||||
_ProgressBar?.Dispose();
|
||||
#endif
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
void IWindows.ConstructProgressBar(int maxTicks, string message)
|
||||
{
|
||||
#if ShellProgressBar
|
||||
_ProgressBar?.Dispose();
|
||||
_ProgressBar = new(maxTicks, message, _ProgressBarOptions);
|
||||
#endif
|
||||
}
|
||||
|
||||
ReadOnlyCollection<string> IWindows.ConvertAndGetFastForwardMovingPictureExpertsGroupFiles(ResultSettings resultSettings, HttpClient? httpClient, FilePath filePath)
|
||||
@ -164,7 +190,7 @@ internal static partial class DeterministicHashCodeHelper
|
||||
string sourceDirectory;
|
||||
List<string> check = [];
|
||||
string archiveEntryFile;
|
||||
long ticks = DateTime.Now.Ticks;
|
||||
Windows windows = new();
|
||||
ReadOnlyCollection<FirstPass> collection;
|
||||
string rootDirectory = Path.GetFullPath(appSettings.ResultSettings.RootDirectory);
|
||||
if (!Directory.Exists(rootDirectory))
|
||||
@ -187,7 +213,7 @@ internal static partial class DeterministicHashCodeHelper
|
||||
archiveEntryFile = Path.Combine(sourceDirectory, zipArchiveEntry.Name);
|
||||
zipArchiveEntry.ExtractToFile(archiveEntryFile);
|
||||
}
|
||||
collection = WindowsWork(logger, appSettings, ticks, sourceDirectory);
|
||||
collection = WindowsWork(windows, logger, appSettings, sourceDirectory);
|
||||
if (check.Count == collection.Count)
|
||||
{
|
||||
json = JsonSerializer.Serialize(collection.ToList(), FirstPassCollectionSourceGenerationContext.Default.ListFirstPass);
|
||||
@ -198,12 +224,11 @@ internal static partial class DeterministicHashCodeHelper
|
||||
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;
|
||||
Windows windows = new();
|
||||
IWindows windowsInterface = windows;
|
||||
logger?.LogInformation("{Ticks} {RootDirectory}", ticks, sourceDirectory);
|
||||
logger?.LogInformation("{Ticks} {RootDirectory}", windows.Ticks, sourceDirectory);
|
||||
A_Metadata metadata = new(appSettings.ResultSettings, appSettings.MetadataSettings);
|
||||
int appSettingsMaxDegreeOfParallelism = appSettings.DeterministicHashCodeConfiguration.MaxDegreeOfParallelism;
|
||||
ReadOnlyCollection<string> files = Directory.GetFiles(sourceDirectory, "*", SearchOption.AllDirectories).AsReadOnly();
|
||||
@ -299,7 +324,7 @@ internal static partial class DeterministicHashCodeHelper
|
||||
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 = [];
|
||||
FirstPass firstPass;
|
||||
|
503
Helpers/DiskInfoHelper.cs
Normal file
503
Helpers/DiskInfoHelper.cs
Normal 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();
|
||||
}
|
||||
|
||||
}
|
@ -68,7 +68,7 @@ internal static partial class HelperCamstarOracle
|
||||
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)
|
||||
throw new NullReferenceException(nameof(_MonIn));
|
||||
@ -100,6 +100,7 @@ internal static partial class HelperCamstarOracle
|
||||
File.WriteAllLines(Path.Combine(directory, $"{dateTime.Ticks}.tsv"), lines);
|
||||
if (_LastValue is null || _LastUpload is null || _LastValue.Value != lines.Count || new TimeSpan(dateTime.Ticks - _LastUpload.Value.Ticks).TotalMinutes > 5)
|
||||
{
|
||||
Heartbeat(appSettings, httpClientFactory, logger, State.Up, cancellationToken);
|
||||
Task<HttpResponseMessage> httpResponseMessage = _MonIn.SendPerformanceMessage(camstarOracleConfiguration.MonitorApplicationSite, camstarOracleConfiguration.MonitorApplicationResource, performanceName, value: lines.Count, description: string.Empty);
|
||||
httpResponseMessage.Wait(cancellationToken);
|
||||
if (httpResponseMessage.Result.StatusCode != System.Net.HttpStatusCode.OK)
|
||||
|
@ -17,7 +17,7 @@ internal static partial class HelperInfinityQS
|
||||
}
|
||||
}
|
||||
|
||||
private static void RunMI()
|
||||
private static void RunMI(string decryptedPassword)
|
||||
{
|
||||
#pragma warning disable CA1416
|
||||
string processName = "iispcmi.exe";
|
||||
@ -27,7 +27,7 @@ internal static partial class HelperInfinityQS
|
||||
Domain = "Infineon",
|
||||
UseShellExecute = false,
|
||||
UserName = "ecfisysadmin",
|
||||
PasswordInClearText = "j(1(P%xB=g}3w9db",
|
||||
PasswordInClearText = decryptedPassword,
|
||||
WorkingDirectory = "C:/Program Files (x86)/InfinityQS International/ProFicient/Applications"
|
||||
};
|
||||
TimeSpan timeSpan = new(DateTime.Now.AddDays(7).Ticks - DateTime.Now.Ticks);
|
||||
@ -36,10 +36,11 @@ internal static partial class HelperInfinityQS
|
||||
#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);
|
||||
RunMI();
|
||||
string decrypted = RijndaelEncryption.Decrypt(appSettings.InfinityQSConfiguration.EncryptedPassword, appSettings.FileWatcherConfiguration.Company);
|
||||
RunMI(decrypted);
|
||||
return true;
|
||||
}
|
||||
}
|
114
Helpers/InfinityQSProjectHelper.cs
Normal file
114
Helpers/InfinityQSProjectHelper.cs
Normal file
@ -0,0 +1,114 @@
|
||||
using File_Watcher.Models;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Net.Mail;
|
||||
|
||||
namespace File_Watcher.Helpers;
|
||||
|
||||
internal static partial class InfinityQSProjectHelper
|
||||
{
|
||||
private record Record(ReadOnlyCollection<string> FilteredLines,
|
||||
DateTime LastWriteTimeUtc,
|
||||
string Path);
|
||||
|
||||
private static long _LastReview = DateTime.UtcNow.Ticks;
|
||||
private static readonly Dictionary<string, Record> _KeyValuePairs = [];
|
||||
|
||||
internal static bool SendEmail(AppSettings appSettings, ILogger<Worker> logger)
|
||||
{
|
||||
InfinityQSProjectConfiguration configuration = appSettings.InfinityQSProjectConfiguration;
|
||||
Clear(logger, configuration);
|
||||
ReadOnlyDictionary<string, Record> keyValuePairs = GetKeyValuePairs(logger, configuration);
|
||||
SendEmail(logger, configuration, keyValuePairs);
|
||||
_LastReview = DateTime.UtcNow.Ticks;
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void Clear(ILogger<Worker> logger, InfinityQSProjectConfiguration configuration)
|
||||
{
|
||||
long check = DateTime.UtcNow.AddHours(-configuration.ClearEveryHours).Ticks;
|
||||
foreach (KeyValuePair<string, Record> keyValuePair in _KeyValuePairs)
|
||||
{
|
||||
if (keyValuePair.Value.LastWriteTimeUtc.Ticks < check)
|
||||
{
|
||||
_ = _KeyValuePairs.Remove(keyValuePair.Key);
|
||||
logger.LogDebug("Clear File:{file}", keyValuePair.Key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static ReadOnlyDictionary<string, Record> GetKeyValuePairs(ILogger<Worker> logger, InfinityQSProjectConfiguration configuration)
|
||||
{
|
||||
bool check;
|
||||
Record? record;
|
||||
string[] lines;
|
||||
FileInfo fileInfo;
|
||||
List<string> filtered = [];
|
||||
Dictionary<string, Record> results = [];
|
||||
string[] files = Directory.GetFiles(configuration.SourceDirectory, configuration.SearchPattern, SearchOption.TopDirectoryOnly);
|
||||
foreach (string file in files)
|
||||
{
|
||||
check = false;
|
||||
filtered.Clear();
|
||||
fileInfo = new(file);
|
||||
if (fileInfo.LastWriteTimeUtc.Ticks < _LastReview)
|
||||
{
|
||||
logger.LogDebug("Old File:{file}", file);
|
||||
continue;
|
||||
}
|
||||
if (_KeyValuePairs.ContainsKey(fileInfo.FullName))
|
||||
{
|
||||
logger.LogDebug("Verified File:{file}", file);
|
||||
continue;
|
||||
}
|
||||
lines = File.ReadAllLines(fileInfo.FullName);
|
||||
foreach (string line in lines)
|
||||
{
|
||||
if (!check && line.Contains(configuration.Search))
|
||||
{
|
||||
check = true;
|
||||
continue;
|
||||
}
|
||||
if (check)
|
||||
{
|
||||
if (line.StartsWith(configuration.Search[0]))
|
||||
break;
|
||||
filtered.Add(line);
|
||||
}
|
||||
}
|
||||
record = new(FilteredLines: filtered.AsReadOnly(),
|
||||
LastWriteTimeUtc: fileInfo.LastWriteTimeUtc,
|
||||
Path: fileInfo.FullName);
|
||||
results.Add(fileInfo.FullName, record);
|
||||
}
|
||||
return results.AsReadOnly();
|
||||
}
|
||||
|
||||
private static void SendEmail(ILogger<Worker> logger, InfinityQSProjectConfiguration configuration, ReadOnlyDictionary<string, Record> keyValuePairs)
|
||||
{
|
||||
string body;
|
||||
foreach (KeyValuePair<string, Record> keyValuePair in keyValuePairs)
|
||||
{
|
||||
logger.LogDebug("File:{file}", keyValuePair.Key);
|
||||
body = $"InfinityQS Project Change Detected{Environment.NewLine}File:{keyValuePair.Key}{Environment.NewLine}LastWriteTimeUtc:{keyValuePair.Value:O}{Environment.NewLine}{string.Join(Environment.NewLine, keyValuePair.Value.FilteredLines)}";
|
||||
logger.LogWarning("SendEmail:{body}", body);
|
||||
SendEmail(configuration.From, configuration.To, configuration.SimpleMailTransferProtocolServer, configuration.Subject, body);
|
||||
}
|
||||
}
|
||||
|
||||
private static void SendEmail(string from, string to, string simpleMailTransferProtocolServer, string subject, string body)
|
||||
{
|
||||
SmtpClient smtpClient = new(simpleMailTransferProtocolServer);
|
||||
MailMessage mailMessage = new()
|
||||
{
|
||||
From = new MailAddress(from),
|
||||
Subject = subject,
|
||||
Body = body,
|
||||
Priority = MailPriority.High
|
||||
};
|
||||
mailMessage.To.Add(new MailAddress(to));
|
||||
smtpClient.Send(mailMessage);
|
||||
smtpClient.Dispose();
|
||||
mailMessage.Dispose();
|
||||
}
|
||||
|
||||
}
|
700
Helpers/LabJackT7Helper.cs
Normal file
700
Helpers/LabJackT7Helper.cs
Normal file
@ -0,0 +1,700 @@
|
||||
using File_Watcher.Models;
|
||||
using System.Diagnostics;
|
||||
using System.Net.Sockets;
|
||||
|
||||
namespace File_Watcher.Helpers;
|
||||
|
||||
#pragma warning disable IDE0300
|
||||
|
||||
internal static partial class LabJackT7Helper
|
||||
{
|
||||
|
||||
private static ModbusTransmissionControlProtocolClient? _ModbusTransmissionControlProtocolClient;
|
||||
|
||||
private class ModbusTransmissionControlProtocolClient : IDisposable
|
||||
{
|
||||
|
||||
private ushort _TransactionID;
|
||||
private NetworkStream? _NetworkStream;
|
||||
private TcpClient? _TransmissionControlProtocolClient;
|
||||
|
||||
public ModbusTransmissionControlProtocolClient(string hostname, int port) =>
|
||||
Connect(hostname, port);
|
||||
|
||||
public void Connect(string hostname, int port)
|
||||
{
|
||||
if (_TransmissionControlProtocolClient is not null)
|
||||
Close();
|
||||
|
||||
_TransmissionControlProtocolClient = new TcpClient(hostname, port);
|
||||
_NetworkStream = _TransmissionControlProtocolClient.GetStream();
|
||||
_TransactionID = 0;
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
_NetworkStream?.Close();
|
||||
_NetworkStream = null;
|
||||
|
||||
_TransmissionControlProtocolClient?.Close();
|
||||
_TransmissionControlProtocolClient = null;
|
||||
}
|
||||
|
||||
public bool IsConnected()
|
||||
{
|
||||
if (_TransmissionControlProtocolClient is not null)
|
||||
return _TransmissionControlProtocolClient.Connected;
|
||||
return false;
|
||||
}
|
||||
|
||||
public void SetTimeouts(int sendTimeout, int receiveTimeout)
|
||||
{
|
||||
if (_TransmissionControlProtocolClient == null)
|
||||
throw new Exception("Not connected.");
|
||||
_TransmissionControlProtocolClient.ReceiveTimeout = receiveTimeout;
|
||||
_TransmissionControlProtocolClient.SendTimeout = sendTimeout;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write a byte array of data to the Modbus device.
|
||||
/// </summary>
|
||||
/// <param name="address">The starting register address.</param>
|
||||
/// <param name="data">The byte array of data to write.</param>
|
||||
public void Write(ushort address, byte[] data)
|
||||
{
|
||||
if (_NetworkStream is null)
|
||||
throw new Exception("Not connected.");
|
||||
|
||||
//Using Modbus function 16
|
||||
|
||||
//Create Modbus Command
|
||||
if (data.Length > 254)
|
||||
throw new Exception("Too many bytes. The maximum is 254.");
|
||||
|
||||
if (data.Length % 2 != 0)
|
||||
throw new Exception("The number of bytes needs to be a multiple of 2.");
|
||||
|
||||
byte[] com = new byte[13 + data.Length];
|
||||
com[7] = 16;
|
||||
com[8] = (byte)(address >> 8);
|
||||
com[9] = (byte)(address & 0xFF);
|
||||
com[10] = 0;
|
||||
com[11] = (byte)(data.Length / 2);
|
||||
com[12] = (byte)data.Length;
|
||||
Array.Copy(data, 0, com, 13, data.Length);
|
||||
SetHeader(com);
|
||||
_NetworkStream.Write(com, 0, com.Length);
|
||||
|
||||
byte[] res = new byte[12];
|
||||
int expectedSize = res.Length;
|
||||
int size = _NetworkStream.Read(res, 0, res.Length);
|
||||
|
||||
Array.Resize(ref res, size);
|
||||
ResponseErrorChecks(res, expectedSize, com);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read a byte array of data from the Modbus device.
|
||||
/// </summary>
|
||||
/// <param name="address">The starting register address.</param>
|
||||
/// <param name="data">The read byte array of data. The array length is
|
||||
/// the amount of bytes to read.</param>
|
||||
public void Read(ushort address, byte[] data)
|
||||
{
|
||||
if (_NetworkStream is null)
|
||||
throw new Exception("Not connected.");
|
||||
|
||||
//Using Modbus function 3
|
||||
|
||||
//Create Modbus Command
|
||||
if (data.Length > 254)
|
||||
throw new Exception("Too many bytes. The maximum is 254.");
|
||||
|
||||
if (data.Length % 2 != 0)
|
||||
throw new Exception("The number of bytes needs to be a multiple of 2.");
|
||||
|
||||
byte[] com = new byte[12];
|
||||
com[7] = 3;
|
||||
com[8] = (byte)(address >> 8);
|
||||
com[9] = (byte)(address & 0xFF);
|
||||
com[10] = 0;
|
||||
com[11] = (byte)(data.Length / 2);
|
||||
SetHeader(com);
|
||||
_NetworkStream.Write(com, 0, com.Length);
|
||||
|
||||
byte[] res = new byte[9 + data.Length];
|
||||
int expectedSize = res.Length;
|
||||
int size = _NetworkStream.Read(res, 0, res.Length);
|
||||
Array.Resize(ref res, size);
|
||||
ResponseErrorChecks(res, expectedSize, com);
|
||||
|
||||
Array.Copy(res, 9, data, 0, data.Length);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write an ushort array of data to the Modbus device.
|
||||
/// </summary>
|
||||
/// <param name="address">The starting register address.</param>
|
||||
/// <param name="data">The ushort array of data to write.</param>
|
||||
public void Write(ushort address, ushort[] data)
|
||||
{
|
||||
if (data.Length > 127)
|
||||
throw new Exception("Too many shorts. The maximum is 127.");
|
||||
|
||||
byte[] bytes = new byte[data.Length * 2];
|
||||
for (int i = 0; i < data.Length; i++)
|
||||
{
|
||||
BitConverter.GetBytes(data[i]).CopyTo(bytes, i * 2);
|
||||
if (BitConverter.IsLittleEndian)
|
||||
Array.Reverse(bytes, i * 2, 2);
|
||||
}
|
||||
Write(address, bytes);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read an ushort array of data from the Modbus device.
|
||||
/// </summary>
|
||||
/// <param name="address">The starting register address.</param>
|
||||
/// <param name="data">The read ushort array of data. The array length
|
||||
/// is the amount of shorts to read.</param>
|
||||
public void Read(ushort address, ushort[] data)
|
||||
{
|
||||
if (data.Length > 127)
|
||||
throw new Exception("Too many shorts. The maximum is 127.");
|
||||
|
||||
byte[] bytes = new byte[data.Length * 2];
|
||||
Read(address, bytes);
|
||||
for (int i = 0; i < data.Length; i++)
|
||||
{
|
||||
if (BitConverter.IsLittleEndian)
|
||||
Array.Reverse(bytes, i * 2, 2);
|
||||
data[i] = BitConverter.ToUInt16(bytes, i * 2);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write an uint array of data to the Modbus device.
|
||||
/// </summary>
|
||||
/// <param name="address">The starting register address.</param>
|
||||
/// <param name="data">The uint array of data to write.</param>
|
||||
public void Write(ushort address, uint[] data)
|
||||
{
|
||||
if (data.Length > 63)
|
||||
throw new Exception("Too many uint. The maximum is 63.");
|
||||
|
||||
byte[] bytes = new byte[data.Length * 4];
|
||||
for (int i = 0; i < data.Length; i++)
|
||||
{
|
||||
BitConverter.GetBytes(data[i]).CopyTo(bytes, i * 4);
|
||||
if (BitConverter.IsLittleEndian)
|
||||
Array.Reverse(bytes, i * 4, 4);
|
||||
}
|
||||
Write(address, bytes);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read an uint array of data from the Modbus device.
|
||||
/// </summary>
|
||||
/// <param name="address">The starting register address.</param>
|
||||
/// <param name="data">The read uint array of data. The array length is
|
||||
/// the amount of ints to read.</param>
|
||||
public void Read(ushort address, uint[] data)
|
||||
{
|
||||
if (data.Length > 63)
|
||||
throw new Exception("Too many ints. The maximum is 63.");
|
||||
|
||||
byte[] bytes = new byte[data.Length * 4];
|
||||
Read(address, bytes);
|
||||
for (int i = 0; i < data.Length; i++)
|
||||
{
|
||||
if (BitConverter.IsLittleEndian)
|
||||
Array.Reverse(bytes, i * 4, 4);
|
||||
data[i] = BitConverter.ToUInt32(bytes, i * 4);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write an int array of data to the Modbus device.
|
||||
/// </summary>
|
||||
/// <param name="address">The starting register address.</param>
|
||||
/// <param name="data">The int array of data to write.</param>
|
||||
public void Write(ushort address, int[] data)
|
||||
{
|
||||
if (data.Length > 63)
|
||||
throw new Exception("Too many ints. The maximum is 63.");
|
||||
|
||||
byte[] bytes = new byte[data.Length * 4];
|
||||
for (int i = 0; i < data.Length; i++)
|
||||
{
|
||||
BitConverter.GetBytes(data[i]).CopyTo(bytes, i * 4);
|
||||
if (BitConverter.IsLittleEndian)
|
||||
Array.Reverse(bytes, i * 4, 4);
|
||||
}
|
||||
Write(address, bytes);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read an int array of data from the Modbus device.
|
||||
/// </summary>
|
||||
/// <param name="address">The starting register address.</param>
|
||||
/// <param name="data">The read int array of data. The array length is
|
||||
/// the amount of ints to read.</param>
|
||||
public void Read(ushort address, int[] data)
|
||||
{
|
||||
if (data.Length > 63)
|
||||
throw new Exception("Too many ints. The maximum is 63.");
|
||||
|
||||
byte[] bytes = new byte[data.Length * 4];
|
||||
Read(address, bytes);
|
||||
for (int i = 0; i < data.Length; i++)
|
||||
{
|
||||
if (BitConverter.IsLittleEndian)
|
||||
Array.Reverse(bytes, i * 4, 4);
|
||||
data[i] = BitConverter.ToInt32(bytes, i * 4);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write a float array of data to the Modbus device.
|
||||
/// </summary>
|
||||
/// <param name="address">The starting register address.</param>
|
||||
/// <param name="data">The float array of data to write.</param>
|
||||
public void Write(ushort address, float[] data)
|
||||
{
|
||||
if (data.Length > 63)
|
||||
throw new Exception("Too many floats. The maximum is 63.");
|
||||
|
||||
byte[] bytes = new byte[data.Length * 4];
|
||||
for (int i = 0; i < data.Length; i++)
|
||||
{
|
||||
BitConverter.GetBytes(data[i]).CopyTo(bytes, i * 4);
|
||||
if (BitConverter.IsLittleEndian)
|
||||
Array.Reverse(bytes, i * 4, 4);
|
||||
}
|
||||
Write(address, bytes);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a float array of data from the Modbus device.
|
||||
/// </summary>
|
||||
/// <param name="address">The starting register address.</param>
|
||||
/// <param name="data">The read float array of data. The array length is
|
||||
/// the amount of floats to read.</param>
|
||||
public void Read(ushort address, float[] data)
|
||||
{
|
||||
if (data.Length > 63)
|
||||
throw new Exception("Too many floats. The maximum is 63.");
|
||||
|
||||
byte[] bytes = new byte[data.Length * 4];
|
||||
Read(address, bytes);
|
||||
for (int i = 0; i < data.Length; i++)
|
||||
{
|
||||
if (BitConverter.IsLittleEndian)
|
||||
Array.Reverse(bytes, i * 4, 4);
|
||||
data[i] = BitConverter.ToSingle(bytes, i * 4);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write a single ushort of data to the Modbus device.
|
||||
/// </summary>
|
||||
/// <param name="address">The register address.</param>
|
||||
/// <param name="data">The ushort data to write.</param>
|
||||
public void Write(ushort address, ushort data)
|
||||
{
|
||||
ushort[] dataArray = new ushort[1];
|
||||
dataArray[0] = data;
|
||||
Write(address, dataArray);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read a single ushort of data from the Modbus device.
|
||||
/// </summary>
|
||||
/// <param name="address">The register address.</param>
|
||||
/// <param name="data">The read ushort data.</param>
|
||||
public void Read(ushort address, ref ushort data)
|
||||
{
|
||||
ushort[] dataArray = new ushort[1];
|
||||
Read(address, dataArray);
|
||||
data = dataArray[0];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write a single uint of data to the Modbus device.
|
||||
/// </summary>
|
||||
/// <param name="address">The starting register address.</param>
|
||||
/// <param name="data">The uint data to write.</param>
|
||||
public void Write(ushort address, uint data)
|
||||
{
|
||||
uint[] dataArray = new uint[1];
|
||||
dataArray[0] = data;
|
||||
Write(address, dataArray);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read a single uint of data from the Modbus device.
|
||||
/// </summary>
|
||||
/// <param name="address">The starting register address.</param>
|
||||
/// <param name="value">The read uint data.</param>
|
||||
public void Read(ushort address, ref uint data)
|
||||
{
|
||||
uint[] dataArray = new uint[1];
|
||||
Read(address, dataArray);
|
||||
data = dataArray[0];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write a single int of data to the Modbus device.
|
||||
/// </summary>
|
||||
/// <param name="address">The starting register address.</param>
|
||||
/// <param name="data">The int data to write.</param>
|
||||
public void Write(ushort address, int data)
|
||||
{
|
||||
int[] dataArray = new int[1];
|
||||
dataArray[0] = data;
|
||||
Write(address, dataArray);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read a single int of data from the Modbus device.
|
||||
/// </summary>
|
||||
/// <param name="address">The starting register address.</param>
|
||||
/// <param name="data">The read int data.</param>
|
||||
public void Read(ushort address, ref int data)
|
||||
{
|
||||
int[] dataArray = new int[1];
|
||||
Read(address, dataArray);
|
||||
data = dataArray[0];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write a single float of data to the Modbus device.
|
||||
/// 1 uint = 2 registers.
|
||||
/// </summary>
|
||||
/// <param name="address">The starting register address.</param>
|
||||
/// <param name="data">The float data to write.</param>
|
||||
public void Write(ushort address, float data)
|
||||
{
|
||||
float[] dataArray = new float[1];
|
||||
dataArray[0] = data;
|
||||
Write(address, dataArray);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read a single float of data from the Modbus device.
|
||||
/// </summary>
|
||||
/// <param name="address">The starting register address.</param>
|
||||
/// <param name="data">The read float data.</param>
|
||||
public void Read(ushort address, ref float data)
|
||||
{
|
||||
float[] dataArray = new float[1];
|
||||
Read(address, dataArray);
|
||||
data = dataArray[0];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the MBAP header of the Modbus TCP command.
|
||||
/// </summary>
|
||||
/// <param name="command">The byte array for the Modbus TCP command.
|
||||
/// The Modbus request bytes 7+ need to be set beforehand. The MBAP
|
||||
/// header bytes 0 to 6 will be updated based on the request bytes.
|
||||
/// </param>
|
||||
private void SetHeader(byte[] command)
|
||||
{
|
||||
//Transaction ID
|
||||
ushort transID = _TransactionID;
|
||||
if (_TransactionID >= 65535)
|
||||
{
|
||||
//Rollover global transaction ID to 0.
|
||||
_TransactionID = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
//Increment global transaction ID.
|
||||
_TransactionID++;
|
||||
}
|
||||
command[0] = (byte)(transID >> 8);
|
||||
command[1] = (byte)(transID & 0xFF);
|
||||
|
||||
//Protocol ID
|
||||
command[2] = 0;
|
||||
command[3] = 0;
|
||||
|
||||
//Length
|
||||
ushort length = (ushort)(command.Length - 6);
|
||||
command[4] = (byte)(length >> 8);
|
||||
command[5] = (byte)(length & 0xFF);
|
||||
|
||||
//Unit ID
|
||||
command[6] = 1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks the Modbus response for errors.
|
||||
/// </summary>
|
||||
/// <param name="response">The Modbus response byte array.</param>
|
||||
/// <param name="expectedSize">The expected response byte array length.</param>
|
||||
/// <param name="command">The Modbus command byte array.</param>
|
||||
private void ResponseErrorChecks(byte[] response, int expectedLength, byte[] command)
|
||||
{
|
||||
if (response.Length < expectedLength)
|
||||
{
|
||||
if (response.Length < 9)
|
||||
{
|
||||
throw new Exception("Invalid Modbus response.");
|
||||
}
|
||||
if ((response[7] & 0x80) > 0)
|
||||
{
|
||||
//Bit 7 set, indicating Modbus error
|
||||
throw new Exception("Modbus exception code " + response[8] +
|
||||
", " + GetExceptionCodeString(response[8]) + ".");
|
||||
}
|
||||
throw new Exception("Other Modbus response error.");
|
||||
}
|
||||
|
||||
if (response[0] != command[0] || response[1] != command[1])
|
||||
{
|
||||
throw new Exception("Modbus transaction ID mismatch.");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the Modbus exception name.
|
||||
/// </summary>
|
||||
/// <param name="code">The exception code.</param>
|
||||
/// <returns>The exception name.</returns>
|
||||
private string GetExceptionCodeString(uint code) =>
|
||||
code switch
|
||||
{
|
||||
1 => "Illegal Function",
|
||||
2 => "Illegal Data Address",
|
||||
3 => "Illegal Data Value",
|
||||
4 => "Slave Device Failure",
|
||||
5 => "Acknowledge",
|
||||
6 => "Slave Device Busy",
|
||||
7 => "Negative Acknowledge",
|
||||
8 => "Memory Parity Error",
|
||||
10 => "Gateway Path Unavailable",
|
||||
11 => "Gateway Target Device Failed to Respond",
|
||||
_ => ""
|
||||
};
|
||||
|
||||
void IDisposable.Dispose() =>
|
||||
Close();
|
||||
|
||||
}
|
||||
|
||||
internal static bool ReadAll(AppSettings appSettings, ILogger<Worker> logger)
|
||||
{
|
||||
LabJackT7Configuration configuration = appSettings.LabJackT7Configuration;
|
||||
_ModbusTransmissionControlProtocolClient ??= new(configuration.InternetProtocolAddress, configuration.Port);
|
||||
ReadAllAnalog(_ModbusTransmissionControlProtocolClient, logger);
|
||||
ReadAllDigitalIO(_ModbusTransmissionControlProtocolClient, logger);
|
||||
if (configuration.InternetProtocolAddress == "false")
|
||||
ReadAllAnalogMux80(_ModbusTransmissionControlProtocolClient, logger);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Displays "AINxx : Values" readings.
|
||||
/// </summary>
|
||||
/// <param name="startingAddress">Starting Modbus address of
|
||||
/// readings.</param>
|
||||
/// <param name="values">Float analog input (AIN) readings.</param>
|
||||
private static void DisplayAnalogInputReadings(ILogger<Worker> logger, ushort startingAddress, float[] values)
|
||||
{
|
||||
for (int i = 0; i < values.Length; i++)
|
||||
{
|
||||
logger.LogInformation("AIN" + (startingAddress + i * 2) / 2 + " : " + values[i] + " V");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Displays all digital I/O readings.
|
||||
/// </summary>
|
||||
/// <param name="directions">Reading from T7 Modbus address
|
||||
/// 2850 (DIO_DIRECTION).</param>
|
||||
/// <param name="states">Reading from T7 Modbus address
|
||||
/// 2800 (DIO_STATE).</param>
|
||||
private static void DisplayDigitalIOReadings(ILogger<Worker> logger, uint directions, uint states)
|
||||
{
|
||||
string fioDirs = "";
|
||||
string fioStates = "";
|
||||
string eioDirs = "";
|
||||
string eioStates = "";
|
||||
string cioDirs = "";
|
||||
string cioStates = "";
|
||||
string mioDirs = "";
|
||||
string mioStates = "";
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
fioDirs += Convert.ToString((directions >> i) & 1);
|
||||
fioStates += Convert.ToString((states >> i) & 1);
|
||||
}
|
||||
logger.LogInformation("FIO0-FIO7 directions = " + fioDirs + ", states = " + fioStates);
|
||||
|
||||
for (int i = 8; i < 16; i++)
|
||||
{
|
||||
eioDirs += Convert.ToString((directions >> i) & 1);
|
||||
eioStates += Convert.ToString((states >> i) & 1);
|
||||
}
|
||||
logger.LogInformation("EIO0-EIO7 directions = " + eioDirs + ", states = " + eioStates);
|
||||
|
||||
for (int i = 16; i < 20; i++)
|
||||
{
|
||||
cioDirs += Convert.ToString((directions >> i) & 1);
|
||||
cioStates += Convert.ToString((states >> i) & 1);
|
||||
}
|
||||
logger.LogInformation("CIO0-CIO3 directions = " + cioDirs + ", states = " + cioStates);
|
||||
|
||||
for (int i = 20; i < 23; i++)
|
||||
{
|
||||
mioDirs += Convert.ToString((directions >> i) & 1);
|
||||
mioStates += Convert.ToString((states >> i) & 1);
|
||||
}
|
||||
logger.LogInformation("MIO0-MIO2 directions = " + mioDirs + ", states = " + mioStates);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Configures range, negative channel, resolution index and settling
|
||||
/// time for all analog inputs.
|
||||
/// AIN_ALL_RANGE, AIN_ALL_NEGATIVE_CH, AIN_ALL_RESOLUTION_INDEX, and
|
||||
/// AIN_ALL_SETTLING_US registers/settings are documented here:
|
||||
/// https://labjack.com/support/datasheets/t-series/ain
|
||||
/// </summary>
|
||||
/// <param name="mb">The ModbusTransmissionControlProtocolClient to the connected T7 </param>
|
||||
/// <param name="range">AIN_ALL_RANGE setting.</param>
|
||||
/// <param name="negativeChannel">AIN_ALL_NEGATIVE_CH setting.</param>
|
||||
/// <param name="resolutionIndex">AIN_ALL_RESOLUTION_INDEX setting.</param>
|
||||
/// <param name="settling">AIN_ALL_SETTLING_US setting.</param>
|
||||
private static void ConfigureAllAnalog(ModbusTransmissionControlProtocolClient mb, float range, ushort negativeChannel, ushort resolutionIndex, float settling)
|
||||
{
|
||||
ushort address;
|
||||
ushort uint16Value;
|
||||
float float32Value;
|
||||
|
||||
// Configure all analog input ranges.
|
||||
address = 43900; // 43900 = AIN_ALL_RANGE
|
||||
float32Value = range;
|
||||
mb.Write(address, float32Value);
|
||||
|
||||
// Configure all analog input negative channels.
|
||||
address = 43902; // 43902 = AIN_ALL_NEGATIVE_CH
|
||||
uint16Value = negativeChannel;
|
||||
mb.Write(address, uint16Value);
|
||||
|
||||
// Configure all analog input resolution indexes.
|
||||
address = 43903; // 43903 = AIN_ALL_RESOLUTION_INDEX
|
||||
uint16Value = resolutionIndex;
|
||||
mb.Write(address, uint16Value);
|
||||
|
||||
// Configure all analog input settling times.
|
||||
address = 43904; // 43904 = AIN_ALL_SETTLING_US
|
||||
float32Value = settling;
|
||||
mb.Write(address, float32Value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Example that configures, reads and displays all the analog
|
||||
/// inputs (AIN0-AIN13) on the T7.
|
||||
/// Analog inputs (AIN) registers used are documented here:
|
||||
/// https://labjack.com/support/datasheets/t-series/ain
|
||||
/// </summary>
|
||||
/// <param name="mb">The ModbusTransmissionControlProtocolClient to the connected T7.</param>
|
||||
private static void ReadAllAnalog(ModbusTransmissionControlProtocolClient modbusTransmissionControlProtocolClient, ILogger<Worker> logger)
|
||||
{
|
||||
logger.LogInformation("Reading AIN0-AIN13.");
|
||||
|
||||
// Configure all analog inputs.
|
||||
// Ranges = +/-10 to.
|
||||
// Negative Channels = 199 (single-ended)
|
||||
// Resolution Indexes = 8
|
||||
// Settlings = 0 (auto)
|
||||
ConfigureAllAnalog(modbusTransmissionControlProtocolClient, 10.0f, 199, 8, 0);
|
||||
|
||||
// Read all 14 analog inputs.
|
||||
ushort startAddress = 0; // 0 = AIN0
|
||||
float[] analogInputReadings = new float[14]; // 14 analog input readings
|
||||
modbusTransmissionControlProtocolClient.Read(startAddress, analogInputReadings);
|
||||
DisplayAnalogInputReadings(logger, startAddress, analogInputReadings);
|
||||
|
||||
logger.LogInformation("");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Example that reads and displays all the digital I/O (FIOs, EIOs,
|
||||
/// CIOs, MIOs) on the T7.
|
||||
/// Digital I/O registers used are documented here:
|
||||
/// https://labjack.com/support/datasheets/t-series/digital-io
|
||||
/// </summary>
|
||||
/// <param name="modbusTransmissionControlProtocolClient">The ModbusTransmissionControlProtocolClient to the connected T7.</param>
|
||||
private static void ReadAllDigitalIO(ModbusTransmissionControlProtocolClient modbusTransmissionControlProtocolClient, ILogger<Worker> logger)
|
||||
{
|
||||
logger.LogInformation("Reading FIOs, EIOs, CIOs and MIO directions and states.");
|
||||
ushort address;
|
||||
uint directions = 0;
|
||||
uint states = 0;
|
||||
|
||||
// Read all digital I/O directions and states.
|
||||
address = 2850; // 2850 = DIO_DIRECTION
|
||||
modbusTransmissionControlProtocolClient.Read(address, ref directions);
|
||||
address = 2800; // 2800 = DIO_STATE
|
||||
modbusTransmissionControlProtocolClient.Read(address, ref states);
|
||||
|
||||
DisplayDigitalIOReadings(logger, directions, states);
|
||||
|
||||
logger.LogInformation("");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Example that configures, reads and displays all the analog
|
||||
/// inputs on the T7 with a Mux80 (AIN0-AIN3, AIN48-AIN127).
|
||||
/// Analog inputs (AIN) registers used are documented here:
|
||||
/// https://labjack.com/support/datasheets/t-series/ain
|
||||
/// Extended channels AIN48+ are further documented here:
|
||||
/// https://labjack.com/support/datasheets/t-series/ain/extended-channels
|
||||
/// Mux80 data sheet can be found here:
|
||||
/// https://labjack.com/support/datasheets/accessories/mux80
|
||||
/// </summary>
|
||||
/// <param name="modbusTransmissionControlProtocolClient">The ModbusTransmissionControlProtocolClient to the connected T7.</param>
|
||||
private static void ReadAllAnalogMux80(ModbusTransmissionControlProtocolClient modbusTransmissionControlProtocolClient, ILogger<Worker> logger)
|
||||
{
|
||||
|
||||
// Many registers to channels are incorrect. Check with Steve.
|
||||
|
||||
logger.LogInformation("Reading AIN0-AIN3, AIN48-AIN127.");
|
||||
|
||||
// Configure all analog inputs.
|
||||
// Ranges = +/-10 to.
|
||||
// Negative Channels = 199 (single-ended)
|
||||
// Resolution Indexes = 1
|
||||
// Settlings = 0 (auto)
|
||||
ConfigureAllAnalog(modbusTransmissionControlProtocolClient, 10.0f, 199, 1, 0);
|
||||
|
||||
//Reading from 84 analog inputs with the Mux80.
|
||||
ushort startAddress;
|
||||
float[] analogInputReadings;
|
||||
|
||||
// Read from AIN0-AIN3 on the T7 terminals.
|
||||
startAddress = 0; // 0 = AIN0
|
||||
analogInputReadings = new float[4]; // 4 analog input readings.
|
||||
modbusTransmissionControlProtocolClient.Read(startAddress, analogInputReadings);
|
||||
DisplayAnalogInputReadings(logger, startAddress, analogInputReadings);
|
||||
|
||||
// Read from AIN48-AIN87 on Mux80.
|
||||
startAddress = 96; // 96 = AIN48
|
||||
analogInputReadings = new float[40]; // 40 analog input readings
|
||||
modbusTransmissionControlProtocolClient.Read(startAddress, analogInputReadings);
|
||||
DisplayAnalogInputReadings(logger, startAddress, analogInputReadings);
|
||||
|
||||
// Read from AIN88-AIN127 on Mux80.
|
||||
startAddress = 176; // 176 = AIN88
|
||||
analogInputReadings = new float[40]; // 40 analog input readings
|
||||
modbusTransmissionControlProtocolClient.Read(startAddress, analogInputReadings);
|
||||
DisplayAnalogInputReadings(logger, startAddress, analogInputReadings);
|
||||
|
||||
logger.LogInformation("");
|
||||
}
|
||||
|
||||
}
|
75
Helpers/NationalInstrumentsHelper.cs
Normal file
75
Helpers/NationalInstrumentsHelper.cs
Normal 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
45
Helpers/SeleniumHelper.cs
Normal 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
51
Helpers/SyncHelper.cs
Normal 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}";
|
||||
}
|
||||
}
|
129
Helpers/TransmissionControlProtocolHelper.cs
Normal file
129
Helpers/TransmissionControlProtocolHelper.cs
Normal file
@ -0,0 +1,129 @@
|
||||
using File_Watcher.Models;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
|
||||
namespace File_Watcher.Helpers;
|
||||
|
||||
internal static partial class TransmissionControlProtocolHelper
|
||||
{
|
||||
|
||||
private record Record(BinaryReader BinaryReader,
|
||||
BinaryWriter BinaryWriter,
|
||||
NetworkStream NetworkStream,
|
||||
List<long> ReadTimes);
|
||||
|
||||
private static long _LastWrite;
|
||||
private static Record? _Record;
|
||||
private static readonly object _Lock = new();
|
||||
|
||||
private static void ReadFiles(TransmissionControlProtocolConfiguration tcpConfiguration, ILogger<Worker> logger)
|
||||
{
|
||||
List<byte> bytes = [];
|
||||
// byte nullByte = Convert.ToByte('\0');
|
||||
string directory = GetDirectory(tcpConfiguration);
|
||||
string[] files = Directory.GetFiles(directory, $"{tcpConfiguration.IPAddress}-*.raw", SearchOption.TopDirectoryOnly);
|
||||
logger.LogInformation("Read {count} files", files.Length);
|
||||
foreach (string file in files)
|
||||
{
|
||||
foreach (byte @byte in File.ReadAllBytes(file))
|
||||
{
|
||||
// if (@byte.Equals(nullByte))
|
||||
// continue;
|
||||
bytes.Add(@byte);
|
||||
}
|
||||
}
|
||||
if (bytes.Count > 0)
|
||||
{
|
||||
string bytesFile = Path.Combine(directory, $"{tcpConfiguration.IPAddress}-{DateTime.Now.Ticks}.pcl");
|
||||
File.WriteAllBytes(bytesFile, bytes.ToArray());
|
||||
foreach (string file in files)
|
||||
File.Delete(file);
|
||||
}
|
||||
}
|
||||
|
||||
private static void CreateClient(AppSettings appSettings, ILogger<Worker> logger)
|
||||
{
|
||||
logger.LogDebug(appSettings.TransmissionControlProtocolConfiguration.IPAddress);
|
||||
TcpClient tcpClient = new(appSettings.TransmissionControlProtocolConfiguration.IPAddress, appSettings.TransmissionControlProtocolConfiguration.Port);
|
||||
NetworkStream networkStream = tcpClient.GetStream();
|
||||
_Record = new(BinaryReader: new(networkStream), BinaryWriter: new(networkStream), NetworkStream: networkStream, ReadTimes: []);
|
||||
}
|
||||
|
||||
private static string GetDirectory(TransmissionControlProtocolConfiguration tcpConfiguration)
|
||||
{
|
||||
string result = Path.GetFullPath(Path.Combine(tcpConfiguration.Destination, tcpConfiguration.IPAddress));
|
||||
if (!Directory.Exists(result))
|
||||
_ = Directory.CreateDirectory(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
private static void NetworkStreamCanRead(TransmissionControlProtocolConfiguration tcpConfiguration, ILogger<Worker> logger, NetworkStream networkStream)
|
||||
{
|
||||
List<byte> results = [];
|
||||
byte[] bytes = new byte[1024];
|
||||
string directory = GetDirectory(tcpConfiguration);
|
||||
do
|
||||
{
|
||||
int count = networkStream.Read(bytes, 0, bytes.Length);
|
||||
if (count > 0)
|
||||
results.AddRange(bytes.Take(count));
|
||||
}
|
||||
while (networkStream.DataAvailable);
|
||||
logger.LogInformation("Read {count} bytes", results.Count);
|
||||
if (results.Count > 0)
|
||||
{
|
||||
bytes = results.ToArray();
|
||||
File.WriteAllBytes(Path.Combine(directory, $"{tcpConfiguration.IPAddress}-{DateTime.Now.Ticks}.raw"), bytes);
|
||||
if (!string.IsNullOrEmpty(tcpConfiguration.DelimiterPattern))
|
||||
{
|
||||
string content = Encoding.ASCII.GetString(bytes);
|
||||
logger.LogDebug("Content {content}", content);
|
||||
if (content.Contains(tcpConfiguration.DelimiterPattern))
|
||||
ReadFiles(tcpConfiguration, logger);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal static bool ReadWrite(AppSettings appSettings, ILogger<Worker> logger)
|
||||
{
|
||||
lock (_Lock)
|
||||
{
|
||||
if (!appSettings.TransmissionControlProtocolConfiguration.Server && _Record is not null && appSettings.TransmissionControlProtocolConfiguration.DelimiterSeconds > 0)
|
||||
{
|
||||
TimeSpan? timeSpan = _Record.ReadTimes.Count == 0 ? null : new(DateTime.Now.Ticks - _Record.ReadTimes[^1]);
|
||||
if (timeSpan is not null && timeSpan.Value.TotalSeconds > appSettings.TransmissionControlProtocolConfiguration.DelimiterSeconds)
|
||||
{
|
||||
ReadFiles(appSettings.TransmissionControlProtocolConfiguration, logger);
|
||||
_Record.ReadTimes.Clear();
|
||||
}
|
||||
}
|
||||
if (!appSettings.TransmissionControlProtocolConfiguration.Server && _Record is not null)
|
||||
{
|
||||
TimeSpan timeSpan = new(DateTime.Now.Ticks - _LastWrite);
|
||||
if (_LastWrite == 0 || timeSpan.TotalMinutes > 1)
|
||||
{
|
||||
try
|
||||
{
|
||||
_Record.NetworkStream.WriteByte(Convert.ToByte('\0'));
|
||||
_LastWrite = DateTime.Now.Ticks;
|
||||
}
|
||||
catch (Exception)
|
||||
{ }
|
||||
}
|
||||
}
|
||||
if (!appSettings.TransmissionControlProtocolConfiguration.Server && (_Record?.NetworkStream is null || !_Record.NetworkStream.Socket.Connected))
|
||||
CreateClient(appSettings, logger);
|
||||
else if (appSettings.TransmissionControlProtocolConfiguration.Server)
|
||||
throw new NotImplementedException($"Use {nameof(HelperTCP)}");
|
||||
if (_Record?.NetworkStream is not null && _Record.NetworkStream.CanRead && _Record.NetworkStream.DataAvailable)
|
||||
{
|
||||
_Record.ReadTimes.Add(DateTime.Now.Ticks);
|
||||
NetworkStreamCanRead(appSettings.TransmissionControlProtocolConfiguration, logger, _Record.NetworkStream);
|
||||
}
|
||||
if (appSettings.TransmissionControlProtocolConfiguration.Server && _Record?.NetworkStream is not null && _Record.NetworkStream.CanWrite)
|
||||
throw new NotImplementedException($"Use {nameof(HelperTCP)}");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
@ -1,24 +1,30 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using View_by_Distance.Shared.Models;
|
||||
using Phares.Shared.Models;
|
||||
|
||||
namespace File_Watcher.Models;
|
||||
|
||||
public record AppSettings(CamstarOracleConfiguration CamstarOracleConfiguration,
|
||||
CompassConfiguration CompassConfiguration,
|
||||
DeterministicHashCodeConfiguration DeterministicHashCodeConfiguration,
|
||||
DiskInfoConfiguration DiskInfoConfiguration,
|
||||
DriveConfiguration DriveConfiguration,
|
||||
EAFLogConfiguration EAFLogConfiguration,
|
||||
EDADatabaseConfiguration EDADatabaseConfiguration,
|
||||
FileWatcherConfiguration FileWatcherConfiguration,
|
||||
InfinityQSConfiguration InfinityQSConfiguration,
|
||||
InfinityQSProjectConfiguration InfinityQSProjectConfiguration,
|
||||
IsoConfiguration IsoConfiguration,
|
||||
LabJackT7Configuration LabJackT7Configuration,
|
||||
MetadataSettings MetadataSettings,
|
||||
MetrologyConfiguration MetrologyConfiguration,
|
||||
NationalInstrumentsConfiguration NationalInstrumentsConfiguration,
|
||||
NugetConfiguration NugetConfiguration,
|
||||
ResultSettings ResultSettings,
|
||||
SeleniumConfiguration SeleniumConfiguration,
|
||||
SerialConfiguration SerialConfiguration,
|
||||
StratusConfiguration StratusConfiguration,
|
||||
SyncConfiguration SyncConfiguration,
|
||||
TransmissionControlProtocolConfiguration TransmissionControlProtocolConfiguration,
|
||||
WaferCounterConfiguration WaferCounterConfiguration)
|
||||
{
|
||||
@ -30,36 +36,48 @@ public record AppSettings(CamstarOracleConfiguration CamstarOracleConfiguration,
|
||||
CamstarOracleConfiguration? camstarOracleConfiguration = configurationRoot.GetSection(nameof(CamstarOracleConfiguration)).Get<CamstarOracleConfiguration>();
|
||||
CompassConfiguration? compassConfiguration = configurationRoot.GetSection(nameof(CompassConfiguration)).Get<CompassConfiguration>();
|
||||
DeterministicHashCodeConfiguration? deterministicHashCodeConfiguration = configurationRoot.GetSection(nameof(DeterministicHashCodeConfiguration)).Get<DeterministicHashCodeConfiguration>();
|
||||
DiskInfoConfiguration? diskInfoConfiguration = configurationRoot.GetSection(nameof(DiskInfoConfiguration)).Get<DiskInfoConfiguration>();
|
||||
DriveConfiguration? driveConfiguration = configurationRoot.GetSection(nameof(DriveConfiguration)).Get<DriveConfiguration>();
|
||||
EAFLogConfiguration? eafLogConfiguration = configurationRoot.GetSection(nameof(EAFLogConfiguration)).Get<EAFLogConfiguration>();
|
||||
EDADatabaseConfiguration? edaDatabaseConfiguration = configurationRoot.GetSection(nameof(EDADatabaseConfiguration)).Get<EDADatabaseConfiguration>();
|
||||
FileWatcherConfiguration? fileWatcherConfiguration = configurationRoot.GetSection(nameof(FileWatcherConfiguration)).Get<FileWatcherConfiguration>();
|
||||
InfinityQSConfiguration? infinityQSConfiguration = configurationRoot.GetSection(nameof(InfinityQSConfiguration)).Get<InfinityQSConfiguration>();
|
||||
InfinityQSProjectConfiguration? infinityQSProjectConfiguration = configurationRoot.GetSection(nameof(InfinityQSProjectConfiguration)).Get<InfinityQSProjectConfiguration>();
|
||||
IsoConfiguration? isoConfiguration = configurationRoot.GetSection(nameof(IsoConfiguration)).Get<IsoConfiguration>();
|
||||
LabJackT7Configuration? labJackT7Configuration = configurationRoot.GetSection(nameof(LabJackT7Configuration)).Get<LabJackT7Configuration>();
|
||||
MetadataSettings? metadataSettings = configurationRoot.GetSection(nameof(MetadataSettings)).Get<MetadataSettings>();
|
||||
MetrologyConfiguration? metrologyConfiguration = configurationRoot.GetSection(nameof(MetrologyConfiguration)).Get<MetrologyConfiguration>();
|
||||
NationalInstrumentsConfiguration? nationalInstrumentsConfiguration = configurationRoot.GetSection(nameof(NationalInstrumentsConfiguration)).Get<NationalInstrumentsConfiguration>();
|
||||
NugetConfiguration? nugetConfiguration = configurationRoot.GetSection(nameof(NugetConfiguration)).Get<NugetConfiguration>();
|
||||
ResultSettings? resultSettings = configurationRoot.GetSection(nameof(ResultSettings)).Get<ResultSettings>();
|
||||
SeleniumConfiguration? seleniumConfiguration = configurationRoot.GetSection(nameof(SeleniumConfiguration)).Get<SeleniumConfiguration>();
|
||||
SerialConfiguration? serialConfiguration = configurationRoot.GetSection(nameof(SerialConfiguration)).Get<SerialConfiguration>();
|
||||
StratusConfiguration? stratusConfiguration = configurationRoot.GetSection(nameof(StratusConfiguration)).Get<StratusConfiguration>();
|
||||
SyncConfiguration? syncConfiguration = configurationRoot.GetSection(nameof(SyncConfiguration)).Get<SyncConfiguration>();
|
||||
TransmissionControlProtocolConfiguration? transmissionControlProtocolConfiguration = configurationRoot.GetSection(nameof(TransmissionControlProtocolConfiguration)).Get<TransmissionControlProtocolConfiguration>();
|
||||
WaferCounterConfiguration? waferCounterConfiguration = configurationRoot.GetSection(nameof(WaferCounterConfiguration)).Get<WaferCounterConfiguration>();
|
||||
#pragma warning restore IL3050, IL2026
|
||||
if (camstarOracleConfiguration is null
|
||||
|| compassConfiguration is null
|
||||
|| deterministicHashCodeConfiguration is null
|
||||
|| diskInfoConfiguration is null
|
||||
|| driveConfiguration is null
|
||||
|| eafLogConfiguration is null
|
||||
|| edaDatabaseConfiguration is null
|
||||
|| fileWatcherConfiguration is null
|
||||
|| infinityQSConfiguration is null
|
||||
|| infinityQSProjectConfiguration is null
|
||||
|| isoConfiguration is null
|
||||
|| labJackT7Configuration is null
|
||||
|| metadataSettings is null
|
||||
|| metrologyConfiguration is null
|
||||
|| nationalInstrumentsConfiguration is null
|
||||
|| nugetConfiguration is null
|
||||
|| resultSettings is null
|
||||
|| seleniumConfiguration is null
|
||||
|| serialConfiguration is null
|
||||
|| stratusConfiguration is null
|
||||
|| syncConfiguration is null
|
||||
|| transmissionControlProtocolConfiguration is null
|
||||
|| waferCounterConfiguration is null
|
||||
|| fileWatcherConfiguration?.Company is null)
|
||||
@ -78,18 +96,24 @@ public record AppSettings(CamstarOracleConfiguration CamstarOracleConfiguration,
|
||||
result = new(camstarOracleConfiguration,
|
||||
compassConfiguration,
|
||||
deterministicHashCodeConfiguration,
|
||||
diskInfoConfiguration,
|
||||
driveConfiguration,
|
||||
eafLogConfiguration,
|
||||
edaDatabaseConfiguration,
|
||||
fileWatcherConfiguration,
|
||||
infinityQSConfiguration,
|
||||
infinityQSProjectConfiguration,
|
||||
isoConfiguration,
|
||||
labJackT7Configuration,
|
||||
metadataSettings,
|
||||
metrologyConfiguration,
|
||||
nationalInstrumentsConfiguration,
|
||||
nugetConfiguration,
|
||||
resultSettings,
|
||||
seleniumConfiguration,
|
||||
serialConfiguration,
|
||||
stratusConfiguration,
|
||||
syncConfiguration,
|
||||
transmissionControlProtocolConfiguration,
|
||||
waferCounterConfiguration);
|
||||
Verify(result);
|
||||
|
24
Models/DiskInfoConfiguration.cs
Normal file
24
Models/DiskInfoConfiguration.cs
Normal 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
|
||||
{
|
||||
}
|
@ -3,17 +3,9 @@ using System.Text.Json.Serialization;
|
||||
|
||||
namespace File_Watcher.Models;
|
||||
|
||||
public record Test(string Name,
|
||||
long Value);
|
||||
|
||||
[JsonSourceGenerationOptions(WriteIndented = true)]
|
||||
[JsonSerializable(typeof(Test[]))]
|
||||
internal partial class TestCollectionSourceGenerationContext : JsonSerializerContext
|
||||
{
|
||||
}
|
||||
|
||||
public record InfinityQSConfiguration(string ConnectionString,
|
||||
string DestinationDirectory,
|
||||
string EncryptedPassword,
|
||||
long SubGroupTime,
|
||||
string TestsFile,
|
||||
Test[] Tests)
|
||||
|
28
Models/InfinityQSProjectConfiguration.cs
Normal file
28
Models/InfinityQSProjectConfiguration.cs
Normal file
@ -0,0 +1,28 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace File_Watcher.Models;
|
||||
|
||||
public record InfinityQSProjectConfiguration(string From,
|
||||
int ClearEveryHours,
|
||||
string Search,
|
||||
string SearchPattern,
|
||||
string SimpleMailTransferProtocolServer,
|
||||
string SourceDirectory,
|
||||
string Subject,
|
||||
string To)
|
||||
{
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
string result = JsonSerializer.Serialize(this, InfinityQSProjectConfigurationSourceGenerationContext.Default.InfinityQSProjectConfiguration);
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
[JsonSourceGenerationOptions(WriteIndented = true)]
|
||||
[JsonSerializable(typeof(InfinityQSProjectConfiguration))]
|
||||
internal partial class InfinityQSProjectConfigurationSourceGenerationContext : JsonSerializerContext
|
||||
{
|
||||
}
|
23
Models/LabJackT7Configuration.cs
Normal file
23
Models/LabJackT7Configuration.cs
Normal file
@ -0,0 +1,23 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace File_Watcher.Models;
|
||||
|
||||
public record LabJackT7Configuration(string InternetProtocolAddress,
|
||||
int Port,
|
||||
string To)
|
||||
{
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
string result = JsonSerializer.Serialize(this, LabJackT7ConfigurationSourceGenerationContext.Default.LabJackT7Configuration);
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
[JsonSourceGenerationOptions(WriteIndented = true)]
|
||||
[JsonSerializable(typeof(LabJackT7Configuration))]
|
||||
internal partial class LabJackT7ConfigurationSourceGenerationContext : JsonSerializerContext
|
||||
{
|
||||
}
|
27
Models/NationalInstrumentsConfiguration.cs
Normal file
27
Models/NationalInstrumentsConfiguration.cs
Normal 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
|
||||
{
|
||||
}
|
23
Models/SeleniumConfiguration.cs
Normal file
23
Models/SeleniumConfiguration.cs
Normal 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
|
||||
{
|
||||
}
|
21
Models/SyncConfiguration.cs
Normal file
21
Models/SyncConfiguration.cs
Normal 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
12
Models/Test.cs
Normal 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
|
||||
{
|
||||
}
|
@ -3,7 +3,9 @@ using System.Text.Json.Serialization;
|
||||
|
||||
namespace File_Watcher.Models;
|
||||
|
||||
public record TransmissionControlProtocolConfiguration(string Destination,
|
||||
public record TransmissionControlProtocolConfiguration(string DelimiterPattern,
|
||||
int DelimiterSeconds,
|
||||
string Destination,
|
||||
string GhostPCLFileName,
|
||||
string IPAddress,
|
||||
int Port,
|
||||
|
55
NancyModules/SyncModule.cs
Normal file
55
NancyModules/SyncModule.cs
Normal 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
23
Startup.cs
Normal 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
|
36
Worker.cs
36
Worker.cs
@ -1,4 +1,4 @@
|
||||
using File_Watcher.Models;
|
||||
using File_Watcher.Models;
|
||||
using Microsoft.Extensions.Hosting.WindowsServices;
|
||||
using System.Data;
|
||||
|
||||
@ -7,7 +7,6 @@ namespace File_Watcher;
|
||||
public partial class Worker : BackgroundService
|
||||
{
|
||||
|
||||
private bool? _First;
|
||||
private readonly bool _IsWindowsService;
|
||||
private readonly ILogger<Worker> _Logger;
|
||||
private readonly AppSettings _AppSettings;
|
||||
@ -22,8 +21,14 @@ public partial class Worker : BackgroundService
|
||||
try
|
||||
{ logger.LogInformation("<{folder}>", Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)); }
|
||||
catch (Exception) { }
|
||||
_First = null;
|
||||
_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)
|
||||
@ -35,11 +40,13 @@ public partial class Worker : BackgroundService
|
||||
|
||||
protected override async Task ExecuteAsync(CancellationToken cancellationToken) =>
|
||||
await Body(cancellationToken);
|
||||
|
||||
private async Task Body(CancellationToken cancellationToken)
|
||||
{
|
||||
if (!_IsWindowsService)
|
||||
{
|
||||
_Logger.LogInformation("Set break point and skip to run {_AppSettings.FileWatcherConfiguration.Helper}!", _AppSettings.FileWatcherConfiguration.Helper);
|
||||
BodyInner(cancellationToken);
|
||||
throw new EvaluateException($"Set break point and skip to run {_AppSettings.FileWatcherConfiguration.Helper}!");
|
||||
}
|
||||
if (!_IsWindowsService)
|
||||
@ -51,41 +58,48 @@ public partial class Worker : BackgroundService
|
||||
}
|
||||
}
|
||||
while (_IsWindowsService && !cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
try
|
||||
{
|
||||
BodyInner(cancellationToken);
|
||||
await Task.Delay(_AppSettings.FileWatcherConfiguration.MillisecondsDelay, cancellationToken);
|
||||
}
|
||||
catch (Exception ex) { _Logger.LogError(ex, "Unexpected Error!"); }
|
||||
}
|
||||
}
|
||||
|
||||
private void BodyInner(CancellationToken cancellationToken)
|
||||
{
|
||||
_Logger.LogInformation("A) Next execute will be at {date}", DateTime.Now.AddMilliseconds(_AppSettings.FileWatcherConfiguration.MillisecondsDelay).ToString("yyyy-MM-dd hh:mm:ss.fff tt"));
|
||||
if (_First 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))
|
||||
_ = Directory.CreateDirectory(_AppSettings.FileWatcherConfiguration.WatchDirectory);
|
||||
else
|
||||
{
|
||||
_ = _AppSettings.FileWatcherConfiguration.Helper switch
|
||||
{
|
||||
nameof(Helpers.SyncHelper) => Helpers.SyncHelper.Check(_AppSettings, _Logger),
|
||||
nameof(Helpers.HelperNuget) => Helpers.HelperNuget.Sync(_AppSettings, _Logger),
|
||||
nameof(Helpers.HelperTCP) => Helpers.HelperTCP.ReadWrite(_AppSettings, _Logger),
|
||||
nameof(Helpers.HelperISO) => Helpers.HelperISO.DirectoryToISO(_AppSettings, _Logger),
|
||||
nameof(Helpers.HelperCompass) => Helpers.HelperCompass.CopyFile(_AppSettings, _Logger),
|
||||
nameof(Helpers.HelperStratus) => Helpers.HelperStratus.MoveFile(_AppSettings, _Logger),
|
||||
nameof(Helpers.HelperEAFLog) => Helpers.HelperEAFLog.DeleteFiles(_AppSettings, _Logger),
|
||||
nameof(Helpers.HelperInfinityQS) => Helpers.HelperInfinityQS.Select(_AppSettings, _Logger),
|
||||
nameof(Helpers.LabJackT7Helper) => Helpers.LabJackT7Helper.ReadAll(_AppSettings, _Logger),
|
||||
nameof(Helpers.DiskInfoHelper) => Helpers.DiskInfoHelper.WriteDiskInfo(_AppSettings, _Logger),
|
||||
nameof(Helpers.HelperEventLog) => Helpers.HelperEventLog.ClearEventLogs(_AppSettings, _Logger),
|
||||
nameof(Helpers.HelperInfinityQS) => Helpers.HelperInfinityQS.ProcessStart(_AppSettings, _Logger),
|
||||
nameof(Helpers.HelperWaferCounter) => Helpers.HelperWaferCounter.MoveFile(_AppSettings, _Logger),
|
||||
nameof(Helpers.HelperSerial) => Helpers.HelperSerial.ReadWrite(_AppSettings, _Logger, cancellationToken),
|
||||
nameof(Helpers.HelperMetrologyFiles) => Helpers.HelperMetrologyFiles.SortAndDelete(_AppSettings, _Logger),
|
||||
nameof(Helpers.HelperCamstarOracle) => Helpers.HelperCamstarOracle.Check(_AppSettings, _Logger, cancellationToken),
|
||||
nameof(Helpers.InfinityQSProjectHelper) => Helpers.InfinityQSProjectHelper.SendEmail(_AppSettings, _Logger),
|
||||
nameof(Helpers.NationalInstrumentsHelper) => Helpers.NationalInstrumentsHelper.WriteData(_AppSettings, _Logger),
|
||||
nameof(Helpers.DeterministicHashCodeHelper) => Helpers.DeterministicHashCodeHelper.WindowsWork(_AppSettings, _Logger),
|
||||
nameof(Helpers.TransmissionControlProtocolHelper) => Helpers.TransmissionControlProtocolHelper.ReadWrite(_AppSettings, _Logger),
|
||||
#if Selenium
|
||||
nameof(Helpers.SeleniumHelper) => Helpers.SeleniumHelper.HyperTextMarkupLanguageToPortableNetworkGraphics(_AppSettings, _Logger),
|
||||
#endif
|
||||
nameof(Helpers.HelperEDADatabase) => Helpers.HelperEDADatabase.SaveDataCollectionPlans(_AppSettings, _Logger, cancellationToken),
|
||||
nameof(Helpers.HelperCamstarOracle) => Helpers.HelperCamstarOracle.Check(_AppSettings, _HttpClientFactory, _Logger, cancellationToken),
|
||||
_ => throw new NotSupportedException()
|
||||
};
|
||||
}
|
||||
|
Reference in New Issue
Block a user