Serial.Lib 1.2.81

This package has a SemVer 2.0.0 package version: 1.2.81+1f2bb1670e350abf68f40e36dfbc601dfd431da1.
dotnet add package Serial.Lib --version 1.2.81
                    
NuGet\Install-Package Serial.Lib -Version 1.2.81
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Serial.Lib" Version="1.2.81" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Serial.Lib" Version="1.2.81" />
                    
Directory.Packages.props
<PackageReference Include="Serial.Lib" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Serial.Lib --version 1.2.81
                    
#r "nuget: Serial.Lib, 1.2.81"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Serial.Lib@1.2.81
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Serial.Lib&version=1.2.81
                    
Install as a Cake Addin
#tool nuget:?package=Serial.Lib&version=1.2.81
                    
Install as a Cake Tool

Serial.Lib

Serial port I/O for .NET that does one job well: cancellable, deadline-honouring reads and writes that never abort spuriously, a bounded open and close, typed failures, and port enumeration with a stable hardware identity. Namespace SharpAstro.Serial, net10.0, AOT and trim compatible. Written for the astronomy devices TianWen drives (mounts, focusers, flat panels, filter wheels), where "it mostly works" is not good enough.

Why

System.IO.Ports.SerialPort async reads are not trustworthy:

  • On a CH34x USB bridge (very common on cheap devices) the first BaseStream.ReadAsync succeeds and every later one aborts with ERROR_OPERATION_ABORTED while the reply still arrives, so replies land one frame late.
  • The "async" is a blocking read on a pool thread anyway (dotnet/runtime#28968), and it ignores ReadTimeout, so a timeout built from Task.WhenAny leaves the read hanging.
  • A write to a Bluetooth serial port with nobody on the far end never completes and ignores its token.

This library drives the port only through blocking calls, each bounded, and builds every guarantee above them once.

Use

using SharpAstro.Serial;

await using var port = await SerialPorts.OpenAsync("COM3", new SerialSettings(9600) { AssertDtr = true, AssertRts = true });

await port.WriteAsync(":00#"u8.ToArray());
var reply = new byte[32];
var n = await port.ReadTerminatedAsync(reply, "#"u8.ToArray());   // throws SerialTimeoutException, never returns a default

The contract

  • A read completes, or throws SerialTimeoutException at its deadline (carrying the bytes that did arrive), or OperationCanceledException for the caller's token, or another SerialException. Cancelling never leaves a read pending that could eat the next reply.
  • Bytes after a reply's terminator are kept for the next read; a reply longer than the buffer is refused (SerialFramingException), never truncated.
  • A write still pending at its deadline marks the port (HasAbandonedIo); every later write throws SerialIoAbandonedException at once instead of stranding another thread.
  • A fault on a port that is no longer enumerated is SerialPortRemovedException, distinct from a timeout.
  • Open and close are bounded; a close that cannot finish abandons the handle, not the caller.
  • Every exception derives from SerialException, which derives from IOException.
  • OpenedAt says when the open finished: opening resets many boards (every CH340 one), and some firmware saves state on a delay.

Testing without hardware

SerialLoopback.CreatePair(settings) returns two ports wired to each other in memory: what one writes, the other reads. They are real ports in every respect but the wire, so a test through them gets the same deadlines, framing and carry-over as a COM port.

Identity

SerialPorts.Enumerate() lists each port with what the OS knows about it: USB vendor and product id, serial number, device instance id, and the USB socket's location path (Windows device tree; Linux sysfs and /dev/serial/by-path / by-id). SerialPortInfo.Identity says what a saved configuration can key on:

Identity keyed on survives
Device vendor, product, serial number moving the device to another socket
Socket the USB location path renames and re-enumeration, but two identical devices swapped between sockets swap identities
PortName the OS name nothing; a COM name follows the socket, a /dev/ttyUSBn name follows enumeration order

IdentityKey renders the strongest one as a string (usb:1a86:7523:SERIAL, socket:..., name:COM3).

A Bluetooth serial port on Windows also says what it leads to (SerialPortInfo.Bluetooth): the paired device's address, its name and its Class of Device as Windows recorded them at pairing (MajorClass), or IsIncoming for Windows' own incoming port, which nothing dials. That is what tells a paired headset (AudioVideo), whose serial channel takes every write and answers none, from a serial module (an HC-05 reports Uncategorized), before a probe spends its budget on it.

Status

1.0 is the managed backend (the blocking half of System.IO.Ports); 1.1 adds reads with no deadline (Timeout.InfiniteTimeSpan, the token alone ends them) and the loopback pair; 1.2 the Bluetooth device behind a port. A native Win32 backend (overlapped I/O driven correctly) is planned as 2.0, behind the same API. Design notes: docs/plans/serial-lib.md in tianwen.

Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on Serial.Lib:

Package Downloads
TianWen.Lib

Astronomical imaging and device-control library for .NET: cameras, mounts, focusers, filter wheels, cover/calibrators and guiders over ASCOM, Alpaca, ZWO, QHYCCD, Meade LX200, Skywatcher, OnStep and PHD2, plus plate solving, deep-sky and planetary stacking, auto-focus and unattended session automation. First-class multi-OTA (dual rig) support. AOT compatible.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.2.81 1,626 9/30/2026
1.1.61 1,032 9/27/2026
1.0.11 33 9/27/2026