Exemple #1
0
        /// <summary>
        /// 获取“响应”报文字节数组命令。
        /// </summary>
        /// <param name="seqNumber">
        /// 消息序号。
        /// <para>uint类型,长度为4个字节。</para>
        /// </param>
        /// <returns></returns>
        public byte[] GetResponseCommand(uint seqNumber)
        {
            // 获取消息头对象。
            MessageHead mh = new MessageHead(MessageType, seqNumber);

            // 返回消息报文字节数组。
            return(new Datagram(mh).GetDatagram());
        }
Exemple #2
0
        /// <summary>
        /// 通过消息头和消息体初始化报文对象实例。
        /// </summary>
        /// <param name="head">
        /// 消息头。
        /// <para><see cref="MessageHead"/>类型,长度为16字节。</para>
        /// </param>
        /// <param name="body">
        /// 消息体。
        /// <para><see cref="MessageBody"/>类型,长度可变。</para>
        /// </param>
        public Datagram(MessageHead head, MessageBody body)
            : this()
        {
            Head = head;
            Body = body;

            // 设置一个值指示采用 DES 密钥加密。
            IsCryptographic = Body.DESKey?.Length == 8;
        }
Exemple #3
0
        /// <summary>
        /// 通过“消息ID”和“参数结构体对象列表”执行操作。
        /// </summary>
        /// <param name="messageId">
        /// 消息ID。
        /// <para><see cref="MessageId"/>类型,长度为2个字节。</para>
        /// </param>
        /// <param name="parameterList">参数结构体对象列表。</param>
        /// <exception cref="CsaException">表示发生错误时引发的 CSA018 异常。</exception>
        /// <returns></returns>
        private byte[] GetOperateCommand(MessageId messageId, List <Parameter> parameterList)
        {
            // 获取消息体对象。
            MessageBody mb = new MessageBody(
                messageId,
                GatewayId,
                LuminaireId,
                parameterList,
                DESKey);

            // 获取消息体字节数组。
            byte[] msgBody = mb.GetBody();

            // 获取消息头对象。
            MessageHead mh = new MessageHead(
                MessageType,
                (ushort)(msgBody.Length),
                Crc32.GetCrc32(msgBody));

            // 返回消息报文字节数组。
            return(new Datagram(mh, mb).GetDatagram());
        }
Exemple #4
0
        /// <summary>
        /// 获取命令执行结果数据报文字节数组。
        /// <para>用于获取“命令执行结果”字节数组。</para>
        /// </summary>
        /// <param name="seqNumber">
        /// 消息序号。
        /// <para>uint类型,长度为4个字节。</para>
        /// </param>
        /// <param name="messageId">
        /// 消息ID。
        /// <para><see cref="MessageId"/>类型,长度为2个字节。</para>
        /// </param>
        /// <param name="errorCode">
        /// 错误代码。
        /// <para><see cref="ErrorCode"/>类型,长度为4个字节。</para>
        /// <para>可选字段,对“命令结果”类型的消息有效。</para>
        /// </param>
        /// <param name="errorInfo">
        /// 错误信息。
        /// <para>string类型,长度可变。</para>
        /// <para>可选字段,对“命令结果”类型的消息有效。</para>
        /// </param>
        /// <returns></returns>
        public byte[] GetResultCommand(uint seqNumber, MessageId messageId, ErrorCode errorCode, string errorInfo = null)
        {
            // 获取消息体对象。
            MessageBody mb = new MessageBody(
                messageId,
                GatewayId,
                LuminaireId,
                errorCode,
                errorInfo,
                DESKey);

            // 获取消息体字节数组。
            byte[] msgBody = mb.GetBody();

            // 获取消息头对象。
            MessageHead mh = new MessageHead(
                MessageType,
                seqNumber,
                (ushort)(msgBody.Length),
                Crc32.GetCrc32(msgBody));

            // 返回消息报文字节数组。
            return(new Datagram(mh, mb).GetDatagram());
        }
Exemple #5
0
 /// <summary>
 /// 通过消息头初始化报文对象实例。
 /// </summary>
 /// <param name="head">
 /// 消息头。
 /// <para><see cref="MessageHead"/>类型,长度为16字节。</para>
 /// </param>
 public Datagram(MessageHead head)
     : this()
 {
     Head = head;
 }
Exemple #6
0
        /// <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);
        }