Introduction
The EnhancedSerialPort
class is inherited from WinForm component, "SerialPort". When you use this class you are taking away the burden
of manually selecting the available serial ports on your code or on the side of the users of your app, and assures that your device is connected to an available serial port in your PC, thereby making your serial port device plug and play. This is very useful when you are developing a system which utilizes multiple serial ports or a serial port hub to manage available ports programmatically. You can also inherit this class and override its OnDataReceived
and OnPinChanged
event handler methods.
Background
Although nowadays, USB is the common communication interface of PCs, unlike "parallel" port or LPT, the legacy RS232 serial port or COM
is still around. You could still find the serial port on new motherboards that supports intel iX series processors. Many devices specially industrial equipments still use the RS232
serial port as their communication interface. That is why there are USB-To-Serial Port converters and PCI-To-Serial Port cards
in the market. There are also virtual serial ports which rides over USB and Serial Port Hubs which lets you have over 16 serial ports to one USB interface. You may search using Google if you want to know more about the basics of serial port.
Using the Code
Below is the code. You may use it in a separate library (DLL) project folder or with your own Visual Studio project folder.
using System;
using System.Collections.Generic;
using System.Text;
using System.IO.Ports;
using System.ComponentModel;
using System.Threading;
namespace EnhancedSerialPort
{
public class EnhancedSerialPort : SerialPort
{
#region Variables
protected string _dataRead = null;
List<string> _availablePorts = new List<string>();
protected bool _connected;
bool _isReceived = false;
#endregion
#region Properties
public string DataRead { get { return _dataRead; } }
public List<string> AvailablePorts
{
get
{
return _availablePorts;
}
}
public string DeviceIdCommand { get; set; }
public string DeviceId { get; set; }
#endregion
#region Constructors
public EnhancedSerialPort() : base()
{
InitializeComponent();
}
public EnhancedSerialPort(IContainer container) : base(container)
{
InitializeComponent();
}
#endregion
#region Methods
public void InitializeComponent()
{
base.WriteTimeout = base.ReadTimeout = 5000;
if (GetAvailablePorts().Count > 0)
base.PortName = _availablePorts[0];
this.DataReceived +=
new System.IO.Ports.SerialDataReceivedEventHandler(
this.OnDataReceived);
this.PinChanged +=
new System.IO.Ports.SerialPinChangedEventHandler(
this.OnPinChanged);
}
private List<string> GetAvailablePorts()
{
foreach (string port in SerialPort.GetPortNames())
{
base.PortName = port;
try
{
if (base.IsOpen)
base.Close();
base.Open();
_availablePorts.Add(base.PortName);
base.Close();
continue;
}
catch (System.IO.IOException ioError)
{
if (ioError.Message.EndsWith("does not exist."))
continue;
}
catch (System.UnauthorizedAccessException uax)
{
if (uax.Message.EndsWith("is denied."))
continue;
}
}
if (_availablePorts.Count == 0)
throw new NoSerialPortAvailableError();
return _availablePorts;
}
public bool CheckConnection()
{
if (!base.IsOpen)
{
foreach (string port in AvailablePorts)
{
if (base.IsOpen) base.Close();
base.PortName = port;
try
{
if (!base.IsOpen) base.Open();
}
catch (System.UnauthorizedAccessException uax)
{
if (uax.Message.EndsWith("is denied."))
continue;
}
base.Write(DeviceIdCommand);
for (int i = 0; i < 10 && !_isReceived; i++)
{
Thread.Sleep(50);
}
_isReceived = false;
if (_dataRead != null)
if (_dataRead.Equals(DeviceId))
{
_connected = true;
return true;
}
_connected = false;
}
}
if (!_connected) throw new DeviceCommunicationError();
return _connected;
}
#endregion
#region Event Handler Methods
protected virtual void OnDataReceived(
object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
_dataRead = ReadLine();
}
protected virtual void OnPinChanged(
object sender, System.IO.Ports.SerialPinChangedEventArgs e)
{
if (e.EventType == SerialPinChange.CDChanged)
{
}
else if (e.EventType == SerialPinChange.CtsChanged)
{
}
else if (e.EventType == SerialPinChange.DsrChanged)
{
}
}
#endregion
#region Exceptions
public class NoSerialPortAvailableError : Exception
{
public override string Message
{
get
{
return "No serial port available.";
}
}
}
public class ConnectionError : Exception
{
public override string Message
{
get
{
return "Disconnected or cannot connect to the device.";
}
}
}
#endregion
}
}