Initial check-in

This commit is contained in:
Duc
2025-01-03 09:50:39 -07:00
parent 45596e360d
commit 1d8f6e4c96
143 changed files with 9835 additions and 0 deletions

View File

@@ -0,0 +1,299 @@
/*-------------------------------------------------------------------------
// UNCLASSIFIED
/*-------------------------------------------------------------------------
RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION
PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS
AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO
UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO
RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS
CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS
OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON
COMPANY.
THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S.
GOVERNMENT.
UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
-------------------------------------------------------------------------*/
using NLog;
using Raytheon.Common;
using System;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
namespace Raytheon.Instruments.EthernetSockets
{
/// <summary>
/// Class for controlling a TCP client communication device
/// </summary>
public class TcpClient : ICommDevice
{
#region PrivateClassMembers
private Socket _sock;
private string _remoteAddress;
private int _remotePort;
private IPEndPoint _remoteEP = null;
private IPAddress _ipAddress = null;
private object _syncObj = new object();
private readonly string _name;
private State _state;
/// <summary>
/// NLog logger
/// </summary>
private static ILogger _logger;
/// <summary>
/// Raytheon configuration
/// </summary>
private readonly IConfigurationManager _configurationManager;
private readonly IConfiguration _configuration;
#endregion
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() => Disconnect();
public void Shutdown() => Disconnect();
public void Reset()
{
Close();
Open();
}
#region Public Functions
/// <summary>
/// CommDevice factory constructor
/// </summary>
/// <param name="deviceInstanceName"></param>
/// <param name="configurationManager"></param>
public TcpClient(string deviceInstanceName, IConfigurationManager configurationManager, ILogger logger, string remoteAddress = "", int remotePort = 0)
{
_name = deviceInstanceName;
_state = State.Uninitialized;
_logger = logger;
_configurationManager = configurationManager;
// configuration obtained from [deviceInstanceName].xml file
_configuration = _configurationManager.GetConfiguration(Name);
if (string.IsNullOrEmpty(remoteAddress))
{
_remoteAddress = _configuration.GetConfigurationValue(deviceInstanceName, TcpClientConfigXml.REMOTE_ADDRESS.ToString(), "127.0.0.1");
}
else
{
_remoteAddress = remoteAddress;
}
if (remotePort == 0)
{
_remotePort = _configuration.GetConfigurationValue(deviceInstanceName, TcpClientConfigXml.REMOTE_PORT.ToString(), 0);
}
else
{
_remotePort = remotePort;
}
}
/// <summary>
/// Constructor
/// </summary>
/// <param name="remoteAddress"></param>
/// <param name="remotePort"></param>
public TcpClient(string remoteAddress, int remotePort)
{
_remoteAddress = remoteAddress;
_remotePort = remotePort;
}
/// <summary>
/// initialize instrument
/// </summary>
public void Initialize()
{
// if remoteAddress is a hostname
if (!IPAddress.TryParse(_remoteAddress, out _ipAddress))
{
string preferredSubnet = "";
IPHostEntry host = Dns.GetHostEntry(_remoteAddress);
foreach (IPAddress ip in host.AddressList)
{
AddressFamily af = ip.AddressFamily;
if (af == AddressFamily.InterNetwork)
{
if (preferredSubnet != String.Empty)
{
if (Regex.IsMatch(ip.ToString(), preferredSubnet, RegexOptions.IgnoreCase))
_ipAddress = ip;
}
else
_ipAddress = ip;
if (_ipAddress != null)
break;
}
}
}
if (_ipAddress != null)
{
if (_remoteEP == null)
_remoteEP = new IPEndPoint(_ipAddress, _remotePort);
}
else
throw new Exception($"Unable to create IPEndPoint to {_remoteAddress}, port {_remotePort}");
if (_sock == null)
_sock = new Socket(_ipAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
}
/// <summary>
/// Connect to remote host
/// </summary>
/// <returns></returns>
public void Connect()
{
lock (_syncObj)
{
try
{
if (!_sock.Connected && IsRemoteHostAlive())
_sock.Connect(_remoteEP);
}
catch (ObjectDisposedException)
{
_sock = new Socket(_ipAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
if (IsRemoteHostAlive())
_sock.Connect(_remoteEP);
}
catch (Exception) { throw; }
}
}
/// <summary>
/// Disconnect from remote host
/// </summary>
/// <returns></returns>
public void Disconnect()
{
lock (_syncObj)
{
if (_sock.Connected)
{
_sock.Shutdown(SocketShutdown.Both);
_sock.Disconnect(true);
_sock.Close();
}
}
}
/// <summary>
/// Ping if remote host is alive
/// </summary>
/// <returns>true/false</returns>
bool IsRemoteHostAlive()
{
bool isRemoteHostAlive = true;
//Do a ping test to see if the server is reachable
try
{
Ping pingTest = new Ping();
PingReply reply = pingTest.Send(_ipAddress);
if (reply.Status != IPStatus.Success)
isRemoteHostAlive = false;
}
catch (PingException)
{
isRemoteHostAlive = false;
}
//See if the tcp state is ok
if (_sock.Poll(5000, SelectMode.SelectRead) && (_sock.Available == 0))
{
isRemoteHostAlive = false;
}
return isRemoteHostAlive;
}
/// <summary>
/// Read data from the device.
/// </summary>
/// <param name="dataBuf"></param>
/// <param name="responseTimeOutMs"></param>
/// <returns>The number of bytes read</returns>
public uint Read(ref byte[] dataBuf)
{
int bytesRec = 0;
lock (_syncObj)
{
try
{
bytesRec = _sock.Receive(dataBuf);
}
catch (SocketException)
{
bytesRec = 0;
}
}
return (uint)bytesRec;
}
/// <summary>
/// Sets the read timeout
/// </summary>
/// <param name="timeoutMs"></param>
public void SetReadTimeout(uint timeoutMs)
{
_sock.ReceiveTimeout = (int)timeoutMs;
}
/// <summary>
/// Write data to device.
/// </summary>
/// <param name="dataBuf"></param>
/// <returns>The number of bytes written</returns>
public uint Write(byte[] dataBuf, uint numBytesToWrite)
{
int bytesWritten = 0;
lock (_syncObj)
{
try
{
bytesWritten = _sock.Send(dataBuf, (int)numBytesToWrite, SocketFlags.None);
}
catch (SocketException)
{
bytesWritten = 0;
}
}
return (uint)bytesWritten;
}
#endregion
}
}

View File

@@ -0,0 +1,33 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="$(SolutionDir)Program.props" />
<PropertyGroup>
<TargetFramework>net472</TargetFramework>
<OutputType>Library</OutputType>
<AssemblyName>Raytheon.Instruments.EthernetSockets.TcpClient</AssemblyName>
<RootNamespace>Raytheon.Instruments</RootNamespace>
<Product>CommDevice TCP implementation</Product>
<Description>CommDevice TCP implementation</Description>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder>
<Company>Raytheon Technologies</Company>
<Authors>TEEC</Authors>
<Copyright>Copyright © Raytheon Technologies $([System.DateTime]::get_now().ToString("yyyy"))</Copyright>
<!-- Dynamic Versioning (Suitable for Release) -->
<!-- <Version>$(Version)$(Suffix)</Version> -->
<!-- Static Versioning (Suitable for Development) -->
<Version>1.0.0</Version>
<Configurations>Debug;Release;Deploy</Configurations>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="NLog" Version="5.0.0" />
<PackageReference Include="Raytheon.Configuration" Version="2.6.1" />
<PackageReference Include="Raytheon.Configuration.Contracts" Version="2.3.0" />
<PackageReference Include="Raytheon.Instruments.CommDevice.Contracts" Version="1.0.0" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,32 @@
/*-------------------------------------------------------------------------
// UNCLASSIFIED
/*-------------------------------------------------------------------------
RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION
PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS
AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO
UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO
RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS
CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS
OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON
COMPANY.
THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S.
GOVERNMENT.
UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
-------------------------------------------------------------------------*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Raytheon.Instruments.EthernetSockets
{
public enum TcpClientConfigXml
{
// List all the keys here
REMOTE_ADDRESS,
REMOTE_PORT
}
}

View File

@@ -0,0 +1,122 @@
/*-------------------------------------------------------------------------
// UNCLASSIFIED
/*-------------------------------------------------------------------------
RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION
PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS
AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO
UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO
RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS
CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS
OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON
COMPANY.
THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S.
GOVERNMENT.
UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
-------------------------------------------------------------------------*/
using NLog;
using Raytheon.Common;
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.IO;
using System.Reflection;
namespace Raytheon.Instruments.EthernetSockets
{
[ExportInstrumentFactory(ModelNumber = "EthernetSocketsTcpClientFactory")]
public class TcpClientFactory : IInstrumentFactory
{
/// <summary>
/// The supported interfaces
/// </summary>
private readonly List<Type> _supportedInterfaces = new List<Type>();
private static ILogger _logger;
private readonly IConfigurationManager _configurationManager;
private const string DefaultConfigPath = @"C:\ProgramData\Raytheon\InstrumentManagerService";
private static string DefaultPath;
public TcpClientFactory(string defaultConfigPath = DefaultConfigPath)
: this(null, defaultConfigPath)
{
}
/// <summary>
/// COECommDeviceInstrumentFactory injection constructor
/// </summary>
/// <param name="configManager"></param>
/// <param name="simEngine"></param>
/// <param name="logger"></param>
[ImportingConstructor]
public TcpClientFactory([Import(AllowDefault = false)] IConfigurationManager configManager,
[Import(AllowDefault = true)] string defaultConfigPath = null)
{
DefaultPath = defaultConfigPath;
_logger = LogManager.GetCurrentClassLogger();
if (NLog.LogManager.Configuration == null)
{
var assemblyFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
NLog.LogManager.Configuration = new NLog.Config.XmlLoggingConfiguration(assemblyFolder + "\\nlog.config");
}
_configurationManager = configManager ?? GetConfigurationManager();
_supportedInterfaces.Add(typeof(ICommDevice));
}
/// <summary>
/// Gets the instrument
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public IInstrument GetInstrument(string name)
{
try
{
return new TcpClient(name, _configurationManager, _logger);
}
catch (Exception ex)
{
_logger.Error(ex, $"Unable to construct {name} instrument instance");
return null;
}
}
/// <summary>
/// Gets the instrument
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public object GetInstrument(string name, bool simulateHw)
{
try
{
return new TcpClient(name, _configurationManager, _logger);
}
catch (Exception ex)
{
_logger.Error(ex, $"Unable to construct {name} instrument instance");
return null;
}
}
/// <summary>
/// Gets supported interfaces
/// </summary>
/// <returns></returns>
public ICollection<Type> GetSupportedInterfaces()
{
return _supportedInterfaces.ToArray();
}
/// <summary>
/// returns confiuration based on the predefined path or default path c:/ProgramData/Raytheon/InstrumentManagerService
/// </summary>
/// <returns></returns>
private static IConfigurationManager GetConfigurationManager()
{
return string.IsNullOrEmpty(DefaultPath) ? new RaytheonConfigurationManager() : new RaytheonConfigurationManager(DefaultPath);
}
}
}