/// <summary>
        /// This function gets message from the remote unit.
        /// </summary>
        /// <param name="Rxmsg">Received message</param>
        /// <param name="Txmsg">Transmited message, information about this frmae could be necessary to properly init received frame.
        /// </param>
        /// <returns>
        ///   ALRes_Success: Operation accomplished successfully
        ///   ALRes_DatTransferErrr: Data transfer is imposible because of a communication error – loss of
        ///      communication with a station
        ///   ALRes_DisInd: Disconnect indication – connection has been shut down remotely or lost because of
        ///      communication error. Data is unavailable
        /// </returns>
        protected override AL_ReadData_Result GetMessage(out ModBusMessage Rxmsg, ModBusMessage Txmsg)
        {
            Rxmsg = null;
            try
            {
                InterCharStopwatch.Reset();
                InterCharStopwatch.Start();
                if (!CheckCharTimeout(GetProtocolParameters.ResponseTimeOutSpan, InterCharStopwatch))
                {
                    GetIProtocolParent.IncStRxNoResponseCounter();
                    return(AL_ReadData_Result.ALRes_DatTransferErrr);
                }
                GetIProtocolParent.TimeMaxResponseDelayAdd(InterCharStopwatch.ElapsedMilliseconds);
                Rxmsg = m_Pool.GetEmptyISesDBuffer();
                Rxmsg.userDataLength = Rxmsg.userBuffLength;
                Rxmsg.offset         = 0;
                bool first = true;
                do
                {
                    byte lastChar;
                    InterCharStopwatch.Reset();
                    InterCharStopwatch.Start();
                    switch (GetICommunicationLayer.GetChar(out lastChar))
                    {
                    case TGetCharRes.Success:
                        if (!Rxmsg.WriteByte(lastChar))
                        {
                            return(AL_ReadData_Result.ALRes_DatTransferErrr);
                        }
                        if (first)
                        {
                            first = false;
                        }
                        else
                        {
                            GetIProtocolParent.TimeCharGapAdd(CAS.Lib.RTLib.Processes.Timer.ToUSeconds(InterCharStopwatch.Elapsed));
                        }
                        break;

                    case TGetCharRes.DisInd:
                        return(AL_ReadData_Result.ALRes_DisInd);
                    }
                }while (CheckCharTimeout(((ModBus_ProtocolParameters)GetProtocolParameters).TimeoutCharacterSpan, InterCharStopwatch));
                Rxmsg.userDataLength = Rxmsg.offset;
                Rxmsg.offset         = 0;
                if (CheckCharTimeout(((ModBus_ProtocolParameters)GetProtocolParameters).TimeoutCharacterSpan, InterCharStopwatch))
                {
                    Flush(((ModBus_ProtocolParameters)GetProtocolParameters).InterframeGapSpan);
                    Rxmsg.ReturnEmptyEnvelope();
                    Rxmsg = null;
                    GetIProtocolParent.IncStRxFragmentedCounter();
                    return(AL_ReadData_Result.ALRes_DatTransferErrr);
                }
                return(AL_ReadData_Result.ALRes_Success);
            }
            catch (DisconnectException) { return(AL_ReadData_Result.ALRes_DisInd); }
        }
        } //GetMessage

        /// <summary>
        /// Transmit message to the remote unit.
        /// </summary>
        /// <param name="Txmsg">Message to be transmitted</param>
        /// <returns>
        ///   ALRes_Success:
        ///      Operation accomplished successfully
        ///   ALRes_DisInd:
        ///      Disconnect indication – connection has been shut down remotely or lost because of
        ///      communication error. Data is unavailable
        /// </returns>
        protected override AL_ReadData_Result TransmitMessage(MBUS_message Txmsg)
        {
            Flush(((MBUS_ProtocolParameters)GetProtocolParameters).InterframeGapSpan);
            GetIProtocolParent.IncStTxFrameCounter();
            switch (GetICommunicationLayer.FrameEndSignal(Txmsg))
            {
            case TFrameEndSignalRes.Success:
                break;

            case TFrameEndSignalRes.DisInd:
                return(AL_ReadData_Result.ALRes_DisInd);
            }
            return(AL_ReadData_Result.ALRes_Success);
        }
        /// <summary>
        /// Transmit message to the remote unit.
        /// </summary>
        /// <param name="toSendMessage">Message to be transmitted</param>
        /// <returns>
        ///   ALRes_Success: Operation accomplished successfully
        ///   ALRes_DatTransferErrr: Data transfer is imposible because of a communication error – loss of
        ///      communication with a station
        ///   ALRes_DisInd: Disconnect indication – connection has been shut down remotely or lost because of
        ///      communication error. Data is unavailable
        /// </returns>
        protected override AL_ReadData_Result TransmitMessage(FrameStateMachine toSendMessage)
        {
            FrameStateMachine preparedToSend = m_Pool.GetEmptyISesDBuffer();

            //tworzymy nowego message'a do wyslania- bedzie on zawieral dodatkowo bajty sumy kontrolna i wstawione znaki
            preparedToSend.PrepareFrameToBeSend(toSendMessage);
            switch (GetICommunicationLayer.FrameEndSignal(preparedToSend))
            {
            case TFrameEndSignalRes.Success:
                GetIProtocolParent.IncStTxFrameCounter(); //uzupelniamy statystyki
                break;

            case TFrameEndSignalRes.DisInd:
                return(AL_ReadData_Result.ALRes_DisInd);
            }
            preparedToSend.ReturnEmptyEnvelope();
            return(AL_ReadData_Result.ALRes_Success);
        }
        /// <summary>
        /// Transmit message to the remote unit.
        /// </summary>
        /// <param name="message">Message to be transmitted</param>
        /// <returns>
        ///   ALRes_Success:
        ///      Operation accomplished successfully
        ///   ALRes_DisInd:
        ///      Disconnect indication – connection has been shut down remotely or lost because of
        ///      communication error. Data is unavailable
        /// </returns>
        protected override AL_ReadData_Result TransmitMessage(ModBusMessage message)
        {
            try
            {
                Flush(((ModBus_ProtocolParameters)GetProtocolParameters).Timeout35Span);
                //flush may throw DisconnectException
            }
            catch (DisconnectException ex)
            {
                AssemblyTraceEvent.Tracer.TraceEvent(TraceEventType.Information, 130, $"ModBusProtocol.TransmitMessage.Flush: exception has been caught {ex.Message}");
                return(AL_ReadData_Result.ALRes_DisInd);
            }
            GetIProtocolParent.IncStTxFrameCounter();
            switch (GetICommunicationLayer.FrameEndSignal(message))
            {
            case TFrameEndSignalRes.Success:
                break;

            case TFrameEndSignalRes.DisInd:
                return(AL_ReadData_Result.ALRes_DisInd);
            }
            return(AL_ReadData_Result.ALRes_Success);
        }
        /// <summary>
        ///This function gets message from the remote unit.
        /// </summary>
        /// <param name="cRxmsg">received message</param>
        /// <param name="cTxmsg">transmited message, information about this frmae are necessary for checking if this is correct answer</param>
        /// <param name="cInfinitewait">true if this function should wait infinite time for the first character - true for slave side , false in master </param>
        ///  <param name="cStation_addrress">address of station - When this function is used by slavet</param>
        ///  <param name="cReset">the value is set to true if we expected response, but have gor request - we must reset and wait for response </param>
        /// <returns>
        ///   ALRes_Success: Operation accomplished successfully
        ///   ALRes_DatTransferErrr: Data transfer is imposible because of a communication error – loss of
        ///      communication with a station
        ///   ALRes_DisInd: Disconnect indication – connection has been shut down remotely or lost because of
        ///      communication error. Data is unavailable
        /// </returns>
        private AL_ReadData_Result GetMessage(out FrameStateMachine cRxmsg, FrameStateMachine cTxmsg, bool cInfinitewait, int cStation_addrress, ref bool cReset)
        {
            IntercharStopwatch.StartReset();
            TimeSpan currTimeOut;

            if (!cInfinitewait)
            {
                currTimeOut = this.GetProtocolParameters.ResponseTimeOutSpan;
            }
            else
            {
                currTimeOut = TimeSpan.MaxValue;
            }
            RecStateEnum currRecState = RecStateEnum.RSE_BeforeHeading;

            cRxmsg = m_Pool.GetEmptyISesDBuffer();
            cRxmsg.InitMsg(cTxmsg);
            bool continueDo = true;
            bool flushWait  = false;

            do
            {
                RecEventEnum lastRecEvent = RecEventEnum.REE_TimeOut;
                byte         lastChar;
                switch (GetICommunicationLayer.GetChar(out lastChar, Convert.ToInt32(currTimeOut.TotalMilliseconds)))
                {
                case TGetCharRes.Success:
                    switch (cRxmsg.DepositeChar(lastChar))
                    {
                    case FrameStateMachine.DepCharacterTypeEnum.DCT_Last:
                        lastRecEvent = RecEventEnum.REE_NewCharLastOne;
                        break;

                    case FrameStateMachine.DepCharacterTypeEnum.DCT_Reset_Answer:
                        GetIProtocolParent.IncStRxSynchError(); //wrong frame type so synchronization error must be monitored
                        cReset       = true;
                        lastRecEvent = RecEventEnum.REE_NewChar;
                        break;

                    case FrameStateMachine.DepCharacterTypeEnum.DCT_Ordinary:
                        lastRecEvent = RecEventEnum.REE_NewChar;
                        break;

                    case FrameStateMachine.DepCharacterTypeEnum.DCT_SOH:
                        lastRecEvent = RecEventEnum.REE_NewCharSOH;
                        break;
                    }
                    break;

                case TGetCharRes.Timeout:
                    lastRecEvent = RecEventEnum.REE_TimeOut;
                    break;

                case TGetCharRes.DisInd:
                    cRxmsg.ReturnEmptyEnvelope();
                    cRxmsg = null;
                    AssemblyTraceEvent.Tracer.TraceEvent(TraceEventType.Verbose, 115, $"SBUSProtocol.GetMessage(): {nameof(TGetCharRes.DisInd)} has occured during receiving frame, I am exitting the receiving loop and returning AL_ReadData_Result.ALRes_DisInd");
                    return(AL_ReadData_Result.ALRes_DisInd);
                }
                switch (currRecState)
                {
                case RecStateEnum.RSE_BeforeHeading:
                {
                    #region RecStateEnum.RSE_BeforeHeading
                    switch (lastRecEvent)
                    {
                    case RecEventEnum.REE_NewChar:
                        break;

                    case RecEventEnum.REE_NewCharSOH:
                    {
                        currRecState = RecStateEnum.RSE_InsideFrame;
                        GetIProtocolParent.TimeMaxResponseDelayAdd((long)(CAS.Lib.RTLib.Processes.Stopwatch.ConvertTo_ms(IntercharStopwatch.Reset)));
                        currTimeOut = ((SBUS_ProtocolParameters)GetProtocolParameters).TimeoutSpanAfterFrame;
                        break;
                    }

                    case RecEventEnum.REE_TimeOut:
                        GetIProtocolParent.IncStRxNoResponseCounter();
                        cRxmsg.ReturnEmptyEnvelope();
                        cRxmsg = null;
                        AssemblyTraceEvent.Tracer.TraceEvent
                        (
                            TraceEventType.Verbose, 137, "SBUSProtocol.GetMessage():RecStateEnum.RSE_BeforeHeading: RecEventEnum.REE_TimeOut has occurred during receiving frame, I am exiting the receiving loop with AL_ReadData_Result.ALRes_DatTransferErrr"
                        );
                        return(AL_ReadData_Result.ALRes_DatTransferErrr);
                    }
                    ;
                    break;
                    #endregion
                }

                case RecStateEnum.RSE_InsideFrame:
                {
                    #region RecStateEnum.RSE_InsideFrame
                    switch (lastRecEvent)
                    {
                    case RecEventEnum.REE_NewChar:
                        GetIProtocolParent.TimeCharGapAdd((long)(CAS.Lib.RTLib.Processes.Stopwatch.ConvertTo_us(IntercharStopwatch.Reset)));
                        break;

                    case RecEventEnum.REE_NewCharLastOne:
                        GetIProtocolParent.TimeCharGapAdd((long)(CAS.Lib.RTLib.Processes.Stopwatch.ConvertTo_us(IntercharStopwatch.Reset)));
                        continueDo = false;
                        break;

                    case RecEventEnum.REE_TimeOut:
                        if (flushWait)
                        {
                            AssemblyTraceEvent.Tracer.TraceEvent(TraceEventType.Information, 200, "SBUSProtocol.GetMessage(): Timeout has occurred during receiving frame, I am emitting the receiving loop");
                            continueDo = false;
                            break;
                        }
                        else
                        {
                            currTimeOut = ((SBUS_ProtocolParameters)GetProtocolParameters).TimeoutSpanAfterFrame;
                            flushWait   = true;
                            break;
                        }
                    }
                    ;
                    break;
                    #endregion
                }
                }
            }while (continueDo);
            return(AL_ReadData_Result.ALRes_Success);
        }//GetMessage
        /// <summary>
        /// This function gets message from the remote unit.
        /// </summary>
        /// <param name="receiveMessage">Received message</param>
        /// <param name="transmitMessage">Transited message, information about this frame could be necessary to properly initialize received frame.
        /// </param>
        /// <returns>
        ///   ALRes_Success: Operation accomplished successfully
        ///   ALRes_DatTransferErrr: Data transfer is imposable because of a communication error – loss of
        ///      communication with a station
        ///   ALRes_DisInd: Disconnect indication – connection has been shut down remotely or lost because of
        ///      communication error. Data is unavailable
        /// </returns>
        protected override AL_ReadData_Result GetMessage(out ModBusMessage receiveMessage, ModBusMessage transmitMessage)
        {
            receiveMessage = null;
            try
            {
                InterCharStopwatch.Reset();
                InterCharStopwatch.Start();
                if (!CheckCharTimeout(GetProtocolParameters.ResponseTimeOutSpan, InterCharStopwatch))
                {
                    GetIProtocolParent.IncStRxNoResponseCounter();
                    return(AL_ReadData_Result.ALRes_DatTransferErrr);
                }
                GetIProtocolParent.TimeMaxResponseDelayAdd(InterCharStopwatch.ElapsedMilliseconds);
                receiveMessage = m_Pool.GetEmptyISesDBuffer();
                receiveMessage.userDataLength = receiveMessage.userBuffLength;
                receiveMessage.offset         = 0;
                bool first = true;
                do
                {
                    byte lastChar;
                    InterCharStopwatch.Reset();
                    InterCharStopwatch.Start();
                    switch (GetICommunicationLayer.GetChar(out lastChar))
                    {
                    case TGetCharRes.Success:
                        if (!receiveMessage.WriteByte(lastChar))
                        {
                            AssemblyTraceEvent.Tracer.TraceEvent(TraceEventType.Warning, 77, "ModBusProtocol.GetMessage: cannot write character received from the Communication Layer");
                            return(AL_ReadData_Result.ALRes_DatTransferErrr);
                        }
                        if (first)
                        {
                            first = false;
                        }
                        else
                        {
                            GetIProtocolParent.TimeCharGapAdd(CAS.Lib.RTLib.Processes.Timer.ToUSeconds(InterCharStopwatch.Elapsed));
                        }
                        break;

                    case TGetCharRes.DisInd:
                        return(AL_ReadData_Result.ALRes_DisInd);
                    }
                }while (CheckCharTimeout(((ModBus_ProtocolParameters)GetProtocolParameters).Timeout15Span, InterCharStopwatch));
                receiveMessage.userDataLength = receiveMessage.offset;
                receiveMessage.offset         = 0;
                if (CheckCharTimeout(((ModBus_ProtocolParameters)GetProtocolParameters).Timeout35Span, InterCharStopwatch))
                {
                    Flush(((ModBus_ProtocolParameters)GetProtocolParameters).Timeout35Span);
                    receiveMessage.ReturnEmptyEnvelope();
                    receiveMessage = null;
                    GetIProtocolParent.IncStRxFragmentedCounter();
                    return(AL_ReadData_Result.ALRes_DatTransferErrr);
                }
                return(AL_ReadData_Result.ALRes_Success);
            }
            catch (DisconnectException)
            {
                return(AL_ReadData_Result.ALRes_DisInd);
            }
        }
        /// <summary>
        /// This function gets message from the remote unit.
        /// </summary>
        /// <param name="Rxmsg">Received message</param>
        /// <param name="Txmsg">Transmited message, information about this frmae could be necessary to properly init received frame.
        /// </param>
        /// <returns>
        ///   ALRes_Success: Operation accomplished successfully
        ///   ALRes_DatTransferErrr: Data transfer is imposible because of a communication error – loss of
        ///      communication with a station
        ///   ALRes_DisInd: Disconnect indication – connection has been shut down remotely or lost because of
        ///      communication error. Data is unavailable
        /// </returns>
        protected override AL_ReadData_Result GetMessage(out MBUS_message Rxmsg, MBUS_message Txmsg)
        {
            int  QuantityOfByteInMessage = 0;
            bool cInfinitewait           = false;

            IntercharStopwatch.StartReset();
            TimeSpan currTimeOut;

            if (!cInfinitewait)
            {
                currTimeOut = this.GetProtocolParameters.ResponseTimeOutSpan;
            }
            else
            {
                currTimeOut = TimeSpan.MaxValue;
            }
            RecStateEnum currRecState = RecStateEnum.RSE_BeforeHeading;

            Rxmsg = m_Pool.GetEmptyISesDBuffer();
            Rxmsg.InitMsg(Txmsg);
            bool continueDo = true;
            bool flushWait  = false;

            do
            {
                RecEventEnum lastRecEvent = RecEventEnum.REE_TimeOut;
                byte         lastChar;
                switch (GetICommunicationLayer.GetChar(out lastChar, Convert.ToInt32(currTimeOut.TotalMilliseconds)))
                {
                case TGetCharRes.Success:
                    switch (Rxmsg.DepositeChar(lastChar))
                    {
                    case DepCharacterTypeEnum.DCT_Last:
                        lastRecEvent = RecEventEnum.REE_NewCharLastOne;
                        break;

                    case DepCharacterTypeEnum.DCT_Reset_Answer:
                        GetIProtocolParent.IncStRxSynchError(); //dostalismy ramke nie taka jak trzeba wiec ustawiamy blad jako blad synchronizacji
                        lastRecEvent = RecEventEnum.REE_NewChar;
                        break;

                    case DepCharacterTypeEnum.DCT_Ordinary:
                        lastRecEvent = RecEventEnum.REE_NewChar;
                        break;

                    case DepCharacterTypeEnum.DCT_SOH:
                        lastRecEvent = RecEventEnum.REE_NewCharSOH;
                        break;
                    }
                    QuantityOfByteInMessage++;
                    break;

                case TGetCharRes.Timeout:
                    lastRecEvent = RecEventEnum.REE_TimeOut;
                    break;

                case TGetCharRes.DisInd:
                    Rxmsg.ReturnEmptyEnvelope();
                    return(AL_ReadData_Result.ALRes_DisInd);
                }
                switch (currRecState)
                {
                case RecStateEnum.RSE_BeforeHeading:
                {
                    #region RecStateEnum.RSE_BeforeHeading
                    switch (lastRecEvent)
                    {
                    case RecEventEnum.REE_NewChar:
                        break;

                    case RecEventEnum.REE_NewCharSOH:
                    {
                        currRecState = RecStateEnum.RSE_InsideFrame;
                        GetIProtocolParent.TimeMaxResponseDelayAdd((long)(CAS.Lib.RTLib.Processes.Stopwatch.ConvertTo_ms(IntercharStopwatch.Reset)));
                        currTimeOut = ((MBUS_ProtocolParameters)GetProtocolParameters).CharacterTimeoutSpan;
                        break;
                    }

                    case RecEventEnum.REE_TimeOut:
                        GetIProtocolParent.IncStRxNoResponseCounter();
                        Rxmsg.ReturnEmptyEnvelope();
                        Rxmsg = null;
                        return(AL_ReadData_Result.ALRes_DatTransferErrr);
                    }
                    ;
                    break;
                    #endregion
                }

                case RecStateEnum.RSE_InsideFrame:
                {
                    #region RecStateEnum.RSE_InsideFrame
                    switch (lastRecEvent)
                    {
                    case RecEventEnum.REE_NewChar:
                        GetIProtocolParent.TimeCharGapAdd((long)(CAS.Lib.RTLib.Processes.Stopwatch.ConvertTo_us(IntercharStopwatch.Reset)));
                        break;

                    case RecEventEnum.REE_NewCharLastOne:
                        GetIProtocolParent.TimeCharGapAdd((long)(CAS.Lib.RTLib.Processes.Stopwatch.ConvertTo_us(IntercharStopwatch.Reset)));
                        continueDo = false;
                        break;

                    case RecEventEnum.REE_TimeOut:
                        if (flushWait)
                        {
                            continueDo = false;
                            break;
                        }
                        else
                        {
                            currTimeOut = ((MBUS_ProtocolParameters)GetProtocolParameters).ResponseTimeOutSpan;//TimeoutAfterFrameTicks;
                            flushWait   = true;
                            break;
                        }
                    }
                    ;
                    break;
                    #endregion
                }
                }
            }while (continueDo);
            return(AL_ReadData_Result.ALRes_Success);
        } //GetMessage