Exemple #1
0
 /// <summary>We retrieve adjusted measurement values within time tolerance of concentrator real-time.</summary>
 /// <param name="key">An <see cref="MeasurementKey"/> representing the measurement key.</param>
 /// <returns>A <see cref="Double"/> representing the adjusted measurement value.</returns>
 public double this[MeasurementKey key]
 {
     get
     {
         return Measurement(key).GetAdjustedValue(m_parent.RealTime);
     }
 }
Exemple #2
0
        /// <summary>
        /// Initializes <see cref="VirtualInputAdapter"/>.
        /// </summary>
        public override void Initialize()
        {
            // In case user defines no inputs or outputs for virutal adapter, we "turn off" interaction with any
            // other real-time adapters by removing this virtual adapter from external routes. To accomplish this
            // we expose I/O demands for an undefined measurement. Leaving values assigning to null would mean
            // that this adapter desires a full "broadcast" of all data - and hence routing demands from all.
            // User can override if desired using standard connection string parameters for I/O measurements.
            InputMeasurementKeys = new MeasurementKey[] { MeasurementKey.Undefined };
            OutputMeasurements = new Measurement[] { Measurement.Undefined };

            base.Initialize();
        }
Exemple #3
0
 public Measurement(int id, string source, double value, double adder, double multiplier, long ticks)
 {
     m_id = id;
     m_source = source;
     m_key = new MeasurementKey(m_id, m_source);
     m_value = value;
     m_adder = adder;
     m_multiplier = multiplier;
     m_ticks = ticks;
     m_valueQualityIsGood = true;
     m_timestampQualityIsGood = true;
 }
Exemple #4
0
        private Metadata(DataRow row)
        {
            MeasurementKey measurementKey;

            Guid.TryParse(row["SignalID"].ToString(), out SignalID);
            MeasurementKey.TryParse(row["ID"].ToString(), out measurementKey);

            PointID         = measurementKey.ID;
            PointTag        = row["PointTag"].ToString();
            SignalReference = row["SignalReference"].ToString();
            DeviceName      = row["DeviceAcronym"].ToString();
            SignalAcronym   = row["SignalAcronym"].ToString();
            Description     = row["Description"].ToString();
        }
Exemple #5
0
        // Converts the given row of CSV data to a single measurement.
        private IMeasurement FromCSV(string csv)
        {
            string[] split     = csv.Split(',');
            DateTime timestamp = DateTime.Parse(split[0]);
            Guid     signalID  = Guid.Parse(split[1]);
            double   value     = double.Parse(split[2]);

            return(new Measurement()
            {
                Metadata = MeasurementKey.LookUpBySignalID(signalID).Metadata,
                Timestamp = timestamp,
                Value = value
            });
        }
Exemple #6
0
        // Adds the given mapping to the key-variable map.
        private void AddMapping(MeasurementKey key, string alias)
        {
            if (m_variableNames.Contains(alias))
            {
                throw new ArgumentException($"Variable name is not unique: {alias}");
            }

            if (alias.Equals("TIME", StringComparison.OrdinalIgnoreCase))
            {
                throw new ArgumentException("Variable name \"TIME\" is reserved.");
            }

            m_variableNames.Add(alias);
            m_keyMapping.Add(key, alias);
        }
Exemple #7
0
        /// <summary>
        /// Creates a new instance of the <see cref="SignalBuffer"/> class.
        /// </summary>
        /// <param name="key">The key which identifies the signal which is buffered.</param>
        public SignalBuffer(MeasurementKey key)
        {
            const int Sentinel = -1;

            m_key    = key;
            m_blocks = new List <MeasurementBlock>();
            m_blocks.Add(new MeasurementBlock(BlockSize));
            m_removedBlockCounts = new RollingWindow <int>(StatWindow);
            m_blockLock          = new object();

            for (int i = 0; i < StatWindow; i++)
            {
                m_removedBlockCounts.Add(Sentinel);
            }
        }
Exemple #8
0
        // Add a measurement to the list of out of range measurements corresponding to the given key.
        private void AddOutOfRangeMeasurement(MeasurementKey key, IMeasurement measurement)
        {
            lock (m_outOfRangeMeasurements)
            {
                LinkedList <IMeasurement> outOfRangeList;

                if (!m_outOfRangeMeasurements.TryGetValue(key, out outOfRangeList))
                {
                    outOfRangeList = new LinkedList <IMeasurement>();
                    m_outOfRangeMeasurements.Add(key, outOfRangeList);
                }

                outOfRangeList.AddLast(measurement);
            }
        }
Exemple #9
0
        /// <summary>
        /// Returns a new measurement equivalent to the one being wrapped.
        /// </summary>
        /// <returns>The wrapped measurement.</returns>
        public IMeasurement GetMeasurement()
        {
            Guid signalID = Guid.Parse(SignalID);

            IMeasurement measurement = new Measurement()
            {
                Adder      = Adder,
                Key        = MeasurementKey.LookUpOrCreate(signalID, Source, unchecked ((uint)ID)),
                Multiplier = Multiplier,
                TagName    = TagName,
                Timestamp  = Timestamp,
                Value      = Value
            };

            return(measurement);
        }
Exemple #10
0
        // Adds a variable to the key-variable map which has not been explicitly aliased.
        private void AddNotAliasedVariable(string token)
        {
            token = token.Trim();
            m_nonAliasedTokens.Add(-token.Length, token);

            MeasurementKey key   = GetKey(token);
            string         alias = token.ReplaceCharacters('_', c => !char.IsLetterOrDigit(c));

            // Ensure that the generated alias is unique
            while (m_variableNames.Contains(alias))
            {
                alias += "_";
            }

            AddMapping(key, alias);
        }
Exemple #11
0
        protected MetaValues CreateMetaValues(FieldMapping fieldMapping)
        {
            if (fieldMapping.RelativeTime != 0.0M)
            {
                AlignmentCoordinator.SampleWindow sampleWindow = CreateSampleWindow(fieldMapping);
                MeasurementKey key = m_keys[m_keyIndex++].Single();
                return(AlignmentCoordinator.CreateMetaValue(key, CurrentFrameTime, sampleWindow));
            }

            return(new MetaValues()
            {
                ID = m_keys[m_keyIndex++].Single().SignalID,
                Timestamp = m_currentFrameTime,
                Flags = MeasurementFlags.CalculatedValue
            });
        }
Exemple #12
0
        /// <summary>
        /// Gets signal type for given measurement key
        /// </summary>
        /// <param name="dataSource">Target <see cref="DataSet"/>.</param>
        /// <param name="key">Source <see cref="MeasurementKey"/>.</param>
        /// <param name="measurementTable">Measurement table name used for meta-data lookup.</param>
        /// <returns><see cref="SignalType"/> as defined for measurement key in data source.</returns>
        public static SignalType GetSignalType(this DataSet dataSource, MeasurementKey key, string measurementTable = "ActiveMeasurements")
        {
            if (dataSource == null)
            {
                throw new ArgumentNullException(nameof(dataSource));
            }

            DataRow record = dataSource.LookupMetadata(key.SignalID, measurementTable);

            if (record != null && Enum.TryParse(record["SignalType"].ToString(), out SignalType signalType))
            {
                return(signalType);
            }

            return(SignalType.NONE);
        }
Exemple #13
0
        /// <summary>
        /// Queries the signal buffer for the measurement whose timestamp is nearest the given timestamp,
        /// but only returns the measurement if its timestamp falls within a specified tolerance around the given timestamp.
        /// </summary>
        /// <param name="key">The key which identifies the signal to be queried.</param>
        /// <param name="timestamp">The timestamp of the measurement to be queried.</param>
        /// <param name="tolerance">The tolerance that determines whether the nearest measurement is valid.</param>
        /// <returns>The measurement whose timestamp is nearest the given timestamp or null if the measurement's timestamp falls outside the given tolerance.</returns>
        public IMeasurement QuerySignalBuffer(MeasurementKey key, DateTime timestamp, TimeSpan tolerance)
        {
            IMeasurement nearestMeasurement = QuerySignalBuffer(key, timestamp);

            if ((object)nearestMeasurement == null)
            {
                return(null);
            }

            if (nearestMeasurement.Timestamp < (timestamp - tolerance).Ticks || nearestMeasurement.Timestamp > (timestamp + tolerance).Ticks)
            {
                return(null);
            }

            return(nearestMeasurement);
        }
        private static Measurement GetMeasurement(Guid signalID)
        {
            MeasurementKey key = MeasurementKey.LookUpBySignalID(signalID);

            if (key.SignalID == Guid.Empty)
            {
                return(null);
            }

            Measurement measurement = new Measurement
            {
                Metadata = key.Metadata,
            };

            return(measurement);
        }
Exemple #15
0
        // Creates an alarm event from the given alarm and measurement.
        private IMeasurement CreateAlarmEvent(Ticks timestamp, Alarm alarm)
        {
            IMeasurement alarmEvent = new Measurement()
            {
                Timestamp = timestamp,
                Value     = (int)alarm.State
            };

            if ((object)alarm.AssociatedMeasurementID != null)
            {
                Guid alarmEventID = alarm.AssociatedMeasurementID.GetValueOrDefault();
                alarmEvent.Metadata = MeasurementKey.LookUpBySignalID(alarmEventID).Metadata;
            }

            return(alarmEvent);
        }
Exemple #16
0
 public async Task <IActionResult> OnGet(int?measurementKeyId)
 {
     if (measurementKeyId.HasValue)
     {
         MeasurementKey = await _measurementKeyData.GetById(measurementKeyId.Value);
     }
     else
     {
         MeasurementKey = new MeasurementKey();
     }
     if (MeasurementKey == null)
     {
         RedirectToPage("../Error");
     }
     return(Page());
 }
Exemple #17
0
        private void m_timer_Elapsed(object sender, ElapsedEventArgs e)
        {
            List <IMeasurement> measurements = new List <IMeasurement>();
            StringBuilder       columnString = new StringBuilder();

            int timestampColumn = GetColumnIndex("Timestamp");
            int idColumn        = GetColumnIndex("SignalID");
            int valueColumn     = GetColumnIndex("Value");

            string      commandString;
            IDbCommand  command;
            IDataReader reader;

            foreach (string columnName in s_measurementColumns)
            {
                if (columnString.Length > 0)
                {
                    columnString.Append(',');
                }

                columnString.Append(columnName);
            }

            commandString       = string.Format("SELECT {0} FROM Measurement LIMIT {1},{2}", columnString, m_startingMeasurement, m_measurementsPerInput);
            command             = m_connection.CreateCommand();
            command.CommandText = commandString;

            using (reader = command.ExecuteReader())
            {
                while (reader.Read())
                {
                    Ticks          timeStamp = m_fakeTimestamps ? new Ticks(DateTime.UtcNow) : new Ticks(reader.GetInt64(timestampColumn));
                    MeasurementKey key       = MeasurementKey.LookUpBySignalID(reader.GetGuid(idColumn));
                    if (key != MeasurementKey.Undefined)
                    {
                        measurements.Add(new Measurement
                        {
                            Key       = key,
                            Value     = reader.GetDouble(valueColumn),
                            Timestamp = timeStamp
                        });
                    }
                }
            }
            OnNewMeasurements(measurements);
            m_startingMeasurement += m_measurementsPerInput;
        }
Exemple #18
0
        public void RefreshMetadata()
        {
            // Force a recalculation of input measurement keys so that system can appropriately update routing tables
            string setting;

            if (Settings.TryGetValue("inputMeasurementKeys", out setting))
            {
                InputMeasurementKeys = ParseInputMeasurementKeys(DataSource, true, setting);
            }
            else
            {
                InputMeasurementKeys = new MeasurementKey[0];
            }

            InputSourceIDs = InputSourceIDs;
            m_metadataRefreshOperation.RunOnceAsync();
        }
Exemple #19
0
        /// <summary>
        /// Creates an instance of <see cref="App"/> class.
        /// </summary>
        public App()
        {
            AppDomain.CurrentDomain.SetPrincipalPolicy(PrincipalPolicy.WindowsPrincipal);

            m_errorLogger                          = new ErrorLogger();
            m_defaultErrorText                     = m_errorLogger.ErrorTextMethod;
            m_errorLogger.ErrorTextMethod          = ErrorText;
            m_errorLogger.ExitOnUnhandledException = false;
            m_errorLogger.HandleUnhandledException = true;
            m_errorLogger.LogToEmail               = false;
            m_errorLogger.LogToEventLog            = true;
            m_errorLogger.LogToFile                = true;
            m_errorLogger.LogToScreenshot          = true;
            m_errorLogger.LogToUI                  = true;
            m_errorLogger.Initialize();

            m_title = AssemblyInfo.EntryAssembly.Title;

            // Setup default cache for measurement keys and associated Guid based signal ID's
            AdoDataConnection database = null;

            try
            {
                database = new AdoDataConnection(CommonFunctions.DefaultSettingsCategory);
                MeasurementKey.EstablishDefaultCache(database.Connection, database.AdapterType);
            }
            catch (Exception ex)
            {
                // First attempt to display a modal dialog will fail to block this
                // thread -- modal dialog displayed by the error logger will block now
                MessageBox.Show(ex.Message);

                // Log and display error, then exit application - manager must connect to database to continue
                m_errorLogger.Log(new InvalidOperationException(string.Format("{0} cannot connect to database: {1}", m_title, ex.Message), ex), true);
            }
            finally
            {
                if (database != null)
                {
                    database.Dispose();
                }
            }

            IsolatedStorageManager.WriteToIsolatedStorage("MirrorMode", false);
        }
Exemple #20
0
        /// <summary>
        /// Looks up measurement key from point tag.
        /// </summary>
        /// <param name="pointTag">Point tag to lookup.</param>
        /// <param name="source">Source metadata.</param>
        /// <returns>Measurement key from source metadata.</returns>
        /// <remarks>
        /// This function uses the <see cref="DataTable.Select(string)"/> function which uses a linear
        /// search algorithm that can be slow for large data sets, it is recommended that any results
        /// for calls to this function be cached to improve performance.
        /// </remarks>
        internal static MeasurementKey KeyFromTag(this string pointTag, DataSet source)
        {
            DataRow record = pointTag.MetadataRecordFromTag(source);

            if ((object)record == null)
            {
                return(MeasurementKey.Undefined);
            }

            try
            {
                return(MeasurementKey.LookUpOrCreate(record["SignalID"].ToNonNullString(Guid.Empty.ToString()).ConvertToType <Guid>(), record["ID"].ToString()));
            }
            catch
            {
                return(MeasurementKey.Undefined);
            }
        }
Exemple #21
0
        // 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);
        }
Exemple #22
0
        private string GetDescription(MeasurementKey key, TableOperations <ActiveMeasurement> table)
        {
            ActiveMeasurement measurement = table.QueryRecordWhere("SignalID = {0}", key.SignalID.ToString());
            string            text        = measurement.Description;
            string            stopAt      = measurement.PhasorType == 'I' ? "-I" : "-V";

            if (!string.IsNullOrWhiteSpace(text))
            {
                int charLocation = text.IndexOf(stopAt, StringComparison.Ordinal);

                if (charLocation > 0)
                {
                    return(text.Substring(0, charLocation));
                }
            }

            return(string.Empty);
        }
        // Lookup signal type for given measurement key
        private SignalType LookupSignalType(MeasurementKey key)
        {
            try
            {
                DataRow[] filteredRows = DataSource.Tables["ActiveMeasurements"].Select(string.Format("ID = '{0}'", key));

                if (filteredRows.Length > 0)
                {
                    return((SignalType)Enum.Parse(typeof(SignalType), filteredRows[0]["SignalType"].ToString(), true));
                }
            }
            catch (Exception ex)
            {
                OnProcessException(new InvalidOperationException(string.Format("Failed to lookup signal type for measurement {0}: {1}", key, ex.Message), ex));
            }

            return(SignalType.NONE);
        }
        private Measurement GetMeasurement(Guid signalID)
        {
            DataRow[] rows = DataSource.Tables["ActiveMeasurements"].Select($"SignalID = '{signalID}'");

            if (!rows.Any())
            {
                return(null);
            }

            Measurement measurement = new Measurement
            {
                Key        = MeasurementKey.LookUpBySignalID(signalID),
                TagName    = rows[0]["PointTag"].ToString(),
                Adder      = Convert.ToDouble(rows[0]["Adder"]),
                Multiplier = Convert.ToDouble(rows[0]["Multiplier"])
            };

            return(measurement);
        }
Exemple #25
0
        /// <summary>
        /// Gets the minimum retention time for the signal identified by the given key.
        /// </summary>
        /// <param name="key">The key that identifies the signal.</param>
        TimeSpan IMapper.GetMinimumRetentionTime(MeasurementKey key)
        {
            TimeSpan retentionTime;

            if (key == MeasurementKey.Undefined)
            {
                return(TimeSpan.Zero);
            }

            lock (m_minimumRetentionLock)
            {
                if (m_minimumRetentionTimes.TryGetValue(key, out retentionTime))
                {
                    return(retentionTime);
                }
            }

            return(TimeSpan.Zero);
        }
Exemple #26
0
        /// <summary>
        /// Get <see cref="MeasurementMetadata"/> for specified <see cref="SignalKind"/>.
        /// </summary>
        /// <param name="lookup">A lookup table by signal reference.</param>
        /// <param name="type"><see cref="SignalKind"/> to request signal reference for.</param>
        /// <param name="index">Index <see cref="SignalKind"/> to request signal reference for.</param>
        /// <param name="count">Number of signals defined for this <see cref="SignalKind"/>.</param>
        /// <returns>The MeasurementMetadata for a given <see cref="SignalKind"/>. Null if it does not exist.</returns>
        public MeasurementMetadata GetMetadata(Dictionary <string, MeasurementKey> lookup, SignalKind type, int index, int count)
        {
            // Clear the cache if the lookup dictionary has changed.
            // Since the instance of Lookup is effectively readonly as implemented in PhasorMeasurementMapper
            // a simple reference check is all that is needed. If it could be modified, this would likely be a
            // concurrent dictionary instead.
            if (m_keyLookupObject != lookup)
            {
                Array.Clear(m_generatedMeasurementKeyCache, 0, m_generatedMeasurementKeyCache.Length);
                m_keyLookupObject = lookup;
            }

            // Gets the cache for the supplied SignalKind
            int typeIndex = (int)type;

            MeasurementKey[] keyArray = m_generatedMeasurementKeyCache[typeIndex];

            // If this SignalKind is null, create the sub array and generate all item lookups, also, rebuild
            // if the count is not the same. This could be because a new config frame was received.
            if ((object)keyArray == null || keyArray.Length != count)
            {
                keyArray = new MeasurementKey[count];
                m_generatedMeasurementKeyCache[typeIndex] = keyArray;

                for (int x = 0; x < count; x++)
                {
                    string         signalReference = GetSignalReference(type, x, count);
                    MeasurementKey key;

                    if (lookup.TryGetValue(signalReference, out key))
                    {
                        keyArray[x] = key;
                    }
                    else
                    {
                        keyArray[x] = MeasurementKey.Undefined;
                    }
                }
            }

            return(keyArray[index]?.Metadata);
        }
        /// <summary>
        /// Read historian data from server.
        /// </summary>
        /// <param name="connection">openHistorian connection.</param>
        /// <param name="startTime">Start time of query.</param>
        /// <param name="stopTime">Stop time of query.</param>
        /// <param name="measurementIDs">Comma separated list of measurement IDs to query - or <c>null</c> for all available points.</param>
        /// <param name="resolution">Resolution for data query.</param>
        /// <returns>Enumeration of <see cref="IMeasurement"/> values read for time range.</returns>
        /// <example>
        /// <code>
        /// using (var connection = new Connection("127.0.0.1", "PPA"))
        ///     foreach(var measurement in GetHistorianData(connection, DateTime.UtcNow.AddMinutes(-1.0D), DateTime.UtcNow))
        ///         Console.WriteLine("{0}:{1} @ {2} = {3}, quality: {4}", measurement.Key.Source, measurement.Key.ID, measurement.Timestamp, measurement.Value, measurement.StateFlags);
        /// </code>
        /// </example>
        public static IEnumerable <IMeasurement> GetHistorianData(Connection connection, DateTime startTime, DateTime stopTime, string measurementIDs = null, Resolution resolution = Resolution.Full)
        {
            SeekFilterBase <HistorianKey> timeFilter;
            MatchFilterBase <HistorianKey, HistorianValue> pointFilter = null;
            HistorianKey   key   = new HistorianKey();
            HistorianValue value = new HistorianValue();

            // Set data scan resolution
            if (resolution == Resolution.Full)
            {
                timeFilter = TimestampSeekFilter.CreateFromRange <HistorianKey>(startTime, stopTime);
            }
            else
            {
                timeFilter = TimestampSeekFilter.CreateFromIntervalData <HistorianKey>(startTime, stopTime, resolution.GetInterval(), new TimeSpan(TimeSpan.TicksPerMillisecond));
            }

            // Setup point ID selections
            if (!string.IsNullOrEmpty(measurementIDs))
            {
                pointFilter = PointIdMatchFilter.CreateFromList <HistorianKey, HistorianValue>(measurementIDs.Split(',').Select(ulong.Parse));
            }

            // Start stream reader for the provided time window and selected points
            using (Database database = connection.OpenDatabase())
            {
                TreeStream <HistorianKey, HistorianValue> stream = database.Read(SortedTreeEngineReaderOptions.Default, timeFilter, pointFilter);

                while (stream.Read(key, value))
                {
                    yield return new Measurement()
                           {
                               Metadata   = MeasurementKey.LookUpOrCreate(connection.InstanceName, (uint)key.PointID).Metadata,
                               Timestamp  = key.TimestampAsDate,
                               Value      = value.AsSingle,
                               StateFlags = (MeasurementStateFlags)value.Value3
                           }
                }
                ;
            }
        }
Exemple #28
0
        /// <summary>
        /// Sets the minimum retention time for the signal identified by the given key.
        /// </summary>
        /// <param name="key">The key that identifies the signal.</param>
        /// <param name="retentionTime">The minimum amount of time measurements are to be retained by the signal buffer.</param>
        void IMapper.SetMinimumRetentionTime(MeasurementKey key, TimeSpan retentionTime)
        {
            if (key == MeasurementKey.Undefined)
            {
                return;
            }

            lock (m_minimumRetentionLock)
            {
                if (retentionTime != TimeSpan.Zero)
                {
                    m_minimumRetentionTimes[key] = retentionTime;
                }
                else
                {
                    m_minimumRetentionTimes.Remove(key);
                }
            }

            UpdateRetentionTimes();
            FixSignalBuffers();
        }
        /// <summary>
        /// Queries a signal buffer for the full collection of measurements over the given sample window.
        /// </summary>
        /// <param name="key">The key that identifies the signal to be queried.</param>
        /// <param name="frameTime">The time of the frame relative to which the sample window is defined.</param>
        /// <param name="window">The sample window that defines the range of time to be queried from the buffer.</param>
        /// <param name="resamplingStrategy">The strategy to use for alignment of data to the sample rate of the window.</param>
        /// <returns>The full collection of measurements for the given signal in the given sample window relative to the given frame time.</returns>
        public List <IMeasurement> GetMeasurements(MeasurementKey key, Ticks frameTime, SampleWindow window, ResamplingStrategy resamplingStrategy)
        {
            SignalBuffer signalBuffer;

            if (!m_signalBuffers.TryGetValue(key, out signalBuffer))
            {
                return(null);
            }

            switch (resamplingStrategy)
            {
            default:
            case ResamplingStrategy.NearestMeasurement:
                return(window.AlignNearest(signalBuffer, frameTime));

            case ResamplingStrategy.FillMissingData:
                return(window.AlignFill(signalBuffer, frameTime));

            case ResamplingStrategy.None:
                return(window.AlignNone(signalBuffer, frameTime));
            }
        }
Exemple #30
0
        private void HandleSendMeasurementsCommand(ClientConnection connection, byte[] buffer, int startIndex, int length)
        {
            int index = startIndex;

            if (length - index < 4)
            {
                throw new Exception("Not enough bytes in buffer to parse measurement count");
            }

            int count = BigEndian.ToInt32(buffer, index);

            index += sizeof(int);

            if (length - index < count * 36)
            {
                throw new Exception("Not enough bytes in buffer to parse all measurements");
            }

            List <IMeasurement> measurements = new List <IMeasurement>(count);

            for (int i = 0; i < count; i++)
            {
                Guid     signalID  = buffer.ToRfcGuid(index); index += 16;
                DateTime timestamp = new DateTime(BigEndian.ToInt64(buffer, index)); index += sizeof(long);
                double   value     = BigEndian.ToDouble(buffer, index); index += sizeof(double);
                MeasurementStateFlags stateFlags = (MeasurementStateFlags)BigEndian.ToInt32(buffer, index); index += sizeof(int);

                measurements.Add(new Measurement()
                {
                    Metadata   = MeasurementKey.LookUpBySignalID(signalID).Metadata,
                    Timestamp  = timestamp,
                    Value      = value,
                    StateFlags = stateFlags
                });
            }

            OnNewMeasurements(measurements);
        }
        /// <summary>
        /// Initializes <see cref="PhasorInputOscillationDetector" />.
        /// </summary>
        public override void Initialize()
        {
            InputCount  = 4;
            OutputCount = Outputs.Length;

            base.Initialize();

            MeasurementKey getMeasurementKey(SignalType signalType) => InputMeasurementKeys.Where((_, index) => InputMeasurementKeyTypes[index] == signalType).FirstOrDefault();

            const string ErrorPrefix = "Angle and magnitude measurements for both a voltage and current phasor are required inputs. ";
            const string ErrorSuffix = " input measurement is missing, cannot initialize adapter.";

            // Validate input contains voltage and current phase angle / magnitude measurement keys
            m_voltageMagnitude = getMeasurementKey(SignalType.VPHM) ?? throw new InvalidOperationException(ErrorPrefix + "Voltage magnitude" + ErrorSuffix);
            m_voltageAngle     = getMeasurementKey(SignalType.VPHA) ?? throw new InvalidOperationException(ErrorPrefix + "Voltage angle" + ErrorSuffix);
            m_currentMagnitude = getMeasurementKey(SignalType.IPHM) ?? throw new InvalidOperationException(ErrorPrefix + "Current magnitude" + ErrorSuffix);
            m_currentAngle     = getMeasurementKey(SignalType.IPHA) ?? throw new InvalidOperationException(ErrorPrefix + "Current angle" + ErrorSuffix);

            // Make sure input measurement keys are in desired order
            InputMeasurementKeys = new[] { m_voltageMagnitude, m_voltageAngle, m_currentMagnitude, m_currentAngle };

            // Provide algorithm with parameters as configured by adapter
            PseudoConfiguration configuration = new PseudoConfiguration
            {
                FramesPerSecond = FramesPerSecond,
                IsLineToNeutral = AdjustmentStrategy == VoltageAdjustmentStrategy.LineToNeutral
            };

            m_detector.DetectorAPI = new PseudoDetectorAPI
            {
                Configuration = configuration
            };

            m_detector.OutputMeasurements = OutputMeasurements;
            m_detector.FramesPerSecond    = FramesPerSecond;
            m_detector.InputTypes         = InputMeasurementKeyTypes;
            m_detector.Initialize(Name);
        }
Exemple #32
0
        private SignalType GetSignalType(MeasurementKey key, TableOperations <ActiveMeasurement> table)
        {
            ActiveMeasurement measurement = table.QueryRecordWhere("SignalID = {0}", key.SignalID.ToString());

            if (measurement.SignalType == "IPHM")
            {
                return(SignalType.IPHM);
            }
            if (measurement.SignalType == "IPHA")
            {
                return(SignalType.IPHA);
            }
            if (measurement.SignalType == "VPHM")
            {
                return(SignalType.VPHM);
            }
            if (measurement.SignalType == "VPHA")
            {
                return(SignalType.VPHA);
            }

            return(SignalType.NONE);
        }
        private void HistorianDataListener_DataExtracted(object sender, EventArgs <IList <IDataPoint> > e)
        {
            try
            {
                List <IMeasurement> measurements = new List <IMeasurement>();

                foreach (IDataPoint dataPoint in e.Argument)
                {
                    measurements.Add(new Measurement
                    {
                        Metadata  = MeasurementKey.LookUpOrCreate(m_historianDataListener.ID, (uint)dataPoint.HistorianID).Metadata,
                        Value     = dataPoint.Value,
                        Timestamp = dataPoint.Time
                    });
                }

                OnNewMeasurements(measurements);
            }
            catch (Exception ex)
            {
                OnProcessException(MessageLevel.Warning, ex);
            }
        }
Exemple #34
0
 /// <summary>
 /// Constructs a new <see cref="Measurement"/> given the specified parameters.
 /// </summary>
 /// <param name="id">Numeric ID of the new measurement.</param>
 /// <param name="source">Source name of the new measurement.</param>
 /// <param name="signalID"><see cref="Guid"/> based signal ID of the new measurement.</param>
 /// <param name="value">Value of the new measurement.</param>
 /// <param name="adder">Defined adder to apply to the new measurement.</param>
 /// <param name="multiplier">Defined multiplier to apply to the new measurement.</param>
 /// <param name="timestamp">Timestamp, in ticks, of the new measurement.</param>
 public Measurement(uint id, string source, Guid signalID, double value, double adder, double multiplier, Ticks timestamp)
 {
     m_id = id;
     m_source = source;
     m_key = new MeasurementKey(m_id, m_source);
     m_signalID = signalID;
     m_value = value;
     m_adder = adder;
     m_multiplier = multiplier;
     m_timestamp = timestamp;
     m_valueQualityIsGood = true;
     m_timestampQualityIsGood = true;
 }
        public void RefreshMetadata()
        {
            // Force a recalculation of input measurement keys so that system can appropriately update routing tables
            string setting;

            if (Settings.TryGetValue("inputMeasurementKeys", out setting))
                InputMeasurementKeys = ParseInputMeasurementKeys(DataSource, true, setting);
            else
                InputMeasurementKeys = new MeasurementKey[0];

            InputSourceIDs = InputSourceIDs;
            m_metadataRefreshOperation.RunOnceAsync();
        }
        /// <summary>
        /// Gets runtime signal index for given <see cref="Guid"/> signal ID.
        /// </summary>
        /// <param name="key">The <see cref="MeasurementKey"/> used to lookup associated runtime signal index.</param>
        /// <returns>Runtime signal index for given <see cref="MeasurementKey"/> <paramref name="key"/>.</returns>
        public ushort GetSignalIndex(MeasurementKey key)
        {
            int value = m_signalIDCache[key.RuntimeID];
            if (value < 0)
                return ushort.MaxValue;

            return (ushort)value;
        }
Exemple #37
0
        // Adds the given mapping to the key-variable map.
        private void AddMapping(MeasurementKey key, string alias)
        {
            if (m_variableNames.Contains(alias))
                throw new ArgumentException(string.Format("Variable name is not unique: {0}", alias));

            m_variableNames.Add(alias);
            m_keyMapping.Add(key, alias);
        }
Exemple #38
0
        // Add a measurement to the list of out of range measurements corresponding to the given key.
        private void AddOutOfRangeMeasurement(MeasurementKey key, IMeasurement measurement)
        {
            lock (m_outOfRangeMeasurements)
            {
                LinkedList<IMeasurement> outOfRangeList;

                if (!m_outOfRangeMeasurements.TryGetValue(key, out outOfRangeList))
                {
                    outOfRangeList = new LinkedList<IMeasurement>();
                    m_outOfRangeMeasurements.Add(key, outOfRangeList);
                }

                outOfRangeList.AddLast(measurement);
            }
        }
        /// <summary>
        /// Initializes <see cref="SynchronizedClientSubscription"/>.
        /// </summary>
        public override void Initialize()
        {
            MeasurementKey[] inputMeasurementKeys;
            string setting;

            if (Settings.TryGetValue("inputMeasurementKeys", out setting))
            {
                // IMPORTANT: The allowSelect argument of ParseInputMeasurementKeys must be null
                //            in order to prevent SQL injection via the subscription filter expression
                inputMeasurementKeys = AdapterBase.ParseInputMeasurementKeys(DataSource, false, setting);
                m_requestedInputFilter = setting;

                // IMPORTANT: We need to remove the setting before calling base.Initialize()
                //            or else we will still be subject to SQL injection
                Settings.Remove("inputMeasurementKeys");
            }
            else
            {
                inputMeasurementKeys = new MeasurementKey[0];
                m_requestedInputFilter = null;
            }

            base.Initialize();

            // Set the InputMeasurementKeys and UsePrecisionTimer properties after calling
            // base.Initialize() so that the base class does not overwrite our settings
            InputMeasurementKeys = inputMeasurementKeys;
            UsePrecisionTimer = false;

            if (Settings.TryGetValue("bufferBlockRetransmissionTimeout", out setting))
                m_bufferBlockRetransmissionTimeout = double.Parse(setting);
            else
                m_bufferBlockRetransmissionTimeout = 5.0D;

            if (Settings.TryGetValue("requestNaNValueFilter", out setting))
                m_isNaNFiltered = m_parent.AllowNaNValueFilter && setting.ParseBoolean();
            else
                m_isNaNFiltered = false;

            m_bufferBlockRetransmissionTimer = new Timer();
            m_bufferBlockRetransmissionTimer.AutoReset = false;
            m_bufferBlockRetransmissionTimer.Interval = m_bufferBlockRetransmissionTimeout * 1000.0D;
            m_bufferBlockRetransmissionTimer.Elapsed += BufferBlockRetransmissionTimer_Elapsed;

            // Handle temporal session initialization
            if (this.TemporalConstraintIsDefined())
                m_iaonSession = this.CreateTemporalSession();
        }
Exemple #40
0
        /// <summary>Associates a new measurement ID with a tag, creating the new tag if needed.</summary>
        /// <remarks>Allows you to define "grouped" points so you can aggregate certain measurements.</remarks>
        /// <param name="key">A <see cref="MeasurementKey"/> to associate with the tag.</param>
        /// <param name="tag">A <see cref="String"/> to represent the key.</param>
        public void AddTaggedMeasurement(string tag, MeasurementKey key)
        {
            // Check for new tag
            if (!m_taggedMeasurements.ContainsKey(tag))
                m_taggedMeasurements.Add(tag, new List<MeasurementKey>());

            // Add measurement to tag's measurement list
            List<MeasurementKey> measurements = m_taggedMeasurements[tag];

            if (measurements.BinarySearch(key) < 0)
            {
                measurements.Add(key);
                measurements.Sort();
            }
        }
Exemple #41
0
        /// <summary>Retrieves the specified immediate temporal measurement, creating it if needed.</summary>
        /// <param name="key">A <see cref="MeasurementKey"/> object indicating the key to use.</param>
        /// <returns>A <see cref="TemporalMeasurement"/> object.</returns>
        public TemporalMeasurement Measurement(MeasurementKey key)
        {
            lock (m_measurements)
            {
                TemporalMeasurement value;

                if (!m_measurements.TryGetValue(key, out value))
                {
                    // Create new temporal measurement if it doesn't exist
                    value = new TemporalMeasurement(key.ID, key.Source, double.NaN, m_parent.RealTime, m_parent.LagTime, m_parent.LeadTime);
                    m_measurements.Add(key, value);
                }

                return value;
            }
        }
Exemple #42
0
        /// <summary>
        /// Intializes <see cref="AdapterBase"/>.
        /// </summary>
        public virtual void Initialize()
        {
            Initialized = false;

            Dictionary<string, string> settings = Settings;
            string setting;

            if (settings.TryGetValue("inputMeasurementKeys", out setting))
                InputMeasurementKeys = AdapterBase.ParseInputMeasurementKeys(DataSource, setting);
            else
                InputMeasurementKeys = new MeasurementKey[0];

            if (settings.TryGetValue("outputMeasurements", out setting))
                OutputMeasurements = AdapterBase.ParseOutputMeasurements(DataSource, setting);

            if (settings.TryGetValue("measurementReportingInterval", out setting))
                MeasurementReportingInterval = int.Parse(setting);
            else
                MeasurementReportingInterval = DefaultMeasurementReportingInterval;

            if (settings.TryGetValue("connectOnDemand", out setting))
                AutoStart = !setting.ParseBoolean();
            else
                AutoStart = true;

            string startTime, stopTime, parameters;

            bool startTimeDefined = settings.TryGetValue("startTimeConstraint", out startTime);
            bool stopTimeDefined = settings.TryGetValue("stopTimeConstraint", out stopTime);

            if (startTimeDefined || stopTimeDefined)
            {
                settings.TryGetValue("timeConstraintParameters", out parameters);
                SetTemporalConstraint(startTime, stopTime, parameters);
            }

            int processingInterval;

            if (settings.TryGetValue("processingInterval", out setting) && !string.IsNullOrWhiteSpace(setting) && int.TryParse(setting, out processingInterval))
                ProcessingInterval = processingInterval;

            if (settings.TryGetValue("dependencyTimeout", out setting))
                m_dependencyTimeout = Ticks.FromSeconds(double.Parse(setting));
            else
                m_dependencyTimeout = Ticks.PerSecond / 30L;
        }
Exemple #43
0
        /// <summary>
        /// Initializes <see cref="ActionAdapterBase"/>.
        /// </summary>
        public virtual void Initialize()
        {
            Initialized = false;

            Dictionary<string, string> settings = Settings;
            const string errorMessage = "{0} is missing from Settings - Example: framesPerSecond=30; lagTime=3; leadTime=1";
            string setting;

            // Load required parameters
            if (!settings.TryGetValue("framesPerSecond", out setting))
                throw new ArgumentException(string.Format(errorMessage, "framesPerSecond"));

            base.FramesPerSecond = int.Parse(setting);

            if (!settings.TryGetValue("lagTime", out setting))
                throw new ArgumentException(string.Format(errorMessage, "lagTime"));

            base.LagTime = double.Parse(setting);

            if (!settings.TryGetValue("leadTime", out setting))
                throw new ArgumentException(string.Format(errorMessage, "leadTime"));

            base.LeadTime = double.Parse(setting);

            // Load optional parameters
            if (settings.TryGetValue("usePrecisionTimer", out setting))
                UsePrecisionTimer = setting.ParseBoolean();

            if (settings.TryGetValue("useLocalClockAsRealTime", out setting))
                UseLocalClockAsRealTime = setting.ParseBoolean();

            if (settings.TryGetValue("ignoreBadTimestamps", out setting))
                IgnoreBadTimestamps = setting.ParseBoolean();

            if (settings.TryGetValue("allowSortsByArrival", out setting))
                AllowSortsByArrival = setting.ParseBoolean();

            if (settings.TryGetValue("inputMeasurementKeys", out setting))
                InputMeasurementKeys = AdapterBase.ParseInputMeasurementKeys(DataSource, true, setting);
            else
                InputMeasurementKeys = new MeasurementKey[0];

            if (settings.TryGetValue("outputMeasurements", out setting))
                OutputMeasurements = AdapterBase.ParseOutputMeasurements(DataSource, true, setting);

            if (settings.TryGetValue("minimumMeasurementsToUse", out setting))
                MinimumMeasurementsToUse = int.Parse(setting);

            if (settings.TryGetValue("timeResolution", out setting))
                TimeResolution = long.Parse(setting);

            if (settings.TryGetValue("allowPreemptivePublishing", out setting))
                AllowPreemptivePublishing = setting.ParseBoolean();

            if (settings.TryGetValue("performTimestampReasonabilityCheck", out setting))
                PerformTimestampReasonabilityCheck = setting.ParseBoolean();

            if (settings.TryGetValue("processByReceivedTimestamp", out setting))
                ProcessByReceivedTimestamp = setting.ParseBoolean();

            if (settings.TryGetValue("trackPublishedTimestamp", out setting))
                TrackPublishedTimestamp = setting.ParseBoolean();

            if (settings.TryGetValue("maximumPublicationTimeout", out setting))
                MaximumPublicationTimeout = int.Parse(setting);

            if (settings.TryGetValue("downsamplingMethod", out setting))
            {
                DownsamplingMethod method;

                if (Enum.TryParse(setting, true, out method))
                {
                    DownsamplingMethod = method;
                }
                else
                {
                    OnStatusMessage("WARNING: No down-sampling method labeled \"{0}\" exists, \"LastReceived\" method was selected.", setting);
                    DownsamplingMethod = DownsamplingMethod.LastReceived;
                }
            }

            if (settings.TryGetValue("inputSourceIDs", out setting))
                InputSourceIDs = setting.Split(',');

            if (settings.TryGetValue("outputSourceIDs", out setting))
                OutputSourceIDs = setting.Split(',');

            if (settings.TryGetValue("connectOnDemand", out setting))
                AutoStart = !setting.ParseBoolean();
            else
                AutoStart = true;

            if (settings.TryGetValue("respectInputDemands", out setting))
                RespectInputDemands = setting.ParseBoolean();
            else
                RespectInputDemands = false;

            if (settings.TryGetValue("respectOutputDemands", out setting))
                RespectOutputDemands = setting.ParseBoolean();
            else
                RespectOutputDemands = true;

            string startTime, stopTime, parameters;

            bool startTimeDefined = settings.TryGetValue("startTimeConstraint", out startTime);
            bool stopTimeDefined = settings.TryGetValue("stopTimeConstraint", out stopTime);

            if (startTimeDefined || stopTimeDefined)
            {
                settings.TryGetValue("timeConstraintParameters", out parameters);
                SetTemporalConstraint(startTime, stopTime, parameters);
            }

            int processingInterval;

            if (settings.TryGetValue("processingInterval", out setting) && !string.IsNullOrWhiteSpace(setting) && int.TryParse(setting, out processingInterval))
                ProcessingInterval = processingInterval;
        }
        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);
        }
Exemple #45
0
        /// <summary>
        /// Prepares the adapter to query data for the points that have been requested for connect on demand. The adapter will
        /// look up PI tag names and start up the thread to start the timers and threads necessary to run.
        /// </summary>
        /// <param name="keys"></param>
        private void HandleNewMeasurementsRequest(MeasurementKey[] keys)
        {
            if (!IsConnected)
                AttemptConnection();

            StopGettingData();

            if (keys != null && keys.Length > 0)
            {
                var query = from row in DataSource.Tables["ActiveMeasurements"].AsEnumerable()
                            from key in keys
                            where row["ID"].ToString().Split(':')[1] == key.ID.ToString() && row["PROTOCOL"].ToString() == "PI"
                            select new
                            {
                                Key = key, AlternateTag = row["ALTERNATETAG"].ToString(), PointTag = row["POINTTAG"].ToString()
                            };

                StringBuilder whereClause = new StringBuilder();

                foreach (var result in query)
                {
                    string tagname = result.PointTag;
                    if (!String.IsNullOrWhiteSpace(result.AlternateTag))
                        tagname = result.AlternateTag;

                    if (!m_tagKeyMap.ContainsKey(tagname))
                        m_tagKeyMap.Add(tagname, result.Key);

                    if (whereClause.Length > 0)
                        whereClause.Append(" OR ");

                    whereClause.Append(string.Format("tag='{0}'", tagname));
                }

                // Store this filtering string for when the PointList is created during query
                m_tagFilter = whereClause.ToString();

                ThreadPool.QueueUserWorkItem(StartGettingData);
            }
        }
Exemple #46
0
        /// <summary>
        /// Initializes <see cref="SerializableMeasurement"/> from the specified binary image.
        /// </summary>
        /// <param name="buffer">Buffer containing binary image to parse.</param>
        /// <param name="startIndex">0-based starting index in the <paramref name="buffer"/> to start parsing.</param>
        /// <param name="length">Valid number of bytes within <paramref name="buffer"/> from <paramref name="startIndex"/>.</param>
        /// <returns>The number of bytes used for initialization in the <paramref name="buffer"/> (i.e., the number of bytes parsed).</returns>
        /// <exception cref="InvalidOperationException">Not enough buffer available to deserialize measurement.</exception>
        /// <exception cref="ArgumentNullException"><paramref name="buffer"/> is null.</exception>
        /// <exception cref="ArgumentOutOfRangeException">
        /// <paramref name="startIndex"/> or <paramref name="length"/> is less than 0 -or- 
        /// <paramref name="startIndex"/> and <paramref name="length"/> will exceed <paramref name="buffer"/> length.
        /// </exception>
        public int ParseBinaryImage(byte[] buffer, int startIndex, int length)
        {
            buffer.ValidateParameters(startIndex, length);

            if (length < FixedLength)
                throw new InvalidOperationException("Not enough buffer available to deserialize measurement");

            int size, index = startIndex;
            uint keyID;
            string keySource = "";

            // Decode key ID
            keyID = EndianOrder.BigEndian.ToUInt32(buffer, index);
            index += 4;

            // Decode key source string length
            size = EndianOrder.BigEndian.ToInt32(buffer, index);
            index += 4;

            // Decode key source string
            if (size > 0)
            {
                keySource = m_encoding.GetString(buffer, index, size);
                index += size;
            }

            // Decode signal ID
            ID = EndianOrder.BigEndian.ToGuid(buffer, index);
            index += 16;

            // Apply parsed key changes
            Key = new MeasurementKey(ID, keyID, keySource);

            // Decode tag name string length
            size = EndianOrder.BigEndian.ToInt32(buffer, index);
            index += 4;

            // Decode tag name string
            if (size > 0)
            {
                TagName = m_encoding.GetString(buffer, index, size);
                index += size;
            }
            else
                TagName = null;

            // Decode value
            Value = EndianOrder.BigEndian.ToDouble(buffer, index);
            index += 8;

            // Decode adder
            Adder = EndianOrder.BigEndian.ToDouble(buffer, index);
            index += 8;

            // Decode multiplier
            Multiplier = EndianOrder.BigEndian.ToDouble(buffer, index);
            index += 8;

            // Decode timestamp
            Timestamp = EndianOrder.BigEndian.ToInt64(buffer, index);
            index += 8;

            // Decode state flags
            StateFlags = (MeasurementStateFlags)EndianOrder.BigEndian.ToUInt32(buffer, index);
            index += 4;

            return (index - startIndex);
        }
        /// <summary>
        /// Initializes <see cref="UnsynchronizedClientSubscription"/>.
        /// </summary>
        public override void Initialize()
        {
            MeasurementKey[] inputMeasurementKeys;
            string setting;

            if (Settings.TryGetValue("inputMeasurementKeys", out setting))
            {
                // IMPORTANT: The allowSelect argument of ParseInputMeasurementKeys must be null
                //            in order to prevent SQL injection via the subscription filter expression
                inputMeasurementKeys = ParseInputMeasurementKeys(DataSource, false, setting);
                m_requestedInputFilter = setting;

                // IMPORTANT: We need to remove the setting before calling base.Initialize()
                //            or else we will still be subject to SQL injection
                Settings.Remove("inputMeasurementKeys");
            }
            else
            {
                inputMeasurementKeys = new MeasurementKey[0];
                m_requestedInputFilter = null;
            }

            base.Initialize();

            // Set the InputMeasurementKeys property after calling base.Initialize()
            // so that the base class does not overwrite our setting
            InputMeasurementKeys = inputMeasurementKeys;

            if (Settings.TryGetValue("publishInterval", out setting))
                m_publishInterval = int.Parse(setting);
            else
                m_publishInterval = -1;

            if (Settings.TryGetValue("includeTime", out setting))
                m_includeTime = setting.ParseBoolean();
            else
                m_includeTime = true;

            if (Settings.TryGetValue("useMillisecondResolution", out setting))
                m_useMillisecondResolution = setting.ParseBoolean();
            else
                m_useMillisecondResolution = false;

            if (Settings.TryGetValue("requestNaNValueFilter", out setting))
                m_isNaNFiltered = m_parent.AllowNaNValueFilter && setting.ParseBoolean();
            else
                m_isNaNFiltered = false;

            if (Settings.TryGetValue("bufferBlockRetransmissionTimeout", out setting))
                m_bufferBlockRetransmissionTimeout = double.Parse(setting);
            else
                m_bufferBlockRetransmissionTimeout = 5.0D;

            if (m_parent.UseBaseTimeOffsets && m_includeTime)
            {
                m_baseTimeRotationTimer = Common.TimerScheduler.CreateTimer(m_useMillisecondResolution ? 60000 : 420000);
                m_baseTimeRotationTimer.AutoReset = true;
                m_baseTimeRotationTimer.Elapsed += BaseTimeRotationTimer_Elapsed;
            }

            m_bufferBlockRetransmissionTimer = Common.TimerScheduler.CreateTimer((int)(m_bufferBlockRetransmissionTimeout * 1000.0D));
            m_bufferBlockRetransmissionTimer.AutoReset = false;
            m_bufferBlockRetransmissionTimer.Elapsed += BufferBlockRetransmissionTimer_Elapsed;

            // Handle temporal session initialization
            if (this.TemporalConstraintIsDefined())
                m_iaonSession = this.CreateTemporalSession();
        }
Exemple #48
0
        // Gets a measurement key based on a token which
        // may be either a signal ID or measurement key.
        private MeasurementKey GetKey(string token)
        {
            MeasurementKey undefined;
            Guid signalId;

            MeasurementKey key;

            if (Guid.TryParse(token, out signalId))
            {
                // Defined using the measurement's GUID
                undefined = MeasurementKey.Undefined;
                key = new MeasurementKey(signalId, undefined.ID, undefined.Source);
            }
            else
            {
                // Defined using the measurement's key
                key = MeasurementKey.Parse(token);
            }

            return key;
        }
Exemple #49
0
 /// <summary>
 /// Determines if specified measurement key is defined in <see cref="InputMeasurementKeys"/>.
 /// </summary>
 /// <param name="item">Primary key of measurement to find.</param>
 /// <returns>true if specified measurement key is defined in <see cref="InputMeasurementKeys"/>.</returns>
 public virtual bool IsInputMeasurement(MeasurementKey item)
 {
     return (m_inputMeasurementKeysHash.BinarySearch(item) >= 0);
 }
Exemple #50
0
        /// <summary>
        /// Intializes <see cref="AdapterBase"/>.
        /// </summary>
        public virtual void Initialize()
        {
            Initialized = false;

            Dictionary<string, string> settings = Settings;
            string setting;

            if (settings.TryGetValue("inputMeasurementKeys", out setting))
                InputMeasurementKeys = AdapterBase.ParseInputMeasurementKeys(DataSource, setting);
            else
                InputMeasurementKeys = new MeasurementKey[0];

            if (settings.TryGetValue("outputMeasurements", out setting))
                OutputMeasurements = AdapterBase.ParseOutputMeasurements(DataSource, setting);

            if (settings.TryGetValue("measurementReportingInterval", out setting))
                MeasurementReportingInterval = int.Parse(setting);
            else
                MeasurementReportingInterval = DefaultMeasurementReportingInterval;

            if (settings.TryGetValue("connectOnDemand", out setting))
                AutoStart = !setting.ParseBoolean();
            else
                AutoStart = true;

            string startTime, stopTime, parameters;

            bool startTimeDefined = settings.TryGetValue("startTimeConstraint", out startTime);
            bool stopTimeDefined = settings.TryGetValue("stopTimeConstraint", out stopTime);

            if (startTimeDefined || stopTimeDefined)
            {
                settings.TryGetValue("timeConstraintParameters", out parameters);
                SetTemporalConstraint(startTime, stopTime, parameters);
            }

            int processingInterval;

            if (settings.TryGetValue("processingInterval", out setting) && !setting.IsNullOrWhiteSpace() && int.TryParse(setting, out processingInterval))
                ProcessingInterval = processingInterval;

//            // Establish any defined external event wait handles needed for inter-adapter synchronization
//            if (settings.TryGetValue("waitHandleNames", out setting) && !setting.IsNullOrWhiteSpace())
//                m_externalEventHandles = setting.Split(',').Select(GetExternalEventHandle).ToArray();

            int waitHandleTimeout;

            if (settings.TryGetValue("waitHandleTimeout", out setting) && !setting.IsNullOrWhiteSpace() && int.TryParse(setting, out waitHandleTimeout))
                m_externalEventTimeout = waitHandleTimeout;
            else
                m_externalEventTimeout = 33;
        }
Exemple #51
0
        /// <summary>
        /// Initializes <see cref="CompactMeasurement"/> from the specified binary image.
        /// </summary>
        /// <param name="buffer">Buffer containing binary image to parse.</param>
        /// <param name="startIndex">0-based starting index in the <paramref name="buffer"/> to start parsing.</param>
        /// <param name="length">Valid number of bytes within <paramref name="buffer"/> from <paramref name="startIndex"/>.</param>
        /// <returns>The number of bytes used for initialization in the <paramref name="buffer"/> (i.e., the number of bytes parsed).</returns>
        /// <exception cref="InvalidOperationException">Not enough buffer available to deserialize measurement.</exception>
        /// <exception cref="ArgumentNullException"><paramref name="buffer"/> is null.</exception>
        /// <exception cref="ArgumentOutOfRangeException">
        /// <paramref name="startIndex"/> or <paramref name="length"/> is less than 0 -or- 
        /// <paramref name="startIndex"/> and <paramref name="length"/> will exceed <paramref name="buffer"/> length.
        /// </exception>
        public int ParseBinaryImage(byte[] buffer, int startIndex, int length)
        {
            buffer.ValidateParameters(startIndex, length);

            if (length < 1)
                throw new InvalidOperationException("Not enough buffer available to deserialize measurement.");

            // Decode flags
            CompactMeasurementStateFlags flags = (CompactMeasurementStateFlags)buffer[startIndex];
            StateFlags = flags.MapToFullFlags();
            m_timeIndex = (flags & CompactMeasurementStateFlags.TimeIndex) > 0 ? 1 : 0;
            m_usingBaseTimeOffset = (flags & CompactMeasurementStateFlags.BaseTimeOffset) > 0;

            int index = startIndex + 1;

            // Decode runtime ID
            ushort id = EndianOrder.BigEndian.ToUInt16(buffer, index);
            index += 2;

            // Restore signal identification
            Tuple<Guid, string, uint> tuple;

            if (m_signalIndexCache.Reference.TryGetValue(id, out tuple))
            {
                ID = tuple.Item1;
                Key = new MeasurementKey(tuple.Item1, tuple.Item3, tuple.Item2);
            }
            else
                throw new InvalidOperationException("Failed to find associated signal identification for runtime ID " + id);

            // Decode value
            Value = EndianOrder.BigEndian.ToSingle(buffer, index);
            index += 4;

            if (m_includeTime)
            {
                if (m_usingBaseTimeOffset)
                {
                    long baseTimeOffset = m_baseTimeOffsets[m_timeIndex];

                    if (m_useMillisecondResolution)
                    {
                        // Decode 2-byte millisecond offset timestamp
                        if (baseTimeOffset > 0)
                            Timestamp = baseTimeOffset + EndianOrder.BigEndian.ToUInt16(buffer, index) * Ticks.PerMillisecond;

                        index += 2;
                    }
                    else
                    {
                        // Decode 4-byte tick offset timestamp
                        if (baseTimeOffset > 0)
                            Timestamp = baseTimeOffset + EndianOrder.BigEndian.ToUInt32(buffer, index);

                        index += 4;
                    }
                }
                else
                {
                    // Decode 8-byte full fidelity timestamp
                    Timestamp = EndianOrder.BigEndian.ToInt64(buffer, index);
                    index += 8;
                }
            }

            return (index - startIndex);
        }
Exemple #52
0
        /// <summary>
        /// Determines if specified measurement key is defined in <see cref="InputMeasurementKeys"/>.
        /// </summary>
        /// <param name="item">Primary key of measurement to find.</param>
        /// <returns>true if specified measurement key is defined in <see cref="InputMeasurementKeys"/>.</returns>
        public virtual bool IsInputMeasurement(MeasurementKey item)
        {
            if (m_inputMeasurementKeysHash != null)
                return (m_inputMeasurementKeysHash.BinarySearch(item) >= 0);

            // If no input measurements are defined we must assume user wants to accept all measurements - yikes!
            return true;
        }
Exemple #53
0
 /// <summary>
 /// Get a collection of out-of-range <see cref="IMeasurement"/>s with the given key.
 /// </summary>
 /// <param name="key">The <see cref="MeasurementKey"/> corresponding to the desired measurements.</param>
 /// <returns>A collection of out-of-range <see cref="IMeasurement"/>s.</returns>
 public ICollection<IMeasurement> GetOutOfRangeMeasurements(MeasurementKey key)
 {
     lock (m_outOfRangeMeasurements)
     {
         PurgeOldMeasurements(key);
         return new LinkedList<IMeasurement>(m_outOfRangeMeasurements[key]);
     }
 }
Exemple #54
0
        // Purge old, out-of-range measurements with the given key.
        private void PurgeOldMeasurements(MeasurementKey key)
        {
            lock (m_outOfRangeMeasurements)
            {
                LinkedList<IMeasurement> measurements = m_outOfRangeMeasurements[key];
                bool donePurging = false;

                // Purge old measurements to prevent redundant warnings.
                while (measurements.Count > 0 && !donePurging)
                {
                    IMeasurement measurement = measurements.First.Value;
                    Ticks diff = base.RealTime - measurement.Timestamp;

                    if (diff >= base.LagTicks + m_timeToPurge)
                        measurements.RemoveFirst();
                    else
                        donePurging = true;
                }
            }
        }
Exemple #55
0
        private void HandleNewMeasurementsRequest(MeasurementKey[] Keys)
        {
            OnStatusMessage("Received request for {0} keys...", new object[] { Keys.Count() });

            if (!IsConnected)
                AttemptConnection();

            var query = from row in DataSource.Tables["ActiveMeasurements"].AsEnumerable()
                        from key in Keys
                        where row["ID"].ToString().Split(':')[1] == key.ID.ToString()
                        select new { Key = key, AlternateTag = row["ALTERNATETAG"].ToString(), PointTag = row["POINTTAG"].ToString() };

            StringBuilder tagFilter = new StringBuilder();
            foreach (var row in query)
            {
                string tagname = row.PointTag;
                if (!String.IsNullOrWhiteSpace(row.AlternateTag))
                    tagname = row.AlternateTag;

                if (!m_tagKeyMap.ContainsKey(tagname))
                {
                    m_tagKeyMap.AddOrUpdate(tagname, row.Key, (k, v) => row.Key);
                }

                if (tagFilter.Length > 0)
                    tagFilter.Append(" OR ");

                tagFilter.Append(string.Format("tag='{0}'", tagname));
            }

            m_points = m_server.GetPoints(tagFilter.ToString());

            // event pipes are only applicable if enabled in connection string and this is a real time session, not playback
            bool useEventPipes = m_useEventPipes && StartTimeConstraint == DateTime.MinValue && StopTimeConstraint == DateTime.MaxValue;
            if (useEventPipes)
            {
                try
                {
                    if (m_pipe != null)
                        ((_DEventPipeEvents_Event)m_pipe).OnNewValue -= (PISDK._DEventPipeEvents_OnNewValueEventHandler)PipeOnOnNewValue;

                    m_pipe = m_points.Data.EventPipe;
                    ((_DEventPipeEvents_Event)m_pipe).OnNewValue += (PISDK._DEventPipeEvents_OnNewValueEventHandler)PipeOnOnNewValue;
                }
                catch (ThreadAbortException) { throw; }
                catch (Exception e)
                {
                    useEventPipes = false; // try to run with polling instead of event pipes;
                    OnProcessException(e);
                }
            }

            if (!useEventPipes)
            {
                // warn that we are going to use a different configuration here...
                if (m_useEventPipes)
                    OnStatusMessage("WARNING: PI adapter switching from event pipes to polling due to error or start/stop time constraints.");

                // set up a new thread to do some long calls to PI and set up threads, timers, etc for polling
                StopGettingData();
                ThreadPool.QueueUserWorkItem(StartGettingData, tagFilter);
            }

            m_useEventPipes = useEventPipes;
        }
Exemple #56
0
 /// <summary>
 /// Spawn routing tables recalculation.
 /// </summary>
 /// <param name="inputMeasurementKeysRestriction">Input measurement keys restriction.</param>
 /// <remarks>
 /// Set the <paramref name="inputMeasurementKeysRestriction"/> to null to use full adapter I/O routing demands.
 /// </remarks>
 public virtual void CalculateRoutingTables(MeasurementKey[] inputMeasurementKeysRestriction)
 {
     try
     {
         m_inputMeasurementKeysRestriction = inputMeasurementKeysRestriction;
         m_calculateRoutingTablesOperation.RunOnceAsync();
     }
     catch (Exception ex)
     {
         // Process exception for logging
         OnProcessException(new InvalidOperationException("Failed to queue routing table calculation: " + ex.Message, ex));
     }
 }