/// <summary> /// LoadKeys <see cref="Phasor"/> information as an <see cref="ObservableCollection{T}"/> style list. /// </summary> /// <param name="database"><see cref="AdoDataConnection"/> to connection to database.</param> /// <param name="filter">The type of phasors to load</param> /// <returns>Collection of <see cref="int"/>.</returns> public static IList <int> LoadKeys(AdoDataConnection database, PhasorType filter = PhasorType.Any) { var createdConnection = false; try { createdConnection = CreateConnection(ref database); var phasorList = new List <int>(); var query = "SELECT ID FROM Phasor"; if (filter != PhasorType.Any) { query += string.Format(" Where Type = '{0}'", filter == PhasorType.Voltage ? "V" : "I"); } var calculationTable = database.Connection.RetrieveData(database.AdapterType, query, DefaultTimeout); foreach (DataRow row in calculationTable.Rows) { phasorList.Add(row.ConvertField <int>("Id")); } return(phasorList); } finally { if (createdConnection && database != null) { database.Dispose(); } } }
/// <summary> /// Creates a new <see cref="PhasorDefinitionBase"/> from serialization parameters. /// </summary> /// <param name="info">The <see cref="SerializationInfo"/> with populated with data.</param> /// <param name="context">The source <see cref="StreamingContext"/> for this deserialization.</param> protected PhasorDefinitionBase(SerializationInfo info, StreamingContext context) : base(info, context) { // Deserialize phasor definition m_type = (PhasorType)info.GetValue("type", typeof(PhasorType)); m_voltageReference = (IPhasorDefinition)info.GetValue("voltageReference", typeof(IPhasorDefinition)); }
/// <summary> /// The designated constructor for the <see cref="LinearStateEstimator.Measurements.PhasorMeasurement"/> class. /// </summary> /// <param name="magnitudeKey">The openPDC input measurement key for the <see cref="LinearStateEstimator.Measurements.PhasorBase.Magnitude"/> of the <see cref="LinearStateEstimator.Measurements.PhasorMeasurement"/>.</param> /// <param name="angleKey">The openPDC input measurement key for the <see cref="LinearStateEstimator.Measurements.PhasorBase.AngleInDegrees"/> of the <see cref="LinearStateEstimator.Measurements.PhasorMeasurement"/>.</param> /// <param name="type">Specifies whether the phasor measurement is a current phasor or a /// voltage phasor or complex power with the <see cref="LinearStateEstimator.Measurements.PhasorType"/> enumeration, either <see cref="LinearStateEstimator.Measurements.PhasorType.VoltagePhasor"/>, /// <see cref="LinearStateEstimator.Measurements.PhasorType.CurrentPhasor"/>, or <see cref="LinearStateEstimator.Measurements.PhasorType.ComplexPower"/>.</param> /// <param name="baseKV">The <see cref="LinearStateEstimator.Modeling.VoltageLevel"/> of the phasor measurement.</param> /// <param name="variance">The measurement variance in per unit.</param> /// <param name="rcf">The <b>Ratio Correction Factor (RCF)</b> for the measurement.</param> /// <param name="pacf">The <b>Phase Angle Correction Factor (PACF)</b> for the measurement in degrees.</param> /// <param name="calibrationSetting">The <see cref="LinearStateEstimator.Calibration.CalibrationSetting"/> type for the <see cref="LinearStateEstimator.Measurements.PhasorMeasurement"/>. Determines how the measurement is included in the calibration algorithm.</param> public PhasorMeasurement(string magnitudeKey, string angleKey, PhasorType type, VoltageLevel baseKV, double variance, double rcf, double pacf, CalibrationSetting calibrationSetting) : base(magnitudeKey, angleKey, type, baseKV) { m_measurementVariance = variance; m_rcf = rcf; m_pacf = pacf; m_calibrationSetting = calibrationSetting; }
/// <summary> /// Creates a new <see cref="PhasorDefinitionBase"/> from specified parameters. /// </summary> /// <param name="parent">The <see cref="IConfigurationCell"/> parent of this <see cref="PhasorDefinitionBase"/>.</param> /// <param name="label">The label of this <see cref="PhasorDefinitionBase"/>.</param> /// <param name="scale">The integer scaling value of this <see cref="PhasorDefinitionBase"/>.</param> /// <param name="offset">The offset of this <see cref="PhasorDefinitionBase"/>.</param> /// <param name="type">The <see cref="PhasorType"/> of this <see cref="PhasorDefinitionBase"/>.</param> /// <param name="voltageReference">The associated <see cref="IPhasorDefinition"/> that represents the voltage reference (if any).</param> protected PhasorDefinitionBase(IConfigurationCell parent, string label, uint scale, double offset, PhasorType type, IPhasorDefinition voltageReference) : base(parent, label, scale, offset) { m_type = type; if (type == PhasorType.Voltage) m_voltageReference = this; else m_voltageReference = voltageReference; }
/// <summary> /// Designated constructor method for the <see cref="PhasorBase"/> object. /// </summary> /// <param name="magnitudeKey">The measurement key which corresponds to the magnitude of the phasor.</param> /// <param name="angleKey">The measurement key which corresponds to the angle of the phasor.</param> /// <param name="type">The <see cref="PhasorType"/> of the phasor.</param> /// <param name="baseKV">The <see cref="VoltageLevel"/> of the phasor.</param> public PhasorBase(string magnitudeKey, string angleKey, PhasorType type, VoltageLevel baseKV) { m_magnitudeValueWasReported = false; m_angleValueWasReported = false; m_magnitude = 0; m_angleInDegrees = 0; m_magnitudeKey = magnitudeKey; m_angleKey = angleKey; m_type = type; m_baseKV = baseKV; }
/// <summary> /// Designated constructor method for the <see cref="PhasorBase"/> object. /// </summary> /// <param name="magnitudeKey">The measurement key which corresponds to the magnitude of the phasor.</param> /// <param name="angleKey">The measurement key which corresponds to the angle of the phasor.</param> /// <param name="type">The <see cref="PhasorType"/> of the phasor.</param> /// <param name="baseKV">The <see cref="VoltageLevel"/> of the phasor.</param> public PhasorBase(string magnitudeKey, string angleKey, PhasorType type, double baseKV) { m_magnitudeValueWasReported = false; m_angleValueWasReported = false; m_magnitude = 0; m_angleInDegrees = 0; m_magnitudeKey = magnitudeKey; m_angleKey = angleKey; m_type = type; m_voltageLevel = baseKV; //m_shouldSerializeData = false; }
/// <summary> /// Creates a new <see cref="PhasorDefinitionBase"/> from specified parameters. /// </summary> /// <param name="parent">The <see cref="IConfigurationCell"/> parent of this <see cref="PhasorDefinitionBase"/>.</param> /// <param name="label">The label of this <see cref="PhasorDefinitionBase"/>.</param> /// <param name="scale">The integer scaling value of this <see cref="PhasorDefinitionBase"/>.</param> /// <param name="offset">The offset of this <see cref="PhasorDefinitionBase"/>.</param> /// <param name="type">The <see cref="PhasorType"/> of this <see cref="PhasorDefinitionBase"/>.</param> /// <param name="voltageReference">The associated <see cref="IPhasorDefinition"/> that represents the voltage reference (if any).</param> protected PhasorDefinitionBase(IConfigurationCell parent, string label, uint scale, double offset, PhasorType type, IPhasorDefinition voltageReference) : base(parent, label, scale, offset) { m_type = type; if (type == PhasorType.Voltage) { m_voltageReference = this; } else { m_voltageReference = voltageReference; } }
/// <summary> /// Creates a new <see cref="PhasorDefinition3"/> from specified parameters. /// </summary> /// <param name="parent">The <see cref="ConfigurationCell3"/> parent of this <see cref="PhasorDefinition3"/>.</param> /// <param name="label">The label of this <see cref="PhasorDefinition3"/>.</param> /// <param name="scale">The integer scaling value of this <see cref="PhasorDefinition3"/>.</param> /// <param name="offset">The offset of this <see cref="PhasorDefinition3"/>.</param> /// <param name="type">The <see cref="PhasorType"/> of this <see cref="PhasorDefinition3"/>.</param> /// <param name="voltageReference">The associated <see cref="IPhasorDefinition"/> that represents the voltage reference (if any).</param> /// <param name="phase">The phase of this <see cref="PhasorDefinition3"/>.</param> public PhasorDefinition3(ConfigurationCell3 parent, string label, uint scale, double offset, PhasorType type, PhasorDefinition3 voltageReference, char phase) : base(parent, label, scale, offset) { PhasorType = type; m_voltageReference = type == PhasorType.Voltage ? this : voltageReference; PhasorComponent = phase switch { 'A' => PhasorComponent.PhaseA, 'B' => PhasorComponent.PhaseB, 'C' => PhasorComponent.PhaseC, '+' => PhasorComponent.PositiveSequence, '-' => PhasorComponent.NegativeSequence, '0' => PhasorComponent.ZeroSequence, _ => PhasorComponent.PositiveSequence,// If phase is not a value IEEE C37.118-2011 supports, default to positive sequence }; }
/// <summary> /// Creates a new <see cref="PhasorDefinition3"/> from specified parameters. /// </summary> /// <param name="parent">The <see cref="ConfigurationCell3"/> parent of this <see cref="PhasorDefinition3"/>.</param> /// <param name="label">The label of this <see cref="PhasorDefinition3"/>.</param> /// <param name="scale">The integer scaling value of this <see cref="PhasorDefinition3"/>.</param> /// <param name="offset">The offset of this <see cref="PhasorDefinition3"/>.</param> /// <param name="type">The <see cref="PhasorType"/> of this <see cref="PhasorDefinition3"/>.</param> /// <param name="voltageReference">The associated <see cref="IPhasorDefinition"/> that represents the voltage reference (if any).</param> /// <param name="phase">The phase of this <see cref="PhasorDefinition3"/>.</param> public PhasorDefinition3(ConfigurationCell3 parent, string label, uint scale, double offset, PhasorType type, PhasorDefinition3 voltageReference, char phase) : base(parent, label, scale, offset) { PhasorType = type; m_voltageReference = type == PhasorType.Voltage ? this : voltageReference; switch (phase) { case 'A': PhasorComponent = PhasorComponent.PhaseA; break; case 'B': PhasorComponent = PhasorComponent.PhaseB; break; case 'C': PhasorComponent = PhasorComponent.PhaseC; break; case '+': PhasorComponent = PhasorComponent.PositiveSequence; break; case '-': PhasorComponent = PhasorComponent.NegativeSequence; break; case '0': PhasorComponent = PhasorComponent.ZeroSequence; break; default: // If phase is not a value IEEE C37.118-2011 supports, default to positive sequence PhasorComponent = PhasorComponent.PositiveSequence; break; } }
/// <summary> /// Creates a new <see cref="PhasorDefinition"/> from specified parameters. /// </summary> /// <param name="parent">The <see cref="ConfigurationCell"/> parent of this <see cref="PhasorDefinition"/>.</param> /// <param name="label">The label of this <see cref="PhasorDefinition"/>.</param> /// <param name="type">The <see cref="PhasorType"/> of this <see cref="PhasorDefinition"/>.</param> /// <param name="voltageReference">The associated <see cref="IPhasorDefinition"/> that represents the voltage reference (if any).</param> public PhasorDefinition(ConfigurationCell parent, string label, PhasorType type, PhasorDefinition voltageReference) : base(parent, label, 1, 0.0D, type, voltageReference) { }
/// <summary> /// Creates a new <see cref="PhasorDefinition"/> from specified parameters. /// </summary> /// <param name="parent">The <see cref="ConfigurationCell"/> parent of this <see cref="PhasorDefinition"/>.</param> /// <param name="label">The label of this <see cref="PhasorDefinition"/>.</param> /// <param name="scale">The integer scaling value of this <see cref="PhasorDefinition"/>.</param> /// <param name="offset">The offset of this <see cref="PhasorDefinition"/>.</param> /// <param name="type">The <see cref="PhasorType"/> of this <see cref="PhasorDefinition"/>.</param> /// <param name="voltageReference">The associated <see cref="IPhasorDefinition"/> that represents the voltage reference (if any).</param> public PhasorDefinition(ConfigurationCell parent, string label, uint scale, double offset, PhasorType type, PhasorDefinition voltageReference) : base(parent, label, scale, offset, type, voltageReference) { }
/// <summary> /// Creates a new <see cref="PhasorDefinition"/> from specified parameters. /// </summary> /// <param name="parent">The <see cref="ConfigurationCell"/> parent of this <see cref="PhasorDefinition"/>.</param> /// <param name="label">The label of this <see cref="PhasorDefinition"/>.</param> /// <param name="scale">The integer scaling value of this <see cref="PhasorDefinition"/>.</param> /// <param name="type">The <see cref="PhasorType"/> of this <see cref="PhasorDefinition"/>.</param> /// <param name="voltageReference">The associated <see cref="IPhasorDefinition"/> that represents the voltage reference (if any).</param> /// <param name="originalSourceIndex">The original source phasor index, if applicable.</param> /// <param name="phase">The phase of this <see cref="PhasorDefinition"/>.</param> public PhasorDefinition(ConfigurationCell parent, string label, uint scale, PhasorType type, PhasorDefinition voltageReference, int originalSourceIndex = -1, char phase = '+') : base(parent, label, scale, 0.0D, type, voltageReference) { OriginalSourceIndex = originalSourceIndex; Phase = phase; }
/// <summary> /// Creates a <see cref="Phasor"/> of the specified <paramref name="type"/> from the given <see cref="ComplexNumber"/>. /// </summary> /// <param name="type">Type of phasor, i.e., current or voltage.</param> /// <param name="z"><see cref="ComplexNumber"/> to be copied.</param> public Phasor(PhasorType type, ComplexNumber z) : this() { Type = type; Value = z; }
/// <summary> /// Creates a <see cref="Phasor"/> of the specified <paramref name="type"/> from the given polar values. /// </summary> /// <param name="type">Type of phasor, i.e., current or voltage.</param> /// <param name="angle">The <see cref="Angle"/> component, in radians, of the <see cref="ComplexNumber"/>.</param> /// <param name="magnitude">The magnitude (or absolute value) component of the <see cref="ComplexNumber"/>.</param> public Phasor(PhasorType type, Angle angle, double magnitude) : this() { Type = type; Value = new ComplexNumber(angle, magnitude); }
/// <summary> /// LoadKeys <see cref="Phasor"/> information as an <see cref="ObservableCollection{T}"/> style list. /// </summary> /// <param name="database"><see cref="AdoDataConnection"/> to connection to database.</param> /// <param name="filter">The type of phasors to load</param> /// <returns>Collection of <see cref="int"/>.</returns> public static IList<int> LoadKeys(AdoDataConnection database, PhasorType filter = PhasorType.Any) { var createdConnection = false; try { createdConnection = CreateConnection(ref database); var phasorList = new List<int>(); var query = "SELECT ID FROM Phasor"; if (filter != PhasorType.Any) { query += string.Format(" Where Type = '{0}'", filter == PhasorType.Voltage ? "V" : "I"); } var calculationTable = database.Connection.RetrieveData(database.AdapterType, query, DefaultTimeout); foreach (DataRow row in calculationTable.Rows) { phasorList.Add(row.ConvertField<int>("Id")); } return phasorList; } finally { if (createdConnection && database != null) database.Dispose(); } }
/// <summary> /// The designated constructor for the <see cref="LinearStateEstimator.Measurements.PhasorEstimate"/> class. /// </summary> /// <param name="magnitudeKey">The openPDC input measurement key for the <see cref="LinearStateEstimator.Measurements.PhasorBase.Magnitude"/> of the <see cref="LinearStateEstimator.Measurements.PhasorEstimate"/>.</param> /// <param name="angleKey">The openPDC input measurement key for the <see cref="LinearStateEstimator.Measurements.PhasorBase.Magnitude"/> of the <see cref="LinearStateEstimator.Measurements.PhasorEstimate"/>.</param> /// <param name="type">Specifies whether the phasor measurement is a current phasor or a voltage phasor or complex power with the <see cref="LinearStateEstimator.Measurements.PhasorType"/> enumeration, either <see cref="LinearStateEstimator.Measurements.PhasorType.VoltagePhasor"/>, <see cref="LinearStateEstimator.Measurements.PhasorType.CurrentPhasor"/>, or <see cref="LinearStateEstimator.Measurements.PhasorType.ComplexPower"/>.</param> /// <param name="baseKV">The <see cref="LinearStateEstimator.Modeling.VoltageLevel"/> of the phasor measurement.</param> public PhasorEstimate(string magnitudeKey, string angleKey, PhasorType type, VoltageLevel baseKV) : base(magnitudeKey, angleKey, type, baseKV) { }
/// <summary> /// A constructor for the <see cref="SynchrophasorAnalytics.Measurements.PhasorMeasurement"/> which only specifies the measurement keys, phasor type, and base KV. /// </summary> /// <param name="magnitudeKey">The openPDC input measurement key for the <see cref="SynchrophasorAnalytics.Measurements.PhasorBase.Magnitude"/> of the <see cref="SynchrophasorAnalytics.Measurements.PhasorMeasurement"/>.</param> /// <param name="angleKey">The openPDC input measurement key for the <see cref="SynchrophasorAnalytics.Measurements.PhasorBase.AngleInDegrees"/> of the <see cref="SynchrophasorAnalytics.Measurements.PhasorMeasurement"/>.</param> /// <param name="type">Specifies whether the phasor measurement is a current phasor or a /// voltage phasor or complex power with the <see cref="SynchrophasorAnalytics.Measurements.PhasorType"/> enumeration, either <see cref="SynchrophasorAnalytics.Measurements.PhasorType.VoltagePhasor"/>, /// <see cref="PhasorType.CurrentPhasor"/>, or <see cref="SynchrophasorAnalytics.Measurements.PhasorType.ComplexPower"/>.</param> /// <param name="baseKV">The <see cref="SynchrophasorAnalytics.Modeling.VoltageLevel"/> of the phasor measurement.</param> public PhasorMeasurement(string magnitudeKey, string angleKey, PhasorType type, VoltageLevel baseKV) : base(magnitudeKey, angleKey, type, baseKV) { }
// Generate a more descriptive phasor label including line phase and phasor type private string GeneratePhasorLabel(string phasorLabel, char phase, PhasorType type) { StringBuilder phaseSuffix = new StringBuilder(); if (string.IsNullOrWhiteSpace(phasorLabel)) phasorLabel = "Phasor"; if (m_addPhaseLabelSuffix) { string suffix = phasorLabel.TruncateLeft(4).TruncateRight(3).ToUpper(); bool appended = false; // Add phase suffix if it's not already there switch (phase) { case '+': // Positive sequence if (suffix != " +S") { phaseSuffix.Append(" +S"); appended = true; } break; case '-': // Negative sequence if (suffix != " -S") { phaseSuffix.Append(" -S"); appended = true; } break; case '0': // Zero sequence if (suffix != " 0S") { phaseSuffix.Append(" 0S"); appended = true; } break; case 'A': // A-Phase if (suffix != " AP") { phaseSuffix.Append(" AP"); appended = true; } break; case 'B': // B-Phase if (suffix != " BP") { phaseSuffix.Append(" BP"); appended = true; } break; case 'C': // C-Phase if (suffix != " CP") { phaseSuffix.Append(" CP"); appended = true; } break; } if (appended) { // Return label with appended phase suffix phaseSuffix.Append(type == PhasorType.Voltage ? 'V' : 'I'); return phasorLabel.TruncateRight(12) + phaseSuffix; } } // Return original label return phasorLabel; }
/// <summary> /// A constructor with default values except for the <see cref="PhasorType"/> and the <see cref="VoltageLevel"/> of the phasor. /// </summary> /// <param name="type">The <see cref="PhasorType"/> of the phasor.</param> /// <param name="baseKV">The <see cref="VoltageLevel"/> of the phasor.</param> public PhasorBase(PhasorType type, VoltageLevel baseKV) : this("Undefined", "Undefined", type, baseKV) { }
/// <summary> /// A constructor for the <see cref="LinearStateEstimator.Measurements.PhasorMeasurement"/> which only specifies the measurement keys, phasor type, base KV and measurement variance. /// </summary> /// <param name="magnitudeKey">The openPDC input measurement key for the <see cref="LinearStateEstimator.Measurements.PhasorBase.Magnitude"/> of the <see cref="LinearStateEstimator.Measurements.PhasorMeasurement"/>.</param> /// <param name="angleKey">The openPDC input measurement key for the <see cref="LinearStateEstimator.Measurements.PhasorBase.AngleInDegrees"/> of the <see cref="LinearStateEstimator.Measurements.PhasorMeasurement"/>.</param> /// <param name="type">Specifies whether the phasor measurement is a current phasor or a voltage phasor or complex power with the <see cref="LinearStateEstimator.Measurements.PhasorType"/> enumeration, either <see cref="LinearStateEstimator.Measurements.PhasorType.VoltagePhasor"/>, <see cref="LinearStateEstimator.Measurements.PhasorType.CurrentPhasor"/>, or <see cref="LinearStateEstimator.Measurements.PhasorType.ComplexPower"/>.</param> /// <param name="baseKV">The <see cref="LinearStateEstimator.Modeling.VoltageLevel"/> of the phasor measurement.</param> /// <param name="variance">The measurement variance in per unit.</param> public PhasorMeasurement(string magnitudeKey, string angleKey, PhasorType type, VoltageLevel baseKV, double variance) : this(magnitudeKey, angleKey, type, baseKV, variance, 1, 0) { }
// Static Methods // Generate a descriptive phasor label private static string GeneratePhasorLabel(string phasorlabel, char phaseType, PhasorType phasorType) { StringBuilder label = new StringBuilder(); label.Append(phasorlabel); switch (phaseType) { case '+': // Positive sequence label.Append(" +S"); break; case '-': // Negative sequence label.Append(" -S"); break; case '0': // Zero sequence label.Append(" 0S"); break; case 'A': // A-Phase label.Append(" AP"); break; case 'B': // B-Phase label.Append(" BP"); break; case 'C': // C-Phase label.Append(" CP"); break; default: // Undetermined label.Append(" ??"); break; } label.Append(phasorType == PhasorType.Voltage ? 'V' : 'I'); return label.ToString(); }
/// <summary> /// A constructor with default values except for the <see cref="PhasorType"/> and the <see cref="VoltageLevel"/> of the phasor. /// </summary> /// <param name="type">The <see cref="PhasorType"/> of the phasor.</param> /// <param name="baseKV">The <see cref="VoltageLevel"/> of the phasor.</param> public PhasorBase(PhasorType type, double baseKV) : this("Undefined", "Undefined", type, baseKV) { }
public static ConfigurationFrame Parse(string configFile, ShowMessageFunc showMessage) { XDocument config = XDocument.Load(configFile); // Load all "SettingsGroup" elements XElement[] settingsGroups = config.Descendants("SettingsGroup").ToArray(); // Load nominal frequency from "Globals" setting group string nominalFrequencySetting = settingsGroups .WhereAttribute("Type").Is("Globals") .Descendants("Setting") .WhereAttribute("Name").Is("Frequency") .GetValue(DefaultLineFrequency); LineFrequency nominalFrequency = nominalFrequencySetting.Equals("50") ? LineFrequency.Hz50 : LineFrequency.Hz60; // Get server gateway instances XElement[] serverGatewayInstances = settingsGroups .WhereAttribute("Type").Is("ServerGateway") .Descendants("Instance") .WhereAttribute("Type").Is("Server") .ToArray(); if (serverGatewayInstances.Length == 0) { throw new NullReferenceException($"No server gateway instances where defined in \"{Path.GetFileName(configFile)}\"."); } int enabledInstanceCount = serverGatewayInstances .Count(elem => elem.Descendants("Setting") .WhereAttribute("Name").Is("Enabled") .GetValue(false)); XElement serverGatewayInstance = null; if (enabledInstanceCount == 0) { if (showMessage($"No enabled server gateway instances where found in \"{Path.GetFileName(configFile)}\", do you want to load a disabled instance?", "No Enabled Server Gateways Found", MessageBoxButtons.YesNo, MessageBoxIcon.Question) != DialogResult.Yes) { throw new NullReferenceException("Failed to load an enabled server gateway instance."); } serverGatewayInstance = serverGatewayInstances.FirstOrDefault(); } else { if (enabledInstanceCount > 1 && showMessage($"Found {enabledInstanceCount:N0} enabled server gateway instances in \"{Path.GetFileName(configFile)}\", do you want to load first enabled instance?", "Multiple Enabled Server Gateways Found", MessageBoxButtons.YesNo, MessageBoxIcon.Question) != DialogResult.Yes) { throw new NullReferenceException("Failed to load an enabled server gateway instance."); } serverGatewayInstance = serverGatewayInstances .FirstOrDefault(elem => elem.Descendants("Setting") .WhereAttribute("Name").Is("Enabled") .GetValue(false)); } if (serverGatewayInstance is null) { throw new NullReferenceException("Failed to load any server gateway instance."); } // Load all "Setting" elements from server gateway instance XElement[] serverGatewaySettings = serverGatewayInstance .Descendants("Setting") .ToArray(); // Load server name setting string serverName = Path.GetFileNameWithoutExtension(configFile).GetCleanAcronym(); // Load ID code setting ushort idCode = serverGatewaySettings .WhereAttribute("Name").Is("ID") .GetValue(DefaultIDCode); // Load frame rate setting ushort frameRate = serverGatewaySettings .WhereAttribute("Name").Is("DataRate") .GetValue(DefaultFrameRate); // With an ID code, frame rate and server name, there's enough info to create a config frame ConfigurationFrame configFrame = new ConfigurationFrame(idCode, frameRate, serverName); // Load all output PMUs IEnumerable <XElement> pmus = serverGatewaySettings .WhereAttribute("Name").Is("OutputTags") .Descendants("PMU"); foreach (XElement pmu in pmus) { string name = pmu.Attribute("Name")?.Value; if (string.IsNullOrWhiteSpace(name)) { continue; } if (!ushort.TryParse(pmu.Attribute("ID")?.Value, out idCode)) { continue; } // With a name and an ID code, there's enough info to create a config cell representing the PMU ConfigurationCell configCell = new ConfigurationCell(configFrame, name, idCode) { NominalFrequency = nominalFrequency, }; // Load all PMU tags XElement[] tags = pmu.Descendants("Tag").ToArray(); // Load all phasor tags IEnumerable <XElement> phasors = tags .WhereAttribute("Type").Is("Phasor"); foreach (XElement phasor in phasors) { name = phasor.Attribute("Name")?.Value; if (string.IsNullOrWhiteSpace(name)) { continue; } string description = phasor.Attribute("Description")?.Value; string quantityType = phasor.Attribute("QuantityType")?.Value ?? DefaultPhasorType; PhasorType phasorType = quantityType.Equals("Current") ? PhasorType.Current : PhasorType.Voltage; string phaseSetting = phasor.Attribute("Phase")?.Value.Trim(); if (string.IsNullOrWhiteSpace(phaseSetting)) { phaseSetting = GuessPhase(phasor.Attribute("OriginalName")?.Value ?? name); } char phase = string.IsNullOrWhiteSpace(phaseSetting) ? DefaultPhase : TranslatePhase(phaseSetting[0]); if (string.IsNullOrWhiteSpace(description)) { description = $"{configCell.StationName} phase {phase} {phasorType.ToString().ToLowerInvariant()} phasor"; } configCell.PhasorDefinitions.Add(new PhasorDefinition(configCell, name, description, phasorType, phase)); } // Load all analog tags IEnumerable <XElement> analogs = tags .WhereAttribute("Type").Is("Analog"); foreach (XElement analog in analogs) { name = analog.Attribute("Name")?.Value; if (string.IsNullOrWhiteSpace(name)) { continue; } string description = analog.Attribute("Description")?.Value; if (string.IsNullOrWhiteSpace(description)) { description = $"{configCell.StationName} {name} analog value"; } configCell.AnalogDefinitions.Add(new AnalogDefinition(configCell, name, description)); } // Load all digital tags IEnumerable <XElement> digitals = tags .WhereAttribute("Type").Is("Digital"); foreach (XElement digital in digitals) { name = digital.Attribute("Name")?.Value; if (string.IsNullOrWhiteSpace(name)) { continue; } string description = digital.Attribute("Description")?.Value; if (string.IsNullOrWhiteSpace(description)) { description = $"{configCell.StationName} {name} digital value"; } configCell.DigitalDefinitions.Add(new DigitalDefinition(configCell, name, description)); } configFrame.Cells.Add(configCell); } // Get connection details configured for SEL PDC string transportProtocol = serverGatewaySettings .WhereAttribute("Name").Is("TransportProtocol") .GetValue(DefaultTransportProtocol) .ToUpperInvariant(); configFrame.TransportProtocol = transportProtocol; ushort commandPort = serverGatewaySettings .WhereAttribute("Name").Is("CommandPort") .GetValue(DefaultCommandPort); ushort dataPort = serverGatewaySettings .WhereAttribute("Name").Is("DataPort") .GetValue(DefaultDataPort); ushort port = serverGatewaySettings .WhereAttribute("Name").Is("Port") .GetValue(DefaultPort); bool multicastEnabled = serverGatewaySettings .WhereAttribute("Name").Is("MulticastEnabled") .GetValue(DefaultMulticastEnabled); string multicastGroup = serverGatewaySettings .WhereAttribute("Name").Is("MulticastGroup") .GetValue(DefaultMulticastGroup); // Setup MultiProtocolFrameParser style connection string Dictionary <string, string> getTcpSettings(bool commandChannel = false) { // Use of simple "protocol" key in commandChannel and separation of // server/port keys are required to create a proper "PmuConnection" // file that can be successfully parsed by the PMU Connection Tester return(new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase) { [commandChannel ? "protocol": nameof(TransportProtocol)] = nameof(TransportProtocol.Tcp), ["server"] = IPAddressToken, ["port"] = commandChannel ? $"{commandPort}" : $"{port}", ["isListener"] = "false", ["interface"] = "0.0.0.0" }); } Dictionary <string, string> settings = configFrame.Settings; settings[nameof(PhasorProtocol)] = nameof(PhasorProtocol.IEEEC37_118V1); if (transportProtocol == "TCP") { foreach (KeyValuePair <string, string> pair in getTcpSettings()) { settings[pair.Key] = pair.Value; } } else if (transportProtocol.StartsWith("UDP")) { settings[nameof(TransportProtocol)] = nameof(TransportProtocol.Udp); settings["localPort"] = $"{dataPort}"; settings["interface"] = "0.0.0.0"; switch (transportProtocol) { case "UDP_T": case "UDP_U": settings["commandChannel"] = getTcpSettings(true).JoinKeyValuePairs(); break; } if (multicastEnabled) { settings["server"] = multicastGroup; settings["remotePort"] = $"{commandPort}"; } } else { settings["error"] = "No valid connection protocol detected"; } // Save device IP configuration Dictionary <string, string> deviceIPs = configFrame.DeviceIPs; // Load "NetworkSettingsGroup" element from settings group XElement networkSettingsGroup = settingsGroups .WhereAttribute("Type").Is("NetworkSettingsGroup") .FirstOrDefault(); if (networkSettingsGroup is null) { deviceIPs["loopback"] = "127.0.0.1"; } else { string gatewayIP = networkSettingsGroup .Descendants("Setting") .WhereAttribute("Name").Is("Gateway") .GetValue(DefaultGatewayIP); // Get array of settings for each NIC interface IEnumerable <XElement[]> interfaceSettingsMap = networkSettingsGroup .Descendants("SettingsGroup") .WhereAttribute("Type").Is("NetworkGroup") .Descendants("Instance") .WhereAttribute("Type").Is("NetworkInterfaceCard") .Select(element => element.Descendants("Setting").ToArray()); foreach (XElement[] interfaceSettings in interfaceSettingsMap) { string name = interfaceSettings .WhereAttribute("Name").Is("Name") .GetValue(null); if (string.IsNullOrWhiteSpace(name)) { continue; } string ipAddress = interfaceSettings .WhereAttribute("Name").Is("IPAddress") .GetValue(null); if (string.IsNullOrWhiteSpace(ipAddress)) { continue; } deviceIPs[name] = ipAddress; } // Set the target device IP to the one that matches gateway IP the closest, // this is just a guess, user must select proper device IP configFrame.TargetDeviceIP = deviceIPs .ToDictionary(pair => pair.Key, pair => gatewayIP.OverlapCoefficient(pair.Value)) .Aggregate((x, y) => x.Value > y.Value ? x : y).Key; if (string.IsNullOrWhiteSpace(configFrame.TargetDeviceIP) && deviceIPs.Count > 0) { configFrame.TargetDeviceIP = deviceIPs.First().Key; } } return(configFrame); }
/// <summary> /// Creates a <see cref="Phasor"/> of the specified <paramref name="type"/> from the given rectangular values. /// </summary> /// <param name="type">Type of phasor, i.e., current or voltage.</param> /// <param name="real">The real component of the <see cref="ComplexNumber"/>.</param> /// <param name="imaginary">The imaginary component of the <see cref="ComplexNumber"/>.</param> public Phasor(PhasorType type, double real, double imaginary) : this() { Type = type; Value = new ComplexNumber(real, imaginary); }
public static ConfigurationFrame Parse(string configFile, ShowMessageFunc showMessage) { string[] rows = File.ReadAllLines(configFile); Dictionary <string, string> configSettings = rows .Select(row => row.Split('=')) .ToDictionary(key => key[0], value => value[1], StringComparer.OrdinalIgnoreCase); // Fixed for now LineFrequency nominalFrequency = LineFrequency.Hz60; // Load server name setting string serverName = configSettings["IPAddr"]; // Load ID code setting if (!ushort.TryParse(configSettings["IdCode"], out ushort idCode)) { idCode = DefaultIDCode; } // Load frame rate setting if (!ushort.TryParse(configSettings["DataRate"], out ushort frameRate)) { frameRate = DefaultFrameRate; } // With an ID code, frame rate and server name, there's enough info to create a config frame ConfigurationFrame configFrame = new(idCode, frameRate, serverName); // Load all output PMUs int index = -1; while (configSettings.TryGetValue($"PmuId{++index}", out string setting) && ushort.TryParse(setting, out idCode)) { string name = configSettings[$"PmuStn{index}"]; if (string.IsNullOrWhiteSpace(name)) { continue; } // With a name and an ID code, there's enough info to create a config cell representing the PMU ConfigurationCell configCell = new(configFrame, name, idCode) { NominalFrequency = nominalFrequency, }; name = "VaChan"; PhasorType phasorType = PhasorType.Voltage; char phase = 'A'; string description = $"{configCell.StationName} phase {phase} {phasorType.ToString().ToLowerInvariant()} phasor"; configCell.PhasorDefinitions.Add(new PhasorDefinition(configCell, name, description, phasorType, phase)); name = "VbChan"; phasorType = PhasorType.Voltage; phase = 'B'; description = $"{configCell.StationName} phase {phase} {phasorType.ToString().ToLowerInvariant()} phasor"; configCell.PhasorDefinitions.Add(new PhasorDefinition(configCell, name, description, phasorType, phase)); name = "VcChan"; phasorType = PhasorType.Voltage; phase = 'C'; description = $"{configCell.StationName} phase {phase} {phasorType.ToString().ToLowerInvariant()} phasor"; configCell.PhasorDefinitions.Add(new PhasorDefinition(configCell, name, description, phasorType, phase)); name = "IaChan"; phasorType = PhasorType.Current; phase = 'A'; description = $"{configCell.StationName} phase {phase} {phasorType.ToString().ToLowerInvariant()} phasor"; configCell.PhasorDefinitions.Add(new PhasorDefinition(configCell, name, description, phasorType, phase)); name = "IbChan"; phasorType = PhasorType.Current; phase = 'B'; description = $"{configCell.StationName} phase {phase} {phasorType.ToString().ToLowerInvariant()} phasor"; configCell.PhasorDefinitions.Add(new PhasorDefinition(configCell, name, description, phasorType, phase)); name = "IcChan"; phasorType = PhasorType.Current; phase = 'C'; description = $"{configCell.StationName} phase {phase} {phasorType.ToString().ToLowerInvariant()} phasor"; configCell.PhasorDefinitions.Add(new PhasorDefinition(configCell, name, description, phasorType, phase)); name = "InChan"; phasorType = PhasorType.Current; phase = 'N'; description = $"{configCell.StationName} phase {phase} {phasorType.ToString().ToLowerInvariant()} phasor"; configCell.PhasorDefinitions.Add(new PhasorDefinition(configCell, name, description, phasorType, phase)); configFrame.Cells.Add(configCell); } // Get connection details configured for APP PDC configFrame.TransportProtocol = DefaultTransportProtocol; if (!ushort.TryParse(configSettings["PortTCP"], out ushort port)) { port = DefaultPort; } //if (!ushort.TryParse(configSettings["PortUDP"], out ushort dataPort)) // dataPort = DefaultDataPort; // Setup MultiProtocolFrameParser style connection string Dictionary <string, string> getTcpSettings(bool commandChannel = false) { // Use of simple "protocol" key in commandChannel and separation of // server/port keys are required to create a proper "PmuConnection" // file that can be successfully parsed by the PMU Connection Tester return(new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase) { [commandChannel ? "protocol": nameof(TransportProtocol)] = nameof(TransportProtocol.Tcp), ["server"] = IPAddressToken, ["port"] = $"{port}", ["isListener"] = "false", ["interface"] = "0.0.0.0" }); } Dictionary <string, string> settings = configFrame.Settings; settings[nameof(PhasorProtocol)] = nameof(PhasorProtocol.IEEEC37_118V1); foreach (KeyValuePair <string, string> pair in getTcpSettings()) { settings[pair.Key] = pair.Value; } // Save device IP configuration Dictionary <string, string> deviceIPs = configFrame.DeviceIPs; deviceIPs[serverName] = serverName; configFrame.TargetDeviceIP = serverName; return(configFrame); }
/// <summary> /// A constructor for the <see cref="LinearStateEstimator.Measurements.PhasorMeasurement"/> which specifies the measurement keys, phasor type, base KV, measurement variance as well as RCF and PACF. /// </summary> /// <param name="magnitudeKey">The openPDC input measurement key for the <see cref="LinearStateEstimator.Measurements.PhasorBase.Magnitude"/> of the <see cref="LinearStateEstimator.Measurements.PhasorMeasurement"/>.</param> /// <param name="angleKey">The openPDC input measurement key for the <see cref="LinearStateEstimator.Measurements.PhasorBase.AngleInDegrees"/> of the <see cref="LinearStateEstimator.Measurements.PhasorMeasurement"/>.</param> /// <param name="type">Specifies whether the phasor measurement is a current phasor or a /// voltage phasor or complex power with the <see cref="LinearStateEstimator.Measurements.PhasorType"/> enumeration, either <see cref="LinearStateEstimator.Measurements.PhasorType.VoltagePhasor"/>, /// <see cref="LinearStateEstimator.Measurements.PhasorType.CurrentPhasor"/>, or <see cref="LinearStateEstimator.Measurements.PhasorType.ComplexPower"/>.</param> /// <param name="baseKV">The <see cref="LinearStateEstimator.Modeling.VoltageLevel"/> of the phasor measurement.</param> /// <param name="variance">The measurement variance in per unit.</param> /// <param name="rcf">The <b>Ratio Correction Factor (RCF)</b> for the measurement.</param> /// <param name="pacf">The <b>Phase Angle Correction Factor (PACF)</b> for the measurementin degrees</param> public PhasorMeasurement(string magnitudeKey, string angleKey, PhasorType type, VoltageLevel baseKV, double variance, double rcf, double pacf) : this(magnitudeKey, angleKey, type, baseKV, variance, rcf, pacf, CalibrationSetting.Inactive) { }