/// <summary> /// Releases the unmanaged resources used by the <see cref="FileExporter"/> object and optionally releases the managed resources. /// </summary> /// <param name="disposing">true to release both managed and unmanaged resources; false to release only unmanaged resources.</param> protected override void Dispose(bool disposing) { if (!m_disposed) { try { if (disposing) { if (m_dataExporter != null) { m_dataExporter.SaveSettings(); m_dataExporter.StatusMessage -= m_dataExporter_StatusMessage; m_dataExporter.ProcessException -= m_dataExporter_ProcessException; m_dataExporter.Dispose(); } m_dataExporter = null; } } finally { m_disposed = true; // Prevent duplicate dispose. base.Dispose(disposing); // Call base class Dispose(). } } }
/// <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; }