Files
DP44/DataPRO/IService/Classes/ConfigurationData.cs
2026-04-17 14:55:32 -04:00

438 lines
16 KiB
C#

using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.IO;
using System.Linq;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;
using DASFactoryDb.Config;
using DTS.Common.Interface.DASFactory;
using DTS.Common.Interface.DASFactory.Config;
using DTS.Common.Utilities.Logging;
namespace DTS.DASLib.Service
{
/// <summary>
/// Each IDASCommunication will have an instance of this class. It provides information
/// about the configuration of the DAS as a whole with regards to the current test/event.
/// The ConfigData object in an IDASCommunication will contain arrays representing the
/// specific modules and channels therein, of which the configurations may be set and
/// retrieved through the ConfigurationData object.
/// </summary>
[Serializable]
[XmlInclude(typeof(DASChannel))]
[XmlInclude(typeof(InputDASChannel))]
[XmlInclude(typeof(AnalogInputDASChannel))]
//[XmlInclude(typeof(DigitalInputDASChannel))]
[XmlInclude(typeof(OutputDASChannel))]
[XmlInclude(typeof(AnalogOutputDASChannel))]
[XmlInclude(typeof(DigitalOutputDASChannel))]
public class ConfigurationData : IConfigurationData, IXmlSerializable
{
/// <summary>
/// Array of Module objects in the DAS.
/// </summary>
public IDASModule[] Modules { get; set; }
/// <summary>
/// EID's for the whole DAS.
/// </summary>
[XmlIgnore]
public IEID[] IDs { get; set; }
/// <summary>
/// The ID of the current test/event.
/// </summary>
public string TestID { get; set; }
public string TestSetupUniqueId { get; set; }
/// <summary>
/// The ID of an instance of a test run, for the purpose
/// of identifying where to download data.
/// </summary>
public string InstanceID { get; set; }
/// <summary>
/// A description of the current test/event.
/// </summary>
public string Description { get; set; }
[XmlIgnore()]
public bool ClearSetup { get; set; } = false;
/// <summary>
/// Counts how many channels are configured. If a channel's
/// 'IsConfigured' property is 'true' it is configured.
/// </summary>
/// <returns>Number of configured channels</returns>
public int NumberOfConfiguredChannels()
{
if (Modules == null || Modules.Length == 0)
return 0;
return Modules.Sum(module => module.NumberOfConfiguredChannels());
}
/// <summary>
/// Count how many channels we have (regardless if they are configured or not).
/// </summary>
/// <returns>Total number of channels</returns>
public int NumberOfChannels()
{
if (Modules == null || Modules.Length == 0)
return 0;
return Modules.Sum(module => module.NumberOfChannels());
}
/// <summary>
/// Count how many downloadable channels (i.e. not UART, StreamOut, etc.) we have (regardless if they are configured or not).
/// </summary>
/// <returns>Total number of downloadable channels</returns>
public int NumberOfDownloadChannels()
{
if (Modules == null || Modules.Length == 0)
return 0;
return Modules.Where(module => !module.IsStreamOut() && !module.IsUart()).Sum(module => module.NumberOfChannels());
}
public ConfigurationData()
{
Modules = null;
IDs = null;
TestID = "";
TestSetupUniqueId = null;
Description = "Default Test ID";
InstanceID = null;
}
public int[] DisplayOrder { get; set; } = new int[] { -1 };
public int DasDisplayOrder { get; set; } = -1;
public int GetDisplayOrder(uint channelIdx)
{
if (channelIdx >= DisplayOrder.Length) { return -1; }
else { return DisplayOrder[channelIdx]; }
}
#region Serialization functions
/// <summary>
/// Serialize configuration data to a file
/// </summary>
/// <param name="file">File name to write to</param>
/// <param name="config">The configuration to serialize</param>
public static void Serialize(string file, ConfigurationData config)
{
System.Xml.Serialization.XmlSerializer xs = new System.Xml.Serialization.XmlSerializer(config.GetType());
StreamWriter writer = File.CreateText(file);
xs.Serialize(writer, config);
writer.Flush();
writer.Close();
}
/// <summary>
/// Serialize configuration data to a string
/// </summary>
/// <param name="config">The configuration to serialize</param>
/// <returns>The serialized data in XML form</returns>
public static string Serialize(ConfigurationData config)
{
System.Xml.Serialization.XmlSerializer xs = new System.Xml.Serialization.XmlSerializer(config.GetType());
StringWriter writer = new StringWriter();
System.Xml.XmlWriterSettings xmlsettings = new System.Xml.XmlWriterSettings();
xmlsettings.NewLineChars = "";
System.Xml.XmlWriter xmlwriter = System.Xml.XmlWriter.Create(writer, xmlsettings);
try
{
xs.Serialize(xmlwriter, config);
}
catch (Exception ex)
{
APILogger.Log(ex); // Maybe useful for forensics?
APILogger.Log($"Current writer buffer:{writer.ToString()}");
// http://manuscript.dts.local/f/cases/26802/Fail-on-serialization-error-for-XML-config-data
writer.Flush();
writer.Close();
throw;
}
writer.Flush();
writer.Close();
var xmlStr = writer.ToString();
return xmlStr;
}
/// <summary>
/// Serialize configuration data to a binary block
/// </summary>
/// <param name="config">The configuration to serialize</param>
/// <returns>The serialized data in binary form</returns>
public static byte[] SerializeBin(ConfigurationData config)
{
BinaryFormatter bf = new BinaryFormatter();
byte[] bytes;
using (MemoryStream ms = new MemoryStream())
{
bf.Serialize(ms, config);
ms.Seek(0, 0);
bytes = ms.ToArray();
}
return bytes;
}
/// <summary>
/// Deserialize an XML string into a new configuration object
/// </summary>
/// <param name="SerializedText">The XML data</param>
/// <returns>A new configuration object</returns>
public static ConfigurationData DeserializeFromString(string SerializedText)
{
if (string.IsNullOrEmpty(SerializedText)) { return null; }
XmlSerializer xs = new System.Xml.Serialization.XmlSerializer(typeof(ConfigurationData));
StringReader reader = new StringReader(SerializedText);
try
{
ConfigurationData config = (ConfigurationData)xs.Deserialize(reader);
return config;
}
catch (Exception ex)
{
APILogger.Log("Failed to read config", ex);
}
finally
{
reader.Close();
}
return null;
}
/// <summary>
/// Deserialize from an XML file to a configuration object
/// </summary>
/// <param name="file">The file name to read from</param>
/// <returns>A new configuration object</returns>
public static ConfigurationData Deserialize(string file)
{
var xs = new XmlSerializer(typeof(ConfigurationData));
if (File.Exists(file))
{
APILogger.Log("reading 67 ", file);
using (StreamReader reader = File.OpenText(file))
{
var c = (ConfigurationData)xs.Deserialize(reader);
reader.Close();
return c;
}
}
else
{
return new ConfigurationData();
}
}
public virtual void WriteXml(XmlWriter writer)
{
//writer.WriteStartElement("ConfigurationData");
// <ConfigurationData xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
writer.WriteAttributeString("xmlns", "xsi", null, "http://www.w3.org/2001/XMLSchema-instance");
writer.WriteAttributeString("xmlns", "xsd", null, "http://www.w3.org/2001/XMLSchema");
// Modules
writer.WriteStartElement("Modules");
if (Modules != null)
{
foreach (var module in Modules)
{
module.WriteXml(writer);
}
}
writer.WriteEndElement();
// TestID
XMLHelper.PutString(writer, "TestID", TestID);
// Description
XMLHelper.PutString(writer, "Description", Description);
// TestSetupUniqueId
XMLHelper.PutString(writer, "TestSetupUniqueId", TestSetupUniqueId);
// InstanceID
XMLHelper.PutString(writer, "InstanceID", InstanceID);
XMLHelper.PutString(writer, "UDPReceiveAddress", UDPReceiveAddress);
//writer.WriteEndElement();
}
private void DumpXml(XmlReader reader)
{
using (var writer = new StreamWriter("xmldump.txt"))
{
while (reader.Read())
{
string n, t, v;
try
{
n = reader.Name;
if (string.IsNullOrEmpty(n))
{
n = "<null>";
}
}
catch
{
n = "<no-name>";
}
try
{
t = reader.NodeType.ToString();
if (string.IsNullOrEmpty(t))
{
t = "<null>";
}
}
catch
{
t = "<no-type>";
}
try
{
v = reader.Value;
if (string.IsNullOrEmpty(v))
{
v = "<null>";
}
}
catch
{
v = "<no-value>";
}
writer.WriteLine("Name: " + n + " Type: " + t + " Value: " + v);
}
}
}
private const string CONFIG_START_TAG = "ConfigurationData";
private const string MODULES_START_TAG = "Modules";
private const string DASMODULE_START_TAG = "DASModule";
private const string TESTID_START_TAG = "TestID";
private const string DESCRIPTION_START_TAG = "Description";
private List<string> KNOWN_STARTING_TAGS = new List<string>(new[] { CONFIG_START_TAG, MODULES_START_TAG, DASMODULE_START_TAG, TESTID_START_TAG, DESCRIPTION_START_TAG });
private void ReadModules(XmlReader reader)
{
var myModules = new List<DASModule>();
var keepGoing = reader.ReadToFollowing(DASMODULE_START_TAG);
while (keepGoing)
{
var deserializedModule = new DASModule();
deserializedModule.ReadXml(reader);
myModules.Add(deserializedModule);
if (reader.Name == MODULES_START_TAG && reader.NodeType == XmlNodeType.EndElement)
{
keepGoing = false;
}
else
{
keepGoing = reader.Name == DASMODULE_START_TAG && reader.NodeType == XmlNodeType.Element || reader.ReadToFollowing(DASMODULE_START_TAG);
}
}
Modules = myModules.ToArray();
}
public virtual void ReadXml(XmlReader reader)
{
// it must be an Element
if (reader.NodeType != XmlNodeType.Element)
{
throw new XmlException("ConfigurationData.ReadXml: Unknown input: " + reader.NodeType.ToString());
}
// remove our start tag
if (reader.Name == CONFIG_START_TAG)
{
reader.Read();
}
else
{
while (reader.Name != CONFIG_START_TAG)
{
reader.Read();
}
}
// try to find our data
do
{
if (reader.NodeType != XmlNodeType.Element) { continue; }
switch (reader.Name)
{
case "Modules": // DASModule[]
ReadModules(reader);
break;
case "TestID":
TestID = XMLHelper.GetString(reader);
break;
case "Description":
Description = XMLHelper.GetString(reader);
break;
case "TestSetupUniqueId":
TestSetupUniqueId = XMLHelper.GetString(reader);
break;
case "InstanceID":
InstanceID = XMLHelper.GetString(reader);
break;
case "UDPReceiveAddress":
UDPReceiveAddress = XMLHelper.GetString(reader);
break;
default:
break;
//throw new XmlException("ConfigurationData.ReadXml: Unknown tag: " + reader.Name);
//return;
}
} while (reader.Read());
// we're going to end with an EndElement, so clean up
if (reader.NodeType == XmlNodeType.EndElement)
{
reader.Read();
}
}
public XmlSchema GetSchema()
{
return null;
}
#endregion
public const int DIAGNOSTIC_FILESTORE = 0;
public const int EVENT_FILE_STORE = 1;
/// <summary>
/// writes the current configuration to the db if available
/// </summary>
public static void SetConfiguration(IDASCommunication das, string xml, int fileStore)
{
if (!DASFactoryDb.DbWrapper.Connected) { return; }
try
{
Config.SetConfiguration(das.RecordId, xml, fileStore);
}
catch (Exception ex)
{
APILogger.Log(ex);
}
}
public string UDPReceiveAddress { get; set; } = "UDP://239.1.2.10:8401";
}
}