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
{
///
/// 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.
///
[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
{
///
/// Array of Module objects in the DAS.
///
public IDASModule[] Modules { get; set; }
///
/// EID's for the whole DAS.
///
[XmlIgnore]
public IEID[] IDs { get; set; }
///
/// The ID of the current test/event.
///
public string TestID { get; set; }
public string TestSetupUniqueId { get; set; }
///
/// The ID of an instance of a test run, for the purpose
/// of identifying where to download data.
///
public string InstanceID { get; set; }
///
/// A description of the current test/event.
///
public string Description { get; set; }
[XmlIgnore()]
public bool ClearSetup { get; set; } = false;
///
/// Counts how many channels are configured. If a channel's
/// 'IsConfigured' property is 'true' it is configured.
///
/// Number of configured channels
public int NumberOfConfiguredChannels()
{
if (Modules == null || Modules.Length == 0)
return 0;
return Modules.Sum(module => module.NumberOfConfiguredChannels());
}
///
/// Count how many channels we have (regardless if they are configured or not).
///
/// Total number of channels
public int NumberOfChannels()
{
if (Modules == null || Modules.Length == 0)
return 0;
return Modules.Sum(module => module.NumberOfChannels());
}
///
/// Count how many downloadable channels (i.e. not UART, StreamOut, etc.) we have (regardless if they are configured or not).
///
/// Total number of downloadable channels
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
///
/// Serialize configuration data to a file
///
/// File name to write to
/// The configuration to serialize
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();
}
///
/// Serialize configuration data to a string
///
/// The configuration to serialize
/// The serialized data in XML form
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;
}
///
/// Serialize configuration data to a binary block
///
/// The configuration to serialize
/// The serialized data in binary form
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;
}
///
/// Deserialize an XML string into a new configuration object
///
/// The XML data
/// A new configuration object
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;
}
///
/// Deserialize from an XML file to a configuration object
///
/// The file name to read from
/// A new configuration object
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");
//
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 = "";
}
}
catch
{
n = "";
}
try
{
t = reader.NodeType.ToString();
if (string.IsNullOrEmpty(t))
{
t = "";
}
}
catch
{
t = "";
}
try
{
v = reader.Value;
if (string.IsNullOrEmpty(v))
{
v = "";
}
}
catch
{
v = "";
}
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 KNOWN_STARTING_TAGS = new List(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();
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;
///
/// writes the current configuration to the db if available
///
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";
}
}