/* Test.Module.AnalogInputChannel.cs Copyright © 2008 Diversified Technical Systems, Inc. All Rights Reserved */ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Xml; using DTS.Common.Utilities; using DTS.Common.Utilities.DotNetProgrammingConstructs; using System.ComponentModel; using DTS.Common.Utilities.Logging; using DTS.Common.Utilities.Xml; namespace DTS.Serialization { // *** see Test.cs *** public partial class Test { // *** see Test.Module.cs *** public partial class Module { /// /// Representation of a calculated channel. /// [XmlSerializationTag("CalculatedChannel")] public class CalculatedChannel : AnalogInputChannel { public CalculatedChannel(Module parentModule) : base(parentModule) { } /// /// Get/set the Source Channel for this channel. /// [XmlSerializationTag("SourceChannelNumber")] public int[] SourceChannelNumber { get => _SourceChannelNumber.Value; set => _SourceChannelNumber.Value = value; } private readonly Property _SourceChannelNumber = new Property( typeof(CalculatedChannel).Namespace + ".Test.Module.CalculatedChannel.SourceChannelNumber", null, false ); /// /// Get/set the Source Channel for this channel. /// [XmlSerializationTag("SourceModuleNumber")] public int[] SourceModuleNumber { get => _SourceModuleNumber.Value; set => _SourceModuleNumber.Value = value; } private readonly Property _SourceModuleNumber = new Property( typeof(CalculatedChannel).Namespace + ".Test.Module.CalculatedChannel.SourceModuleNumber", null, false ); /// /// Get/set the Source Channel for this channel. /// [XmlSerializationTag("SourceModuleSerialNumber")] public string[] SourceModuleSerialNumber { get => _SourceModuleSerialNumber.Value; set => _SourceModuleSerialNumber.Value = value; } private readonly Property _SourceModuleSerialNumber = new Property( typeof(CalculatedChannel).Namespace + ".Test.Module.CalculatedChannel.SourceModuleSerialNumber", null, false ); /// /// the calculation for the channel(s) involved /// [XmlSerializationTag("Calculation")] public string Calculation { get => _Calculation.Value; set => _Calculation.Value = value; } private readonly Property _Calculation = new Property( typeof(CalculatedChannel).Namespace + ".Test.Module.CalculatedChannel.Calculation", "NONE", false ); [XmlSerializationTag("T1")] public ulong T1 { get => _T1.Value; set => _T1.Value = value; } private readonly Property _T1 = new Property( typeof(CalculatedChannel).Namespace + ".Test.Module.CalculatedChannel.T1", 0, false); [XmlSerializationTag("T2")] public ulong T2 { get => _T2.Value; set => _T2.Value = value; } private readonly Property _T2 = new Property( typeof(CalculatedChannel).Namespace + ".Test.Module.CalculatedChannel.T2", 0, false); [XmlSerializationTag("HIC")] public double HIC { get => _HIC.Value; set => _HIC.Value = value; } private readonly Property _HIC = new Property( typeof(CalculatedChannel).Namespace + ".Test.Module.CalculatedChannel.HIC", 0D, false); /// /// Get/set the sample rate for this test module. /// [XmlSerializationTag("SampleRateHz")] public double SampleRateHz { get => _SampleRateHz.Value; set => _SampleRateHz.Value = value; } private readonly Property _SampleRateHz = new Property( typeof(CalculatedChannel).Namespace + ".Test.Module.CalculatedChannel.SampleRateHz", 0, false ); private const string BeginTagModifier = "Begin"; private const string EndTagModifier = "End"; /// /// Write XML serialization for this object to the specified writer. /// /// /// /// The to which this object's XML serialization /// will be written. /// /// public override void WriteXml(XmlWriter writer) { try { APILogger.Log("writing CalculatedChannel::WriteXML"); var cult = new System.Globalization.CultureInfo(""); var attributeExtractor = new AttributeExtractor(); writer.WriteStartElement(attributeExtractor.ExtractAttachedAttributeFromObject(this).Value); writeXmlAttributes(writer); writer.WriteAttributeString(attributeExtractor.ExtractAttachedAttributeFromProperty(this, "SourceChannelNumber").Value, IntArrayToString(SourceChannelNumber)); writer.WriteAttributeString(attributeExtractor.ExtractAttachedAttributeFromProperty(this, "SourceModuleNumber").Value, IntArrayToString(SourceModuleNumber)); writer.WriteAttributeString( attributeExtractor.ExtractAttachedAttributeFromProperty(this, "SourceModuleSerialNumber") .Value, StringArrayToString(SourceModuleSerialNumber)); writer.WriteAttributeString(attributeExtractor.ExtractAttachedAttributeFromProperty(this, "Calculation").Value, Calculation.ToString(cult)); writer.WriteAttributeString(attributeExtractor.ExtractAttachedAttributeFromProperty(this, "SampleRateHz").Value, SampleRateHz.ToString(cult)); if (_HIC.IsValueInitialized) { writer.WriteAttributeString(attributeExtractor.ExtractAttachedAttributeFromProperty(this, "HIC").Value, HIC.ToString(System.Globalization.CultureInfo.InvariantCulture)); writer.WriteAttributeString(attributeExtractor.ExtractAttachedAttributeFromProperty(this, "T1").Value, T1.ToString(System.Globalization.CultureInfo.InvariantCulture)); writer.WriteAttributeString(attributeExtractor.ExtractAttachedAttributeFromProperty(this, "T2").Value, T2.ToString(System.Globalization.CultureInfo.InvariantCulture)); } writer.WriteEndElement(); } catch (System.Exception ex) { throw new Exception("encountered problem converting " + GetType().FullName + " object to XML: ", ex); } } /// /// Read XML serialization for this object from the specified reader. /// /// /// /// The from which this object's XML serialization /// will be read. /// /// public override void ReadXml(XmlReader reader) { try { var cult = new System.Globalization.CultureInfo(""); var attributeExtractor = new AttributeExtractor(); var xmlAttributeDecoder = new PropertyAttributeDecoder(this); base.ReadXml(reader); SourceChannelNumber = StringToIntArray(xmlAttributeDecoder.ExtractStringProperty("SourceChannelNumber", reader)); SourceModuleNumber = StringToIntArray(xmlAttributeDecoder.ExtractStringProperty("SourceModuleNumber", reader)); SourceModuleSerialNumber = StringToStringArray(xmlAttributeDecoder.ExtractStringProperty("SourceModuleSerialNumber", reader)); Calculation = xmlAttributeDecoder.ExtractStringProperty("Calculation", reader); SampleRateHz = xmlAttributeDecoder.ExtractDoubleProperty("SampleRateHz", reader); var s = reader.GetAttribute("HIC"); if (!string.IsNullOrWhiteSpace(s)) { HIC = Convert.ToDouble(s); T1 = Convert.ToUInt64(reader.GetAttribute("T1")); T2 = Convert.ToUInt64(reader.GetAttribute("T2")); } } catch (System.Exception ex) { throw new Exception("encountered problem converting XML to " + GetType().FullName + " object", ex); } } private int[] StringToIntArray(string s) { var ints = new List(); var tokens = s.Split(new char[] { ',' }); foreach (var token in tokens) { if (int.TryParse(token, System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture, out int i)) { ints.Add(i); } } return ints.ToArray(); } private string[] StringToStringArray(string s) { var tokens = s.Split(new string[] { "_.-._" }, StringSplitOptions.None); return tokens; } private string IntArrayToString(int[] array) { var sb = new StringBuilder(); foreach (var i in array) { if (sb.Length > 0) { sb.Append(","); } sb.Append(i.ToString(System.Globalization.CultureInfo.InvariantCulture)); } return sb.ToString(); } private string StringArrayToString(string[] array) { return string.Join("_.-._", array); } /// /// Test the specified object for equality with this object. /// /// /// /// The to be tested for equality. /// /// /// /// true if the specified object has memeberwise equality with /// this object; false otherwise. /// /// public override bool Equals(object obj) { try { var that = obj as CalculatedChannel; return (null != obj) // Must-be-initialized properties. && ChannelId.Equals(that.ChannelId) && SourceChannelNumber.Equals(that.SourceChannelNumber) && ChannelDescriptionString.Equals(that.ChannelDescriptionString) && EngineeringUnits.Equals(that.EngineeringUnits, StringComparison.OrdinalIgnoreCase) && Calculation.Equals(that.Calculation) && IsoCode.Equals(that.IsoCode); } catch (System.Exception ex) { throw new Exception("encountered problem equality-testing the object " + (null != obj ? "\"" + obj.ToString() + "\"" : "<>"), ex); } } /// /// Return the hash code for this object. /// /// /// /// The hash code for this object. /// /// public override int GetHashCode() { return base.GetHashCode(); } public override string ToString() { return ChannelDescriptionString; } /// /// creates a new calculated channel, with the modulenumbers, channelnumbers, and moduleserialnumbers composed of all the inputs /// /// /// /// public static CalculatedChannel CreateInstance(Channel[] channels) { var cc = new CalculatedChannel(channels.First().ParentModule); var maxSampleRAte = channels.Select(ch => ch.ParentModule.SampleRateHz).Max(); //CC only values var channelNumbers = new List(); var moduleNumbers = new List(); var moduleSerialNumbers = new List(); var sps = channels.First().ParentModule.SampleRateHz; foreach (var ch in channels) { channelNumbers.Add(ch.Number); moduleSerialNumbers.Add(ch.ParentModule.SerialNumber); if (0 != maxSampleRAte % ch.ParentModule.SampleRateHz) { throw new InvalidOperationException($"sample rate: {maxSampleRAte} is not a multiple of sample rate: {ch.ParentModule.SampleRateHz}"); } } cc.SourceChannelNumber = channelNumbers.ToArray(); cc.SourceModuleNumber = moduleNumbers.ToArray(); cc.SourceModuleSerialNumber = moduleSerialNumbers.ToArray(); cc.SampleRateHz = sps; //Rip a copy. Can't use cloning foreach ( PropertyDescriptor item in TypeDescriptor.GetProperties( channels.First() as AnalogInputChannel)) { try { item.SetValue(cc, item.GetValue(channels.First())); } catch (System.Exception ex) { APILogger.Log(ex); } } //need a copy not the original for linearization formula... cc.LinearizationFormula = new DTS.Common.Classes.Sensors.LinearizationFormula( (channels.First() as AnalogInputChannel).LinearizationFormula); return cc; } /// /// creates a calculated channel using a single source channel /// /// /// public static CalculatedChannel CreateInstance(Channel sourceChannel) { //Dammit, need to manually clone properties from souce channel var cc = new CalculatedChannel(sourceChannel.ParentModule); //CC only values cc.SourceChannelNumber = new int[] { sourceChannel.Number }; cc.SourceModuleNumber = new int[] { sourceChannel.ParentModule.Number }; cc.SourceModuleSerialNumber = new string[] { sourceChannel.ParentModule.SerialNumber }; cc.SampleRateHz = sourceChannel.ParentModule.SampleRateHz; //Rip a copy. Can't use cloning foreach (PropertyDescriptor item in TypeDescriptor.GetProperties(sourceChannel as AnalogInputChannel)) { try { item.SetValue(cc, item.GetValue(sourceChannel)); } catch { } } return cc; } } } } }