Major upgrade

This commit is contained in:
Duc
2025-10-24 15:18:11 -07:00
parent fd85735c93
commit ce583d1664
478 changed files with 237518 additions and 47610 deletions

View File

@@ -15,375 +15,370 @@ GOVERNMENT.
UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
-------------------------------------------------------------------------*/
using NLog;
using Raytheon.Common;
using System;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using NLog;
using Raytheon.Common;
namespace Raytheon.Instruments
{
/// <summary>
/// Class for controlling a TCP client communication device
/// </summary>
public class CommDeviceTcpClient : ICommDevice, IDisposable
{
#region PrivateClassMembers
private const uint _DEFAULT_READ_TIMEOUT = 25;
private const uint _DEFAULT_SEND_TIMEOUT = 5000;
private const uint _DEFAULT_READ_BUFFER_SIZE = 1024;
private static object _syncObj = new object();
private TcpClient _tcpClient;
private NetworkStream _tcpIpStream;
private readonly int _remotePort;
private readonly string _remoteAddress;
private readonly string _name;
private State _state;
/// <summary>
/// Class for controlling a TCP client communication device
/// </summary>
public class CommDeviceTcpClient : ICommDevice, IDisposable
{
#region PrivateClassMembers
private const uint _DEFAULT_READ_TIMEOUT = 25;
private const uint _DEFAULT_SEND_TIMEOUT = 5000;
private const uint _DEFAULT_READ_BUFFER_SIZE = 1024;
private static object _syncObj = new object();
private TcpClient _tcpClient;
private NetworkStream _tcpIpStream;
private readonly int _remotePort;
private readonly string _remoteAddress;
private readonly string _name;
private State _state;
/// <summary>
/// NLog logger
/// </summary>
private readonly ILogger _logger;
/// <summary>
/// Raytheon configuration
/// </summary>
private readonly IConfigurationManager _configurationManager;
private readonly IConfiguration _configuration;
private readonly ILogger _logger;
#endregion
private readonly IConfigurationManager _configurationManager;
private readonly IConfiguration _configuration;
public bool ClearErrors() => false;
public bool FrontPanelEnabled { get => false; set => throw new NotImplementedException(); }
public bool DisplayEnabled { get => false; set => throw new NotImplementedException(); }
public string DetailedStatus => $"This is a TCP/IP Device called {_name}";
public InstrumentMetadata Info => throw new NotImplementedException();
public State Status => _state;
public string Name => _name;
public SelfTestResult PerformSelfTest() => SelfTestResult;
public SelfTestResult SelfTestResult => SelfTestResult.Unknown;
public void Open() => Initialize();
public void Close() => Shutdown();
public void Reset()
{
Close();
Open();
}
#endregion
#region Private Functions
/// <summary>
/// Dispose of the resources contained by this object
/// </summary>
public void Dispose()
{
try
{
lock (_syncObj)
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
catch (Exception err)
{
_logger.Error(err.Message + "\r\n" + err.StackTrace);
}
}
public bool ClearErrors() => false;
public bool FrontPanelEnabled { get => false; set => throw new NotImplementedException(); }
public bool DisplayEnabled { get => false; set => throw new NotImplementedException(); }
public string DetailedStatus => $"This is a TCP/IP Device called {_name}";
public InstrumentMetadata Info => throw new NotImplementedException();
public State Status => _state;
public string Name => _name;
public SelfTestResult PerformSelfTest() => SelfTestResult;
public SelfTestResult SelfTestResult => SelfTestResult.Unknown;
public void Open() => Initialize();
public void Close() => Shutdown();
public void Reset()
{
Close();
Open();
}
/// <summary>
/// Dispose of the resources contained by this object
/// </summary>
/// <param name="disposing"></param>
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
// close the socket
try
{
Shutdown();
}
catch (Exception err)
{
_logger.Error(err.Message + "\r\n" + err.StackTrace);
}
}
}
#region Private Functions
/// <summary>
/// Dispose of the resources contained by this object
/// </summary>
public void Dispose()
{
try
{
lock (_syncObj)
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
catch (Exception err)
{
_logger.Error(err.Message + "\r\n" + err.StackTrace);
}
}
#endregion
/// <summary>
/// Dispose of the resources contained by this object
/// </summary>
/// <param name="disposing"></param>
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
// close the socket
try
{
Shutdown();
}
catch (Exception err)
{
_logger.Error(err.Message + "\r\n" + err.StackTrace);
}
}
}
#region Public Functions
#endregion
/// <summary>
/// CommDevice factory constructor
/// </summary>
/// <param name="name"></param>
/// <param name="configurationManager"></param>
public CommDeviceTcpClient(string name, IConfigurationManager configurationManager, ILogger logger, string remoteAddress = "", int remotePort = 0)
{
_name = name;
#region Public Functions
// _tcpClient is created in Initialize()
_tcpClient = null;
_tcpIpStream = null;
/// <summary>
/// CommDevice factory constructor
/// </summary>
/// <param name="deviceName"></param>
/// <param name="configurationManager"></param>
public CommDeviceTcpClient(string deviceName, IConfigurationManager configurationManager, string remoteAddress = "", int remotePort = 0)
{
_name = deviceName;
_state = State.Uninitialized;
// _tcpClient is created in Initialize()
_tcpClient = null;
_tcpIpStream = null;
_logger = logger;
_state = State.Uninitialized;
_configurationManager = configurationManager;
_configuration = _configurationManager.GetConfiguration(Name);
_logger = LogManager.GetLogger($"{this.GetType().Name} - {deviceName}");
if(string.IsNullOrEmpty(remoteAddress))
{
_remoteAddress = _configuration.GetConfigurationValue("TcpClient", "RemoteAddress", "127.0.0.1");
}
else
{
_remoteAddress = remoteAddress;
}
if(remotePort == 0)
{
_remotePort = _configuration.GetConfigurationValue("TcpClient", "RemotePort", 0);
}
else
{
_remotePort = remotePort;
}
}
_configurationManager = configurationManager;
_configuration = _configurationManager.GetConfiguration(Name);
/// <summary>
/// legacy constructor
/// </summary>
/// <param name="name">The name of this device</param>
/// <param name="remoteAddress">The address of the server</param>
/// <param name="remotePort">The port that the server is listening on</param>
public CommDeviceTcpClient(string name, string remoteAddress, int remotePort)
{
_name = name;
_remotePort = remotePort;
_remoteAddress = remoteAddress;
if (string.IsNullOrEmpty(remoteAddress))
{
_remoteAddress = _configuration.GetConfigurationValue("TcpClient", "RemoteAddress", "127.0.0.1");
}
else
{
_remoteAddress = remoteAddress;
}
// _tcpClient is created in Initialize()
_tcpClient = null;
_tcpIpStream = null;
if (remotePort == 0)
{
_remotePort = _configuration.GetConfigurationValue("TcpClient", "RemotePort", 0);
}
else
{
_remotePort = remotePort;
}
}
_logger = LogManager.GetCurrentClassLogger();
/// <summary>
/// legacy constructor
/// </summary>
/// <param name="deviceName">The name of this device</param>
/// <param name="remoteAddress">The address of the server</param>
/// <param name="remotePort">The port that the server is listening on</param>
public CommDeviceTcpClient(string deviceName, string remoteAddress, int remotePort)
{
_name = deviceName;
_remotePort = remotePort;
_remoteAddress = remoteAddress;
_state = State.Uninitialized;
}
// _tcpClient is created in Initialize()
_tcpClient = null;
_tcpIpStream = null;
/// <summary>
/// initialize instrument
/// </summary>
public void Initialize()
{
lock (_syncObj)
{
if (_state == State.Uninitialized)
{
_tcpClient = new TcpClient(_remoteAddress, _remotePort);
_logger = LogManager.GetLogger($"{this.GetType().Name} - {deviceName}");
// set timeouts
_tcpClient.Client.SendTimeout = (int)_DEFAULT_SEND_TIMEOUT;
_tcpClient.Client.ReceiveTimeout = (int)_DEFAULT_READ_TIMEOUT;
_state = State.Uninitialized;
}
// get the stream
_tcpIpStream = _tcpClient.GetStream();
/// <summary>
/// initialize instrument
/// </summary>
public void Initialize()
{
lock (_syncObj)
{
if (_state == State.Uninitialized)
{
_tcpClient = new TcpClient(_remoteAddress, _remotePort);
_state = State.Ready;
}
else
{
throw new Exception($"expected the state to be Uninitialized, state was: {_state} on device {_name}");
}
}
}
// set timeouts
_tcpClient.Client.SendTimeout = (int)_DEFAULT_SEND_TIMEOUT;
_tcpClient.Client.ReceiveTimeout = (int)_DEFAULT_READ_TIMEOUT;
/// <summary>
/// shuts down the device
/// </summary>
public void Shutdown()
{
lock (_syncObj)
{
if (_state == State.Ready)
{
_tcpIpStream.Dispose();
_tcpClient.Dispose();
_state = State.Uninitialized;
}
}
}
// get the stream
_tcpIpStream = _tcpClient.GetStream();
/// <summary>
/// Read data from the device.
/// </summary>
/// <param name="dataRead">The buffer to put the data in</param>
/// <returns>The number of bytes read</returns>
public uint Read(ref byte[] dataRead)
{
lock (_syncObj)
{
if (_tcpIpStream.DataAvailable == true)
{
_state = State.Busy;
uint numBytesRead = (uint)(_tcpIpStream.Read(dataRead, 0, dataRead.Length));
_state = State.Ready;
return numBytesRead;
}
else
{
return 0;
}
}
}
_state = State.Ready;
}
else
{
throw new Exception($"expected the state to be Uninitialized, state was: {_state} on device {_name}");
}
}
}
/// <summary>
/// Read data from the device asynchronously.
/// </summary>
/// <param name="dataRead">The buffer to put the data in</param>
/// <returns>The number of bytes read</returns>
public async Task<uint> ReadAsync(byte[] dataRead)
{
if (_tcpIpStream.DataAvailable == true)
{
_state = State.Busy;
var bytesRead = await _tcpIpStream.ReadAsync(dataRead, 0, dataRead.Length);
_state = State.Ready;
return (uint)bytesRead;
}
else
{
return 0;
}
}
/// <summary>
/// shuts down the device
/// </summary>
public void Shutdown()
{
lock (_syncObj)
{
if (_state == State.Ready)
{
_tcpIpStream.Dispose();
_tcpClient.Dispose();
_state = State.Uninitialized;
}
}
}
/// <summary>
/// Read string from the device asynchronously.
/// </summary>
/// <param name="dataRead">The buffer to put the data in</param>
/// <returns>The number of bytes read</returns>
public async Task<string> ReadAsync(CancellationToken token = default)
{
if (_tcpIpStream.DataAvailable == true)
{
_state = State.Busy;
var buffer = new byte[_DEFAULT_READ_BUFFER_SIZE];
var bytesRead = await _tcpIpStream.ReadAsync(buffer, 0, buffer.Length, token);
_state = State.Ready;
return Encoding.UTF8.GetString(buffer, 0, bytesRead);
}
else
{
return null;
}
}
/// <summary>
/// Read data from the device.
/// </summary>
/// <param name="dataRead">The buffer to put the data in</param>
/// <returns>The number of bytes read</returns>
public uint Read(ref byte[] dataRead)
{
lock (_syncObj)
{
if (_tcpIpStream.DataAvailable == true)
{
_state = State.Busy;
uint numBytesRead = (uint)(_tcpIpStream.Read(dataRead, 0, dataRead.Length));
_state = State.Ready;
return numBytesRead;
}
else
{
return 0;
}
}
}
/// <summary>
/// Read data from the device asynchronously.
/// </summary>
/// <param name="dataRead">The buffer to put the data in</param>
/// <returns>The number of bytes read</returns>
public async Task<uint> ReadAsync(byte[] dataRead)
{
if (_tcpIpStream.DataAvailable == true)
{
_state = State.Busy;
var bytesRead = await _tcpIpStream.ReadAsync(dataRead, 0, dataRead.Length);
_state = State.Ready;
return (uint)bytesRead;
}
else
{
return 0;
}
}
/// <summary>
/// Read string from the device asynchronously.
/// </summary>
/// <param name="dataRead">The buffer to put the data in</param>
/// <returns>The number of bytes read</returns>
public async Task<string> ReadAsync(CancellationToken token = default)
{
if (_tcpIpStream.DataAvailable == true)
{
_state = State.Busy;
var buffer = new byte[_DEFAULT_READ_BUFFER_SIZE];
var bytesRead = await _tcpIpStream.ReadAsync(buffer, 0, buffer.Length, token);
_state = State.Ready;
return Encoding.UTF8.GetString(buffer, 0, bytesRead);
}
else
{
return null;
}
}
/// <summary>
/// Sets the read timeout
/// </summary>
/// <param name="timeoutMs"></param>
public void SetReadTimeout(uint timeoutMs)
{
_tcpClient.Client.ReceiveTimeout = (int)timeoutMs;
}
/// <summary>
/// Sets the read timeout
/// </summary>
/// <param name="timeoutMs"></param>
public void SetReadTimeout(uint timeoutMs)
{
_tcpClient.Client.ReceiveTimeout = (int)timeoutMs;
}
/// <summary>
/// Write data to the device
/// </summary>
/// <param name="dataToSend">The data to write</param>
/// <param name="numBytesToWrite">The number of bytes to write</param>
/// <returns>The number of bytes that were written</returns>
public uint Write(byte[] dataToSend, uint numBytesToWrite)
{
lock (_syncObj)
{
_state = State.Busy;
_tcpIpStream.Write(dataToSend, 0, (int)numBytesToWrite);
_state = State.Ready;
return numBytesToWrite;
}
}
/// <summary>
/// Write data to the device
/// </summary>
/// <param name="dataToSend">The data to write</param>
/// <param name="numBytesToWrite">The number of bytes to write</param>
/// <returns>The number of bytes that were written</returns>
public uint Write(byte[] dataToSend, uint numBytesToWrite)
{
lock (_syncObj)
{
_state = State.Busy;
_tcpIpStream.Write(dataToSend, 0, (int)numBytesToWrite);
_state = State.Ready;
return numBytesToWrite;
}
}
/// <summary>
/// Write data to the device asynchronously
/// </summary>
/// <param name="dataToSend"></param>
/// <param name="numBytesToWrite"></param>
/// <returns></returns>
public async Task<uint> WriteAsync(byte[] dataToSend, uint numBytesToWrite)
{
_state = State.Busy;
await _tcpIpStream.WriteAsync(dataToSend, 0, (int)numBytesToWrite);
_state = State.Ready;
return numBytesToWrite;
}
/// <summary>
/// Write data to the device asynchronously
/// </summary>
/// <param name="dataToSend"></param>
/// <param name="numBytesToWrite"></param>
/// <returns></returns>
public async Task<uint> WriteAsync(byte[] dataToSend, uint numBytesToWrite)
{
_state = State.Busy;
await _tcpIpStream.WriteAsync(dataToSend, 0, (int)numBytesToWrite);
_state = State.Ready;
return numBytesToWrite;
}
/// <summary>
/// Write string data to the device asynchronously
/// </summary>
/// <param name="message"></param>
/// <returns></returns>
public async Task WriteAsync(string message)
{
_state = State.Busy;
var buffer = Encoding.UTF8.GetBytes(message);
await _tcpIpStream.WriteAsync(buffer, 0, buffer.Length);
_state = State.Ready;
}
/// <summary>
/// Write string data to the device asynchronously
/// </summary>
/// <param name="message"></param>
/// <returns></returns>
public async Task WriteAsync(string message)
{
_state = State.Busy;
var buffer = Encoding.UTF8.GetBytes(message);
await _tcpIpStream.WriteAsync(buffer, 0, buffer.Length);
_state = State.Ready;
}
/// <summary>
/// Send Command and Get Response asynchronously
/// </summary>
/// <param name="message"></param>
/// <param name="timeoutInMs"></param>
/// <returns></returns>
public async Task<string> SendCommandGetResponseAsync(string message, int timeoutInMs = 5000)
{
_logger.Info($"Sending command waiting for response ({_remoteAddress}:{_remotePort}), message: {message}");
/// <summary>
/// Send Command and Get Response asynchronously
/// </summary>
/// <param name="message"></param>
/// <param name="timeoutInMs"></param>
/// <returns></returns>
public async Task<string> SendCommandGetResponseAsync(string message, int timeoutInMs = 5000)
{
_logger.Info($"Sending command waiting for response ({_remoteAddress}:{_remotePort}), message: {message}");
await WriteAsync(message);
await WriteAsync(message);
CancellationTokenSource tokenSource = new CancellationTokenSource(new TimeSpan(0, 0, 0, 0, milliseconds:timeoutInMs));
CancellationTokenSource tokenSource = new CancellationTokenSource(new TimeSpan(0, 0, 0, 0, milliseconds: timeoutInMs));
string readResponse = await ReadAsync(tokenSource.Token);
string readResponse = await ReadAsync(tokenSource.Token);
_logger.Info($"Received response: {readResponse}");
_logger.Info($"Received response: {readResponse}");
return readResponse;
}
return readResponse;
}
/// <summary>
/// keeps reading until canceled via token,
/// received messages sent to dataReceived function
/// </summary>
/// <param name="cancellationToken"></param>
/// <param name="dataReceived"></param>
/// <returns></returns>
public async Task KeepReadingAsync(CancellationToken cancellationToken, Action<string> dataReceived)
{
_logger.Info($"About to start continuous reading from {_remoteAddress}:{_remotePort} ...");
/// <summary>
/// keeps reading until canceled via token,
/// received messages sent to dataReceived function
/// </summary>
/// <param name="cancellationToken"></param>
/// <param name="dataReceived"></param>
/// <returns></returns>
public async Task KeepReadingAsync(CancellationToken cancellationToken, Action<string> dataReceived)
{
_logger.Info($"About to start continuous reading from {_remoteAddress}:{_remotePort} ...");
byte[] buffer = new byte[_DEFAULT_READ_BUFFER_SIZE];
while (!cancellationToken.IsCancellationRequested)
{
int bytesRead = await _tcpIpStream.ReadAsync(buffer, 0, buffer.Length, cancellationToken);
if (bytesRead > 0)
{
string data = Encoding.UTF8.GetString(buffer, 0, bytesRead);
byte[] buffer = new byte[_DEFAULT_READ_BUFFER_SIZE];
while (!cancellationToken.IsCancellationRequested)
{
int bytesRead = await _tcpIpStream.ReadAsync(buffer, 0, buffer.Length, cancellationToken);
if (bytesRead > 0)
{
string data = Encoding.UTF8.GetString(buffer, 0, bytesRead);
_logger.Info($"Message received from {_remoteAddress}:{_remotePort}: {data}");
_logger.Info($"Message received from {_remoteAddress}:{_remotePort}: {data}");
dataReceived(data);
Array.Clear(buffer, 0, bytesRead);
}
}
}
dataReceived(data);
Array.Clear(buffer, 0, bytesRead);
}
}
}
#endregion
}
#endregion
}
}