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 { } }
/// <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 ^-^-^-^-^"); } }
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(); }
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. } } } } }