public void UpdateConfiguration() { const int labelLength = 16; Dictionary<string, int> signalCellIndexes = new Dictionary<string, int>(); ConfigurationCell cell; SignalReference signal; SignalReference[] signals; MeasurementKey measurementKey; PhasorType phasorType; AnalogType analogType; char phaseType; string label; int order; uint scale; double offset; // Define a protocol independent configuration frame m_baseConfigurationFrame = new ConfigurationFrame(m_idCode, DateTime.UtcNow.Ticks, (ushort)base.FramesPerSecond); // Define configuration cells (i.e., PMU's that will appear in outgoing data stream) foreach (DataRow deviceRow in DataSource.Tables["OutputStreams"].Select(string.Format("StreamID={0}", ID))) { try { // Create a new configuration cell cell = new ConfigurationCell(m_baseConfigurationFrame, ushort.Parse(deviceRow["ID"].ToString()), deviceRow["IsVirtual"].ToNonNullString("false").ParseBoolean()); // The base class defaults to floating-point, polar values, derived classes can change cell.PhasorDataFormat = DataFormat.FloatingPoint; cell.PhasorCoordinateFormat = CoordinateFormat.Polar; cell.FrequencyDataFormat = DataFormat.FloatingPoint; cell.AnalogDataFormat = DataFormat.FloatingPoint; cell.IDLabel = deviceRow["Acronym"].ToString().Trim(); cell.StationName = deviceRow["Name"].ToString().TruncateRight(cell.MaximumStationNameLength).Trim(); // Define all the phasors configured for this device foreach (DataRow phasorRow in DataSource.Tables["OutputStreamPhasors"].Select(string.Format("DeviceID={0}", cell.IDCode), "Order")) { order = int.Parse(phasorRow["Order"].ToNonNullString("0")); label = phasorRow["Label"].ToNonNullString("Phasor " + order).Trim().RemoveDuplicateWhiteSpace().TruncateRight(labelLength - 4); phasorType = phasorRow["PhasorType"].ToNonNullString("V").Trim().ToUpper().StartsWith("V") ? PhasorType.Voltage : PhasorType.Current; phaseType = phasorRow["PhaseType"].ToNonNullString("+").Trim().ToUpper()[0]; cell.PhasorDefinitions.Add( new PhasorDefinition( cell, GeneratePhasorLabel(label, phaseType, phasorType), phasorType, null)); } // Add frequency definition label = string.Format("{0} Freq", cell.IDLabel.TruncateRight(labelLength - 5)).Trim(); cell.FrequencyDefinition = new FrequencyDefinition(cell, label); // Optionally define all the analogs configured for this device if (DataSource.Tables.Contains("OutputStreamAnalogs")) { foreach (DataRow analogRow in DataSource.Tables["OutputStreamAnalogs"].Select(string.Format("DeviceID={0}", cell.IDCode), "Order")) { order = int.Parse(analogRow["Order"].ToNonNullString("0")); label = analogRow["Label"].ToNonNullString("Analog " + order).Trim().RemoveDuplicateWhiteSpace().TruncateRight(labelLength); scale = uint.Parse(analogRow["Scale"].ToNonNullString("1")); offset = double.Parse(analogRow["Offset"].ToNonNullString("0.0")); analogType = analogRow["AnalogType"].ToNonNullString("SinglePointOnWave").ConvertToType<AnalogType>(); cell.AnalogDefinitions.Add( new AnalogDefinition( cell, label, scale, offset, analogType)); } } // Optionally define all the digitals configured for this device if (DataSource.Tables.Contains("OutputStreamDigitals")) { foreach (DataRow digitalRow in DataSource.Tables["OutputStreamDigitals"].Select(string.Format("DeviceID={0}", cell.IDCode), "Order")) { order = int.Parse(digitalRow["Order"].ToNonNullString("0")); label = digitalRow["Label"].ToNonNullString("Digital " + order).Trim().RemoveDuplicateWhiteSpace().TruncateRight(labelLength); cell.DigitalDefinitions.Add( new DigitalDefinition( cell, label)); } } m_baseConfigurationFrame.Cells.Add(cell); } catch (Exception ex) { OnProcessException(new InvalidOperationException(string.Format("Failed to define output stream device \"{0}\" due to exception: {1}", deviceRow["Acronym"].ToString().Trim(), ex.Message), ex)); } } OnStatusMessage("Defined {0} output stream devices...", m_baseConfigurationFrame.Cells.Count); // Create a new signal reference dictionary indexed on measurement keys m_signalReferences = new Dictionary<MeasurementKey, SignalReference[]>(); // Define measurement to signals cross reference dictionary foreach (DataRow measurementRow in DataSource.Tables["OutputStreamMeasurements"].Select(string.Format("StreamID={0}", ID))) { try { // Create a new signal reference signal = new SignalReference(measurementRow["SignalReference"].ToString()); // Lookup cell index by acronym - doing this work upfront will save a huge amount // of work during primary measurement sorting if (!signalCellIndexes.TryGetValue(signal.Acronym, out signal.CellIndex)) { // We cache these indicies locally to speed up initialization as we'll be // requesting them for the same devices over and over signal.CellIndex = m_configurationFrame.Cells.IndexOfIDLabel(signal.Acronym); signalCellIndexes.Add(signal.Acronym, signal.CellIndex); } // Define measurement key measurementKey = new MeasurementKey(uint.Parse(measurementRow["PointID"].ToString()), measurementRow["Historian"].ToString()); // It is possible, but not as common, that a measurement will have multiple destinations // within an outgoing data stream frame, hence the following if (m_signalReferences.TryGetValue(measurementKey, out signals)) { // Add a new signal to existing collection List<SignalReference> signalList = new List<SignalReference>(signals); signalList.Add(signal); m_signalReferences[measurementKey] = signalList.ToArray(); } else { // Add new signal to new collection signals = new SignalReference[1]; signals[0] = signal; m_signalReferences.Add(measurementKey, signals); } } catch (Exception ex) { OnProcessException(new InvalidOperationException(string.Format("Failed to associate measurement key to signal reference \"{0}\" due to exception: {1}", measurementRow["SignalReference"].ToString().Trim(), ex.Message), ex)); } } // Assign action adapter input measurement keys InputMeasurementKeys = m_signalReferences.Keys.ToArray(); // Create a new protocol specific configuration frame m_configurationFrame = CreateNewConfigurationFrame(m_baseConfigurationFrame); // Cache new protocol specific configuration frame CacheConfigurationFrame(m_configurationFrame); }
/// <summary> /// Creates a new <see cref="FrequencyDefinition"/> from specified parameters. /// </summary> /// <param name="parent">The <see cref="ConfigurationCell"/> parent of this <see cref="FrequencyDefinition"/>.</param> /// <param name="label">The label of this <see cref="FrequencyDefinition"/>.</param> public FrequencyDefinition(ConfigurationCell parent, string label) : base(parent, label, 1000, 100, 0.0D) { }
private void CopyDevice(ConfigurationCell sourceDevice) { // Create a new configuration cell to hold copied information ConfigurationCell copiedDevice = new ConfigurationCell(m_configurationFrame, 0); copiedDevice.IDCode = (ushort)m_configurationFrame.Cells.Count; copiedDevice.StationName = "Device " + (copiedDevice.IDCode + 1); // Create equivalent derived phasor definitions foreach (PhasorDefinition sourcePhasor in sourceDevice.PhasorDefinitions) { copiedDevice.PhasorDefinitions.Add(new PhasorDefinition(copiedDevice, sourcePhasor.Label, sourcePhasor.ScalingValue, sourcePhasor.PhasorType, null)); } // Create equivalent dervied frequency definition IFrequencyDefinition sourceFrequency = sourceDevice.FrequencyDefinition; if (sourceFrequency != null) copiedDevice.FrequencyDefinition = new FrequencyDefinition(copiedDevice, sourceFrequency.Label); // Create equivalent dervied analog definitions (assuming analog type = SinglePointOnWave) foreach (AnalogDefinition sourceAnalog in sourceDevice.AnalogDefinitions) { copiedDevice.AnalogDefinitions.Add(new AnalogDefinition(copiedDevice, sourceAnalog.Label, sourceAnalog.ScalingValue, sourceAnalog.AnalogType)); } // Create equivalent dervied digital definitions foreach (DigitalDefinition sourceDigital in sourceDevice.DigitalDefinitions) { copiedDevice.DigitalDefinitions.Add(new DigitalDefinition(copiedDevice, sourceDigital.Label, sourceDigital.MaskValue)); } // Add new copied cell to the list and select it m_configurationFrame.Cells.Add(copiedDevice); listBoxDevices.SelectedIndex = (m_configurationFrame.Cells.Count - 1); }
private void buttonDeviceAdd_Click(object sender, RoutedEventArgs e) { ConfigurationCell device = new ConfigurationCell(m_configurationFrame, 0); device.IDCode = (ushort)m_configurationFrame.Cells.Count; device.StationName = "Device " + (device.IDCode + 1); m_configurationFrame.Cells.Add(device); listBoxDevices.SelectedIndex = (m_configurationFrame.Cells.Count - 1); }
/// <summary> /// Creates a new <see cref="AnalogDefinition"/> from specified parameters. /// </summary> /// <param name="parent">The <see cref="ConfigurationCell"/> parent of this <see cref="AnalogDefinition"/>.</param> /// <param name="label">The label of this <see cref="AnalogDefinition"/>.</param> /// <param name="scale">The integer scaling value of this <see cref="AnalogDefinition"/>.</param> /// <param name="offset">The offset of this <see cref="AnalogDefinition"/>.</param> /// <param name="type">The <see cref="AnalogType"/> of this <see cref="AnalogDefinition"/>.</param> public AnalogDefinition(ConfigurationCell parent, string label, uint scale, double offset, AnalogType type) : base(parent, label, scale, offset, type) { }
/// <summary> /// Intializes <see cref="PhasorMeasurementMapper"/>. /// </summary> public override void Initialize() { Dictionary<string, string> settings = Settings; ConfigurationCell definedDevice; string setting, signalReference; // Load required mapper specific connection parameters m_isConcentrator = settings["isConcentrator"].ParseBoolean(); m_accessID = ushort.Parse(settings["accessID"].ToString()); // Load optional mapper specific connection parameters if (settings.TryGetValue("virtual", out setting)) m_isVirtual = setting.ParseBoolean(); else m_isVirtual = false; if (settings.TryGetValue("timeZone", out setting)) m_timezone = TimeZoneInfo.FindSystemTimeZoneById(setting); else m_timezone = TimeZoneInfo.Utc; if (settings.TryGetValue("timeAdjustmentTicks", out setting)) m_timeAdjustmentTicks = long.Parse(setting); else m_timeAdjustmentTicks = 0; if (settings.TryGetValue("dataLossInterval", out setting)) m_dataStreamMonitor.Interval = double.Parse(setting) * 1000.0D; else m_dataStreamMonitor.Interval = 35000.0D; // Create a new phasor protocol frame parser for non-virtual connections if (!m_isVirtual) { MultiProtocolFrameParser frameParser = new MultiProtocolFrameParser(); // Most of the parameters in the connection string will be for the frame parser so we provide all of them, // other parameters will simply be ignored frameParser.ConnectionString = ConnectionString; // For captured data simulations we will inject a simulated timestamp and auto-repeat file stream... if (frameParser.TransportProtocol == TransportProtocol.File) { if (settings.TryGetValue("definedFrameRate", out setting)) frameParser.DefinedFrameRate = 1.0D / double.Parse(setting); else frameParser.DefinedFrameRate = 1.0D / 30.0D; if (settings.TryGetValue("simulateTimestamp", out setting)) frameParser.InjectSimulatedTimestamp = setting.ParseBoolean(); else frameParser.InjectSimulatedTimestamp = true; if (settings.TryGetValue("autoRepeatFile", out setting)) frameParser.AutoRepeatCapturedPlayback = setting.ParseBoolean(); else frameParser.AutoRepeatCapturedPlayback = true; } // Provide access ID to frame parser as this may be necessary to make a phasor connection frameParser.DeviceID = m_accessID; frameParser.SourceName = Name; // Assign reference to frame parser and attach to needed events this.FrameParser = frameParser; } // Load device list for this mapper connection m_definedDevices = new Dictionary<ushort, ConfigurationCell>(); if (m_isConcentrator) { StringBuilder deviceStatus = new StringBuilder(); int index = 0; deviceStatus.AppendLine(); deviceStatus.AppendLine(); deviceStatus.Append("Loading expected concentrator device list..."); deviceStatus.AppendLine(); deviceStatus.AppendLine(); // Making a connection to a concentrator that can support multiple devices foreach (DataRow row in DataSource.Tables["ActiveConcentratorDevices"].Select(string.Format("Acronym='{0}'", Name))) { definedDevice = new ConfigurationCell(ushort.Parse(row["AccessID"].ToString()), m_isVirtual); definedDevice.IDLabel = row["Acronym"].ToString(); definedDevice.Tag = uint.Parse(row["ID"].ToString()); m_definedDevices.Add(definedDevice.IDCode, definedDevice); // Create status display string for expected device deviceStatus.Append(" Device "); deviceStatus.Append((index++).ToString("00")); deviceStatus.Append(": "); deviceStatus.Append(definedDevice.IDLabel); deviceStatus.Append(" ("); deviceStatus.Append(definedDevice.IDCode); deviceStatus.Append(')'); deviceStatus.AppendLine(); } OnStatusMessage(deviceStatus.ToString()); } else { // Making a connection to a single device definedDevice = new ConfigurationCell(m_accessID, m_isVirtual); definedDevice.IDLabel = Name; definedDevice.Tag = ID; m_definedDevices.Add(definedDevice.IDCode, definedDevice); } // Load active device measurements for this mapper connection m_definedMeasurements = new Dictionary<string, IMeasurement>(); foreach (DataRow row in DataSource.Tables["ActiveDeviceMeasurements"].Select(string.Format("Acronym='{0}'", Name))) { signalReference = row["SignalReference"].ToString(); if (!string.IsNullOrEmpty(signalReference)) { try { m_definedMeasurements.Add(signalReference, new Measurement( uint.Parse(row["PointID"].ToString()), row["Historian"].ToString(), signalReference, double.Parse(row["Adder"].ToString()), double.Parse(row["Multiplier"].ToString()))); } catch (Exception ex) { OnProcessException(new InvalidOperationException(string.Format("Failed to load signal reference \"{0}\" due to exception: {1}", signalReference, ex.Message), ex)); } } } OnStatusMessage("Loaded {0} active device measurements...", m_definedMeasurements.Count); }