/// <summary> /// Closes the serial port. /// </summary> private void CloseSerialPort() { lock (_lock) { Trace.TraceInformation("{0}.CloseSerialPort: CommPort={1}", CLASSNAME, _serialPort.PortName); // Attempt to close the serial port object if (_serialPort != null) { _serialPort.DataReceived -= SerialPort_DataReceived; _serialPort.ErrorReceived -= SerialPort_ErrorReceived; if (_serialPort.IsOpen) { try { _serialPort.Close(); } catch (IOException) { } catch (Exception ex) { Trace.TraceError("{0}.CloseSerialPort: CommPort={1} Exception={2}", CLASSNAME, _serialPort.PortName, ex.GetBaseException()); throw ex; } } _serialPort.Dispose(); _serialPort = null; _buffer = null; _bufPos = 0; _state = RecvrState.NoDeviceFound; } } // end lock }
/// <summary> /// Opens the serial port. /// </summary> private void OpenSerialPort(string commPort) { lock (_lock) { // Open the serial port connection _serialPort = new SerialPort() { PortName = commPort, BaudRate = BAUD_RATE, DataBits = DATA_BITS, StopBits = STOP_BITS, Parity = PARITY, WriteTimeout = WRITE_TIMEOUT, Handshake = HANDSHAKE }; Trace.TraceInformation("{0}.OpenSerialPort: CommPort={1}", CLASSNAME, _serialPort.PortName); try { _serialPort.Open(); } catch (Exception ex) { Trace.TraceError("{0}.OpenSerialPort: CommPort={1} Exception={2}", CLASSNAME, _serialPort.PortName, ex.GetBaseException()); throw ex; } _buffer = new byte[BUFFER_SIZE]; _bufPos = 0; _state = RecvrState.Waiting; _serialPort.DataReceived += SerialPort_DataReceived; _serialPort.ErrorReceived += SerialPort_ErrorReceived; GC.SuppressFinalize(_serialPort.BaseStream); // Work around, see http://social.msdn.microsoft.com/Forums/en-US/netfxbcl/thread/8a1825d2-c84b-4620-91e7-3934a4d47330 } // end lock }
/// <summary> /// Handles the DataReceived event of the serialPort control. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">The <see cref="System.IO.Ports.SerialDataReceivedEventArgs"/> instance containing the event data.</param> private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e) { // Data format: STX COUNT DATA ... CHECKSUM ETX DataPacketReceivedEventArgs eventData = null; lock (_lock) { try { while (_serialPort.BytesToRead > 0) { byte data = (byte)_serialPort.ReadByte(); switch (_state) { case RecvrState.Waiting: if (data == 0x02) { _state = RecvrState.PacketLength; } break; case RecvrState.PacketLength: _checksum = data; _dataLength = data - 1; _bufPos = 0; _buffer.Initialize(); _state = RecvrState.PacketData; break; case RecvrState.PacketData: if (_bufPos < _dataLength) { _buffer[_bufPos++] = data; _checksum ^= data; } if (_bufPos == _dataLength) { _state = RecvrState.Checksum; } break; case RecvrState.Checksum: if (_checksum != data) { Trace.TraceWarning("{0}.SerialPort_DataReceived: Checksum mismatch. Expected={1} Actual={2}", CLASSNAME, _checksum, data); _state = RecvrState.Waiting; } else { _state = RecvrState.Received; } break; case RecvrState.Received: if (data == 0x03) { // We got a message! eventData = new DataPacketReceivedEventArgs() { CommPort = _serialPort.PortName, DataLength = _dataLength, DataPacket = new byte[_bufPos] }; Array.Copy(_buffer, 0, eventData.DataPacket, 0, _bufPos); _state = RecvrState.Waiting; } break; default: Trace.TraceError("{0}.SerialPort_DataReceived: Unknown receive state, resetting state"); _state = RecvrState.Waiting; break; } } } catch (InvalidOperationException ex) { Trace.TraceError("{0}.SerialPort_DataReceived: CommPort={1} Exception={2}", CLASSNAME, _serialPort.PortName, ex.GetBaseException()); } } // end lock // Fire event if we have data (we are outside our lock here) if (eventData != null) { OnDataPacketReceived(eventData); } }
/// <summary> /// Handles the ErrorReceived event of the serialPort control. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">The <see cref="System.IO.Ports.SerialErrorReceivedEventArgs"/> instance containing the event data.</param> private void SerialPort_ErrorReceived(object sender, SerialErrorReceivedEventArgs e) { _state = RecvrState.Waiting; }
/// <summary> /// Handles the DataReceived event of the serialPort control. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">The <see cref="System.IO.Ports.SerialDataReceivedEventArgs"/> instance containing the event data.</param> private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e) { // Data format: STX COUNT DATA ... CHECKSUM ETX DataPacketReceivedEventArgs eventData = null; lock (_lock) { try { while (_serialPort.BytesToRead > 0) { byte data = (byte)_serialPort.ReadByte(); switch (_state) { case RecvrState.Waiting: if (data == 0x02) { _state = RecvrState.PacketLength; } break; case RecvrState.PacketLength: _checksum = data; _dataLength = data - 1; _bufPos = 0; _buffer.Initialize(); _state = RecvrState.PacketData; break; case RecvrState.PacketData: if (_bufPos < _dataLength) { _buffer[_bufPos++] = data; _checksum ^= data; } if (_bufPos == _dataLength) { _state = RecvrState.Checksum; } break; case RecvrState.Checksum: if (_checksum != data) { Trace.TraceWarning("{0}.SerialPort_DataReceived: Checksum mismatch. Expected={1} Actual={2}", CLASSNAME, _checksum, data); _state = RecvrState.Waiting; } else { _state = RecvrState.Received; } break; case RecvrState.Received: if (data == 0x03) { // We got a message! eventData = new DataPacketReceivedEventArgs() { CommPort = _serialPort.PortName, DataLength = _dataLength, DataPacket = new byte[_bufPos] }; Array.Copy(_buffer, 0, eventData.DataPacket, 0, _bufPos); _state = RecvrState.Waiting; } break; default: Trace.TraceError("{0}.SerialPort_DataReceived: Unknown receive state, resetting state"); _state = RecvrState.Waiting; break; } } } catch (InvalidOperationException ex) { Trace.TraceError("{0}.SerialPort_DataReceived: CommPort={1} Exception={2}", CLASSNAME, _serialPort.PortName, ex.GetBaseException()); } } // end lock // Fire event if we have data (we are outside our lock here) if (eventData != null) OnDataPacketReceived(eventData); }