Exemple #1
0
        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);
            }
        }
 internal PrimaryMessageWrapper(SecsGem secsGem, MessageHeader header, SecsMessage msg)
 {
     _secsGem = secsGem;
     _header = header;
     Message = msg;
 }
Exemple #3
0
 internal PrimaryMessageWrapper(SecsGem secsGem, MessageHeader header, SecsMessage message)
 {
     this.weakReferenceSecsGem = new WeakReference <SecsGem>(secsGem);
     this.header  = header;
     this.Message = message;
 }
Exemple #4
0
 internal PrimaryMessageWrapper(SecsGem secsGem, MessageHeader header, SecsMessage msg)
 {
     _secsGem = secsGem;
     _header  = header;
     Message  = msg;
 }