/// <summary> /// Creates a new local system cache from one that was received remotely. /// </summary> /// <param name="dataSource"><see cref="DataSet"/> based data source used to interpret local measurement keys.</param> /// <param name="remoteCache">Deserialized remote signal index cache.</param> public SignalIndexCache(DataSet dataSource, SignalIndexCache remoteCache) { m_subscriberID = remoteCache.SubscriberID; // If active measurements are defined, interpret signal cache in context of current measurement key definitions if (dataSource != null && dataSource.Tables != null && dataSource.Tables.Contains("ActiveMeasurements")) { DataTable activeMeasurements = dataSource.Tables["ActiveMeasurements"]; m_reference = new ConcurrentDictionary <ushort, Tuple <Guid, string, uint> >(); foreach (KeyValuePair <ushort, Tuple <Guid, string, uint> > signalIndex in remoteCache.Reference) { Guid signalID = signalIndex.Value.Item1; DataRow[] filteredRows = activeMeasurements.Select("SignalID = '" + signalID.ToString() + "'"); if (filteredRows.Length > 0) { DataRow row = filteredRows[0]; MeasurementKey key = MeasurementKey.Parse(row["ID"].ToNonNullString(MeasurementKey.Undefined.ToString()), signalID); m_reference.TryAdd(signalIndex.Key, new Tuple <Guid, string, uint>(signalID, key.Source, key.ID)); } } m_unauthorizedSignalIDs = remoteCache.UnauthorizedSignalIDs; } else { // Just use remote signal index cache as-is if no local configuration exists m_reference = remoteCache.Reference; m_unauthorizedSignalIDs = remoteCache.UnauthorizedSignalIDs; } }
// Gets a measurement key based on a token which // may be either a signal ID or measurement key. private MeasurementKey GetKey(string token) { Guid signalID; return(Guid.TryParse(token, out signalID) ? MeasurementKey.LookUpBySignalID(signalID) : MeasurementKey.Parse(token)); }
// Gets a measurement key based on a token which // may be either a signal ID or measurement key. private MeasurementKey GetKey(string token) { Guid signalID; MeasurementKey key; if (Guid.TryParse(token, out signalID)) { // Defined using the measurement's GUID key = MeasurementKey.LookUpBySignalID(signalID); } else { // Defined using the measurement's key key = MeasurementKey.Parse(token); } return(key); }
/// <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(); }
// Attempt to read the next record private bool ReadNextRecord(long currentTime) { try { List <IMeasurement> newMeasurements = new List <IMeasurement>(); long fileTime = 0; int timestampColumn = 0; string[] fields = m_inStream.ReadLine().ToNonNullString().Split(','); if (m_inStream.EndOfStream || fields.Length < m_columns.Count) { return(false); } // Read time from Timestamp column in transverse mode if (m_transverse) { if (m_simulateTimestamp) { fileTime = currentTime; } else { timestampColumn = m_columnMappings.First(kvp => string.Compare(kvp.Value.TagName, "Timestamp", StringComparison.OrdinalIgnoreCase) == 0).Key; fileTime = long.Parse(fields[timestampColumn]); } } for (int i = 0; i < m_measurementsPerInterval; i++) { IMeasurement measurement; if (m_transverse) { // No measurement will be defined for timestamp column if (i == timestampColumn) { continue; } if (m_columnMappings.TryGetValue(i, out measurement)) { measurement = Measurement.Clone(measurement); measurement.Value = double.Parse(fields[i]); } else { measurement = new Measurement(); measurement.Metadata = MeasurementKey.Undefined.Metadata; measurement.Value = double.NaN; } if (m_simulateTimestamp) { measurement.Timestamp = currentTime; } else if (m_columns.ContainsKey("Timestamp")) { measurement.Timestamp = fileTime; } } else { measurement = new Measurement(); if (m_columns.ContainsKey("Signal ID")) { Guid measurementID = new Guid(fields[m_columns["Signal ID"]]); if (m_columns.ContainsKey("Measurement Key")) { measurement.Metadata = MeasurementKey.LookUpOrCreate(measurementID, fields[m_columns["Measurement Key"]]).Metadata; } else { measurement.Metadata = MeasurementKey.LookUpBySignalID(measurementID).Metadata; } } else if (m_columns.ContainsKey("Measurement Key")) { measurement.Metadata = MeasurementKey.Parse(fields[m_columns["Measurement Key"]]).Metadata; } if (m_simulateTimestamp) { measurement.Timestamp = currentTime; } else if (m_columns.ContainsKey("Timestamp")) { measurement.Timestamp = long.Parse(fields[m_columns["Timestamp"]]); } if (m_columns.ContainsKey("Value")) { measurement.Value = double.Parse(fields[m_columns["Value"]]); } } newMeasurements.Add(measurement); } OnNewMeasurements(newMeasurements); } catch (Exception ex) { OnProcessException(MessageLevel.Warning, ex); } return(true); }