Пример #1
0
 /// <summary>
 /// Encodes sampled value tag with only a 16-bit length.
 /// </summary>
 /// <param name="length">Value to encode.</param>
 /// <param name="tag">Sampled value tag to encode.</param>
 /// <param name="buffer">Buffer to hold encoded sampled value.</param>
 /// <param name="index">Start index of buffer where tag will begin - will be auto-incremented.</param>
 public static void EncodeTagLength(this ushort length, SampledValueTag tag, byte[] buffer, ref int index)
 {
     buffer[index++] = (byte)tag;
     buffer[index++] = 0x80 | 2;
     buffer[index++] = (byte)((length & 0xFF00) >> 8);
     buffer[index++] = (byte)(length & 0x00FF);
 }
Пример #2
0
        /// <summary>
        /// Encodes byte based sampled value tag.
        /// </summary>
        /// <param name="value">Value to encode.</param>
        /// <param name="tag">Sampled value tag to encode.</param>
        /// <param name="buffer">Buffer to hold encoded sampled value.</param>
        /// <param name="index">Start index of buffer where tag will begin - will be auto-incremented.</param>
        public static void EncodeTagValue(this byte value, SampledValueTag tag, byte[] buffer, ref int index)
        {
            const ushort length = 1;

            buffer[index++] = (byte)tag;
            length.EncodeTagLength(buffer, ref index);
            buffer[index++] = value;
        }
Пример #3
0
        /// <summary>
        /// Validates sample value tag exists and skips past it.
        /// </summary>
        /// <param name="buffer">Buffer containing sampled value tag length.</param>
        /// <param name="tag">Sampled value tag to validate.</param>
        /// <param name="index">Start index of buffer where tag length begins - will be auto-incremented.</param>
        public static int ValidateTag(this byte[] buffer, SampledValueTag tag, ref int index)
        {
            if ((SampledValueTag)buffer[index] != tag)
            {
                throw new InvalidOperationException($"Encountered out-of-sequence or unknown sampled value tag: 0x{buffer[index].ToString("X").PadLeft(2, '0')}");
            }

            index++;
            return(buffer.ParseTagLength(ref index));
        }
Пример #4
0
        /// <summary>
        /// Validates and parses string sample value tag.
        /// </summary>
        /// <param name="buffer">Buffer containing sampled value.</param>
        /// <param name="tag">Sampled value tag to parse.</param>
        /// <param name="index">Start index of buffer where tag length begins - will be auto-incremented.</param>
        public static string ParseStringTag(this byte[] buffer, SampledValueTag tag, ref int index)
        {
            if ((SampledValueTag)buffer[index] != tag)
            {
                throw new InvalidOperationException($"Encountered out-of-sequence or unknown sampled value tag: 0x{buffer[index].ToString("X").PadLeft(2, '0')}");
            }

            index++;
            int tagLength = buffer.ParseTagLength(ref index);

            string result = Encoding.ASCII.GetString(buffer, index, tagLength);

            index += tagLength;

            return(result);
        }
Пример #5
0
        /// <summary>
        /// Validates and parses 8-byte length sample value tag.
        /// </summary>
        /// <param name="buffer">Buffer containing sampled value.</param>
        /// <param name="tag">Sampled value tag to parse.</param>
        /// <param name="index">Start index of buffer where tag length begins - will be auto-incremented.</param>
        public static ulong ParseUInt64Tag(this byte[] buffer, SampledValueTag tag, ref int index)
        {
            if ((SampledValueTag)buffer[index] != tag)
            {
                throw new InvalidOperationException($"Encountered out-of-sequence or unknown sampled value tag: 0x{buffer[index].ToString("X").PadLeft(2, '0')}");
            }

            index++;
            int tagLength = buffer.ParseTagLength(ref index);

            if (tagLength < 8)
            {
                throw new InvalidOperationException($"Unexpected length for \"{tag}\" tag: {tagLength}");
            }

            ulong result = BigEndian.ToUInt64(buffer, index);

            index += tagLength;

            return(result);
        }
Пример #6
0
        /// <summary>
        /// Validates and parses 4-byte length sample value tag.
        /// </summary>
        /// <param name="buffer">Buffer containing sampled value.</param>
        /// <param name="tag">Sampled value tag to parse.</param>
        /// <param name="index">Start index of buffer where tag length begins - will be auto-incremented.</param>
        public static uint ParseUInt32Tag(this byte[] buffer, SampledValueTag tag, ref int index)
        {
            if ((SampledValueTag)buffer[index] != tag)
            {
                throw new InvalidOperationException("Encountered out-of-sequence or unknown sampled value tag: 0x" + buffer[index].ToString("X").PadLeft(2, '0'));
            }

            index++;
            int tagLength = buffer.ParseTagLength(ref index);

            if (tagLength < 4)
            {
                throw new InvalidOperationException(string.Format("Unexpected length for \"{0}\" tag: {1}", tag, tagLength));
            }

            uint result = BigEndian.ToUInt32(buffer, index);

            index += tagLength;

            return(result);
        }
Пример #7
0
        /// <summary>
        /// Encodes primitive type sampled value tag.
        /// </summary>
        /// <param name="value">Value to encode.</param>
        /// <param name="tag">Sampled value tag to encode.</param>
        /// <param name="buffer">Buffer to hold encoded sampled value.</param>
        /// <param name="index">Start index of buffer where tag will begin - will be auto-incremented.</param>
        public static void EncodeTagValue <T>(this T value, SampledValueTag tag, byte[] buffer, ref int index) where T : struct, IConvertible
        {
            if (!typeof(T).IsPrimitive)
            {
                throw new ArgumentException("Value type is not primitive", nameof(value));
            }

            // Not sure if booleans would be encoded correctly here (due to Marshal sizeof) - also not sure
            // how IEC 61850 deals with booleans - as a result, booleans should likely be avoided.
            // I wonder if compiler is smart enough to exclude this expression in implementations since this
            // is always false for non boolean types - where is my WHERE expression like "~bool"...
            if (typeof(T) == typeof(bool))
            {
                throw new ArgumentOutOfRangeException(nameof(value), "Boolean encoding is currently not supported");
            }

            ushort length = (ushort)Marshal.SizeOf(typeof(T));

            buffer[index++] = (byte)tag;
            length.EncodeTagLength(buffer, ref index);
            index += BigEndian.CopyBytes(value, buffer, index);
        }
Пример #8
0
        /// <summary>
        /// Encodes string based sampled value tag.
        /// </summary>
        /// <param name="value">String to encode - null string will be encoded as empty string.</param>
        /// <param name="tag">Sampled value tag to encode.</param>
        /// <param name="buffer">Buffer to hold encoded sampled value.</param>
        /// <param name="index">Start index of buffer where tag will begin - will be auto-incremented.</param>
        public static void EncodeTagValue(this string value, SampledValueTag tag, byte[] buffer, ref int index)
        {
            if (value is null)
            {
                value = "";
            }

            if (value.Length > ushort.MaxValue)
            {
                throw new ArgumentOutOfRangeException(nameof(value), $"Current implementation will not encode a string larger than {ushort.MaxValue}");
            }

            ushort length = (ushort)value.Length;

            buffer[index++] = (byte)tag;
            length.EncodeTagLength(buffer, ref index);

            if (length > 0)
            {
                byte[] bytes = Encoding.ASCII.GetBytes(value);
                Buffer.BlockCopy(bytes, 0, buffer, index, bytes.Length);
                index += bytes.Length;
            }
        }