Compare commits
2 Commits
Author | SHA1 | Date | |
---|---|---|---|
5045133cf8 | |||
a5b224cee1 |
1
.vscode/settings.json
vendored
1
.vscode/settings.json
vendored
@ -33,6 +33,7 @@
|
||||
"Kofax",
|
||||
"linc",
|
||||
"Linc",
|
||||
"Modbus",
|
||||
"NOPAUSE",
|
||||
"NSFX",
|
||||
"OBJE",
|
||||
|
@ -20,7 +20,7 @@
|
||||
<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.19" />
|
||||
<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.16" />
|
||||
<PackageReference Include="System.IO.Ports" Version="8.0.0" />
|
||||
|
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("");
|
||||
}
|
||||
|
||||
}
|
@ -13,7 +13,9 @@ public record AppSettings(CamstarOracleConfiguration CamstarOracleConfiguration,
|
||||
EDADatabaseConfiguration EDADatabaseConfiguration,
|
||||
FileWatcherConfiguration FileWatcherConfiguration,
|
||||
InfinityQSConfiguration InfinityQSConfiguration,
|
||||
InfinityQSProjectConfiguration InfinityQSProjectConfiguration,
|
||||
IsoConfiguration IsoConfiguration,
|
||||
LabJackT7Configuration LabJackT7Configuration,
|
||||
MetadataSettings MetadataSettings,
|
||||
MetrologyConfiguration MetrologyConfiguration,
|
||||
NationalInstrumentsConfiguration NationalInstrumentsConfiguration,
|
||||
@ -33,14 +35,16 @@ public record AppSettings(CamstarOracleConfiguration CamstarOracleConfiguration,
|
||||
#pragma warning disable IL3050, IL2026
|
||||
CamstarOracleConfiguration? camstarOracleConfiguration = configurationRoot.GetSection(nameof(CamstarOracleConfiguration)).Get<CamstarOracleConfiguration>();
|
||||
CompassConfiguration? compassConfiguration = configurationRoot.GetSection(nameof(CompassConfiguration)).Get<CompassConfiguration>();
|
||||
DiskInfoConfiguration? diskInfoConfiguration = configurationRoot.GetSection(nameof(DiskInfoConfiguration)).Get<DiskInfoConfiguration>();
|
||||
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>();
|
||||
@ -62,7 +66,9 @@ public record AppSettings(CamstarOracleConfiguration CamstarOracleConfiguration,
|
||||
|| 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
|
||||
@ -96,7 +102,9 @@ public record AppSettings(CamstarOracleConfiguration CamstarOracleConfiguration,
|
||||
edaDatabaseConfiguration,
|
||||
fileWatcherConfiguration,
|
||||
infinityQSConfiguration,
|
||||
infinityQSProjectConfiguration,
|
||||
isoConfiguration,
|
||||
labJackT7Configuration,
|
||||
metadataSettings,
|
||||
metrologyConfiguration,
|
||||
nationalInstrumentsConfiguration,
|
||||
|
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
|
||||
{
|
||||
}
|
@ -46,6 +46,7 @@ public partial class Worker : BackgroundService
|
||||
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)
|
||||
@ -83,12 +84,14 @@ public partial class Worker : BackgroundService
|
||||
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.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.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),
|
||||
|
Reference in New Issue
Block a user