### Install libnserial package on Ubuntu Source: https://github.com/jcurl/rjcp.dll.serialportstream/blob/master/BUILD.md Use this command to install the libnserial package on Ubuntu systems. Ensure you have the correct version number for your distribution. ```bash # apt install libnserial_1.1.4-0ubuntu1~focal1_amd64.deb ``` -------------------------------- ### Build and Install SerialPortStream Support Library on Linux Source: https://github.com/jcurl/rjcp.dll.serialportstream/blob/master/README.md Steps to build and install the native support library for Linux system-wide using CMake and make. This method installs the library to the system's default library paths. ```sh cd serialportstream/dll/serialunix mkdir mybuild cd mybuild cmake .. && make sudo make install ``` -------------------------------- ### Serial Port Configuration Example Source: https://context7.com/jcurl/rjcp.dll.serialportstream/llms.txt Configure serial port parameters such as BaudRate, DataBits, StopBits, Parity, and Handshake. Buffer sizes must be set before opening the port. This example demonstrates setting various properties including flow control and buffer tuning. ```csharp using RJCP.IO.Ports; using var serial = new SerialPortStream(); serial.PortName = "COM3"; serial.BaudRate = 57600; serial.DataBits = 8; serial.StopBits = StopBits.One; serial.Parity = Parity.Even; serial.ParityReplace = 0x00; // Replace bad bytes with 0x00 (0 = disable) serial.Handshake = Handshake.Rts; // RTS/CTS hardware flow control // serial.Handshake = Handshake.XOn; // XON/XOFF software flow control // serial.Handshake = Handshake.RtsXOn; // Both // serial.Handshake = Handshake.Dtr; // DTR/DSR (uncommon) serial.DtrEnable = true; serial.RtsEnable = true; serial.TxContinueOnXOff = false; // Pause TX when XOFF received serial.DiscardNull = false; // Keep null bytes // Buffer tuning (must be before Open) serial.ReadBufferSize = 1024 * 1024; // 1 MB receive buffer serial.WriteBufferSize = 128 * 1024; // 128 KB transmit buffer serial.DriverInQueue = 4096; // Driver-level in-queue hint serial.DriverOutQueue = 4096; // Driver-level out-queue hint serial.ReceivedBytesThreshold = 1; // Fire DataReceived after 1+ bytes serial.Open(); Console.WriteLine(serial.ToString()); // COM3:57600,8,E,1,to=off,xon=off,idsr=off,icts=hs,odtr=on,orts=hs ``` -------------------------------- ### Build dll/serialunix Locally on Ubuntu Source: https://github.com/jcurl/rjcp.dll.serialportstream/blob/master/dll/serialunix/BUILD.md Installs Google Test and Doxygen, then executes the build script. Ensure you are using Ubuntu 16.04 or later. ```shell sudo apt install libgtest-dev sudo apt install doxygen ./build.sh ``` -------------------------------- ### Clone and Build GoogleTest Framework Source: https://github.com/jcurl/rjcp.dll.serialportstream/blob/master/dll/serialunix/README.cygwin.md Clone the GoogleTest framework from GitHub, create a build directory, configure with CMake, and install it. This is a prerequisite for building the serialunix package with unit tests. ```sh $ git clone https://github.com/google/googletest.git $ mkdir gtestbuild $ cd gtestbuild $ cmake ../googletest $ make $ make install ``` -------------------------------- ### Modem / Pin Status Properties Example Source: https://context7.com/jcurl/rjcp.dll.serialportstream/llms.txt Read modem line states such as CTS, DSR, CD, and Ring Indicator while the serial port is open. This example also shows how to send a break signal by manipulating the BreakState property. ```csharp using RJCP.IO.Ports; using System; using var serial = new SerialPortStream("COM3", 9600); serial.Open(); Console.WriteLine($"CTS: {serial.CtsHolding}"); // Clear-To-Send Console.WriteLine($"DSR: {serial.DsrHolding}"); // Data-Set-Ready Console.WriteLine($"CD: {serial.CDHolding}"); // Carrier-Detect Console.WriteLine($"Ring: {serial.RingHolding}"); // Ring Indicator // Send a break signal for ~300 ms serial.BreakState = true; System.Threading.Thread.Sleep(300); serial.BreakState = false; ``` -------------------------------- ### Find and Link nserial Library with CMake Source: https://github.com/jcurl/rjcp.dll.serialportstream/blob/master/dll/serialunix/README.cmake.md Use this CMake configuration to find the nserial package and link its libraries to your executable. Ensure nserial is installed via its config file. ```cmake cmake_minimum_required(VERSION 2.8) project(helloworld) add_executable(helloworld hello.c) find_package(Threads REQUIRED) find_package(nserial CONFIG REQUIRED) include_directories(${nserial_INCLUDE_DIRS}) target_link_libraries(helloworld ${nserial_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}) ``` -------------------------------- ### Configure Logging via app.config (.NET Framework) Source: https://context7.com/jcurl/rjcp.dll.serialportstream/llms.txt Example of configuring TraceSource for SerialPortStream logging in .NET Framework applications using app.config. Ensure the switchValue is set to 'Verbose' for detailed diagnostics. ```xml ``` -------------------------------- ### Basic C Program to Get Serial Version Source: https://github.com/jcurl/rjcp.dll.serialportstream/blob/master/dll/serialunix/README.cmake.md A simple C program that includes the nserial library and prints its version string. This demonstrates basic integration with the library. ```c #include #include #include void main(void) { printf("Version: %s\n", serial_version()); } ``` -------------------------------- ### Build SerialPortStream Support Library on Linux Source: https://github.com/jcurl/rjcp.dll.serialportstream/blob/master/README.md Instructions for cloning the repository and building the native support library for Linux using GCC and CMake. Ensure you have a compatible compiler and cmake installed. ```sh git clone https://github.com/jcurl/serialportstream.git cd serialportstream/dll/serialunix ./build.sh ``` -------------------------------- ### Enumerate Serial Ports Source: https://context7.com/jcurl/rjcp.dll.serialportstream/llms.txt Demonstrates how to get a list of available serial port names using GetPortNames() and richer descriptions including device details using GetPortDescriptions() via WMI. ```csharp using RJCP.IO.Ports; using System; var probe = new SerialPortStream(); // Raw names foreach (string name in probe.GetPortNames()) { Console.WriteLine($"Port: {name}"); // Output: Port: COM1 // Port: COM3 } // Rich descriptions foreach (PortDescription desc in probe.GetPortDescriptions()) { Console.WriteLine($"{desc.Port}: {desc.Description} [{desc.Manufacturer}]"); // Output: COM3: USB Serial Device (COM3) [Microsoft] } ``` -------------------------------- ### Configure WinSerialPortStream with Native Settings Source: https://context7.com/jcurl/rjcp.dll.serialportstream/llms.txt This example shows how to use WinSerialPortStream to access and modify low-level Win32 COMMTIMEOUTS settings. This is particularly useful for drivers that require specific WriteTotalTimeoutConstant behavior. The code is marked with SupportedOSPlatform("windows"). ```csharp using RJCP.IO.Ports; using RJCP.IO.Ports.Serial; using System; using System.Runtime.Versioning; [SupportedOSPlatform("windows")] static void OpenWithWinSettings() { using var serial = new WinSerialPortStream("COM3", 115200, 8, Parity.None, StopBits.One); // Access Windows-specific COMMTIMEOUTS settings IWinNativeSettings settings = serial.Settings; settings.ReadIntervalTimeout = 0; // ms between bytes (0 = disabled) settings.ReadTotalTimeoutMultiplier = 0; // ms × bytes settings.ReadTotalTimeoutConstant = 0; // ms constant (0+0 = infinite) settings.WriteTotalTimeoutMultiplier = 0; settings.WriteTotalTimeoutConstant = 0; // 0 = no driver-level write timeout serial.Open(); Console.WriteLine($"Version: {serial.Version}"); serial.WriteLine("AT"); string response = serial.ReadLine(); Console.WriteLine($"Response: {response}"); } ``` -------------------------------- ### Get List of COM Ports Source: https://github.com/jcurl/rjcp.dll.serialportstream/wiki/Getting-a-List-of-Serial-Ports-with-SerialPortStream Use this method to get a list of available COM port names, compatible with the Microsoft implementation. Ensure System.Diagnostics is imported. ```csharp using System.Diagnostic; foreach (string c in SerialPortStream.GetPortNames()) { Trace.WriteLine("GetPortNames: " + c); } ``` -------------------------------- ### Configure Serial Port with StopBits Enum Source: https://context7.com/jcurl/rjcp.dll.serialportstream/llms.txt This example demonstrates configuring a SerialPortStream with a specific number of stop bits using the StopBits enum. Available options are One, One5, and Two. ```csharp // RJCP.IO.Ports.StopBits // One = 0 — 1 stop bit (most common) // One5 = 1 — 1.5 stop bits // Two = 2 — 2 stop bits var serial = new SerialPortStream("COM3", 9600, 8, Parity.None, StopBits.Two); ``` -------------------------------- ### Console Output of Parity Error (Chipset FAIL) Source: https://github.com/jcurl/rjcp.dll.serialportstream/blob/master/dll/serialunix/README.linux.md Example console output demonstrating how a parity error is reported by non-compliant chipsets, marking multiple bytes as incorrect. ```console 0000030: 3031 3233 3435 3637 3839 ff00 3aff 003b 0123456789..:..; 0000040: ff00 3cff 003d ff00 3eff 003f ff00 40ff ..<..=..>..?..@. 0000050: 0041 ff00 42ff 0043 ff00 44ff 0045 4647 .A..B..C..D..EFG ``` -------------------------------- ### SerialPortStream.Open / OpenDirect / Close / Dispose Source: https://context7.com/jcurl/rjcp.dll.serialportstream/llms.txt Explains how to open, open directly, close, and dispose of a SerialPortStream instance. Opening applies settings and starts monitoring, OpenDirect skips settings, Close stops I/O, and Dispose releases resources. ```APIDOC ## SerialPortStream.Open / OpenDirect / Close `Open()` applies the configured settings to the driver, then starts a background monitoring thread. `OpenDirect()` skips the settings-apply step, useful for virtual COM ports. `Close()` stops I/O but leaves read-buffer data readable. `Dispose()` releases all resources. ```csharp using RJCP.IO.Ports; using System; using var serial = new SerialPortStream("COM3", 115200, 8, Parity.None, StopBits.One); serial.ReadTimeout = 2000; // ms serial.WriteTimeout = 2000; serial.Open(); Console.WriteLine($"Port open: {serial.IsOpen}"); // True // For virtual/USB serial ports that ignore DCB state: // serial.OpenDirect(); serial.Close(); Console.WriteLine($"Port open: {serial.IsOpen}"); // False // Can re-open after Close serial.Open(); serial.Dispose(); // Also closes if open; cannot be reopened after Dispose ``` ``` -------------------------------- ### Open, Close, and Dispose SerialPortStream Source: https://context7.com/jcurl/rjcp.dll.serialportstream/llms.txt Shows how to open, close, and dispose of a SerialPortStream. Open() applies settings and starts monitoring, OpenDirect() skips settings, Close() stops I/O but keeps buffer data readable, and Dispose() releases all resources. ```csharp using RJCP.IO.Ports; using System; using var serial = new SerialPortStream("COM3", 115200, 8, Parity.None, StopBits.One); serial.ReadTimeout = 2000; // ms serial.WriteTimeout = 2000; serial.Open(); Console.WriteLine($"Port open: {serial.IsOpen}"); // True // For virtual/USB serial ports that ignore DCB state: // serial.OpenDirect(); serial.Close(); Console.WriteLine($"Port open: {serial.IsOpen}"); // False // Can re-open after Close serial.Open(); serial.Dispose(); // Also closes if open; cannot be reopened after Dispose ``` -------------------------------- ### Console Output of Parity Error (Chipset PASS) Source: https://github.com/jcurl/rjcp.dll.serialportstream/blob/master/dll/serialunix/README.linux.md Example console output showing the expected behavior of a compliant chipset (like 16550A) where only the directly affected byte is marked as incorrect. ```console 0000030: 3031 3233 3435 3637 3839 3a3b 3c3d 3e3f 0123456789:;<=>? 0000040: 4041 4243 ff00 4445 4647 4849 4a4b 4c4d @ABC..DEFGHIJKLM 0000050: 4e4f 5051 5253 5455 5657 5859 5a5b 5c5d NOPQRSTUVWXYZ[\ ] ``` -------------------------------- ### Configure Serial Port with Parity Enum Source: https://context7.com/jcurl/rjcp.dll.serialportstream/llms.txt This example shows how to configure a SerialPortStream with a specific parity setting using the Parity enum. The enum defines options for parity checking: None, Odd, Even, Mark, and Space. ```csharp // RJCP.IO.Ports.Parity // None = 0 — No parity checking // Odd = 1 — Parity bit set so total 1-bits is odd // Even = 2 — Parity bit set so total 1-bits is even // Mark = 3 — Parity bit always 1 // Space= 4 — Parity bit always 0 var serial = new SerialPortStream("COM3", 9600, 7, Parity.Even, StopBits.One); ``` -------------------------------- ### ErrorReceived Event Handling Example Source: https://context7.com/jcurl/rjcp.dll.serialportstream/llms.txt Handle the ErrorReceived event to be notified of communication errors reported by the driver. This example checks for common error flags such as RXOver, Overrun, Parity, Frame, and TXFull. ```csharp using RJCP.IO.Ports; using System; using var serial = new SerialPortStream("COM3", 9600); serial.ErrorReceived += (sender, e) => { if ((e.EventType & SerialError.RXOver) != 0) Console.WriteLine("RX buffer near full (80%)"); if ((e.EventType & SerialError.Overrun) != 0) Console.WriteLine("Driver overrun — bytes lost!"); if ((e.EventType & SerialError.RXParity) != 0) Console.WriteLine("Parity error detected"); if ((e.EventType & SerialError.Frame) != 0) Console.WriteLine("Framing error detected"); if ((e.EventType & SerialError.TXFull) != 0) Console.WriteLine("TX buffer full"); }; serial.Open(); Console.ReadLine(); ``` -------------------------------- ### Build Release Mode Source: https://github.com/jcurl/rjcp.dll.serialportstream/blob/master/BUILD.md Builds the project in Release mode. This is unsigned and useful for testing. ```cmd PS1> dotnet build -c Release ``` -------------------------------- ### Execute Unit Tests on Linux Source: https://github.com/jcurl/rjcp.dll.serialportstream/blob/master/BUILD.md Run this command in the project directory to execute unit tests on a Linux environment. ```bash $ dotnet test ``` -------------------------------- ### Read Current Port Settings Source: https://context7.com/jcurl/rjcp.dll.serialportstream/llms.txt Explains how to use GetPortSettings() to temporarily open a port, read its current driver configuration (DCB settings), and then close it. This is useful for discovering the OS-level configuration before applying new settings. ```csharp using RJCP.IO.Ports; using System; var serial = new SerialPortStream(); serial.PortName = "COM3"; // Reads current driver state without setting any properties serial.GetPortSettings(); Console.WriteLine($"Current baud: {serial.BaudRate}"); // e.g. 9600 Console.WriteLine($"Current parity: {serial.Parity}"); // e.g. None Console.WriteLine($"Data bits: {serial.DataBits}"); // e.g. 8 Console.WriteLine($"Stop bits: {serial.StopBits}"); // e.g. One ``` -------------------------------- ### Run SerialUnix Unit and Component Tests Source: https://github.com/jcurl/rjcp.dll.serialportstream/blob/master/dll/serialunix/README.cygwin.md Navigate to the test directories within the serialunix build and execute the unit and component test executables. This is done manually after setting up the environment variables. ```sh $ cd $SERIALUNIXBASE/build/libnserial/unittest $ ./nserialtest.exe $ cd $SERIALUNIXBASE/build/libnserial/comptest $ ./nserialcomptest.exe ``` -------------------------------- ### Get Serial Port Descriptions Source: https://github.com/jcurl/rjcp.dll.serialportstream/wiki/Getting-a-List-of-Serial-Ports-with-SerialPortStream Retrieve a list of serial ports along with their descriptions. This method returns SerialPortStream.PortDescription objects. Ensure System.Diagnostics is imported. ```csharp using System.Diagnostic; foreach (SerialPortStream.PortDescription desc in SerialPortStream.GetPortDescriptions()) { Trace.WriteLine("GetPortDescriptions: " + desc.Port + "; Description: " + desc.Description); } ``` -------------------------------- ### Package for NuGet Upload Source: https://github.com/jcurl/rjcp.dll.serialportstream/blob/master/BUILD.md Builds and packages the project for upload to NuGet, including source symbols. ```cmd PS1> dotnet build -c release .\code\SerialPortStream.csproj PS1> dotnet pack -c release --include-source .\code\SerialPortStream.csproj ``` -------------------------------- ### Run Unit Tests in Release Mode Source: https://github.com/jcurl/rjcp.dll.serialportstream/blob/master/BUILD.md Executes unit tests for the Release configuration, logging results to a 'trx' file. ```cmd PS1> dotnet test -c Release --logger "trx" ``` -------------------------------- ### Instantiate SerialPortStream with Full Constructor Parameters Source: https://github.com/jcurl/rjcp.dll.serialportstream/wiki/Overview-of-SerialPortStream-properties Instantiate SerialPortStream with all basic serial communication parameters: port name, baud rate, data bits, parity, and stop bits. ```csharp SerialPortStream s3 = new SerialPortStream("COM3", 115200, 8, Parity.None, StopBits.One); ``` -------------------------------- ### Run BufferBytesTest Integration Test Source: https://github.com/jcurl/rjcp.dll.serialportstream/blob/master/test/README.md Execute the BufferBytesTest command-line tool to send data over a serial port and monitor buffer status. Requires specifying the serial port, baud rate, and data length. ```cmd BufferBytesTest --port COM1 --baud 115200 --length 163840 ``` -------------------------------- ### DataReceived Event Handling Example Source: https://context7.com/jcurl/rjcp.dll.serialportstream/llms.txt Handle the DataReceived event, which fires when data is available in the read buffer or an EOF character is detected. The event handler executes on a thread-pool thread and receives data as bytes, which can then be decoded. ```csharp using RJCP.IO.Ports; using System; using System.Text; using var serial = new SerialPortStream("COM3", 9600); serial.Encoding = Encoding.ASCII; serial.ReceivedBytesThreshold = 1; serial.ReadTimeout = 500; serial.DataReceived += (sender, e) => { var s = (SerialPortStream)sender; if (e.EventType == SerialData.Eof) { Console.WriteLine("[EOF character received]"); return; } // SerialData.Chars byte[] buf = new byte[s.BytesToRead]; int n = s.Read(buf, 0, buf.Length); Console.WriteLine($"Received {n} bytes: {Encoding.ASCII.GetString(buf, 0, n)}"); }; serial.Open(); Console.ReadLine(); // Keep alive ``` -------------------------------- ### Instantiate SerialPortStream Source: https://context7.com/jcurl/rjcp.dll.serialportstream/llms.txt Demonstrates various ways to instantiate SerialPortStream, from default configuration to full parameter specification. For .NET 6+, an ILogger can be injected for diagnostics. ```csharp using RJCP.IO.Ports; // Default: no port assigned yet var s1 = new SerialPortStream(); s1.PortName = "COM3"; s1.BaudRate = 9600; // Port name only (baud/data/parity/stop loaded from current OS settings) var s2 = new SerialPortStream("COM3"); // Port + baud var s3 = new SerialPortStream("COM3", 115200); // Full parameters: port, baud, data bits, parity, stop bits var s4 = new SerialPortStream("COM3", 115200, 8, Parity.None, StopBits.One); // .NET 6+ with injected ILogger using Microsoft.Extensions.Logging; ILogger logger = LoggerFactory.Create(b => b.AddConsole()).CreateLogger("Serial"); var s5 = new SerialPortStream(logger); s5.PortName = "COM3"; ``` -------------------------------- ### DiscardInBuffer and DiscardOutBuffer Example Source: https://context7.com/jcurl/rjcp.dll.serialportstream/llms.txt Use DiscardInBuffer to clear unread bytes from the receive buffer and DiscardOutBuffer to clear unsent bytes from the transmit buffer. This is useful for dropping stale data before a protocol exchange or canceling pending outbound data. ```csharp using RJCP.IO.Ports; using var serial = new SerialPortStream("COM3", 9600); serial.Open(); // Drop any stale data before starting a protocol exchange serial.DiscardInBuffer(); Console.WriteLine($"Bytes to read after discard: {serial.BytesToRead}"); // 0 // Cancel pending outbound data serial.DiscardOutBuffer(); Console.WriteLine($"Bytes to write after discard: {serial.BytesToWrite}"); // 0 ``` -------------------------------- ### Configure Logging via Singleton LogSource (.NET Core) Source: https://context7.com/jcurl/rjcp.dll.serialportstream/llms.txt Demonstrates setting a global ILoggerFactory for SerialPortStream instances when dependency injection is not used, suitable for migrating from .NET Framework. Call LogSource.SetLoggerFactory() once at application startup. ```csharp using Microsoft.Extensions.Logging; using RJCP.Diagnostics.Trace; // Call once at application startup ILoggerFactory factory = LoggerFactory.Create(builder => { builder .AddConsole() .AddFilter("RJCP", LogLevel.Debug); }); LogSource.SetLoggerFactory(factory); // Now all SerialPortStream instances created normally will log via factory using var serial = new RJCP.IO.Ports.SerialPortStream("COM3", 9600); serial.Open(); serial.WriteLine("HELLO"); ``` -------------------------------- ### SerialPortStream Constructors Source: https://context7.com/jcurl/rjcp.dll.serialportstream/llms.txt Demonstrates various ways to instantiate the SerialPortStream class, from default initialization to specifying full port parameters and injecting an ILogger for diagnostics. ```APIDOC ## SerialPortStream Constructors The `SerialPortStream` class inherits from `System.IO.Stream` and can be instantiated with zero arguments (deferred configuration), with a port name only, with port + baud, or with full port parameters. On .NET 6+, an `ILogger` can be injected for diagnostics. ```csharp using RJCP.IO.Ports; // Default: no port assigned yet var s1 = new SerialPortStream(); s1.PortName = "COM3"; s1.BaudRate = 9600; // Port name only (baud/data/parity/stop loaded from current OS settings) var s2 = new SerialPortStream("COM3"); // Port + baud var s3 = new SerialPortStream("COM3", 115200); // Full parameters: port, baud, data bits, parity, stop bits var s4 = new SerialPortStream("COM3", 115200, 8, Parity.None, StopBits.One); // .NET 6+ with injected ILogger using Microsoft.Extensions.Logging; ILogger logger = LoggerFactory.Create(b => b.AddConsole()).CreateLogger("Serial"); var s5 = new SerialPortStream(logger); s5.PortName = "COM3"; ``` ``` -------------------------------- ### Build SerialPortStream on Linux Source: https://github.com/jcurl/rjcp.dll.serialportstream/blob/master/BUILD.md Execute the dotnet build command from the solution directory to compile the SerialPortStream project. This command builds all projects in the solution, including the main library and test projects. ```bash $ dotnet build Microsoft (R) Build Engine version 16.9.0+57a23d249 for .NET Copyright (C) Microsoft Corporation. All rights reserved. Determining projects to restore... All projects are up-to-date for restore. SerialPortStream -> /home/jcurl/source/rjcp.dll.serialportstream/code/bin/Debug/net40/RJCP.SerialPortStream.dll SerialPortStream -> /home/jcurl/source/rjcp.dll.serialportstream/code/bin/Debug/net45/RJCP.SerialPortStream.dll SerialPortStreamTest -> /home/jcurl/source/rjcp.dll.serialportstream/test/SerialPortStreamTest/bin/Debug/net45/RJCP.SerialPortStreamTest.dll DatastructuresTest -> /home/jcurl/source/rjcp.dll.serialportstream/test/DatastructuresTest/bin/Debug/net40/RJCP.DatastructuresTest.dll SerialPortStreamTest -> /home/jcurl/source/rjcp.dll.serialportstream/test/SerialPortStreamTest/bin/Debug/net40/RJCP.SerialPortStreamTest.dll DatastructuresTest -> /home/jcurl/source/rjcp.dll.serialportstream/test/DatastructuresTest/bin/Debug/net45/RJCP.DatastructuresTest.dll ``` -------------------------------- ### Assigning the Virtual Factory Source: https://github.com/jcurl/rjcp.dll.serialportstream/blob/master/test/SerialPortStream.Virtual/README.md This code snippet shows how to assign the VirtualSerialPortFactory to the global instance, enabling the use of virtual serial ports for testing. ```csharp SerialPortFactory.Instance = new VirtualSerialPortFactory() ``` -------------------------------- ### Build Docker Image for Ubuntu Source: https://github.com/jcurl/rjcp.dll.serialportstream/blob/master/dll/docker/README.md Builds the Docker image for a specific Ubuntu version. Set the CODENAME environment variable before running. ```sh export CODENAME=focal docker build --build-arg CODE_VERSION=${CODENAME} -t libnserial:${CODENAME} . ``` -------------------------------- ### Find and Configure GTest for nserial Unit Tests Source: https://github.com/jcurl/rjcp.dll.serialportstream/blob/master/dll/serialunix/libnserial/unittest/CMakeLists.txt This snippet finds the Google Test framework and configures the build to include it. It's essential for running the unit tests. ```cmake find_package(GTest) # Don't forget to enable_testing() in the root of your project if(GTEST_FOUND) find_package(Threads REQUIRED) include_directories(${GTEST_INCLUDE_DIRS}) set(SERIALUNIX_GTEST_SRCS serialinit.cpp serialopen.cpp serialerror.cpp serialmodem.cpp main.cpp configuration.cpp) add_executable(nserialtest ${SERIALUNIX_GTEST_SRCS}) target_link_libraries(nserialtest nserial ${GTEST_MAIN_LIBRARIES} ${GTEST_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}) add_test(NAME nserialtests COMMAND nserialtest) endif(GTEST_FOUND) ``` -------------------------------- ### Configure App.Config for SerialPortStream Tracing Source: https://github.com/jcurl/rjcp.dll.serialportstream/wiki/Tracing Add this XML configuration to your App.Config file to enable tracing for the IO.Ports.SerialPortStream source. Use a switchValue of 'Warning' or less for general debugging. Avoid tracing to the console as it can halt your application. ```xml ``` -------------------------------- ### Initialize Singleton Logger with LoggerFactory Source: https://github.com/jcurl/rjcp.dll.serialportstream/blob/master/README.md Configure and set a LoggerFactory for LogSource to obtain an ILogger instance. This is useful for .NET Core applications to manage logging configurations, especially when migrating from .NET Framework singletons. Ensure the factory is set once in your production code. ```csharp using Microsoft.Extensions.Logging; using RJCP.CodeQuality.NUnitExtensions.Trace; using RJCP.Diagnostics.Trace; internal static class GlobalLogger { static GlobalLogger() { ILoggerFactory factory = LoggerFactory.Create(builder => { builder .AddFilter("Microsoft", LogLevel.Warning) .AddFilter("System", LogLevel.Warning) .AddFilter("RJCP", LogLevel.Debug) .AddNUnitLogger(); }); LogSource.SetLoggerFactory(factory); } public static void Initialize() { /* Intentially empty. By calling this method, the static constructor will be automatically called */ } } ``` -------------------------------- ### Build Debug Mode Source: https://github.com/jcurl/rjcp.dll.serialportstream/blob/master/BUILD.md Builds the project in Debug mode. This does not generate a NuGet package. ```cmd PS1> dotnet build ``` -------------------------------- ### Implement APM Pattern with SerialPortStream Source: https://context7.com/jcurl/rjcp.dll.serialportstream/llms.txt This code illustrates the use of the Asynchronous Programming Model (APM) with SerialPortStream, supporting legacy code that does not use async/await. It demonstrates BeginRead and BeginWrite operations. ```csharp using RJCP.IO.Ports; using System; using System.Threading; using var serial = new SerialPortStream("COM3", 9600); serial.Open(); byte[] readBuf = new byte[64]; ManualResetEvent done = new(false); IAsyncResult ar = serial.BeginRead(readBuf, 0, readBuf.Length, result => { int n = serial.EndRead(result); Console.WriteLine($"APM read: {n} bytes"); done.Set(); }, null); // Write some data to trigger the read byte[] tx = System.Text.Encoding.ASCII.GetBytes("Hello\n"); IAsyncResult war = serial.BeginWrite(tx, 0, tx.Length, result => { serial.EndWrite(result); Console.WriteLine("APM write complete"); }, null); done.WaitOne(3000); ``` -------------------------------- ### Instantiate SerialPortStream with Default Constructor Source: https://github.com/jcurl/rjcp.dll.serialportstream/wiki/Overview-of-SerialPortStream-properties Use the default constructor to create a SerialPortStream object with predefined default settings. Ensure PortName is set before opening. ```csharp SerialPortStream s = new SerialPortStream(); ``` -------------------------------- ### Configure Logging with Dependency Injection (.NET Core) Source: https://context7.com/jcurl/rjcp.dll.serialportstream/llms.txt Shows how to inject an ILogger into SerialPortStream for structured logging in .NET 6+ applications. Configure the LoggerFactory to include console output and set the minimum log level. ```csharp using Microsoft.Extensions.Logging; using RJCP.IO.Ports; ILoggerFactory loggerFactory = LoggerFactory.Create(builder => builder .AddConsole() .SetMinimumLevel(LogLevel.Debug) .AddFilter("RJCP", LogLevel.Trace)); ILogger logger = loggerFactory.CreateLogger(); using var serial = new SerialPortStream(logger); serial.PortName = "COM3"; serial.BaudRate = 115200; serial.Open(); serial.Write(new byte[] { 0x01, 0x02 }, 0, 2); ``` -------------------------------- ### Create Serial Port using SerialPortStreamFactory Source: https://context7.com/jcurl/rjcp.dll.serialportstream/llms.txt This snippet demonstrates using SerialPortStreamFactory to create a platform-neutral SerialPortStream instance. It also shows how to replace the default factory for testing purposes with a custom virtual serial port factory. ```csharp using RJCP.IO.Ports; using System; // Use the default factory ISerialPortStreamFactory factory = SerialPortStreamFactory.Factory; using SerialPortStream serial = factory.Create("COM3", 115200, 8, Parity.None, StopBits.One); serial.ReadTimeout = 1000; serial.Open(); serial.WriteLine("PING"); Console.WriteLine(serial.ReadLine()); // ─── For unit testing: inject a custom factory ───────────────────────────── // SerialPortStreamFactory.Factory = new MyVirtualSerialFactory(); // ─── For dependency injection (test-friendly signature) ──────────────────── void Configure(ISerialPortStreamFactory fac) { using var s = fac.Create("COM3", 9600); s.Open(); s.WriteLine("STATUS?"); } Configure(SerialPortStreamFactory.Factory); ``` -------------------------------- ### Instantiate SerialPortStream with Port Name and Baud Rate Source: https://github.com/jcurl/rjcp.dll.serialportstream/wiki/Overview-of-SerialPortStream-properties Instantiate SerialPortStream with the port name and baud rate. Other parameters will use default values. ```csharp SerialPortStream s2 = new SerialPortStream("COM2", 115200); ``` -------------------------------- ### Compile Software within Docker Container Source: https://github.com/jcurl/rjcp.dll.serialportstream/blob/master/dll/docker/README.md Compiles the software inside a Docker container. Ensure you are in the 'dll/serialunix' directory and have a 'build' directory. Mounts source and build directories, and uses a temporary filesystem for /tmp. ```sh mkdir -p ../build docker run -it --rm --read-only --cap-drop all \ -v ${PWD}:/source:ro \ -v ${PWD}/../build:/build:rw \ --tmpfs /tmp \ -u $(id -u ${USER}):$(id -g ${USER}) \ libnserial:${CODENAME} ``` -------------------------------- ### Serial Configuration Properties Source: https://context7.com/jcurl/rjcp.dll.serialportstream/llms.txt Configures serial port parameters such as baud rate, data bits, parity, and flow control. Buffer sizes must be set before opening the port. ```APIDOC ## Serial Configuration Properties Port parameters (`BaudRate`, `DataBits`, `StopBits`, `Parity`, `Handshake`, `DtrEnable`, `RtsEnable`, `BreakState`, etc.) can be set before or after `Open()`. Buffer sizes must be set before `Open()`. ```csharp using RJCP.IO.Ports; using var serial = new SerialPortStream(); serial.PortName = "COM3"; serial.BaudRate = 57600; serial.DataBits = 8; serial.StopBits = StopBits.One; serial.Parity = Parity.Even; serial.ParityReplace = 0x00; // Replace bad bytes with 0x00 (0 = disable) serial.Handshake = Handshake.Rts; // RTS/CTS hardware flow control // serial.Handshake = Handshake.XOn; // XON/XOFF software flow control // serial.Handshake = Handshake.RtsXOn; // Both // serial.Handshake = Handshake.Dtr; // DTR/DSR (uncommon) serial.DtrEnable = true; serial.RtsEnable = true; serial.TxContinueOnXOff = false; // Pause TX when XOFF received serial.DiscardNull = false; // Keep null bytes // Buffer tuning (must be before Open) serial.ReadBufferSize = 1024 * 1024; // 1 MB receive buffer serial.WriteBufferSize = 128 * 1024; // 128 KB transmit buffer serial.DriverInQueue = 4096; // Driver-level in-queue hint serial.DriverOutQueue = 4096; // Driver-level out-queue hint serial.ReceivedBytesThreshold = 1; // Fire DataReceived after 1+ bytes serial.Open(); Console.WriteLine(serial.ToString()); // COM3:57600,8,E,1,to=off,xon=off,idsr=off,icts=hs,odtr=on,orts=hs ``` ``` -------------------------------- ### Define GTest Component Test Executable Source: https://github.com/jcurl/rjcp.dll.serialportstream/blob/master/dll/serialunix/libnserial/comptest/CMakeLists.txt Defines the 'nserialcomptest' executable, linking it with the 'nserial' library and Google Test libraries. This builds the main component test suite. ```cmake set(SERIALUNIXCOMP_GTEST_SRCS SerialSendReceiveTest.cpp SerialParityTest.cpp SerialModemSignalsTest.cpp SerialModemEvents.cpp main.cpp SerialConfiguration.cpp Buffer.cpp BuffDump.cpp SerialReadWrite.cpp) add_executable(nserialcomptest ${SERIALUNIXCOMP_GTEST_SRCS}) target_link_libraries(nserialcomptest nserial ${GTEST_MAIN_LIBRARIES} ${GTEST_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} rt) ``` -------------------------------- ### Test Garbage Data on Serial Port Open Source: https://github.com/jcurl/rjcp.dll.serialportstream/blob/master/README.md This command executes the kernelbug test to identify garbage data appearing at the beginning of a serial stream on certain Linux kernels and USB-SER drivers. Running the test twice can reveal the error. ```sh $ kernelbug /dev/ttyUSB0 /dev/ttyUSB1 Offset: 4 Flushing... Writing Complete... Reading complete... Comparison MATCH <---- PASS Flushing... Reading complete... Complete... $ kernelbug /dev/ttyUSB0 /dev/ttyUSB1 Offset: 108 Flushing... Flush 2 bytes Writing Complete... Reading complete... ERROR: Comparison mismatch <---- ERROR Flushing... Flush 510 bytes Reading complete... Complete... ``` -------------------------------- ### Configure Handshake Settings for SerialPortStream Source: https://context7.com/jcurl/rjcp.dll.serialportstream/llms.txt Demonstrates setting the Handshake property on a SerialPortStream instance. Use Handshake flags to specify hardware or software flow control. ```csharp var serial = new SerialPortStream("COM3", 115200); serial.Handshake = Handshake.Rts; // RTS/CTS only // serial.Handshake = Handshake.RtsXOn; // RTS/CTS + software XON/XOFF ``` -------------------------------- ### App.config Test Port Settings Source: https://github.com/jcurl/rjcp.dll.serialportstream/blob/master/BUILD.md Configuration settings for unit tests, specifying serial ports for Windows and Linux. Modify Win32SourcePort and Win32DestPort for actual hardware. ```xml ``` -------------------------------- ### Instantiate SerialPortStream with Port Name Source: https://github.com/jcurl/rjcp.dll.serialportstream/wiki/Overview-of-SerialPortStream-properties Instantiate SerialPortStream by providing the port name. Other parameters will use default values. ```csharp SerialPortStream s1 = new SerialPortStream("COM1"); ``` -------------------------------- ### Build Icount Executable Source: https://github.com/jcurl/rjcp.dll.serialportstream/blob/master/dll/serialunix/libnserial/comptest/CMakeLists.txt Compiles the 'icount.c' file into a standalone executable. This utility might be used for counting or monitoring serial port events. ```cmake add_executable(icount icount.c) ``` -------------------------------- ### Find and Configure GTest Source: https://github.com/jcurl/rjcp.dll.serialportstream/blob/master/dll/serialunix/libnserial/comptest/CMakeLists.txt Locates the Google Test framework and includes its directories. This is necessary for building tests that use GTest. ```cmake find_package(GTest) ```