예제 #1
0
        protected virtual void OnConnectionLost()
        {
            _isConnected = false;
            _connectionMonitorState = ConnectionMonitorState.AttemptingToConnect;

            if (ConnectionLost != null)
            {
                try
                {
                    ConnectionLost(this, new EventArgs());
                }
                catch
                {
                    // just catch the error in the user code and continue.
                }
            }

            try
            {
                // Since OnConnectionLost can be called from a superclass (such as from the TcpCommunication.readCallback()) we need to change the timer to _connectionAttemptInterval.
                if (_connectionMonitorEnabled && _connectionMonitorTimer != null) // just in case it was disabled while the above was running.
                {
                    //System.Diagnostics.Debug.WriteLine(DateTime.Now.ToString() + "************************************** OnConnectionLost Setting timer interval to " + _connectionAttemptInterval);

                    _connectionMonitorTimer.Change(_connectionAttemptInterval, System.Threading.Timeout.Infinite);
                }
            }
            catch
            {
            }
        }
예제 #2
0
        /// <summary>
        /// Add the specified data to the internal buffer and parses the buffer for delimited data.
        /// </summary>
        public void ProcessReceivedData(byte[] data, int byteCount)
        {
            //System.Diagnostics.Debug.WriteLine(DateTime.Now.ToString() + "  " + System.Reflection.Assembly.GetEntryAssembly().GetName().Name + "  " + System.Threading.Thread.CurrentThread.GetHashCode() + "  ProcessReceivedData received utf8:   " + Encoding.UTF8.GetString(data, 0, byteCount));

            lock (_readBufferString_lock)
            {
                _lastReceivedDataDateTime = DateTime.Now;

                startCommunicatingTimer();

                try
                {
                    if (_totalReceivedByteCount != ulong.MaxValue) // did we already max out?
                        checked // force OverflowException on overflow.
                        {
                            _totalReceivedByteCount += (ulong)byteCount;
                        }
                }
                catch (OverflowException)
                {
                    _totalReceivedByteCount = ulong.MaxValue;
                }

                if (_connectionMonitorEnabled)
                {
                    if (_connectionMonitorTimer != null)
                        _connectionMonitorTimer.Change(_connectionMonitorTimeout, System.Threading.Timeout.Infinite);

                    _connectionMonitorState = ConnectionMonitorState.Connected;
                }

                //**************************************************************
                // Check for connection reestablished
                //**************************************************************
                if (_isConnected == false)
                    OnConnectionEstablished();

                //**************************************************************
                // Write the data to the user accessible buffer.
                //**************************************************************
                if (_bufferReader != null && MaximumReadBufferSize > 0)
                {
                    if (_bufferReader.Length + byteCount <= MaximumReadBufferSize)
                    {
                        // Append all the incoming bytes to the buffer.
                        _bufferReader.WriteInternal(data, 0, byteCount);
                    }
                    else
                    {
                        // Fill the rest of the buffer with as many bytes as we can.
                        _bufferReader.WriteInternal(data, 0, MaximumReadBufferSize - (int)_bufferReader.Length);
                        OnBufferOverflow(); // let the user know that the buffer overflowed.
                    }
                }

                //*****************************************************************************************************************
                // Fire the ReceivedBytes.
                //*****************************************************************************************************************
                OnReceivedBytes(data, byteCount);

                //*******************************************************
                // Decode the bytes to a string.
                //*******************************************************
                string receivedString = null;
                if (_encoding != null)
                {
                    //*******************************************************
                    // Copy the data to the end of the existing byte buffer.
                    //*******************************************************
                    try
                    {
                        byte[] tempStringDecodingBuffer = new byte[_stringDecodingBuffer.Length + byteCount];
                        System.Buffer.BlockCopy(_stringDecodingBuffer, 0, tempStringDecodingBuffer, 0, _stringDecodingBuffer.Length);
                        System.Buffer.BlockCopy(data, 0, tempStringDecodingBuffer, _stringDecodingBuffer.Length, byteCount);
                        _stringDecodingBuffer = tempStringDecodingBuffer;
                        tempStringDecodingBuffer = null;
                    }
                    catch (Exception ex)
                    {
                        //System.Diagnostics.Debugger.Break();
                        _logger.Error("An error occurred while copying the data to the end of the existing byte buffer.", ex);
                    }

                    //*********************************************************************************************************************
                    // Convert the bytes to a string (keeping track of how any good bytes there are in case a character spans two buffers.
                    //*********************************************************************************************************************
                    Decoder decoder = _encoding.GetDecoder();
                    int charCount = decoder.GetCharCount(_stringDecodingBuffer, 0, _stringDecodingBuffer.Length);
                    char[] chars = new char[charCount];
                    decoder.GetChars(_stringDecodingBuffer, 0, _stringDecodingBuffer.Length, chars, 0);

                    //**************************************************************
                    // Add the received string to the buffer.
                    //**************************************************************
                    //System.Diagnostics.Debug.WriteLine(DateTime.Now.ToString() + "  " + System.Reflection.Assembly.GetEntryAssembly().GetName().Name + "  " + System.Threading.Thread.CurrentThread.GetHashCode() + "  ProcessReceivedData buffer before: " + _readBufferString);
                    receivedString = new string(chars);
                    _readBufferString += receivedString;
                    //System.Diagnostics.Debug.WriteLine(DateTime.Now.ToString() + "  " + System.Reflection.Assembly.GetEntryAssembly().GetName().Name + "  " + System.Threading.Thread.CurrentThread.GetHashCode() + "  ProcessReceivedData buffer after:  " + _readBufferString);

                    // Determine how many bytes were actually decoded.
                    Encoder encoder = _encoding.GetEncoder();
                    int decodedByteCount = encoder.GetByteCount(chars, 0, charCount, false);

                    // Determine how many bytes at the end of the buffer are unprocessed partial utf8 bytes.
                    int unprocessedByteCount = _stringDecodingBuffer.Length - decodedByteCount;

                    try
                    {
                        // Set _stringDecodingBuffer to the unprocessed left over (partial character) bytes at the end.
                        byte[] tempStringDecodingBuffer = new byte[unprocessedByteCount];
                        System.Buffer.BlockCopy(_stringDecodingBuffer, decodedByteCount, tempStringDecodingBuffer, 0, unprocessedByteCount);
                        _stringDecodingBuffer = tempStringDecodingBuffer;
                        tempStringDecodingBuffer = null;
                    }
                    catch (Exception ex)
                    {
                        //System.Diagnostics.Debugger.Break();
                        _logger.Error("An error occurred while setting _stringDecodingBuffer to the unprocessed left over (partial character) bytes at the end.", ex);
                    }
                }

                //*****************************************************************************************************************
                // Fire the ReceivedString.
                //*****************************************************************************************************************
                if (string.IsNullOrEmpty(receivedString)) // only fire the event if we decoded at least one character.
                    OnReceivedString(receivedString);

                // NOTE: I WAS USING a StringBuilder object for both the logs and the input buffer, but it unexpectidly seemed to causes crashes!?!?

                if (_delimiter != null && _readBufferString.Length > 0)
                {
                    //System.Diagnostics.Debug.WriteLine(DateTime.Now.ToString() + "  " + System.Threading.Thread.CurrentThread.GetHashCode() + "  " + "BaseCommunication.ProcessReceivedData() processing: " + _readBufferString.Replace("\r", "<CR>").Replace("\n", "<LF>"));

                    // Loop over buffer processing any full responses.
                    int eolPos = _readBufferString.IndexOf(_delimiter);
                    while (eolPos >= 0)
                    {
                        // Pull out response from buffer
                        string response;
                        if (_includeDelimiterInRawResponse)
                            response = _readBufferString.Substring(0, eolPos + _delimiter.Length).Trim();
                        else
                            response = _readBufferString.Substring(0, eolPos).Trim();
                        _readBufferString = _readBufferString.Remove(0, eolPos + _delimiter.Length);

                        //System.Diagnostics.Debug.WriteLine(DateTime.Now.ToString() + "  " + System.Reflection.Assembly.GetEntryAssembly().GetName().Name + "  " + System.Threading.Thread.CurrentThread.GetHashCode() + "  ProcessReceivedData extracted response:  " + response);
                        //System.Diagnostics.Debug.WriteLine(DateTime.Now.ToString() + "  " + System.Reflection.Assembly.GetEntryAssembly().GetName().Name + "  " + System.Threading.Thread.CurrentThread.GetHashCode() + "  ProcessReceivedData buffer after removal:  " + _readBufferString);

                        //TODO:OnLog("port_DataReceived() received '" + response + "'");

                        OnReceivedDelimitedString(response, _includeDelimiterInRawResponse);

                        eolPos = _readBufferString.IndexOf(_delimiter);
                    }
                }
                else
                {
                    // There is no delimiter, so just clear the string buffer so it doesn't grow.
                    _readBufferString = "";
                    // Don't clear the byte buffer since it can contain partial character bytes for the decoder.
                }

                //TODO:OnLog("port_DataReceived() Exiting ^-^-^-^-^");
            }
        }
예제 #3
0
        protected virtual void OnConnectionAttempt()
        {
            try
            {
                open(); // attempt to open the connection.
            }
            catch (Exception ex)
            {
                // If it failed to connect the just return. The driver should test the Connected property after calling Open() or StartMonitoring().

                // The typical reasons for failure at this time are:
                // * Serial Port does not exist: NOT RECOVERABLE, however the configuration system only shows existing COM ports when the user created the device which is helpful.
                // * Serial Port already opened: RECOVERABLE (unless more than one driver is configured to use the same port)... once the other process releases the serial port, the connection monitoring will have access to the port.
                // * Tcp connection could not be established: RECOVERABLE if the Address is correct.
                // * Tcp network card is not installed: NOT RECOVERABLE

                OnConnectionAttemptFailed(ex);

                throw;
            }

            // Successfull Connection
            _connectionMonitorState = ConnectionMonitorState.Connected;
            OnConnectionEstablished();
        }
예제 #4
0
        void _connectionMonitorTimer_Elapsed(Object stateInfo)
        {
            if (_connectionMonitorEnabled)
            {
                int timerInterval = _connectionMonitorTimeout;

                // If we haven't received any data in a while...
                try
                {
                    TimeSpan timeSinceReceived = DateTime.Now - _lastReceivedDataDateTime;
                    //System.Diagnostics.Debug.WriteLine("TIME SINCE LAST RECEIVED DATA: " + timeSinceReceived.ToString());

                    switch (_connectionMonitorState)
                    {
                        case ConnectionMonitorState.AttemptingToConnect:
                            // Attempt to make a connection
                            try
                            {
                                OnConnectionAttempt(); // the serial class overrides this and does nothing if the serial connection has already been opened.
                            }
                            catch
                            {
                                // don't throw an error if it fails
                            }

                            timerInterval = _connectionAttemptInterval;

                            break;

                        case ConnectionMonitorState.Connected:
                            // We haven't received data in the time limit so send out the test connection request.

                            _connectionMonitorState = ConnectionMonitorState.Connected_WaitingForResponse; // set this to waiting whether there is a test request to send out or not.

                            if (_connectionMonitorTestRequestBytes != null && _connectionMonitorTestRequestBytes.Length > 0)
                            {
                                // Send the request since we haven't received anything for a while.
                                try
                                {
                                    timerInterval = _connectionMonitorWaitForResponseTimeout;

                                    //#if DEBUG
                                    //if (_connectionMonitorTestRequestString != null && _connectionMonitorTestRequestString.Length > 0)
                                    //    System.Diagnostics.Debug.WriteLine(DateTime.Now.ToString() + "  " + System.Threading.Thread.CurrentThread.GetHashCode() + "  _connectionMonitorTimer_Elapsed() sending: " + _connectionMonitorTestRequestString.Replace("\r", "<CR>").Replace("\n", "<LF>"));
                                    //else
                                    //    System.Diagnostics.Debug.WriteLine(DateTime.Now.ToString() + "  " + System.Threading.Thread.CurrentThread.GetHashCode() + "  _connectionMonitorTimer_Elapsed() sending: " + global::Common.SystemUtility.ByteArrayToHexString(_connectionMonitorTestRequestBytes, " "));
                                    //#endif

                                    Send(_connectionMonitorTestRequestBytes);
                                }
                                catch
                                {
                                    // just catch the error in and continue
                                }
                            }

                            // Fire the ConnectionMonitorTest event.
                            OnConnectionMonitorTest();
                            break;

                        case ConnectionMonitorState.Connected_WaitingForResponse:
                            // We were connected, but didn't receive a response after the request,
                            // so we are now considered disconnected.
                            _logger.Error("Connection monitoring sent a request after " + (_connectionMonitorTimeout/1000) + " seconds of device silence and failed to receive a response from the device within " + (_connectionMonitorWaitForResponseTimeout/1000) + " seconds so the connection is assumed to be lost.");
                            OnConnectionLost();

                            timerInterval = _connectionAttemptInterval;

                            // Attempt to reconnect
                            try
                            {
                                OnConnectionAttempt(); // the serial class overrides this and does nothing if the serial connection has already been opened.
                            }
                            catch
                            {
                                // don't throw an error if it fails
                            }

                            break;
                    }
                }
                catch (Exception ex)
                {
                    // do nothing
                }
                finally
                {
                    if (_connectionMonitorEnabled && _connectionMonitorTimer != null) // just in case it was disabled while the above was running.
                    {
                        //System.Diagnostics.Debug.WriteLine(DateTime.Now.ToString() + "************************************** _connectionMonitorTimer_Elapsed-finally Setting timer interval to " + timerInterval);

                        try
                        {
                            // I've seen this be null even though we just checked that, so I wrapped it in a try/catch.
                            _connectionMonitorTimer.Change(timerInterval, System.Threading.Timeout.Infinite);
                        }
                        catch
                        {
                            // _connectionMonitorTimer was probably null so ignore it.
                        }
                    }
                }
            }
        }