コード例 #1
0
ファイル: Datagram.cs プロジェクト: li2008kui/CSA018
        /// <summary>
        /// 获取消息报文对象列表。
        /// </summary>
        /// <param name="dataArray">消息报文字节数组。</param>
        /// <param name="desKey">
        /// DES 密钥,默认不加密。
        /// <para>该密钥运算模式采用 ECB 模式。</para>
        /// </param>
        /// <param name="isTcpOrUdp">报文承载方式是否是TCP或UDP,默认为false。</param>
        /// <param name="isCheckCrc">是否校验CRC。</param>
        /// <returns>消息报文对象列表。</returns>
        internal static List <Datagram> GetDatagramList(byte[] dataArray, byte[] desKey = null, bool isTcpOrUdp = false, bool isCheckCrc = true)
        {
            List <byte> dataList = new List <byte>(dataArray);

            for (int i = dataArray.Length - 1; i >= 0; i--)
            {
                if (dataList[i] > 0)
                {
                    break;
                }

                dataList.RemoveAt(i);
            }

            if (dataList.Count < 15)
            {
                foreach (var item in dataList)
                {
                    if (item == 0xFF)
                    {
                        return(new List <Datagram>()
                        {
                            new Datagram
                            (
                                new MessageHead(MessageType.HeartbeatData)
                            )
                        });
                    }

                    if (item == 0xFE)
                    {
                        return(new List <Datagram>()
                        {
                            new Datagram
                            (
                                new MessageHead(MessageType.HeartbeatResponse)
                            )
                        });
                    }
                }

                throw new CsaException("消息解析错误。", ErrorCode.MessageParseError);
            }

            List <Datagram> datagramList = new List <Datagram>();
            List <byte[]>   newByteArrayList;

            if (!isTcpOrUdp)
            {
                List <byte[]> byteArrayList = new List <byte[]>();
                GetByteArrayList(dataList.ToArray(), 0, ref byteArrayList);
                newByteArrayList = Descaping(byteArrayList);
            }
            else
            {
                newByteArrayList = new List <byte[]> {
                    dataList.ToArray()
                };
            }

            foreach (var tempByteArray in newByteArrayList)
            {
                if (tempByteArray.Length > 15)
                {
                    if (!Enum.IsDefined(typeof(MessageType), tempByteArray[0]))
                    {
                        throw new CsaException("参数类型未定义。", ErrorCode.ParameterTypeUndefined);
                    }

                    Datagram    d  = new Datagram();
                    MessageHead mh = new MessageHead();
                    mh.Type      = (MessageType)tempByteArray[0];
                    mh.SeqNumber = (uint)((tempByteArray[1] << 24) + (tempByteArray[2] << 16) + (tempByteArray[3] << 8) + tempByteArray[4]);
                    mh.Length    = (ushort)((tempByteArray[5] << 8) + tempByteArray[6]);
                    mh.Reserved  = (ulong)((tempByteArray[7] << 32) + (tempByteArray[8] << 24) + (tempByteArray[9] << 16) + (tempByteArray[10] << 8) + tempByteArray[11]);
                    mh.Crc32     = (uint)((tempByteArray[12] << 24) + (tempByteArray[13] << 16) + (tempByteArray[14] << 8) + tempByteArray[15]);

                    if (mh.Type == MessageType.Command ||
                        mh.Type == MessageType.Event ||
                        mh.Type == MessageType.CommandResult)
                    {
                        byte[] newByteArray = tempByteArray.Where((b, index) => index >= 16 && index < 16 + mh.Length).ToArray();
                        byte[] msgBody;

                        if (desKey?.Length == 8)
                        {
                            DESHelper des = new DESHelper();
                            msgBody = des.Decrypt(desKey, newByteArray);

                            // 设置一个值指示采用 DES 密钥加密。
                            d.IsCryptographic = true;
                        }
                        else
                        {
                            msgBody = newByteArray;
                        }

                        if (msgBody.Length >= 10)
                        {
                            if (!Enum.IsDefined(typeof(MessageId), (ushort)((msgBody[0] << 8) + msgBody[1])))
                            {
                                throw new CsaException("消息ID未定义。", ErrorCode.MessageIdUndefined);
                            }

                            MessageBody mb = new MessageBody();
                            mb.MessageId   = (MessageId)((msgBody[0] << 8) + msgBody[1]);
                            mb.GatewayId   = ((uint)msgBody[2] << 24) + ((uint)msgBody[3] << 16) + ((uint)msgBody[4] << 8) + msgBody[5];
                            mb.LuminaireId = ((uint)msgBody[6] << 24) + ((uint)msgBody[7] << 16) + ((uint)msgBody[8] << 8) + msgBody[9];

                            if (mh.Type == MessageType.CommandResult)
                            {
                                mb.ErrorCode = (ErrorCode)((msgBody[10] << 24) + (msgBody[11] << 16) + (msgBody[12] << 8) + msgBody[13]);
                                List <byte> errorInfoArrayList = new List <byte>();

                                for (int i = 14; i < msgBody.Length; i++)
                                {
                                    errorInfoArrayList.Add(msgBody[i]);
                                }

                                if (errorInfoArrayList.Count > 0)
                                {
                                    mb.ErrorInfo = errorInfoArrayList.ToArray().ToString2();
                                }
                            }
                            else
                            {
                                List <Parameter> pmtList = new List <Parameter>();
                                Parameter.GetParameterList(msgBody, 10, ref pmtList);
                                mb.ParameterList = pmtList;
                            }

                            if (isCheckCrc && Crc32.GetCrc32(newByteArray) != mh.Crc32)
                            {
                                throw new CsaException("消息体CRC校验错误。", ErrorCode.ChecksumError);
                            }

                            d.Body = mb;
                        }
                        else
                        {
                            throw new CsaException("消息解析错误。", ErrorCode.MessageParseError);
                        }
                    }

                    d.Head = mh;
                    datagramList.Add(d);
                }
            }

            return(datagramList);
        }