private async void AnalyzeReceivedData()
        {
            try {
                var headerBuffer = new byte[2];
                while (_readData)
                {
                    // Pay@Table functionalities handling.
                    if (_settings.ConnectionMode.Equals(ConnectionModes.PAY_AT_TABLE))
                    {
                        byte[] buffer        = new byte[8192];
                        int    bytesReceived = _stream.ReadAsync(buffer, 0, buffer.Length).Result;

                        if (bytesReceived > 0)
                        {
                            byte[] readBuffer = buffer.SubArray(0, bytesReceived);
                            string raw        = Encoding.UTF8.GetString(readBuffer);
                            string dataETX    = raw.Substring(1, raw.Length - 2);

                            byte[] bufferLRC   = TerminalUtilities.CalculateLRC(raw.Substring(raw.Length - 1));
                            string receivedLRC = BitConverter.ToString(bufferLRC);

                            byte[] calculateLRC  = TerminalUtilities.CalculateLRC(dataETX);
                            string calculatedLRC = BitConverter.ToString(calculateLRC);

                            if (receivedLRC.Equals(calculatedLRC))
                            {
                                string data       = raw.Substring(1, raw.Length - 3);
                                byte[] patRequest = Encoding.UTF8.GetBytes(data);
                                OnPayAtTableRequest?.Invoke(new PATRequest(patRequest));
                            }
                        }
                    }
                    else
                    {
                        // Standard functionalities handling
                        _stream.Read(headerBuffer, 0, headerBuffer.Length);

                        if (!_readData)
                        {
                            throw new Exception();
                        }

                        int dataLength = await Task.Run(() => TerminalUtilities.HeaderLength(headerBuffer));

                        if (dataLength > 0)
                        {
                            byte[] dataBuffer = new byte[dataLength];

                            var incomplete = true;
                            int offset     = 0;
                            int tempLength = dataLength;

                            do
                            {
                                // Read data
                                int bytesReceived = _stream.Read(dataBuffer, offset, tempLength);
                                if (!_readData)
                                {
                                    throw new Exception();
                                }
                                if (bytesReceived != tempLength)
                                {
                                    offset     += bytesReceived;
                                    tempLength -= bytesReceived;
                                }
                                else
                                {
                                    incomplete = false;
                                }
                            } while (incomplete);

                            var readBuffer = new byte[dataLength];
                            Array.Copy(dataBuffer, readBuffer, dataLength);

                            if (isBroadcast(readBuffer))
                            {
                                _broadcastMessage = new BroadcastMessage(readBuffer);
                                OnBroadcastMessage?.Invoke(_broadcastMessage.Code, _broadcastMessage.Message);
                            }
                            else if (isKeepAlive(readBuffer) && INGENICO_GLOBALS.KeepAlive)
                            {
                                _isKeepAlive = true;

                                if (_isKeepAlive && !_isKeepAliveRunning)
                                {
                                    _stream.ReadTimeout = _settings.Timeout;
                                    _isKeepAliveRunning = true;
                                }

                                var keepAliveRep = KeepAliveResponse(readBuffer);
                                _stream.WriteAsync(keepAliveRep, 0, keepAliveRep.Length).Wait();
                            }
                            else     // Receiving request response data.
                            {
                                _termResponse = readBuffer;
                            }
                        }
                        else
                        {
                            _receivingException = new ApiException("No data received.");
                        }
                    }
                }
            } catch (Exception ex) {
                if (_settings.ConnectionMode != ConnectionModes.PAY_AT_TABLE)
                {
                    if (_isResponseNeeded || _isKeepAlive)
                    {
                        _receivingException = ex;
                        _stream.ReadTimeout = -1;
                        _isKeepAlive        = false;
                    }

                    if (_readData)
                    {
                        AnalyzeReceivedData();
                    }
                    else
                    {
                        _disposable = true;
                    }
                }
            }
        }
        private async Task <bool> WriteMessage(IDeviceMessage message)
        {
            return(await Task.Run(() => {
                try {
                    int enquiryCount = 0;
                    _messageResponse = new List <byte>();

                    if (_serialPort == null)
                    {
                        return false;
                    }

                    do
                    {
                        _serialPort.Write(BitConverter.GetBytes((char)ControlCodes.ENQ), 0, 1);

                        if (!_isAcknowledge)
                        {
                            Thread.Sleep(1000);
                            _serialPort.Write(BitConverter.GetBytes((char)ControlCodes.EOT), 0, 1);
                            enquiryCount++;

                            if (enquiryCount.Equals(3))
                            {
                                throw new MessageException("Terminal did not respond in enquiry for three (3) times. Send aborted.");
                            }
                        }
                        else
                        {
                            do
                            {
                                byte[] msg = message.GetSendBuffer();
                                foreach (byte b in msg)
                                {
                                    byte[] _b = new byte[] { b };
                                    _serialPort.Write(_b, 0, 1);
                                }

                                if (_isAcknowledge)
                                {
                                    _serialPort.Write(BitConverter.GetBytes((char)ControlCodes.EOT), 0, 1);
                                    _isAcknowledge = false;
                                    break;
                                }
                            } while (true);

                            do
                            {
                                Thread.Sleep(100);
                                if (_isBroadcast)
                                {
                                    byte[] bMsg = Encoding.ASCII.GetBytes(_bufferReceived);
                                    BroadcastMessage broadcastMsg = new BroadcastMessage(bMsg);
                                    OnBroadcastMessage?.Invoke(broadcastMsg.Code, broadcastMsg.Message);
                                    _isBroadcast = false;
                                }

                                if (_isXML)
                                {
                                    while (!_transComplete)
                                    {
                                        if (_report.ToString().Contains(INGENICO_RESP.ENDXML))
                                        {
                                            string xmlData = _report.ToString().Substring(1, _report.ToString().Length - 3);

                                            if (MessageReceived(xmlData))
                                            {
                                                _serialPort.Write(BitConverter.GetBytes((char)ControlCodes.ACK), 0, 1);
                                                _report = new StringBuilder();
                                                _isXML = false;
                                                _transComplete = true;
                                            }
                                        }
                                        else
                                        {
                                            _report.Append(_bufferReceived);
                                        }

                                        Thread.Sleep(0500);
                                    }
                                    ;
                                }

                                if (_isResult)
                                {
                                    string check = Encoding.UTF8.GetString(message.GetSendBuffer());
                                    string refNumber = check.Substring(0, 2);

                                    if (_bufferReceived.Contains(refNumber))
                                    {
                                        do
                                        {
                                            string responseData = _bufferReceived.Substring(1, _bufferReceived.Length - 3);
                                            string actualReceived = _bufferReceived.Substring(1, _bufferReceived.Length - 3);
                                            bool validateLRC = ValidateResponseLRC(responseData, actualReceived);

                                            if (validateLRC)
                                            {
                                                if (MessageReceived(responseData))
                                                {
                                                    _serialPort.Write(BitConverter.GetBytes((char)ControlCodes.ACK), 0, 1);
                                                    _isResult = false;
                                                    _transComplete = true;
                                                }
                                            }
                                        } while (!_transComplete);
                                    }
                                }
                            } while (!_transComplete);

                            return _transComplete;
                        }
                    } while (true);
                } catch (ApiException e) {
                    throw new ApiException(e.Message);
                }
            }));
        }