question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Introduce a Serial Port class

See original GitHub issue

The initial discussion started here.

Background and motivation

The System.IO.Ports.SerialPort class has been widely adopted in the .NET world to support serial port communication. Since it was first added in the .NET Framework, its implementation is quite old and does not support many of the new language and runtime improvements.

As opposed to many other classes, it is very difficult validating the behavior of the serial port class because it strictly depends on the serial port driver and the connected hardware. For this reason it is preferable not to touch the existing implementation which could cause serious breaking changes. Instead, it is better providing a brand new implementation exposing a modern API and flexible API.

Anyway, the lower layer code (interacting with the serial hardware) is precious and already working cross-platform, therefore it is desirable to reuse it as much as possible.

This is not yet an API proposal that will follow right after collecting all the basic requirements that will shape the new implementation.

Requirements

This is a list of basic requirements that will guide shaping the final API. In the triage team we expect to see this list growing and discussions will follow to include or not them in the final list.

Modernization

  • Use tasks in place of the Begin/End pattern (used in BeginRead, EndRead, BeginWrite, EndWrite)
  • Use Span<byte> in place of byte[] in the API parameters
  • Possibly exposing a parameterless constructor to evaluate the opportunity to use Dependency Injection
  • Being minimal and let the user easily add an “application layer” to support various communication patterns. Examples:
    • Pure text communication (considering UTF8, UTF16 and endianess variants). Evaluate whether exposing text oriented reads using extension methods.
    • Fixed size (binary) packet oriented communication (w/o header)
    • Dynamic size (binary) packet oriented communication (where the header contains the packet size)

Features

  • Expose the installed COM port list by name including the low level name (e.g. COM10) and also the PnP name (e.g. “Silicon Labs Dual CP210x…”)
  • Thread-affinity is important to communicate over the serial port. In certain scenarios, the asynchronous communication is interleaved with operations that needs to be fulfilled in a single thread. The current implementation has an EventLoop class that could be wrapped to this purpose. It would be even more interesting to reuse an implementation for a cross-platform message-pump (if available) in the runtime (@stephentoub suggestions?)
  • Provide the ability to bitbang the pins of the serial port like CTS/RTS/DSR/DTR/DCD/RING
  • Provide DisposeAsync
  • In addition to exposing the System.IO.Stream, evaluate the possibility to expose Pipes or Channel (as done in ASP.NET Kestrel)
  • Expose Interrupt-driven callbacks (e.g. old DataReceived event) as delegate instead
  • Verify supporting all the parameters to sustain the popular handshakes (RTS/CTS, DTR/DSR, Xon/Xoff)
  • Verify whether it is possible to support 9 bit word communication typically used by RS485 in microcontrollers
  • Provide support to a future Virtual COM implementation to test application code without the actual device

These lists were on the top of my heads and they are certainly not exhaustive, therefore any feedback/suggestion from the members of the community is welcome.

/cc @joperezr @Ellerbach @krwq @pgrawehr

Issue Analytics

  • State:open
  • Created 2 years ago
  • Reactions:8
  • Comments:37 (28 by maintainers)

github_iconTop GitHub Comments

2reactions
slyshykOcommented, Mar 18, 2023

Is it possible to add an ability to enable RS-485 support on Linux according to https://www.kernel.org/doc/Documentation/serial/serial-rs485.txt ?

Thanks in advance.

2reactions
Ellerbachcommented, Mar 11, 2022

So the DataReceived event would deliver the actual data (either as byte[] or string) as argument. Then you don’t have the problem of duplicate reads. And while rare, I did have use cases where multiple classes need to talk to the same serial port.

Correct but the issue you have with serial port is that you don’t really know how much has arrived. Or how much you want to read. Let me have few examples as this should help finding the right way of calling the event:

  • Option 1: you are interested in a fixed number of bytes. Let say, every 10 bytes received, you want the event to be raised. This is typical of fixed size protocols
  • Option2: you want it to be called as soon as you have received special character(s) (always the same), let’s say for this example \r\n. That would be the equivalent of calling every time you have a new line
  • Option 3: be called on a variable way and adjustable based on elements. This is typical of chunk based protocol where first few bytes determined how many bytes you’ll receive after. For simplicity, let’s say first 2 bytes will determine how many will be received after.

Those 3 options regroup like 80%+, of the case we see in serial and if the data are sent there should be a way to setup this option.

For the 20% remaining (nothing fixed, not really easy to predict), this is where the pattern proposed to have a delegate handling this can be very handy.

Read more comments on GitHub >

github_iconTop Results From Across the Web

SerialPort Class (System.IO.Ports)
Use this class to control a serial port file resource. This class provides synchronous and event-driven I/O, access to pin and break states,...
Read more >
SerialPort Constructor (System.IO.Ports)
Use this constructor to create a new instance of the SerialPort class when you want to specify the port name, the baud rate,...
Read more >
Creating a Serial Port Wrapper — C# .NET Framework
I'll first give you a brief introduction to what serial communication is and how it works and then we'll do a wrapper class,...
Read more >
c# - Designing Serial Port Class
I am creating wrapper static class around SerialPort. My concern is, I will have an static initialize method which will open the port....
Read more >
A simple class for using serial COM ports
This class was written to make it easier to implement and use serial ports in Windows for native C++ programs. While the references...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found