/// <summary>
        /// Generates a <c>SECSItem</c> from data in &quot;wire/transmission&quot; format.
        /// </summary>
        /// <returns>The resulting <c>SECSItem</c>.</returns>
        /// <param name="data">An array of bytes that is in wire/transmission format.</param>
        /// <param name="offset">The byte offset into <c>data</c> where the data for
        /// a <c>SECSITEM</c> starts.</param>
        public static SECSItem GenerateSECSItem(byte[] data, int offset)
        {
            SECSItem result = null;

            SECSItemFormatCode formatCode = SECSItemFormatCodeFunctions.GetSECSItemFormatCodeFromNumber((byte)((data[offset] >> 2) & 0x0000003F));
            int numberOfLengthBytes       = (data[offset] & 0x03);
            int incomingDataLength        = 0;

            switch (numberOfLengthBytes)
            {
            case 1:
            {
                byte[] temp = new byte[4];
                temp[0] = 0;
                temp[1] = 0;
                temp[2] = 0;
                temp[3] = data[offset + 1];

                if (BitConverter.IsLittleEndian)
                {
                    Array.Reverse(temp);
                }

                incomingDataLength = BitConverter.ToInt32(temp, 0);
                break;
            }

            case 2:
            {
                byte[] temp = new byte[4];
                temp[0] = 0;
                temp[1] = 0;
                temp[2] = data[offset + 1];
                temp[3] = data[offset + 2];
                if (BitConverter.IsLittleEndian)
                {
                    Array.Reverse(temp);
                }

                incomingDataLength = BitConverter.ToInt32(temp, 0);
                break;
            }

            case 3:
            {
                byte[] temp = new byte[4];
                temp[0] = 0;
                temp[1] = data[offset + 1];
                temp[2] = data[offset + 2];
                temp[3] = data[offset + 3];
                if (BitConverter.IsLittleEndian)
                {
                    Array.Reverse(temp);
                }

                incomingDataLength = BitConverter.ToInt32(temp, 0);
                break;
            }
            }


            switch (formatCode)
            {
            case SECSItemFormatCode.L:
                result = new ListSECSItem(data, offset);
                break;

            case SECSItemFormatCode.B:
                result = new BinarySECSItem(data, offset);
                break;

            case SECSItemFormatCode.BO:
                if (incomingDataLength == 1)
                {
                    result = new BooleanSECSItem(data, offset);
                }
                else
                {
                    result = new BooleanArraySECSItem(data, offset);
                }
                break;

            case SECSItemFormatCode.A:
                result = new ASCIISECSItem(data, offset);
                break;

            case SECSItemFormatCode.J8:
                break;

            case SECSItemFormatCode.C2:
                break;

            case SECSItemFormatCode.I8:
                if (incomingDataLength == 8)
                {
                    result = new I8SECSItem(data, offset);
                }
                else
                {
                    result = new I8ArraySECSItem(data, offset);
                }
                break;

            case SECSItemFormatCode.I1:
                if (incomingDataLength == 1)
                {
                    result = new I1SECSItem(data, offset);
                }
                else
                {
                    result = new I1ArraySECSItem(data, offset, 0);                             // Need to use this version because of method signature issues
                }
                break;

            case SECSItemFormatCode.I2:
                if (incomingDataLength == 2)
                {
                    result = new I2SECSItem(data, offset);
                }
                else
                {
                    result = new I2ArraySECSItem(data, offset);
                }
                break;

            case SECSItemFormatCode.I4:
                if (incomingDataLength == 4)
                {
                    result = new I4SECSItem(data, offset);
                }
                else
                {
                    result = new I4ArraySECSItem(data, offset);
                }
                break;

            case SECSItemFormatCode.F8:
                if (incomingDataLength == 8)
                {
                    result = new F8SECSItem(data, offset);
                }
                else
                {
                    result = new F8ArraySECSItem(data, offset);
                }
                break;

            case SECSItemFormatCode.F4:
                if (incomingDataLength == 4)
                {
                    result = new F4SECSItem(data, offset);
                }
                else
                {
                    result = new F4ArraySECSItem(data, offset);
                }
                break;

            case SECSItemFormatCode.U8:
                if (incomingDataLength == 8)
                {
                    result = new U8SECSItem(data, offset);
                }
                else
                {
                    result = new U8ArraySECSItem(data, offset);
                }
                break;

            case SECSItemFormatCode.U1:
                if (incomingDataLength == 1)
                {
                    result = new U1SECSItem(data, offset);
                }
                else
                {
                    result = new U1ArraySECSItem(data, offset, 0);                              // Remember to use the proper constructor for this case
                }
                break;

            case SECSItemFormatCode.U2:
                if (incomingDataLength == 2)
                {
                    result = new U2SECSItem(data, offset);
                }
                else
                {
                    result = new U2ArraySECSItem(data, offset);
                }
                break;

            case SECSItemFormatCode.U4:
                if (incomingDataLength == 4)
                {
                    result = new U4SECSItem(data, offset);
                }
                else
                {
                    result = new U4ArraySECSItem(data, offset);
                }
                break;

            case SECSItemFormatCode.UNDEFINED:
                break;

            case SECSItemFormatCode.HeaderOnly:
                break;

            default:
                break;
            }

            return(result);
        }
示例#2
0
        /// <summary>
        ///  This is a base class constructor for a SECSItem.  This form of the constructor
        /// is used when parsing wire/transmission format data and converting it into
        /// its "C# form".
        ///
        /// This constructor sets the following base class attributes from the provided data:
        /// <c>formatCode</c>,
        /// <c>inboundNumberOfLengthBytes</c>,
        /// <c>outboundNumberOfLengthBytes</c>
        /// <c>lengthInBytes</c> or if the <c>formatCode</c> is of type <c>L</c>(List) <c>lengthInBytes</c>
        /// will be the number of items in the list.
        ///
        /// The exception <c>ArgumentException</c> will be thrown in the following circumstances:
        /// the <c>data</c> argument is <c>null</c>, the <c>data</c> argument has a length of zero, or
        /// the number of length bytes parsed out is zero.
        ///
        /// In normal use the only time the <c>ArgumentException</c>
        /// exception should be caught is if you are reading data from a piece of
        /// equipment that does not properly speak SECS and you want to be able to
        /// recover from the error gracefully.Typically the ACM process will have
        /// detected this equipment and it will not be allowed into the factory in
        /// the first place.
        /// </summary>
        protected SECSItem(byte[] data, int itemOffset)
        {
            if (data == null)
            {
                throw new ArgumentNullException("\"data\" argument must not be null.");
            }

            if (data.Length < 2)
            {
                throw new ArgumentException("\"data\" argument must have a length >= 2.");
            }

            /*
             * if (data.Length == 0)
             * {
             *  throw new ArgumentException ("The number of length bytes is not allowed to be ZERO.");
             * }
             */

            formatCode = SECSItemFormatCodeFunctions.GetSECSItemFormatCodeFromNumber((byte)((data[itemOffset] >> 2) & 0x0000003F));

            byte[] temp1 = new byte[4];
            switch (data [itemOffset] & 0x03)
            {
            case 0:
            {
                throw new ArgumentException("The number of length bytes is not allowed to be ZERO.");
            }

            case 1:
            {
                inboundNumberOfLengthBytes  = SECSItemNumLengthBytes.ONE;
                outboundNumberOfLengthBytes = inboundNumberOfLengthBytes;
                temp1[0] = 0;
                temp1[1] = 0;
                temp1[2] = 0;
                temp1[3] = data[itemOffset + 1];

                break;
            }

            case 2:
            {
                inboundNumberOfLengthBytes  = SECSItemNumLengthBytes.TWO;
                outboundNumberOfLengthBytes = inboundNumberOfLengthBytes;
                if (data.Length < 3)
                {
                    throw new ArgumentException("With two length bytes the minimum length for the \"data\" argument is 3.");
                }

                temp1[0] = 0;
                temp1[1] = 0;
                temp1[2] = data[itemOffset + 1];
                temp1[3] = data[itemOffset + 2];
                break;
            }

            case 3:
            {
                inboundNumberOfLengthBytes  = SECSItemNumLengthBytes.THREE;
                outboundNumberOfLengthBytes = inboundNumberOfLengthBytes;
                if (data.Length < 4)
                {
                    throw new ArgumentException("With three length bytes the minimum length for the \"data\" argument is 4.");
                }

                temp1[0] = 0;
                temp1[1] = data[itemOffset + 1];
                temp1[2] = data[itemOffset + 2];
                temp1[3] = data[itemOffset + 3];
                break;
            }
            }

            if (BitConverter.IsLittleEndian)
            {
                Array.Reverse(temp1);
            }

            lengthInBytes = BitConverter.ToInt32(temp1, 0);

            /*
             * if (formatCode == SECSItemFormatCode.L)
             *  numberOfElements = incomingDataLength;
             * else
             *  lengthInBytes = incomingDataLength;
             */
        }