Introduce a Serial Port class
See original GitHub issueThe 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 ofbyte[]
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.
Issue Analytics
- State:
- Created 2 years ago
- Reactions:8
- Comments:37 (28 by maintainers)
Top GitHub Comments
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.
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:
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.