Skip to content

Instantly share code, notes, and snippets.

@adamkewley
Created December 4, 2015 20:33
Show Gist options
  • Save adamkewley/c607e872dbd260d15c63 to your computer and use it in GitHub Desktop.
Save adamkewley/c607e872dbd260d15c63 to your computer and use it in GitHub Desktop.
Extension methods to make System.IO.Ports.SerialPort easier to use with .NET 4.5 async workflows (Does not support timeouts)
using System.IO.Ports;
namespace AsyncExtensions {
public static class SerialPortExtensions
{
/// <summary>
/// Read a line from the SerialPort asynchronously
/// </summary>
/// <param name="serialPort">The port to read data from</param>
/// <returns>A line read from the input</returns>
public static async Task<string> ReadLineAsync(
this SerialPort serialPort)
{
byte[] buffer = new byte[1];
string ret = string.Empty;
// Read the input one byte at a time, convert the
// byte into a char, add that char to the overall
// response string, once the response string ends
// with the line ending then stop reading
while(true)
{
await serialPort.BaseStream.ReadAsync(buffer, 0, 1);
ret += serialPort.Encoding.GetString(buffer);
if (ret.EndsWith(serialPort.NewLine))
// Truncate the line ending
return ret.Substring(0, ret.Length - serialPort.NewLine.Length);
}
}
/// <summary>
/// Write a line to the SerialPort asynchronously
/// </summary>
/// <param name="serialPort">The port to send text to</param>
/// <param name="str">The text to send</param>
/// <returns></returns>
public static async Task WriteLineAsync(
this SerialPort serialPort, string str)
{
byte[] encodedStr =
serialPort.Encoding.GetBytes(str + serialPort.NewLine);
await serialPort.BaseStream.WriteAsync(encodedStr, 0, encodedStr.Length);
await serialPort.BaseStream.FlushAsync();
}
/// <summary>
/// Write a line to the ICommunicationPortAdaptor asynchronously followed
/// immediately by attempting to read a line from the same port. Useful
/// for COMMAND --> RESPONSE type communication.
/// </summary>
/// <param name="serialPort">The port to process commands through</param>
/// <param name="command">The command to send through the port</param>
/// <returns>The response from the port</returns>
public static async Task<string> SendCommandAsync(
this SerialPort serialPort, string command)
{
await serialPort.WriteLineAsync(command);
return await serialPort.ReadLineAsync();
}
}
}
@gmkado
Copy link

gmkado commented Jun 18, 2020

Great stuff, thanks!

@majumajid
Copy link

majumajid commented Sep 5, 2021

ReadLineAsync is not working, do you have any unit testing code ?

@adamkewley
Copy link
Author

@majumajid no tests, sorry - this was written a long time ago as throwaway code to demonstrate a basic feature

@HenKun
Copy link

HenKun commented Feb 6, 2024

Read method might not work for UTF8 and other encodings that can use more than one byte per character. The GetString can return erroneous results. This answer can help with that: https://stackoverflow.com/a/26901612

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment