/// <summary> /// Initializes <see cref="FileExporter"/>. /// </summary> public override void Initialize() { base.Initialize(); Dictionary <string, string> settings = Settings; const string errorMessage = "{0} is missing from Settings - Example: exportInterval=5; useReferenceAngle=True; referenceAngleMeasurement=DEVARCHIVE:6; companyTagPrefix=TVA; useNumericQuality=True; inputMeasurementKeys={{FILTER ActiveMeasurements WHERE Device='SHELBY' AND SignalType='FREQ'}}"; string setting; double seconds; // Load required parameters if (!settings.TryGetValue("exportInterval", out setting) || !double.TryParse(setting, out seconds)) { throw new ArgumentException(string.Format(errorMessage, "exportInterval")); } m_exportInterval = (int)(seconds * 1000.0D); m_lastPublicationTime = 0; if (m_exportInterval <= 0) { throw new ArgumentException("exportInterval should not be 0 - Example: exportInterval=5.5"); } if (InputMeasurementKeys == null || InputMeasurementKeys.Length == 0) { throw new InvalidOperationException("There are no input measurements defined. You must define \"inputMeasurementKeys\" to define which measurements to export."); } if (!settings.TryGetValue("useReferenceAngle", out setting)) { throw new ArgumentException(string.Format(errorMessage, "useReferenceAngle")); } m_useReferenceAngle = setting.ParseBoolean(); if (m_useReferenceAngle) { // Reference angle measurement has to be defined if using reference angle if (!settings.TryGetValue("referenceAngleMeasurement", out setting)) { throw new ArgumentException(string.Format(errorMessage, "referenceAngleMeasurement")); } m_referenceAngleKey = MeasurementKey.Parse(setting); // Make sure reference angle is part of input measurement keys collection if (!InputMeasurementKeys.Contains(m_referenceAngleKey)) { InputMeasurementKeys = InputMeasurementKeys.Concat(new[] { m_referenceAngleKey }).ToArray(); } // Make sure sure reference angle key is actually an angle measurement SignalType signalType = InputMeasurementKeyTypes[InputMeasurementKeys.IndexOf(key => key == m_referenceAngleKey)]; if (signalType != SignalType.IPHA && signalType != SignalType.VPHA) { throw new InvalidOperationException(string.Format("Specified reference angle measurement key is a {0} signal, not a phase angle.", signalType.GetFormattedName())); } } // Load optional parameters if (settings.TryGetValue("companyTagPrefix", out setting)) { m_companyTagPrefix = setting.ToUpper().Trim(); } else { m_companyTagPrefix = null; } if (settings.TryGetValue("useNumericQuality", out setting)) { m_useNumericQuality = setting.ParseBoolean(); } else { m_useNumericQuality = false; } // Suffix company tag prefix with an underscore if defined if (!string.IsNullOrWhiteSpace(m_companyTagPrefix)) { m_companyTagPrefix = m_companyTagPrefix.EnsureEnd('_'); } // Define a default export location - user can override and add multiple locations in config later... m_dataExporter = new MultipleDestinationExporter(ConfigurationSection, m_exportInterval); m_dataExporter.StatusMessage += m_dataExporter_StatusMessage; m_dataExporter.ProcessException += m_dataExporter_ProcessException; m_dataExporter.Initialize(new[] { new ExportDestination(FilePath.GetAbsolutePath(ConfigurationSection + ".txt"), false) }); // Create new measurement tag name dictionary m_measurementTags = new ConcurrentDictionary <MeasurementKey, string>(); string pointID = "undefined"; // Lookup point tag name for input measurement in the ActiveMeasurements table foreach (MeasurementKey key in InputMeasurementKeys) { try { // Get measurement key as a string pointID = key.ToString(); // Lookup measurement key in active measurements table DataRow row = DataSource.Tables["ActiveMeasurements"].Select(string.Format("ID='{0}'", pointID))[0]; // Remove invalid symbols that may be in tag name string pointTag = row["PointTag"].ToNonNullString(pointID).Replace('-', '_').Replace(':', '_').ToUpper(); // Prefix point tag with company prefix if defined if (!string.IsNullOrWhiteSpace(m_companyTagPrefix) && !pointTag.StartsWith(m_companyTagPrefix)) { pointTag = m_companyTagPrefix + pointTag; } m_measurementTags.TryAdd(key, pointTag); } catch (ThreadAbortException) { throw; } catch (Exception ex) { OnProcessException(new InvalidOperationException(string.Format("Failed to lookup point tag for measurement [{0}] due to exception: {1}", pointID, ex.Message))); } } // We enable tracking of latest measurements so we can use these values if points are missing - since we are using // latest measurement tracking, we sort all incoming points even though most of them will be thrown out... TrackLatestMeasurements = true; }
/// <summary> /// Initializes <see cref="FileExporter"/>. /// </summary> public override void Initialize() { base.Initialize(); Dictionary <string, string> settings = Settings; const string errorMessage = "{0} is missing from Settings - Example: exportInterval=5; modelIdentifier=Goslin; referenceAngleMeasurement=DEVARCHIVE:6; inputMeasurementKeys={{FILTER ActiveMeasurements WHERE Device='SHELBY' AND SignalType='FREQ'}}"; string setting; double seconds; // Load required parameters if (!settings.TryGetValue("exportInterval", out setting) || !double.TryParse(setting, out seconds)) { throw new ArgumentException(string.Format(errorMessage, "exportInterval")); } if (!settings.TryGetValue("fileExportPath", out m_fileExportPath)) { m_fileExportPath = FilePath.GetAbsolutePath(""); } m_exportInterval = (int)(seconds * 1000.0D); if (m_exportInterval <= 0) { throw new ArgumentException("exportInterval should not be 0 - Example: exportInterval=5.5"); } if ((object)InputMeasurementKeys == null || InputMeasurementKeys.Length == 0) { throw new InvalidOperationException("There are no input measurements defined. You must define \"inputMeasurementKeys\" to define which measurements to export."); } // Reference angle measurement has to be defined if using reference angle if (!settings.TryGetValue("referenceAngleMeasurement", out setting)) { throw new ArgumentException(string.Format(errorMessage, "referenceAngleMeasurement")); } m_referenceAngleKey = MeasurementKey.Parse(setting); // Make sure reference angle is first angle of input measurement keys collection InputMeasurementKeys = (new[] { m_referenceAngleKey }).Concat(InputMeasurementKeys).ToArray(); // Make sure sure reference angle key is actually an angle measurement SignalType signalType = InputMeasurementKeyTypes[InputMeasurementKeys.IndexOf(key => key == m_referenceAngleKey)]; if (signalType != SignalType.IPHA && signalType != SignalType.VPHA) { throw new InvalidOperationException(string.Format("Specified reference angle measurement key is a {0} signal, not a phase angle.", signalType.GetFormattedName())); } Comments = settings.TryGetValue("comments", out setting) ? setting : "Comment section---"; if (!settings.TryGetValue("modelIdentifier", out setting)) { throw new ArgumentException(string.Format(errorMessage, "modelIdentifier")); } ModelIdentifier = setting; // We enable tracking of latest measurements so we can use these values if points are missing - since we are using // latest measurement tracking, we sort all incoming points even though most of them will be thrown out... TrackLatestMeasurements = true; //// Create a new dictionary of base voltages //m_baseVoltages = new Dictionary<MeasurementKey, double>(); StringBuilder header = new StringBuilder(); //MeasurementKey voltageMagnitudeKey; //double baseKV; // Write header row header.Append("TimeStamp"); DataTable measurements = DataSource.Tables["ActiveMeasurements"]; int tieLines = 0; bool referenceAdded = false; for (int i = 0; i < InputMeasurementKeys.Length; i++) { // Lookup measurement key in active measurements table DataRow row = measurements.Select(string.Format("ID='{0}'", InputMeasurementKeys[i]))[0]; string deviceName = row["Device"].ToNonNullString("UNDEFINED").ToUpper().Trim(); if (!referenceAdded && InputMeasurementKeys[i] == m_referenceAngleKey) { header.AppendFormat(",Ref. Angle of {0}", deviceName); referenceAdded = true; } else { switch (InputMeasurementKeyTypes[i]) { case SignalType.VPHM: header.AppendFormat(",{0} |V|", deviceName); tieLines++; //voltageMagnitudeKey = InputMeasurementKeys[i]; //if (settings.TryGetValue(voltageMagnitudeKey + "BaseKV", out setting) && double.TryParse(setting, out baseKV)) //{ // m_baseVoltages.Add(voltageMagnitudeKey, baseKV * SI.Kilo); //} //else //{ // int baseKVCode; // // Second check if base KV can be inferred from device name suffixed KV index // if (int.TryParse(deviceName[deviceName.Length - 1].ToString(), out baseKVCode) && baseKVCode > 1 && baseKVCode < BaseKVs.Length) // { // m_baseVoltages.Add(voltageMagnitudeKey, BaseKVs[baseKVCode]); // } // else // { // OnStatusMessage("WARNING: Did not find a valid base KV setting for voltage magnitude {0}, assumed 500KV", voltageMagnitudeKey.ToString()); // m_baseVoltages.Add(voltageMagnitudeKey, 500.0D * SI.Kilo); // } //} break; case SignalType.VPHA: header.AppendFormat(",{0} Voltage Angle", deviceName); break; case SignalType.IPHM: header.AppendFormat(",{0} |I|", deviceName); break; case SignalType.IPHA: header.AppendFormat(",{0} Current Angle", deviceName); break; default: header.AppendFormat(",{0} ??", deviceName); break; } } } string row5 = header.ToString(); header = new StringBuilder(); // Add row 1 header.AppendFormat("Comments: {0}\r\n", Comments); // Add row 2 header.AppendFormat("Model Identifier: {0}\r\n", ModelIdentifier); // Add row 3 header.Append("Datapoints,Tielines,TimeStep"); if (InputMeasurementKeys.Length - 3 > 0) { header.Append(new string(',', InputMeasurementKeys.Length - 3)); } header.AppendLine(); // Add row 4 header.AppendFormat("{0},{1},{2}", RowCountMarker, tieLines, 1.0D / FramesPerSecond); header.AppendLine(); // Add row 5 header.AppendLine(row5); // Cache header for each file export m_header = header.ToString(); }