예제 #1
0
 /// <summary>
 /// Creates a new <see cref="DataCell"/> from serialization parameters.
 /// </summary>
 /// <param name="info">The <see cref="SerializationInfo"/> with populated with data.</param>
 /// <param name="context">The source <see cref="StreamingContext"/> for this deserialization.</param>
 protected DataCell(SerializationInfo info, StreamingContext context)
     : base(info, context)
 {
     // Deserialize data cell
     m_channelFlags  = (ChannelFlags)info.GetValue("channelFlags", typeof(ChannelFlags));
     m_reservedFlags = (ReservedFlags)info.GetValue("reservedFlags", typeof(ReservedFlags));
     m_sampleNumber  = info.GetUInt16("sampleNumber");
 }
예제 #2
0
        /// <summary>
        /// Parses the binary header image.
        /// </summary>
        /// <param name="buffer">Binary image to parse.</param>
        /// <param name="startIndex">Start index into <paramref name="buffer"/> to begin parsing.</param>
        /// <param name="length">Length of valid data within <paramref name="buffer"/>.</param>
        /// <returns>The length of the data that was parsed.</returns>
        protected override int ParseHeaderImage(byte[] buffer, int startIndex, int length)
        {
            DataFrame             parentFrame = Parent;
            DataFrameParsingState frameState = parentFrame.State;
            IDataCellParsingState state = State;
            RevisionNumber        revision = parentFrame.ConfigurationFrame.RevisionNumber;
            int  x, index = startIndex;
            byte analogs, digitals, phasors;

            // Read data buffer if using phasor data file format
            if (UsePhasorDataFileFormat && frameState.RemainingPdcBlockPmus == 0)
            {
                m_dataBuffer = BigEndian.ToUInt32(buffer, index);
                index       += 4;
            }

            // Get data cell flags
            m_channelFlags = (ChannelFlags)buffer[index];
            analogs        = buffer[index + 1];
            index         += 2;

            // Parse PDCstream specific header image
            if (revision >= RevisionNumber.Revision2 && frameState.RemainingPdcBlockPmus == 0)
            {
                // Strip off reserved flags
                m_reservedFlags = (ReservedFlags)analogs & ~ReservedFlags.AnalogWordsMask;

                // Leave analog word count
                analogs &= (byte)ReservedFlags.AnalogWordsMask;
            }
            else
            {
                // Older revisions didn't allow analogs
                m_dataRate = analogs;
                analogs    = 0;
            }

            if (frameState.RemainingPdcBlockPmus > 0)
            {
                // PDC Block PMU's contain exactly 2 phasors, 0 analogs and 1 digital
                phasors  = 2;
                analogs  = 0;
                digitals = 1;
                UsingPdcExchangeFormat = true;

                // Decrement remaining PDC block PMU's
                frameState.RemainingPdcBlockPmus--;
            }
            else
            {
                // Parse number of digitals and phasors for normal PMU cells
                digitals = buffer[index];
                phasors  = buffer[index + 1];
                index   += 2;

                if (revision >= RevisionNumber.Revision2)
                {
                    // Strip off IEEE flags
                    FormatFlags = (FormatFlags)digitals & ~FormatFlags.DigitalWordsMask;

                    // Leave digital word count
                    digitals &= (byte)FormatFlags.DigitalWordsMask;
                }

                // Check for PDC exchange format
                if (UsingPdcExchangeFormat)
                {
                    // In cases where we are using PDC exchange the phasor count is the number of PMU's in the PDC block
                    int pdcBlockPmus = phasors - 1; // <-- Current PMU counts as one
                    frameState.RemainingPdcBlockPmus = pdcBlockPmus;
                    frameState.CellCount            += pdcBlockPmus;

                    // PDC Block PMU's contain exactly 2 phasors, 0 analogs and 1 digital
                    phasors  = 2;
                    analogs  = 0;
                    digitals = 1;

                    // Get data cell flags for PDC block PMU
                    m_channelFlags         = (ChannelFlags)buffer[index];
                    UsingPdcExchangeFormat = true;
                    index += 2;
                }
                else
                {
                    // Parse PMU's sample number
                    m_sampleNumber = BigEndian.ToUInt16(buffer, index);
                    index         += 2;
                }
            }

            // Algorithm Case: Determine best course of action when stream counts don't match counts defined in the
            // external INI based configuration file.  Think about what *will* happen when new data appears in the
            // stream that's not in the config file - you could raise an event notifying consumer about the mismatch
            // instead of raising an exception - could even make a boolean property that would allow either case.
            // The important thing to consider is that to parse the cell images you have to have a defined
            // definition (see base class method "DataCellBase.ParseBodyImage").  If you have more items defined
            // in the stream than you do in the config file then you won't get the new value, too few items and you
            // don't have enough definitions to correctly interpret the data (that would be bad) - either way the
            // definitions won't line up with the appropriate data value and you won't know which one is missing or
            // added.  I can't change the protocol so this is enough argument to just raise an error for config
            // file/stream mismatch.  So for now we'll just throw an exception and deal with consequences :)
            // Note that this only applies to BPA PDCstream protocol because of external configuration.

            // Addendum: After running this with several protocol implementations I noticed that if a device wasn't
            // reporting, the phasor count dropped to zero even if there were phasors defined in the configuration
            // file, so the only time an exception is thrown is if there are more phasors defined in the the stream
            // than there are defined in the INI file...

            // At least this number of phasors should be already defined in BPA PDCstream configuration file
            if (phasors > ConfigurationCell.PhasorDefinitions.Count)
            {
                throw new InvalidOperationException(
                          "Stream/Config File Mismatch: Phasor value count in stream (" + phasors +
                          ") does not match defined count in configuration file (" + ConfigurationCell.PhasorDefinitions.Count +
                          ") for " + ConfigurationCell.IDLabel);
            }

            // If analog values get a clear definition in INI file at some point, we can validate the number in the
            // stream to the number in the config file, in the mean time we dyanmically add analog definitions to
            // configuration cell as needed (they are only defined in data frame of BPA PDCstream)
            if (analogs > ConfigurationCell.AnalogDefinitions.Count)
            {
                for (x = ConfigurationCell.AnalogDefinitions.Count; x < analogs; x++)
                {
                    ConfigurationCell.AnalogDefinitions.Add(new AnalogDefinition(ConfigurationCell, "Analog " + (x + 1), 1, 0.0D, AnalogType.SinglePointOnWave));
                }
            }

            // If digital values get a clear definition in INI file at some point, we can validate the number in the
            // stream to the number in the config file, in the mean time we dyanmically add digital definitions to
            // configuration cell as needed (they are only defined in data frame of BPA PDCstream)
            if (digitals > ConfigurationCell.DigitalDefinitions.Count)
            {
                for (x = ConfigurationCell.DigitalDefinitions.Count; x < digitals; x++)
                {
                    ConfigurationCell.DigitalDefinitions.Add(new DigitalDefinition(ConfigurationCell, "Digital Word " + (x + 1)));
                }
            }

            // Unlike most all other protocols the counts defined for phasors, analogs and digitals in the data frame
            // may not exactly match what's defined in the configuration frame as these values are defined in an external
            // INI file for BPA PDCstream.  As a result, we manually assign the counts to the parsing state so that these
            // will be the counts used to parse values from data frame in the base class ParseBodyImage method
            state.PhasorCount  = phasors;
            state.AnalogCount  = analogs;
            state.DigitalCount = digitals;

            // Status flags and remaining data elements will parsed by base class in the ParseBodyImage method
            return(index - startIndex);
        }
예제 #3
0
파일: DataCell.cs 프로젝트: rmc00/gsf
        /// <summary>
        /// Parses the binary header image.
        /// </summary>
        /// <param name="buffer">Binary image to parse.</param>
        /// <param name="startIndex">Start index into <paramref name="buffer"/> to begin parsing.</param>
        /// <param name="length">Length of valid data within <paramref name="buffer"/>.</param>
        /// <returns>The length of the data that was parsed.</returns>
        protected override int ParseHeaderImage(byte[] buffer, int startIndex, int length)
        {
            DataFrame parentFrame = Parent;
            DataFrameParsingState frameState = parentFrame.State;
            IDataCellParsingState state = State;
            RevisionNumber revision = parentFrame.ConfigurationFrame.RevisionNumber;
            int x, index = startIndex;
            byte analogs, digitals, phasors;

            // Read data buffer if using phasor data file format
            if (UsePhasorDataFileFormat && frameState.RemainingPdcBlockPmus == 0)
            {
                m_dataBuffer = BigEndian.ToUInt32(buffer, index);
                index += 4;
            }

            // Get data cell flags
            m_channelFlags = (ChannelFlags)buffer[index];
            analogs = buffer[index + 1];
            index += 2;

            // Parse PDCstream specific header image
            if (revision >= RevisionNumber.Revision2 && frameState.RemainingPdcBlockPmus == 0)
            {
                // Strip off reserved flags
                m_reservedFlags = (ReservedFlags)analogs & ~ReservedFlags.AnalogWordsMask;

                // Leave analog word count
                analogs &= (byte)ReservedFlags.AnalogWordsMask;
            }
            else
            {
                // Older revisions didn't allow analogs
                m_dataRate = analogs;
                analogs = 0;
            }

            if (frameState.RemainingPdcBlockPmus > 0)
            {
                // PDC Block PMU's contain exactly 2 phasors, 0 analogs and 1 digital
                phasors = 2;
                analogs = 0;
                digitals = 1;
                UsingPdcExchangeFormat = true;

                // Decrement remaining PDC block PMU's
                frameState.RemainingPdcBlockPmus--;
            }
            else
            {
                // Parse number of digitals and phasors for normal PMU cells
                digitals = buffer[index];
                phasors = buffer[index + 1];
                index += 2;

                if (revision >= RevisionNumber.Revision2)
                {
                    // Strip off IEEE flags
                    FormatFlags = (FormatFlags)digitals & ~FormatFlags.DigitalWordsMask;

                    // Leave digital word count
                    digitals &= (byte)FormatFlags.DigitalWordsMask;
                }

                // Check for PDC exchange format
                if (UsingPdcExchangeFormat)
                {
                    // In cases where we are using PDC exchange the phasor count is the number of PMU's in the PDC block
                    int pdcBlockPmus = phasors - 1; // <-- Current PMU counts as one
                    frameState.RemainingPdcBlockPmus = pdcBlockPmus;
                    frameState.CellCount += pdcBlockPmus;

                    // PDC Block PMU's contain exactly 2 phasors, 0 analogs and 1 digital
                    phasors = 2;
                    analogs = 0;
                    digitals = 1;

                    // Get data cell flags for PDC block PMU
                    m_channelFlags = (ChannelFlags)buffer[index];
                    UsingPdcExchangeFormat = true;
                    index += 2;
                }
                else
                {
                    // Parse PMU's sample number
                    m_sampleNumber = BigEndian.ToUInt16(buffer, index);
                    index += 2;
                }
            }

            // Algorithm Case: Determine best course of action when stream counts don't match counts defined in the
            // external INI based configuration file.  Think about what *will* happen when new data appears in the
            // stream that's not in the config file - you could raise an event notifying consumer about the mismatch
            // instead of raising an exception - could even make a boolean property that would allow either case.
            // The important thing to consider is that to parse the cell images you have to have a defined
            // definition (see base class method "DataCellBase.ParseBodyImage").  If you have more items defined
            // in the stream than you do in the config file then you won't get the new value, too few items and you
            // don't have enough definitions to correctly interpret the data (that would be bad) - either way the
            // definitions won't line up with the appropriate data value and you won't know which one is missing or
            // added.  I can't change the protocol so this is enough argument to just raise an error for config
            // file/stream mismatch.  So for now we'll just throw an exception and deal with consequences :)
            // Note that this only applies to BPA PDCstream protocol because of external configuration.

            // Addendum: After running this with several protocol implementations I noticed that if a device wasn't
            // reporting, the phasor count dropped to zero even if there were phasors defined in the configuration
            // file, so the only time an exception is thrown is if there are more phasors defined in the the stream
            // than there are defined in the INI file...

            // At least this number of phasors should be already defined in BPA PDCstream configuration file
            if (phasors > ConfigurationCell.PhasorDefinitions.Count)
                throw new InvalidOperationException(
                    "Stream/Config File Mismatch: Phasor value count in stream (" + phasors +
                    ") does not match defined count in configuration file (" + ConfigurationCell.PhasorDefinitions.Count +
                    ") for " + ConfigurationCell.IDLabel);

            // If analog values get a clear definition in INI file at some point, we can validate the number in the
            // stream to the number in the config file, in the mean time we dyanmically add analog definitions to
            // configuration cell as needed (they are only defined in data frame of BPA PDCstream)
            if (analogs > ConfigurationCell.AnalogDefinitions.Count)
            {
                for (x = ConfigurationCell.AnalogDefinitions.Count; x < analogs; x++)
                {
                    ConfigurationCell.AnalogDefinitions.Add(new AnalogDefinition(ConfigurationCell, "Analog " + (x + 1), 1, 0.0D, AnalogType.SinglePointOnWave));
                }
            }

            // If digital values get a clear definition in INI file at some point, we can validate the number in the
            // stream to the number in the config file, in the mean time we dyanmically add digital definitions to
            // configuration cell as needed (they are only defined in data frame of BPA PDCstream)
            if (digitals > ConfigurationCell.DigitalDefinitions.Count)
            {
                for (x = ConfigurationCell.DigitalDefinitions.Count; x < digitals; x++)
                {
                    ConfigurationCell.DigitalDefinitions.Add(new DigitalDefinition(ConfigurationCell, "Digital Word " + (x + 1)));
                }
            }

            // Unlike most all other protocols the counts defined for phasors, analogs and digitals in the data frame
            // may not exactly match what's defined in the configuration frame as these values are defined in an external
            // INI file for BPA PDCstream.  As a result, we manually assign the counts to the parsing state so that these
            // will be the counts used to parse values from data frame in the base class ParseBodyImage method
            state.PhasorCount = phasors;
            state.AnalogCount = analogs;
            state.DigitalCount = digitals;

            // Status flags and remaining data elements will parsed by base class in the ParseBodyImage method
            return (index - startIndex);
        }
예제 #4
0
파일: DataCell.cs 프로젝트: rmc00/gsf
 /// <summary>
 /// Creates a new <see cref="DataCell"/> from serialization parameters.
 /// </summary>
 /// <param name="info">The <see cref="SerializationInfo"/> with populated with data.</param>
 /// <param name="context">The source <see cref="StreamingContext"/> for this deserialization.</param>
 protected DataCell(SerializationInfo info, StreamingContext context)
     : base(info, context)
 {
     // Deserialize data cell
     m_channelFlags = (ChannelFlags)info.GetValue("channelFlags", typeof(ChannelFlags));
     m_reservedFlags = (ReservedFlags)info.GetValue("reservedFlags", typeof(ReservedFlags));
     m_sampleNumber = info.GetUInt16("sampleNumber");
 }