using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Xml; using DTS.Common.Enums; using DTS.Common.Interface.DASFactory.Diagnostics; using DTS.Common.Utilities.Logging; namespace DTS.DASLib.Service { /// /// Base class for SQUIB channels. /// [Serializable] public class OutputSquibChannel : AnalogOutputDASChannel, IComparable { public SquibFireMode[] SupportedSquibFireModes { get; set; } = { SquibFireMode.AC, SquibFireMode.CAP, SquibFireMode.CONSTANT, SquibFireMode.NONE }; public IDiagnosticResult Diagnostics { get { try { IDiagnosticResult[] allChannelDiagnostics; IEnumerable theseChannelDiagnostics; if (null == (allChannelDiagnostics = OwningModule.OwningDAS.ChannelDiagnosticsResults)) throw new InvalidDataException("No diagnostics available (for any channel)"); if (null == (theseChannelDiagnostics = (allChannelDiagnostics.Where(r => r.DASChannelNumber == Number)))) throw new NullReferenceException("No diagnostics available (for this channel)"); if (theseChannelDiagnostics.Count() > 1) throw new InvalidDataException("Several diagnostics results were found for the specified channel; only one was expected"); if (theseChannelDiagnostics.Count() < 1) { throw new NullReferenceException("No diagnostics available (for this channel)"); } return theseChannelDiagnostics.First(); } catch (Exception ex) { throw new ApplicationException("encountered problem getting diagnostics for channel ", ex); } } } public override string ToString() { if (!string.IsNullOrEmpty(SquibDescription.Trim())) return SquibDescription.Trim(); return base.ToString(); } int IComparable.CompareTo(object o) { if (null == o) { return 1; } if (o is OutputSquibChannel) { return SquibDescription.CompareTo((o as OutputSquibChannel).SquibDescription); } return SquibDescription.CompareTo(o.ToString()); } public SquibFireMode FireMode { get; set; } = SquibFireMode.NONE; public SquibMeasurementType MeasurementType { get; set; } = SquibMeasurementType.NONE; public bool BypassCurrentFilter { get; set; } = false; public bool BypassVoltageFilter { get; set; } = false; public double SquibToleranceLow { get; set; } = 0D; public double SquibToleranceHigh { get; set; } = 0D; public double SquibOutputCurrent { get; set; } = 0D; public double SquibMeasuredOhms { get; set; } = 0D; public bool SquibFiredValid { get; set; } = false; public bool SquibFiredPassed { get; set; } = false; public double DelayMS { get; set; } = 0D; public double DurationMS { get; set; } = 0D; public string SquibDescription { get; set; } = ""; public string ISOCode { get; set; } = ""; public string ChannelId { get; set; } public string ChannelName2 { get; set; } public string HardwareChannelName { get; set; } public bool LimitDuration { get; set; } public short PreTestDataZeroLevelADC { get; set; } public double ScaleFactorMv { get; set; } = 0D; public bool LocalOnly { get; set; } = false; public string LastModifiedBy { get; set; } public string Sensor { get; set; } public string SerialNumber { get; set; } = ""; /// /// controls the frequency of software filters for squib channels /// 8747 - TDC by default will filter at 1650hz /// public double SoftwareFilterFrequency { get; set; } public OutputSquibChannel(XmlReader reader) { SupportedSquibFireModes = new[] { SquibFireMode.AC, SquibFireMode.CAP, SquibFireMode.CONSTANT, SquibFireMode.NONE }; IDs = new[] { new EID() }; ReadXml(reader); } public OutputSquibChannel(DASModule owner, int channelNumber) : base(owner, channelNumber) { SupportedSquibFireModes = new[] { SquibFireMode.AC, SquibFireMode.CAP, SquibFireMode.CONSTANT, SquibFireMode.NONE }; IDs = new[] { new EID() }; } public OutputSquibChannel() { SupportedSquibFireModes = new[] { SquibFireMode.AC, SquibFireMode.CAP, SquibFireMode.CONSTANT, SquibFireMode.NONE }; IDs = new[] { new EID() }; } public override void WriteXmlCRC32(XmlWriter writer) { base.WriteXmlCRC32(writer); XMLHelper.PutBool(writer, "BypassCurrentFilter", BypassCurrentFilter); XMLHelper.PutBool(writer, "BypassVoltageFilter", BypassVoltageFilter); XMLHelper.PutDouble(writer, "DelayMS", DelayMS); XMLHelper.PutDouble(writer, "DurationMS", DurationMS); XMLHelper.PutString(writer, "FireMode", FireMode.ToString()); XMLHelper.PutString(writer, "ISOCode", ISOCode); XMLHelper.PutString(writer, "MeasurementType", MeasurementType.ToString()); XMLHelper.PutString(writer, "SquibDescription", SquibDescription); XMLHelper.PutString(writer, "ChannelName2", ChannelName2); XMLHelper.PutString(writer, "ChannelId", ChannelId); XMLHelper.PutString(writer, "ChannelGroupName", ChannelGroupName); XMLHelper.PutString(writer, "HardwareChannelName", HardwareChannelName); XMLHelper.PutDouble(writer, "SquibOutputCurrent", SquibOutputCurrent); XMLHelper.PutDouble(writer, "SquibToleranceHigh", SquibToleranceHigh); XMLHelper.PutDouble(writer, "SquibToleranceLow", SquibToleranceLow); XMLHelper.PutBool(writer, "LimitDuration", LimitDuration); XMLHelper.PutString(writer, "ArticleId", ""); XMLHelper.PutString(writer, "SupportedSquibFireModes", GetSerializedSupportedSquibFireModes()); XMLHelper.PutDouble(writer, "SoftwareFilterFrequency", SoftwareFilterFrequency); XMLHelper.PutString(writer, "Sensor", Sensor); } private readonly string _SEPARATOR = "@"; public override void WriteXml(XmlWriter writer) { base.WriteXml(writer); XMLHelper.PutBool(writer, "BypassCurrentFilter", BypassCurrentFilter); XMLHelper.PutBool(writer, "BypassVoltageFilter", BypassVoltageFilter); XMLHelper.PutDouble(writer, "DelayMS", DelayMS); XMLHelper.PutDouble(writer, "DurationMS", DurationMS); XMLHelper.PutString(writer, "FireMode", FireMode.ToString()); XMLHelper.PutString(writer, "ISOCode", ISOCode); XMLHelper.PutString(writer, "MeasurementType", MeasurementType.ToString()); XMLHelper.PutString(writer, "SquibDescription", SquibDescription); XMLHelper.PutString(writer, "ChannelName2", ChannelName2); XMLHelper.PutString(writer, "ChannelId", ChannelId); XMLHelper.PutString(writer, "ChannelGroupName", ChannelGroupName); XMLHelper.PutString(writer, "HardwareChannelName", HardwareChannelName); XMLHelper.PutBool(writer, "SquibFirePassed", SquibFiredPassed); XMLHelper.PutBool(writer, "SquibFireValid", SquibFiredValid); XMLHelper.PutDouble(writer, "SquibOhms", SquibMeasuredOhms); XMLHelper.PutDouble(writer, "SquibOutputCurrent", SquibOutputCurrent); XMLHelper.PutDouble(writer, "SquibToleranceHigh", SquibToleranceHigh); XMLHelper.PutDouble(writer, "SquibToleranceLow", SquibToleranceLow); XMLHelper.PutBool(writer, "LimitDuration", LimitDuration); XMLHelper.PutDouble(writer, "ScaleFactorMv", ScaleFactorMv); XMLHelper.PutInt(writer, "PreTestDataZeroLevelADC", PreTestDataZeroLevelADC); XMLHelper.PutString(writer, "ArticleId", ""); XMLHelper.PutString(writer, "SupportedSquibFireModes", GetSerializedSupportedSquibFireModes()); XMLHelper.PutDouble(writer, "SoftwareFilterFrequency", SoftwareFilterFrequency); XMLHelper.PutString(writer, "Sensor", Sensor); XMLHelper.PutString(writer, "SerialNumber", SerialNumber); } public int Version { get; set; } public DateTime Date { get; set; } public string GetSerializedSupportedSquibFireModes() { var sb = new StringBuilder(); foreach (var s in SupportedSquibFireModes) { if (sb.Length > 0) { sb.Append(_SEPARATOR); } sb.Append(s); } return sb.ToString(); } private SquibFireMode[] DeserializeSquibFireModes(string s) { var modes = new List(); var tokens = s.Split(new[] { _SEPARATOR }, StringSplitOptions.None); foreach (var token in tokens) { if (Enum.TryParse(token, out SquibFireMode mode)) { modes.Add(mode); } } return modes.ToArray(); } private const string BYPASSCURRENTFILTER_TAG = "BypassCurrentFilter"; private const string BYPASSVOLTAGEFILTER_TAG = "BypassVoltageFilter"; private const string DELAYMS_TAG = "DelayMS"; private const string DURATIONMS_TAG = "DurationMS"; private const string FIREMODE_TAG = "FireMode"; private const string ISOCODE_TAG = "ISOCode"; private const string MEASUREMENTTYPE_TAG = "MeasurementType"; private const string SQUIBDESCRIPTION_TAG = "SquibDescription"; private const string CHANNELID_TAG = "ChannelId"; private const string CHANNELGROUPNAME_TAG = "ChannelGroupName"; private const string CHANNELNAME2_TAG = "ChannelName2"; private const string HARDWARECHANNELNAME_TAG = "HardwareChannelName"; private const string SQUIBFIREPASSED_TAG = "SquibFirePassed"; private const string SQUIBFIREVALID_TAG = "SquibFireValid"; private const string SQUIBOHMS_TAG = "SquibOhms"; private const string SQUIBOUTPUTCURRENT_TAG = "SquibOutputCurrent"; private const string SQUIBTOLERANCEHIGH_TAG = "SquibToleranceHigh"; private const string SQUIBTOLERANCELOW_TAG = "SquibToleranceLow"; private const string LIMITDURATION_TAG = "LimitDuration"; private const string SCALEFACTORMV_TAG = "ScaleFactorMv"; private const string PRETESTDATAZEROLEVELADC_TAG = "PreTestDataZeroLevelADC"; private const string ARTICLEID_TAG = "ArticleId"; private const string SUPPORTEDSQUIBFIREMODES_TAG = "SupportedSquibFireModes"; private const string SOFTWAREFILTERHZ_TAG = "SoftwareFilterFrequency"; private const string SENSOR_TAG = "Sensor"; private const string SERIALNUMBER_TAG = "SerialNumber"; protected override void HandleElement(XmlReader reader) { base.HandleElement(reader); if (reader.NodeType == XmlNodeType.Element) { switch (reader.Name) { case BYPASSCURRENTFILTER_TAG: BypassCurrentFilter = XMLHelper.GetBool(reader); break; case BYPASSVOLTAGEFILTER_TAG: BypassVoltageFilter = XMLHelper.GetBool(reader); break; case DELAYMS_TAG: DelayMS = XMLHelper.GetDouble(reader); break; case DURATIONMS_TAG: DurationMS = XMLHelper.GetDouble(reader); break; case FIREMODE_TAG: String mode = XMLHelper.GetString(reader); try { FireMode = (SquibFireMode)Enum.Parse(typeof(SquibFireMode), mode); } catch (Exception ex) { APILogger.Log("Failed to load firemode ", mode, ex); } break; case ISOCODE_TAG: ISOCode = XMLHelper.GetString(reader); break; case MEASUREMENTTYPE_TAG: string measurementType = XMLHelper.GetString(reader); try { MeasurementType = (SquibMeasurementType)Enum.Parse(typeof(SquibMeasurementType), measurementType); } catch (Exception ex) { APILogger.Log("Failed to load MeasurementType ", measurementType, ex); } break; case SQUIBDESCRIPTION_TAG: SquibDescription = XMLHelper.GetString(reader); break; case CHANNELID_TAG: ChannelId = XMLHelper.GetString(reader); break; case SENSOR_TAG: Sensor = XMLHelper.GetString(reader); break; case SERIALNUMBER_TAG: SerialNumber = XMLHelper.GetString(reader); break; case CHANNELGROUPNAME_TAG: ChannelGroupName = XMLHelper.GetString(reader); break; case CHANNELNAME2_TAG: ChannelName2 = XMLHelper.GetString(reader); break; case HARDWARECHANNELNAME_TAG: HardwareChannelName = XMLHelper.GetString(reader); break; case SQUIBFIREPASSED_TAG: SquibFiredPassed = XMLHelper.GetBool(reader); break; case SQUIBFIREVALID_TAG: SquibFiredValid = XMLHelper.GetBool(reader); break; case SQUIBOHMS_TAG: SquibMeasuredOhms = XMLHelper.GetDouble(reader); break; case SQUIBOUTPUTCURRENT_TAG: SquibOutputCurrent = XMLHelper.GetDouble(reader); break; case SQUIBTOLERANCEHIGH_TAG: SquibToleranceHigh = XMLHelper.GetDouble(reader); break; case SQUIBTOLERANCELOW_TAG: SquibToleranceLow = XMLHelper.GetDouble(reader); break; case LIMITDURATION_TAG: LimitDuration = XMLHelper.GetBool(reader); break; case SCALEFACTORMV_TAG: ScaleFactorMv = XMLHelper.GetDouble(reader); break; case PRETESTDATAZEROLEVELADC_TAG: PreTestDataZeroLevelADC = Convert.ToInt16(XMLHelper.GetInt(reader)); break; case ARTICLEID_TAG: //2021-05-21 - why aren't we using this id? -DTM _ = XMLHelper.GetString(reader); IDs = new EID[] { new EID() }; break; case SUPPORTEDSQUIBFIREMODES_TAG: string s = XMLHelper.GetString(reader); SupportedSquibFireModes = DeserializeSquibFireModes(s); break; case SOFTWAREFILTERHZ_TAG: var freq = XMLHelper.GetOptionalDouble(reader); if (null != freq) { SoftwareFilterFrequency = (double)freq; } break; default: // let child handle it break; } } } public override bool IsConfigured() { return FireMode != SquibFireMode.NONE && !string.IsNullOrEmpty(SquibDescription); } public const double DEFAULT_MIN_FIRE_DURATION_MS = 0.20; // FB 5439; don't allow user to set below min duration public const double DEFAULT_MIN_FIRE_DELAY_MS = 0.0D; // FB 5827 Saving squibs with invalid delay settings public const double DEFAULT_DEFINEINTEST_FIRE_DELAY_FLAG = -1; // FB 14623 A flag which specifies the Delay has to be defined in the test setup, also when updating please update the -1 check for SquibDelay in EditSquibControl public const double DEFAULT_MAX_FIRE_DURATION_MS = 25.5D; //stole it out of the UI in datapro public const double DEFAULT_MAX_FIRE_DELAY_MS = 99000D; //also stolen } }