/// <summary> /// A verbose descriptive string representation of the <see cref="LinearStateEstimator.Measurements.PhasorBase"/> class. /// </summary> /// <returns>A verbose descriptive string representation of the <see cref="LinearStateEstimator.Measurements.PhasorBase"/> class.</returns> public string ToVerboseString() { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.AppendLine(); stringBuilder.AppendFormat("----- Phasor Base --------------------------------------------------------------"); stringBuilder.AppendLine(); stringBuilder.AppendFormat(" Type: " + m_type.ToString() + "{0}", Environment.NewLine); stringBuilder.AppendFormat(" Base KV: " + m_baseKV.ToString() + "{0}", Environment.NewLine); stringBuilder.AppendFormat(" MagnitudKey: " + m_magnitudeKey + "{0}", Environment.NewLine); stringBuilder.AppendFormat(" AngleKey: " + m_angleKey + "{0}", Environment.NewLine); stringBuilder.AppendFormat(" Magnitude: " + m_magnitude.ToString() + "{0}", Environment.NewLine); stringBuilder.AppendFormat(" Angle: " + m_angleInDegrees.ToString() + "{0}", Environment.NewLine); stringBuilder.AppendFormat("MagnitudeReportd: " + m_magnitudeValueWasReported.ToString() + "{0}", Environment.NewLine); stringBuilder.AppendFormat("AngleWasReported: " + m_angleValueWasReported.ToString() + "{0}", Environment.NewLine); stringBuilder.AppendLine(); return(stringBuilder.ToString()); }
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); }
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); }