コード例 #1
0
        /// <summary>
        /// Decoder step 1: get message header 10 bytes
        /// </summary>
        /// <param name="length"></param>
        /// <param name="need"></param>
        /// <returns>The decoder step to execute next.</returns>
        private int DecoderStep1GetMessageHeader(ref int length, out int need)
        {
            if (!StreamDecoder.CheckAvailable(length, 10, out need))
            {
                return(1);
            }

            this.messageHeader      = MessageHeader.Decode(new ReadOnlySpan <byte>(this.Buffer, this.decodeIndex, 10));
            this.decodeIndex       += 10;
            this.messageDataLength -= 10;
            length -= 10;
            if (this.messageDataLength == 0)
            {
                if (this.messageHeader.MessageType == MessageType.DataMessage)
                {
                    this.dataMessageHandler(this.messageHeader, new SecsMessage(this.messageHeader.S, this.messageHeader.F, string.Empty, replyExpected: this.messageHeader.ReplyExpected));
                }
                else
                {
                    this.controlMessageHandler(this.messageHeader);
                }

                return(0);
            }

            if (length >= this.messageDataLength)
            {
                Trace.WriteLine("Get Complete Data Message with total data");
                this.dataMessageHandler(this.messageHeader, new SecsMessage(this.messageHeader.S, this.messageHeader.F, string.Empty, StreamDecoder.BufferedDecodeItem(this.Buffer, ref this.decodeIndex), this.messageHeader.ReplyExpected));
                length -= (int)this.messageDataLength;
                this.messageDataLength = 0;
                return(0);                //completeWith message received
            }
            return(this.DecoderStep2GetItemHeader(ref length, out need));
        }
コード例 #2
0
ファイル: SecsEquipment.cs プロジェクト: lhf552004/SIAPMCos
        private void parseMessage(byte[] bytes, int length, bool isMessageComplelte = false)
        {
            if (isMessageComplelte == true)
            {
            }
            else
            {
                if (length == 14 && isHeader == true)
                {
                    //it is a header

                    isHeader = false;
                    Array.Copy(bytes, messageBytes, length);


                    byte[] messageLengths = new byte[4];
                    Array.Copy(bytes, 0, messageLengths, 0, 4);
                    Array.Reverse(messageLengths, 0, 4);
                    _messageDataLength = (int)BitConverter.ToUInt32(messageLengths, 0);

                    MsgHeader = MessageHeader.Decode(bytes, 4);
                }
                else
                {
                    isHeader = true;

                    if (_messageDataLength - 10 == length)
                    {
                        //it is the message
                        int  index = 0;
                        Item item  = decoder.BufferedDecodeItem(bytes, ref index);
                        Msg = new SecsMessage(MsgHeader.S, MsgHeader.F, MsgHeader.ReplyExpected, "", item);
                        SecsDataReceivedEventArgs arg = new SecsDataReceivedEventArgs(Msg, SCESEquipment);
                        DataReceived(SocketClient, arg);
                    }
                }
            }
        }
コード例 #3
0
ファイル: StreamDecoder.cs プロジェクト: lhf552004/SIAPMCos
        public StreamDecoder(int streamBufferSize, Action <MessageHeader> controlMsgHandler, Action <MessageHeader, SecsMessage> dataMsgHandler)
        {
            _buffer            = new byte[streamBufferSize];
            _bufferOffset      = 0;
            _decodeIndex       = 0;
            _dataMsgHandler    = dataMsgHandler;
            _controlMsgHandler = controlMsgHandler;

            _decoders = new Decoder[]
            {
                GetTotalMessageLength,
                GetMessageHeader,
                GetItemHeader,
                GetItemLength,
                GetItem,
            };

            // 0: get total message length 4 bytes
            int GetTotalMessageLength(ref int length, out int need)
            {
                if (!CheckAvailable(ref length, 4, out need))
                {
                    return(0);
                }

                Array.Reverse(_buffer, _decodeIndex, 4);
                _messageDataLength = BitConverter.ToUInt32(_buffer, _decodeIndex);
                Trace.WriteLine($"Get Message Length: {_messageDataLength}");
                _decodeIndex += 4;
                length       -= 4;
                return(GetMessageHeader(ref length, out need));
            }

            // 1: get message header 10 bytes
            int GetMessageHeader(ref int length, out int need)
            {
                if (!CheckAvailable(ref length, 10, out need))
                {
                    return(1);
                }

                _msgHeader          = MessageHeader.Decode(_buffer, _decodeIndex);
                _decodeIndex       += 10;
                _messageDataLength -= 10;
                length             -= 10;
                if (_messageDataLength == 0)
                {
                    if (_msgHeader.MessageType == MessageType.DataMessage)
                    {
                        _dataMsgHandler(_msgHeader, new SecsMessage(_msgHeader.S, _msgHeader.F, _msgHeader.ReplyExpected, string.Empty));
                    }
                    else
                    {
                        _controlMsgHandler(_msgHeader);
                    }
                    return(0);
                }

                if (length >= _messageDataLength)
                {
                    Trace.WriteLine("Get Complete Data Message with total data");
                    _dataMsgHandler(_msgHeader, new SecsMessage(_msgHeader.S, _msgHeader.F, _msgHeader.ReplyExpected, string.Empty, BufferedDecodeItem(_buffer, ref _decodeIndex)));
                    length            -= (int)_messageDataLength;
                    _messageDataLength = 0;
                    return(0); //completeWith message received
                }
                return(GetItemHeader(ref length, out need));
            }

            // 2: get _format + lengthBits(2bit) 1 byte
            int GetItemHeader(ref int length, out int need)
            {
                if (!CheckAvailable(ref length, 1, out need))
                {
                    return(2);
                }

                _format     = (SecsFormat)(_buffer[_decodeIndex] & 0xFC);
                _lengthBits = (byte)(_buffer[_decodeIndex] & 3);
                _decodeIndex++;
                _messageDataLength--;
                length--;
                return(GetItemLength(ref length, out need));
            }

            // 3: get _itemLength _lengthBits bytes, at most 3 byte
            int GetItemLength(ref int length, out int need)
            {
                if (!CheckAvailable(ref length, _lengthBits, out need))
                {
                    return(3);
                }

                Array.Copy(_buffer, _decodeIndex, _itemLengthBytes, 0, _lengthBits);
                Array.Reverse(_itemLengthBytes, 0, _lengthBits);

                _itemLength = BitConverter.ToInt32(_itemLengthBytes, 0);
                Array.Clear(_itemLengthBytes, 0, 4);
                Trace.WriteLineIf(_format != SecsFormat.List, $"Get format: {_format}, length: {_itemLength}");

                _decodeIndex       += _lengthBits;
                _messageDataLength -= _lengthBits;
                length             -= _lengthBits;
                return(GetItem(ref length, out need));
            }

            // 4: get item value
            int GetItem(ref int length, out int need)
            {
                need = 0;
                Item item;

                if (_format == SecsFormat.List)
                {
                    if (_itemLength == 0)
                    {
                        item = Item.L();
                    }
                    else
                    {
                        _stack.Push(new List <Item>(_itemLength));
                        return(GetItemHeader(ref length, out need));
                    }
                }
                else
                {
                    if (!CheckAvailable(ref length, _itemLength, out need))
                    {
                        return(4);
                    }

                    item = Item.BytesDecode(ref _format, _buffer, ref _decodeIndex, ref _itemLength);
                    Trace.WriteLine($"Complete Item: {_format}");

                    _decodeIndex       += _itemLength;
                    _messageDataLength -= (uint)_itemLength;
                    length             -= _itemLength;
                }

                if (_stack.Count == 0)
                {
                    Trace.WriteLine("Get Complete Data Message by stream decoded");
                    _dataMsgHandler(_msgHeader, new SecsMessage(_msgHeader.S, _msgHeader.F, _msgHeader.ReplyExpected, string.Empty, item));
                    return(0);
                }

                var list = _stack.Peek();

                list.Add(item);
                while (list.Count == list.Capacity)
                {
                    item = Item.L(_stack.Pop());
                    Trace.WriteLine($"Complete List: {item.Count}");
                    if (_stack.Count > 0)
                    {
                        list = _stack.Peek();
                        list.Add(item);
                    }
                    else
                    {
                        Trace.WriteLine("Get Complete Data Message by stream decoded");
                        _dataMsgHandler(_msgHeader, new SecsMessage(_msgHeader.S, _msgHeader.F, _msgHeader.ReplyExpected, string.Empty, item));
                        return(0);
                    }
                }

                return(GetItemHeader(ref length, out need));
            }

            bool CheckAvailable(ref int length, int required, out int need)
            {
                need = required - length;
                if (need > 0)
                {
                    return(false);
                }
                need = 0;
                return(true);
            }
        }