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"; } }