Beispiel #1
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>
        /// <returns>The <see cref="MeasurementMetadata"/> for a given <see cref="SignalKind"/>; otherwise <c>null</c> if value does not exist.</returns>
        public MeasurementMetadata GetMetadata(Dictionary <string, MeasurementMetadata> lookup, SignalKind type)
        {
            // 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_metadataLookupObject != lookup)
            {
                Array.Clear(m_generatedMeasurementMetadataCache, 0, m_generatedMeasurementMetadataCache.Length);
                m_metadataLookupObject = lookup;
            }

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

            MeasurementMetadata[] metadataArray = m_generatedMeasurementMetadataCache[typeIndex];

            // If this SignalKind is null, create the sub array and generate all item lookups
            if ((object)metadataArray == null)
            {
                metadataArray = new MeasurementMetadata[1];
                m_generatedMeasurementMetadataCache[typeIndex] = metadataArray;

                string signalReference = GetSignalReference(type);
                MeasurementMetadata metadata;

                if (lookup.TryGetValue(signalReference, out metadata))
                {
                    metadataArray[0] = metadata;
                }
            }

            return(metadataArray[0]);
        }
        public static bool TryGetMeasurementMetdataFromConfigurationFrame(System.Guid signalID, ConfigurationFrame sourceFrame, out MeasurementMetadata measurementMetadata)
        {
            guid_t tempsignalID = Common.ParseGuid(signalID.ToByteArray(), true);

            measurementMetadata = new MeasurementMetadata();
            {
                bool ret = CommonPINVOKE.SubscriberInstanceBase_TryGetMeasurementMetdataFromConfigurationFrame(guid_t.getCPtr(tempsignalID), ConfigurationFrame.getCPtr(sourceFrame), MeasurementMetadata.getCPtr(measurementMetadata));
                if (CommonPINVOKE.SWIGPendingException.Pending)
                {
                    throw CommonPINVOKE.SWIGPendingException.Retrieve();
                }
                return(ret);
            }
        }
Beispiel #3
0
        private static void MapMeasurementAttributes(ICollection <IMeasurement> mappedMeasurements, string signalReference, IMeasurement parsedMeasurement)
        {
            // Coming into this function the parsed measurement value will only have a "value" and a "timestamp";
            // the measurement will not yet be associated with an actual historian measurement ID as the measurement
            // will have come directly out of the parsed phasor protocol data frame.  We take the generated signal
            // reference and use that to lookup the actual historian measurement ID, source, adder and multipler.
            MeasurementMetadata definedMeasurement = m_definedMeasurements.GetOrAdd(signalReference,
                                                                                    signal => MeasurementKey.LookUpOrCreate(Guid.NewGuid(), signal, ++measurementID).Metadata);

            // Assign ID and other relevant attributes to the parsed measurement value
            parsedMeasurement.Metadata = definedMeasurement;

            // Add the updated measurement value to the destination measurement collection
            mappedMeasurements.Add(parsedMeasurement);
        }
Beispiel #4
0
        private void PublishRandomValues()
        {
            const ulong Interval = 1000;

            // If metadata can change, the following integer should not be static:
            int  count     = m_measurementMetadata.Count;
            long timestamp = RoundToSubsecondDistribution(DateTime.UtcNow.Ticks, 30);

            Measurement[] measurements = new Measurement[count];
            Random        rand         = new Random();

            // Create new measurement values for publication
            for (int i = 0; i < count; i++)
            {
                MeasurementMetadata metadata    = m_measurementMetadata[i];
                Measurement         measurement = new Measurement(metadata.SignalID, timestamp);

                double randFraction = rand.NextDouble();
                double sign         = randFraction > 0.5D ? 1.0D : -1.0D;

                measurement.Value = metadata.Reference.Kind switch
                {
                    SignalKind.Frequency => 60.0D + sign * randFraction * 0.1D,
                    SignalKind.DfDt => sign * randFraction * 2.0D,
                    SignalKind.Magnitude => 500.0D + sign * randFraction * 50.0D,
                    SignalKind.Angle => sign * randFraction * 180.0D,
                    _ => sign * randFraction * uint.MaxValue
                };

                measurements[i] = measurement;
            }

            // Publish measurements
            PublishMeasurements(measurements);

            // Display a processing message every few seconds
            bool showMessage = m_processCount + (ulong)count >= (m_processCount / Interval + 1) * Interval && GetTotalMeasurementsSent() > 0;

            m_processCount += (ulong)count;

            if (showMessage)
            {
                StatusMessage($"{GetTotalMeasurementsSent()} measurements published so far...\n");
            }
        }
Beispiel #5
0
        //Later, a more sophisticated factory method is required
        public RowReaderWriter CreateRowReaderWriter(MeasurementMetadata metadata)
        {
            var valueType = metadata.ColumnsInternal[1].ValueType;

            if (valueType == typeof(float))
            {
                return(new FloatRowReaderWriter());
            }
            if (valueType == typeof(double))
            {
                return(new DoubleRowReaderWriter());
            }
            if (valueType == typeof(bool))
            {
                return(new BoolRowReaderWriter());
            }
            if (valueType == typeof(byte))
            {
                return(new ByteRowReaderWriter());
            }
            if (valueType == typeof(short))
            {
                return(new ShortRowReaderWriter());
            }
            if (valueType == typeof(int))
            {
                return(new IntRowReaderWriter());
            }
            if (valueType == typeof(long))
            {
                return(new LongRowReaderWriter());
            }
            if (valueType == typeof(decimal))
            {
                return(new DecimalRowReaderWriter());
            }
            if (valueType == typeof(DateTime))
            {
                return(new DateTimeRowReaderWriter());
            }

            throw new NotSupportedException("Invalid column type");
        }
Beispiel #6
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, MeasurementMetadata> 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_metadataLookupObject != lookup)
            {
                Array.Clear(m_generatedMeasurementMetadataCache, 0, m_generatedMeasurementMetadataCache.Length);
                m_metadataLookupObject = lookup;
            }

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

            MeasurementMetadata[] metadataArray = m_generatedMeasurementMetadataCache[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)metadataArray == null || metadataArray.Length != count)
            {
                metadataArray = new MeasurementMetadata[count];
                m_generatedMeasurementMetadataCache[typeIndex] = metadataArray;

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

                    if (lookup.TryGetValue(signalReference, out metadata))
                    {
                        metadataArray[x] = metadata;
                    }
                }
            }

            return(metadataArray[index]);
        }
Beispiel #7
0
        // In this example we use predefined structures to setup synchrophasor style metadata. This is only for setup simplification of
        // the initial target uses cases that interact with IEEE C37.118. Technically the publisher can create its own metadata sets.
        private void DefineMetadata()
        {
            // This sample just generates random Guid measurement and device identifiers - for a production system,
            // these Guid values would need to persist between runs defining a permanent association between the
            // defined metadata and the identifier...

            DeviceMetadata device1Metadata = new DeviceMetadata();
            DateTime       timestamp       = DateTime.UtcNow;

            // Add a device
            device1Metadata.Name            = "Test PMU";
            device1Metadata.Acronym         = device1Metadata.Name.Replace(" ", "").ToUpper();
            device1Metadata.UniqueID        = Guid.NewGuid();
            device1Metadata.Longitude       = 300;
            device1Metadata.Latitude        = 200;
            device1Metadata.FramesPerSecond = 30;
            device1Metadata.ProtocolName    = "STTP";
            device1Metadata.UpdatedOn       = timestamp;

            m_deviceMetadata.Add(device1Metadata);

            string pointTagPrefix    = device1Metadata.Acronym + ".";
            string measurementSource = "PPA:";
            int    runtimeIndex      = 1;

            // Add a frequency measurement
            MeasurementMetadata measurement1Metadata = new MeasurementMetadata();

            measurement1Metadata.ID                = $"{measurementSource}{runtimeIndex++}";
            measurement1Metadata.PointTag          = pointTagPrefix + "FREQ";
            measurement1Metadata.SignalID          = Guid.NewGuid();
            measurement1Metadata.DeviceAcronym     = device1Metadata.Acronym;
            measurement1Metadata.Reference.Acronym = device1Metadata.Acronym;
            measurement1Metadata.Reference.Kind    = SignalKind.Frequency;
            measurement1Metadata.Reference.Index   = 0;
            measurement1Metadata.PhasorSourceIndex = 0;
            measurement1Metadata.UpdatedOn         = timestamp;

            // Add a dF/dt measurement
            MeasurementMetadata measurement2Metadata = new MeasurementMetadata();

            measurement2Metadata.ID                = $"{measurementSource}{runtimeIndex++}";
            measurement2Metadata.PointTag          = pointTagPrefix + "DFDT";
            measurement2Metadata.SignalID          = Guid.NewGuid();
            measurement2Metadata.DeviceAcronym     = device1Metadata.Acronym;
            measurement2Metadata.Reference.Acronym = device1Metadata.Acronym;
            measurement2Metadata.Reference.Kind    = SignalKind.DfDt;
            measurement2Metadata.Reference.Index   = 0;
            measurement2Metadata.PhasorSourceIndex = 0;
            measurement2Metadata.UpdatedOn         = timestamp;

            // Add a phase angle measurement
            MeasurementMetadata measurement3Metadata = new MeasurementMetadata();

            measurement3Metadata.ID                = $"{measurementSource}{runtimeIndex++}";
            measurement3Metadata.PointTag          = pointTagPrefix + "VPHA";
            measurement3Metadata.SignalID          = Guid.NewGuid();
            measurement3Metadata.DeviceAcronym     = device1Metadata.Acronym;
            measurement3Metadata.Reference.Acronym = device1Metadata.Acronym;
            measurement3Metadata.Reference.Kind    = SignalKind.Angle;
            measurement3Metadata.Reference.Index   = 1; // First phase angle
            measurement3Metadata.PhasorSourceIndex = 1; // Match to Phasor.SourceIndex = 1
            measurement3Metadata.UpdatedOn         = timestamp;

            // Add a phase magnitude measurement
            MeasurementMetadata measurement4Metadata = new MeasurementMetadata();

            measurement4Metadata.ID                = $"{measurementSource}{runtimeIndex++}";
            measurement4Metadata.PointTag          = pointTagPrefix + "VPHM";
            measurement4Metadata.SignalID          = Guid.NewGuid();
            measurement4Metadata.DeviceAcronym     = device1Metadata.Acronym;
            measurement4Metadata.Reference.Acronym = device1Metadata.Acronym;
            measurement4Metadata.Reference.Kind    = SignalKind.Magnitude;
            measurement4Metadata.Reference.Index   = 1; // First phase magnitude
            measurement4Metadata.PhasorSourceIndex = 1; // Match to Phasor.SourceIndex = 1
            measurement4Metadata.UpdatedOn         = timestamp;

            m_measurementMetadata.Add(measurement1Metadata);
            m_measurementMetadata.Add(measurement2Metadata);
            m_measurementMetadata.Add(measurement3Metadata);
            m_measurementMetadata.Add(measurement4Metadata);

            // Add a phasor
            PhasorMetadata phasor1Metadata = new PhasorMetadata();

            phasor1Metadata.DeviceAcronym = device1Metadata.Acronym;
            phasor1Metadata.Label         = device1Metadata.Name + " Voltage Phasor";
            phasor1Metadata.Type          = "V"; // Voltage phasor
            phasor1Metadata.Phase         = "+"; // Positive sequence
            phasor1Metadata.SourceIndex   = 1;   // Phasor number 1
            phasor1Metadata.UpdatedOn     = timestamp;

            m_phasorMetadata.Add(phasor1Metadata);

            m_metadataVersion++;

            // Pass meta-data to publisher instance for proper conditioning
            base.DefineMetadata(m_deviceMetadata, m_measurementMetadata, m_phasorMetadata, m_metadataVersion);
        }
Beispiel #8
0
 public MetadataFormatProvider(MeasurementMetadata metadata, string signalTypeAcronym)
 {
     m_metadata          = metadata;
     m_signalTypeAcronym = signalTypeAcronym;
 }
Beispiel #9
0
 internal static global::System.Runtime.InteropServices.HandleRef getCPtr(MeasurementMetadata obj) {
   return (obj == null) ? new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero) : obj.swigCPtr;
 }