diff --git a/ThreeByte.LinkLib/ThreeByte.LinkLib.NetBooter/README.md b/ThreeByte.LinkLib/ThreeByte.LinkLib.NetBooter/README.md
new file mode 100644
index 0000000..54f0c0b
--- /dev/null
+++ b/ThreeByte.LinkLib/ThreeByte.LinkLib.NetBooter/README.md
@@ -0,0 +1,188 @@
+# π ThreeByte.LinkLib.NetBooter
+
+**Client library for controlling Synaccess NetBooter networked power controllers β toggle outlets, poll state, and monitor power remotely.**
+
+[](https://www.nuget.org/packages/ThreeByte.LinkLib.NetBooter)
+
+
+---
+
+## β¨ Features
+
+| Feature | Description |
+|---------|-------------|
+| π **Outlet Control** | Turn individual power outlets on and off programmatically |
+| π **State Polling** | Query all outlet states in a single call |
+| π **Property Change Notifications** | Implements `INotifyPropertyChanged` for UI data binding |
+| π **HTTP-Based** | Communicates via the NetBooter's built-in web API |
+| β οΈ **Error Events** | Event-driven error reporting |
+
+---
+
+## π¦ Installation
+
+```
+dotnet add package ThreeByte.LinkLib.NetBooter
+```
+
+or via the NuGet Package Manager:
+
+```
+Install-Package ThreeByte.LinkLib.NetBooter
+```
+
+---
+
+## π Quick Start
+
+```csharp
+using ThreeByte.LinkLib.NetBooter;
+
+// Connect to a NetBooter device
+var netBooter = new NetBooterLink("192.168.1.10");
+
+// Subscribe to errors
+netBooter.ErrorOccurred += (s, ex) =>
+ Console.WriteLine($"Error: {ex.Message}");
+
+// Turn on outlet 1
+netBooter.Power(outlet: 1, state: true);
+
+// Turn off outlet 3
+netBooter.Power(outlet: 3, state: false);
+
+// Poll all outlet states from the device
+netBooter.PollState();
+
+// Check individual outlet states
+bool outlet1 = netBooter[1]; // true = ON
+bool outlet2 = netBooter[2]; // false = OFF
+Console.WriteLine($"Outlet 1: {(outlet1 ? "ON" : "OFF")}");
+Console.WriteLine($"Outlet 2: {(outlet2 ? "ON" : "OFF")}");
+```
+
+### WPF / MVVM Data Binding
+
+`NetBooterLink` implements `INotifyPropertyChanged`, making it easy to bind to UI:
+
+```xml
+
+
+
+
+
+
+```
+
+---
+
+## π API Reference
+
+### `NetBooterLink`
+
+#### Constructor
+
+```csharp
+NetBooterLink(string ipAddress)
+```
+
+#### Properties
+
+| Property | Type | Description |
+|----------|------|-------------|
+| `this[int port]` | `bool` | Indexer β get the power state of outlet N (`true` = ON) |
+
+#### Methods
+
+| Method | Returns | Description |
+|--------|---------|-------------|
+| `Power(int outlet, bool state)` | `void` | Set outlet power: `true` = ON, `false` = OFF |
+| `PollState()` | `void` | Query all outlet states from the device |
+
+#### Events
+
+| Event | Args | Description |
+|-------|------|-------------|
+| `PropertyChanged` | `PropertyChangedEventArgs` | Fires when an outlet state changes (INotifyPropertyChanged) |
+| `ErrorOccurred` | `Exception` | Fires on communication errors |
+
+---
+
+## ποΈ Architecture
+
+```
+ββββββββββββββββββββββββββββββββββββββββββββββββ
+β NetBooterLink β
+β β
+β Power(outlet, state) ββββββ β
+β βΌ β
+β βββββββββββββββββββββββ β
+β β HTTP Commands β β
+β β β β
+β β SET: $A3 {o} {s} β β
+β β POLL: $A5 β β
+β ββββββββββ¬βββββββββββββ β
+β β β
+β βΌ β
+β βββββββββββββββββββββββ β
+β β NetBooter Device β β
+β β http://{ip}/ β β
+β β cmd.cgi β β
+β βββββββββββββββββββββββ β
+β β β
+β PollState() ββββββββββββββ β
+β β β
+β βΌ β
+β βββββββββββββββββββββββββββββββββββββββββββ β
+β β Outlet State Dictionary β β
+β β { 1: ON, 2: OFF, 3: ON, ... } β β
+β βββββββββββββββββββββββββββββββββββββββββββ β
+β β β
+β βΌ β
+β PropertyChanged events β UI binding β
+ββββββββββββββββββββββββββββββββββββββββββββββββ
+```
+
+---
+
+## π§ How It Works
+
+The library communicates with Synaccess NetBooter devices via their HTTP CGI interface:
+
+| Operation | HTTP Request | Example |
+|-----------|-------------|---------|
+| **Power On** outlet 1 | `GET /cmd.cgi?$A3 1 1` | Turns on outlet 1 |
+| **Power Off** outlet 2 | `GET /cmd.cgi?$A3 2 0` | Turns off outlet 2 |
+| **Poll State** | `GET /cmd.cgi?$A5` | Returns binary string of all outlet states |
+
+### State Response Format
+
+The device returns a binary string where each bit (right-to-left) represents an outlet:
+
+```
+Response: "1101"
+ ||||
+ |||ββ Outlet 1: ON
+ ||βββ Outlet 2: OFF
+ |ββββ Outlet 3: ON
+ βββββ Outlet 4: ON
+```
+
+---
+
+## π― Platform Support
+
+| Platform | Supported |
+|----------|-----------|
+| .NET 10.0 | β
|
+| .NET Standard 2.1 | β
|
+| .NET Standard 2.0 | β
|
+| Windows | β
|
+| Linux | β
|
+| macOS | β
|
+
+---
+
+## π License
+
+Part of the [ThreeByte.LinkLib](https://github.com/Three-Byte/three-byte.link-lib) family of communication libraries.
diff --git a/ThreeByte.LinkLib/ThreeByte.LinkLib.NetBooter/ThreeByte.LinkLib.NetBooter.csproj b/ThreeByte.LinkLib/ThreeByte.LinkLib.NetBooter/ThreeByte.LinkLib.NetBooter.csproj
index ec69a40..3cbdfae 100644
--- a/ThreeByte.LinkLib/ThreeByte.LinkLib.NetBooter/ThreeByte.LinkLib.NetBooter.csproj
+++ b/ThreeByte.LinkLib/ThreeByte.LinkLib.NetBooter/ThreeByte.LinkLib.NetBooter.csproj
@@ -4,8 +4,13 @@
net10.0;netstandard2.0;netstandard2.1
enable
latest
+ README.md
+
+
+
+
diff --git a/ThreeByte.LinkLib/ThreeByte.LinkLib.ProjectorLink/README.md b/ThreeByte.LinkLib/ThreeByte.LinkLib.ProjectorLink/README.md
new file mode 100644
index 0000000..0ccc607
--- /dev/null
+++ b/ThreeByte.LinkLib/ThreeByte.LinkLib.ProjectorLink/README.md
@@ -0,0 +1,208 @@
+# π¬ ThreeByte.LinkLib.ProjectorLink
+
+**PJLink protocol client for controlling projectors over TCP β power on/off, state queries, and device info.**
+
+[](https://www.nuget.org/packages/ThreeByte.LinkLib.ProjectorLink)
+
+
+---
+
+## β¨ Features
+
+| Feature | Description |
+|---------|-------------|
+| π¬ **PJLink 1.0** | Full implementation of the PJLink Class 1 protocol |
+| π **Authentication** | MD5 password authentication when required by projector |
+| β‘ **Power Control** | Turn projectors on and off programmatically |
+| π **State Queries** | Query power state: Off, On, Cooling, Warming Up |
+| βΉοΈ **Device Info** | Retrieve manufacturer, product name, and projector name |
+| π **Error Events** | Event-driven error reporting |
+
+---
+
+## π¦ Installation
+
+```
+dotnet add package ThreeByte.LinkLib.ProjectorLink
+```
+
+or via the NuGet Package Manager:
+
+```
+Install-Package ThreeByte.LinkLib.ProjectorLink
+```
+
+---
+
+## π Quick Start
+
+```csharp
+using ThreeByte.LinkLib.ProjectorLink;
+
+// Connect to a projector (default PJLink port 4352)
+using var projector = new Projector("192.168.1.200");
+
+// Power on
+bool success = projector.TurnOn();
+Console.WriteLine(success ? "β
Projector turning on" : "β Power on failed");
+
+// Query state
+PowerStatus status = projector.GetState();
+Console.WriteLine($"Status: {status}");
+// Output: Status: WARMUP β ON
+
+// Get device info
+string info = projector.GetInfo();
+Console.WriteLine($"Projector: {info}");
+// Output: Projector: Epson EB-L1755U (Main Hall)
+
+// Power off
+projector.TurnOff();
+```
+
+### With Authentication
+
+```csharp
+// Some projectors require a password
+using var projector = new Projector("192.168.1.200", password: "admin123");
+
+projector.ErrorOccurred += (s, ex) =>
+ Console.WriteLine($"Projector error: {ex.Message}");
+
+projector.TurnOn();
+```
+
+### Custom Port
+
+```csharp
+// Non-standard PJLink port
+using var projector = new Projector("10.0.0.50", port: 5000, password: "secret");
+```
+
+---
+
+## π API Reference
+
+### `Projector`
+
+#### Constructors
+
+```csharp
+Projector(string host) // Default port 4352, no auth
+Projector(string host, int port) // Custom port, no auth
+Projector(string host, string password) // Default port, with auth
+Projector(string host, int port, string password) // Custom port + auth
+```
+
+#### Properties
+
+| Property | Type | Description |
+|----------|------|-------------|
+| `Address` | `string` | Formatted as `"host/port"` |
+
+#### Methods
+
+| Method | Returns | Description |
+|--------|---------|-------------|
+| `TurnOn()` | `bool` | Sends power-on command. Returns `true` on success |
+| `TurnOff()` | `bool` | Sends power-off command. Returns `true` on success |
+| `GetState()` | `PowerStatus` | Queries the current power state |
+| `GetInfo()` | `string` | Returns `"Manufacturer Product (Name)"` |
+| `Dispose()` | `void` | Releases resources |
+
+#### Events
+
+| Event | Args | Description |
+|-------|------|-------------|
+| `ErrorOccurred` | `Exception` | Fires on communication or protocol errors |
+
+---
+
+### `PowerStatus` Enum
+
+| Value | Int | Description |
+|-------|-----|-------------|
+| `OFF` | 0 | Projector is powered off |
+| `ON` | 1 | Projector is running normally |
+| `COOLING` | 2 | Projector is cooling down after power-off |
+| `WARMUP` | 3 | Projector lamp is warming up after power-on |
+| `UNKNOWN` | 4 | State could not be determined |
+
+### `CommandResponse` Enum
+
+| Value | Description |
+|-------|-------------|
+| `SUCCESS` | Command executed successfully |
+| `UNDEFINED_CMD` | Projector does not recognize the command |
+| `OUT_OF_PARAMETER` | Invalid parameter sent |
+| `UNAVAILABLE_TIME` | Command not available in current state |
+| `PROJECTOR_FAILURE` | Projector hardware error |
+| `AUTH_FAILURE` | Authentication failed |
+| `COMMUNICATION_ERROR` | Network or protocol error |
+
+---
+
+## ποΈ Architecture
+
+```
+ββββββββββββββββββββββββββββββββββββββββββββ
+β Projector β
+β β
+β TurnOn() βββ β
+β TurnOff()βββ€ ββββββββββββββββββββββββ β
+β GetState()ββ€ β PJLink Commands β β
+β GetInfo()βββ β β β
+β β PowerCommand β β
+β β ManufacturerName β β
+β β ProductName β β
+β β ProjectorName β β
+β ββββββββββββ¬ββββββββββββ β
+β β β
+β βΌ β
+β ββββββββββββββββββββββββ β
+β β TCP Connection β β
+β β (per-command) β β
+β β β β
+β β ββββββββββββββββββ β β
+β β β MD5 Auth β β β
+β β β (if required) β β β
+β β ββββββββββββββββββ β β
+β ββββββββββββββββββββββββ β
+ββββββββββββββββββββββββββββββββββββββββββββ
+```
+
+---
+
+## π PJLink Protocol Reference
+
+This library implements the [PJLink](https://pjlink.jbmia.or.jp/english/) Class 1 specification:
+
+| PJLink Command | Method | Description |
+|----------------|--------|-------------|
+| `%1POWR 1` | `TurnOn()` | Power on |
+| `%1POWR 0` | `TurnOff()` | Power off |
+| `%1POWR ?` | `GetState()` | Query power status |
+| `%1INF1 ?` | (via `GetInfo()`) | Query manufacturer |
+| `%1INF2 ?` | (via `GetInfo()`) | Query product name |
+| `%1NAME ?` | (via `GetInfo()`) | Query projector name |
+
+> **Default PJLink port:** TCP 4352
+
+---
+
+## π― Platform Support
+
+| Platform | Supported |
+|----------|-----------|
+| .NET 10.0 | β
|
+| .NET Standard 2.1 | β
|
+| .NET Standard 2.0 | β
|
+| Windows | β
|
+| Linux | β
|
+| macOS | β
|
+
+---
+
+## π License
+
+Part of the [ThreeByte.LinkLib](https://github.com/olaafrossi/three-byte.link-lib) family of communication libraries.
diff --git a/ThreeByte.LinkLib/ThreeByte.LinkLib.ProjectorLink/ThreeByte.LinkLib.ProjectorLink.csproj b/ThreeByte.LinkLib/ThreeByte.LinkLib.ProjectorLink/ThreeByte.LinkLib.ProjectorLink.csproj
index 3f9cdcd..526214a 100644
--- a/ThreeByte.LinkLib/ThreeByte.LinkLib.ProjectorLink/ThreeByte.LinkLib.ProjectorLink.csproj
+++ b/ThreeByte.LinkLib/ThreeByte.LinkLib.ProjectorLink/ThreeByte.LinkLib.ProjectorLink.csproj
@@ -4,8 +4,13 @@
net10.0;netstandard2.0;netstandard2.1
enable
latest
+ README.md
+
+
+
+
diff --git a/ThreeByte.LinkLib/ThreeByte.LinkLib.SerialLink/README.md b/ThreeByte.LinkLib/ThreeByte.LinkLib.SerialLink/README.md
new file mode 100644
index 0000000..7b1e5f4
--- /dev/null
+++ b/ThreeByte.LinkLib/ThreeByte.LinkLib.SerialLink/README.md
@@ -0,0 +1,248 @@
+# π ThreeByte.LinkLib.SerialLink
+
+**Serial port (RS-232) communication with optional frame-based protocol support, auto-reconnection, and message queuing.**
+
+[](https://www.nuget.org/packages/ThreeByte.LinkLib.SerialLink)
+
+
+---
+
+## β¨ Features
+
+| Feature | Description |
+|---------|-------------|
+| π **RS-232 Support** | Full serial port configuration β baud rate, data bits, parity |
+| π **Frame Protocol** | Optional header/footer framing via `FramedSerialLink` |
+| π **Auto-Reconnect** | Automatically recovers from serial port errors |
+| π¦ **Message Queuing** | Incoming data queued FIFO (up to 100 messages) |
+| π **Thread-Safe** | All operations protected with locks |
+| π **Event-Driven** | Connection changes, data arrival, and error events |
+| ποΈ **Enable/Disable** | Pause and resume without closing the port |
+
+---
+
+## π¦ Installation
+
+```
+dotnet add package ThreeByte.LinkLib.SerialLink
+```
+
+or via the NuGet Package Manager:
+
+```
+Install-Package ThreeByte.LinkLib.SerialLink
+```
+
+---
+
+## π Quick Start
+
+### Raw Serial Communication
+
+```csharp
+using ThreeByte.LinkLib.SerialLink;
+
+// Open a serial port at 9600 baud
+var serial = new SerialLink("COM3", baudRate: 9600);
+
+// Subscribe to events
+serial.IsConnectedChanged += (s, connected) =>
+ Console.WriteLine(connected ? "β
Port open" : "β Port closed");
+
+serial.DataReceived += (s, e) =>
+{
+ byte[]? data = serial.GetMessage();
+ if (data != null)
+ Console.WriteLine($"Received {data.Length} bytes");
+};
+
+// Send raw bytes
+byte[] command = new byte[] { 0x01, 0x02, 0x03 };
+serial.SendData(command);
+
+// Check for queued data
+while (serial.HasData)
+{
+ byte[]? response = serial.GetMessage();
+}
+
+serial.Dispose();
+```
+
+### Framed Serial Communication
+
+Use `FramedSerialLink` when your device protocol uses header/footer delimiters:
+
+```csharp
+using ThreeByte.LinkLib.SerialLink;
+
+var framed = new FramedSerialLink("COM4", baudRate: 115200);
+
+// Configure frame delimiters
+framed.SendFrame = new SerialFrame
+{
+ Header = new byte[] { 0x02 }, // STX
+ Footer = new byte[] { 0x03 } // ETX
+};
+
+framed.ReceiveFrame = new SerialFrame
+{
+ Header = new byte[] { 0x02 },
+ Footer = new byte[] { 0x03 }
+};
+
+// Send a framed message β header/footer added automatically
+framed.SendMessage("STATUS?");
+// Wire: [0x02] S T A T U S ? [0x03]
+
+// Receive complete framed messages
+framed.DataReceived += (s, e) =>
+{
+ string? response = framed.GetMessage();
+ Console.WriteLine($"Device says: {response}");
+};
+
+framed.Dispose();
+```
+
+---
+
+## π API Reference
+
+### `SerialLink` β Raw Serial Port
+
+#### Constructors
+
+```csharp
+SerialLink(string comPort, int baudRate = 9600, int dataBits = 8,
+ Parity parity = Parity.None, bool enabled = true)
+SerialLink(SerialLinkSettings settings, bool enabled = true)
+```
+
+#### Properties
+
+| Property | Type | Description |
+|----------|------|-------------|
+| `IsConnected` | `bool` | Whether the serial port is open and active |
+| `IsEnabled` | `bool` | Whether messaging is active |
+| `IsOpen` | `bool` | Whether the underlying port is open |
+| `HasData` | `bool` | Whether there are queued messages |
+| `ComPort` | `string` | The COM port name (e.g., `"COM3"`) |
+
+#### Methods
+
+| Method | Returns | Description |
+|--------|---------|-------------|
+| `SendData(byte[])` | `void` | Sends raw bytes over the serial port |
+| `GetMessage()` | `byte[]?` | Dequeues the next incoming byte array (FIFO) |
+| `SetEnabled(bool)` | `void` | Enables or disables communication |
+| `Dispose()` | `void` | Closes the port and releases resources |
+
+---
+
+### `FramedSerialLink` β Framed Protocol
+
+#### Constructors
+
+```csharp
+FramedSerialLink(string comPort, int baudRate = 9600, int dataBits = 8,
+ Parity parity = Parity.None, bool enabled = true)
+FramedSerialLink(SerialLinkSettings settings, bool enabled = true)
+```
+
+#### Properties
+
+| Property | Type | Description |
+|----------|------|-------------|
+| `SendFrame` | `SerialFrame` | Header/footer config for outgoing messages |
+| `ReceiveFrame` | `SerialFrame` | Header/footer config for incoming messages |
+| `IsConnected` | `bool` | Whether the underlying serial port is connected |
+| `IsEnabled` | `bool` | Whether messaging is active |
+| `HasData` | `bool` | Whether there are complete framed messages queued |
+
+#### Methods
+
+| Method | Returns | Description |
+|--------|---------|-------------|
+| `SendMessage(string)` | `void` | Sends a string message wrapped in the configured frame |
+| `GetMessage()` | `string?` | Dequeues the next complete framed message (FIFO) |
+| `SetEnabled(bool)` | `void` | Enables or disables communication |
+| `Dispose()` | `void` | Closes the port and releases resources |
+
+---
+
+### `SerialFrame` β Frame Configuration
+
+```csharp
+var frame = new SerialFrame
+{
+ Header = new byte[] { 0x02 }, // Start-of-text
+ Footer = new byte[] { 0x0D, 0x0A } // CR+LF
+};
+```
+
+| Property | Type | Description |
+|----------|------|-------------|
+| `Header` | `byte[]` | Bytes prepended to every outgoing message / expected at start of incoming |
+| `Footer` | `byte[]` | Bytes appended to every outgoing message / expected at end of incoming |
+
+---
+
+## ποΈ Architecture
+
+```
+ββββββββββββββββββββββββββββββββββββββββββββββββββββ
+β FramedSerialLink β
+β ββββββββββββββ ββββββββββββββββββββββ β
+β β SendFrame β β ReceiveFrame β β
+β β [HDR][MSG] β β Detect [HDR].. β β
+β β [FTR] β β ..[FTR] β β
+β βββββββ¬βββββββ ββββββββββ¬ββββββββββββ β
+β β β β
+β βΌ βΌ β
+β βββββββββββββββββββββββββββββββββββββββββββββββββ
+β β SerialLink (Raw) ββ
+β β ββ
+β β COM Port ββ Read/Write ββ Message Queue ββ
+β β β ββ
+β β Auto-Reconnect Timer ββ
+β βββββββββββββββββββββββββββββββββββββββββββββββββ
+ββββββββββββββββββββββββββββββββββββββββββββββββββββ
+```
+
+---
+
+## π§ Configuration
+
+Use `SerialLinkSettings` for structured configuration:
+
+```csharp
+var settings = new SerialLinkSettings("COM3", 9600, 8, Parity.None);
+var serial = new SerialLink(settings);
+```
+
+| Property | Type | Default | Description |
+|----------|------|---------|-------------|
+| `ComPort` | `string` | β | Serial port name (e.g., `"COM3"`, `"/dev/ttyUSB0"`) |
+| `BaudRate` | `int` | `9600` | Communication speed |
+| `DataBits` | `int` | `8` | Data bits per byte |
+| `Parity` | `Parity` | `None` | Parity checking mode |
+
+---
+
+## π― Platform Support
+
+| Platform | Supported |
+|----------|-----------|
+| .NET 10.0 | β
|
+| .NET Standard 2.1 | β
|
+| .NET Standard 2.0 | β
|
+| Windows (`COM1`..`COM256`) | β
|
+| Linux (`/dev/ttyUSB0`, `/dev/ttyS0`) | β
|
+| macOS (`/dev/tty.usbserial`) | β
|
+
+---
+
+## π License
+
+Part of the [ThreeByte.LinkLib](https://github.com/olaafrossi/three-byte.link-lib) family of communication libraries.
diff --git a/ThreeByte.LinkLib/ThreeByte.LinkLib.SerialLink/ThreeByte.LinkLib.SerialLink.csproj b/ThreeByte.LinkLib/ThreeByte.LinkLib.SerialLink/ThreeByte.LinkLib.SerialLink.csproj
index 2ab1895..3053fcd 100644
--- a/ThreeByte.LinkLib/ThreeByte.LinkLib.SerialLink/ThreeByte.LinkLib.SerialLink.csproj
+++ b/ThreeByte.LinkLib/ThreeByte.LinkLib.SerialLink/ThreeByte.LinkLib.SerialLink.csproj
@@ -4,8 +4,13 @@
net10.0;netstandard2.0;netstandard2.1
enable
latest
+ README.md
+
+
+
+
diff --git a/ThreeByte.LinkLib/ThreeByte.LinkLib.Shared/README.md b/ThreeByte.LinkLib/ThreeByte.LinkLib.Shared/README.md
new file mode 100644
index 0000000..5664e4b
--- /dev/null
+++ b/ThreeByte.LinkLib/ThreeByte.LinkLib.Shared/README.md
@@ -0,0 +1,124 @@
+# π§© ThreeByte.LinkLib.Shared
+
+**Shared logging infrastructure for all ThreeByte.LinkLib packages β consistent, standardized console logging via `Microsoft.Extensions.Logging`.**
+
+[](https://www.nuget.org/packages/ThreeByte.LinkLib.Shared)
+
+
+---
+
+## β¨ Features
+
+| Feature | Description |
+|---------|-------------|
+| π§© **Shared Foundation** | Common utilities used by all LinkLib packages |
+| π **Structured Logging** | Built on `Microsoft.Extensions.Logging` for standardized output |
+| π₯οΈ **Console Output** | Pre-configured console logging provider |
+| π **Logger Factory** | Simple `LogFactory.Create()` API for creating typed loggers |
+
+---
+
+## π¦ Installation
+
+```
+dotnet add package ThreeByte.LinkLib.Shared
+```
+
+> **Note:** This package is automatically included as a dependency when you install any other ThreeByte.LinkLib package (TcpLink, UdpLink, SerialLink, ProjectorLink, or NetBooter).
+
+---
+
+## π Quick Start
+
+```csharp
+using ThreeByte.LinkLib.Shared;
+
+// Create a typed logger for your class
+ILogger logger = LogFactory.Create();
+
+logger.LogInformation("Service started on port {Port}", 8080);
+logger.LogWarning("Connection attempt timed out");
+logger.LogError("Failed to send data: {Error}", ex.Message);
+```
+
+---
+
+## π API Reference
+
+### `LogFactory`
+
+A static factory that creates pre-configured `ILogger` instances with console output.
+
+#### Methods
+
+| Method | Returns | Description |
+|--------|---------|-------------|
+| `Create()` | `ILogger` | Creates a console logger with the category name of type `T` |
+
+#### Example Output
+
+```
+info: MyApp.DeviceController[0]
+ Connected to projector at 192.168.1.200
+warn: MyApp.DeviceController[0]
+ Reconnection attempt #3
+```
+
+---
+
+## ποΈ How It Fits Together
+
+```
+ββββββββββββββββββββββββββββββββββββββββββββββββββββ
+β Your Application β
+ββββββββββ¬βββββββββββ¬βββββββββββ¬βββββββββββ¬βββββββββ
+ β β β β
+ βΌ βΌ βΌ βΌ
+ βββββββββββ ββββββββββ ββββββββββ βββββββββββ
+ β TcpLink β βUdpLink β βSerial β βProjectorβ
+ β β β β β Link β β Link β
+ ββββββ¬βββββ βββββ¬βββββ βββββ¬βββββ ββββββ¬βββββ
+ β β β β
+ ββββββββββββ΄βββββββ¬ββββ΄ββββββββββββ
+ β
+ βΌ
+ βββββββββββββββββββββββββββ
+ β ThreeByte.LinkLib β
+ β .Shared β
+ β β
+ β LogFactory.Create()β
+ β β β
+ β βΌ β
+ β Microsoft.Extensions β
+ β .Logging.Console β
+ βββββββββββββββββββββββββββ
+```
+
+---
+
+## π Dependencies
+
+| Package | Version | Purpose |
+|---------|---------|---------|
+| `Microsoft.Extensions.Logging` | 9.0.2 | Core logging abstractions |
+| `Microsoft.Extensions.Logging.Abstractions` | 9.0.2 | `ILogger` interface |
+| `Microsoft.Extensions.Logging.Console` | 9.0.2 | Console output provider |
+
+---
+
+## π― Platform Support
+
+| Platform | Supported |
+|----------|-----------|
+| .NET 10.0 | β
|
+| .NET Standard 2.1 | β
|
+| .NET Standard 2.0 | β
|
+| Windows | β
|
+| Linux | β
|
+| macOS | β
|
+
+---
+
+## π License
+
+Part of the [ThreeByte.LinkLib](https://github.com/olaafrossi/three-byte.link-lib) family of communication libraries.
diff --git a/ThreeByte.LinkLib/ThreeByte.LinkLib.Shared/ThreeByte.LinkLib.Shared.csproj b/ThreeByte.LinkLib/ThreeByte.LinkLib.Shared/ThreeByte.LinkLib.Shared.csproj
index 0ccccae..acb92a9 100644
--- a/ThreeByte.LinkLib/ThreeByte.LinkLib.Shared/ThreeByte.LinkLib.Shared.csproj
+++ b/ThreeByte.LinkLib/ThreeByte.LinkLib.Shared/ThreeByte.LinkLib.Shared.csproj
@@ -4,8 +4,13 @@
net10.0;netstandard2.0;netstandard2.1
enable
latest
+ README.md
+
+
+
+
diff --git a/ThreeByte.LinkLib/ThreeByte.LinkLib.TcpLink/README.md b/ThreeByte.LinkLib/ThreeByte.LinkLib.TcpLink/README.md
new file mode 100644
index 0000000..20e6582
--- /dev/null
+++ b/ThreeByte.LinkLib/ThreeByte.LinkLib.TcpLink/README.md
@@ -0,0 +1,164 @@
+# π ThreeByte.LinkLib.TcpLink
+
+**Asynchronous TCP client with automatic reconnection, message queuing, and thread-safe operation.**
+
+[](https://www.nuget.org/packages/ThreeByte.LinkLib.TcpLink)
+
+
+---
+
+## β¨ Features
+
+| Feature | Description |
+|---------|-------------|
+| π **Auto-Reconnect** | Automatically re-establishes connections with a 3-second retry on failure |
+| π¦ **Message Queuing** | Incoming data is queued (FIFO, up to 100 messages) for reliable retrieval |
+| π **Thread-Safe** | All operations are protected with locking for concurrent access |
+| β‘ **Fully Async** | Uses `BeginConnect` / `BeginRead` / `BeginWrite` for non-blocking I/O |
+| π **Event-Driven** | Rich event model for connection changes, data arrival, and errors |
+| ποΈ **Enable/Disable** | Pause and resume communication without destroying the connection |
+
+---
+
+## π¦ Installation
+
+```
+dotnet add package ThreeByte.LinkLib.TcpLink
+```
+
+or via the NuGet Package Manager:
+
+```
+Install-Package ThreeByte.LinkLib.TcpLink
+```
+
+---
+
+## π Quick Start
+
+```csharp
+using ThreeByte.LinkLib.TcpLink;
+
+// Create a TCP link to a remote device
+var tcp = new AsyncTcpLink("192.168.1.100", 5000);
+
+// Subscribe to events
+tcp.IsConnectedChanged += (s, connected) =>
+ Console.WriteLine(connected ? "β
Connected" : "β Disconnected");
+
+tcp.DataReceived += (s, e) =>
+ Console.WriteLine($"Data arrived: {tcp.GetMessage()?.Length} bytes");
+
+tcp.ErrorOccurred += (s, ex) =>
+ Console.WriteLine($"Error: {ex.Message}");
+
+// Send a message
+byte[] command = System.Text.Encoding.ASCII.GetBytes("HELLO\r\n");
+tcp.SendMessage(command);
+
+// Retrieve queued incoming data
+if (tcp.HasData)
+{
+ byte[]? response = tcp.GetMessage();
+}
+
+// Clean up
+tcp.Dispose();
+```
+
+---
+
+## π API Reference
+
+### `AsyncTcpLink`
+
+#### Constructors
+
+```csharp
+AsyncTcpLink(string address, int port)
+AsyncTcpLink(string address, int port, bool enabled = true)
+```
+
+#### Properties
+
+| Property | Type | Description |
+|----------|------|-------------|
+| `IsConnected` | `bool` | Whether the TCP socket is currently connected |
+| `IsEnabled` | `bool` | Whether messaging is active |
+| `Address` | `string` | Remote host address |
+| `Port` | `int` | Remote host port |
+| `HasData` | `bool` | Whether there are queued incoming messages |
+
+#### Methods
+
+| Method | Returns | Description |
+|--------|---------|-------------|
+| `SendMessage(byte[])` | `void` | Sends a byte array to the remote host |
+| `GetMessage()` | `byte[]?` | Dequeues and returns the next incoming message (FIFO) |
+| `SetEnabled(bool)` | `void` | Enables or disables communication |
+| `Dispose()` | `void` | Releases all resources and closes the connection |
+
+#### Events
+
+| Event | Args | Description |
+|-------|------|-------------|
+| `IsConnectedChanged` | `bool` | Fires when connection state changes |
+| `IsEnabledChanged` | `bool` | Fires when enabled state changes |
+| `ErrorOccurred` | `Exception` | Fires on communication errors |
+| `DataReceived` | `EventArgs` | Fires when new data arrives |
+
+---
+
+## π§ Configuration
+
+Use `TcpLinkSettings` for structured configuration:
+
+```csharp
+var settings = new TcpLinkSettings("192.168.1.100", 5000);
+// Access settings.Address, settings.Port
+```
+
+---
+
+## ποΈ Architecture
+
+```
+βββββββββββββββββββββββββββββββββββββββββββββββ
+β AsyncTcpLink β
+β β
+β βββββββββββββ βββββββββββββ βββββββββββ β
+β β Connect β β Read β β Write β β
+β β (Async) β β (Async) β β (Async) β β
+β βββββββ¬ββββββ βββββββ¬ββββββ ββββββ¬βββββ β
+β β β β β
+β βΌ βΌ βΌ β
+β ββββββββββββββββββββββββββββββββββββββββββββ
+β β Thread-Safe Message Queue ββ
+β β (FIFO, max 100) ββ
+β ββββββββββββββββββββββββββββββββββββββββββββ
+β β β
+β βΌ β
+β ββββββββββββββββββββββββββββββββββββββββββββ
+β β Auto-Reconnect Timer (3 sec) ββ
+β ββββββββββββββββββββββββββββββββββββββββββββ
+βββββββββββββββββββββββββββββββββββββββββββββββ
+```
+
+---
+
+## π― Platform Support
+
+| Platform | Supported |
+|----------|-----------|
+| .NET 10.0 | β
|
+| .NET Standard 2.1 | β
|
+| .NET Standard 2.0 | β
|
+| Windows | β
|
+| Linux | β
|
+| macOS | β
|
+
+---
+
+## π License
+
+Part of the [ThreeByte.LinkLib](https://github.com/olaafrossi/three-byte.link-lib) family of communication libraries.
diff --git a/ThreeByte.LinkLib/ThreeByte.LinkLib.TcpLink/ThreeByte.LinkLib.TcpLink.csproj b/ThreeByte.LinkLib/ThreeByte.LinkLib.TcpLink/ThreeByte.LinkLib.TcpLink.csproj
index ec69a40..3cbdfae 100644
--- a/ThreeByte.LinkLib/ThreeByte.LinkLib.TcpLink/ThreeByte.LinkLib.TcpLink.csproj
+++ b/ThreeByte.LinkLib/ThreeByte.LinkLib.TcpLink/ThreeByte.LinkLib.TcpLink.csproj
@@ -4,8 +4,13 @@
net10.0;netstandard2.0;netstandard2.1
enable
latest
+ README.md
+
+
+
+
diff --git a/ThreeByte.LinkLib/ThreeByte.LinkLib.UdpLink/README.md b/ThreeByte.LinkLib/ThreeByte.LinkLib.UdpLink/README.md
new file mode 100644
index 0000000..7aa54bb
--- /dev/null
+++ b/ThreeByte.LinkLib/ThreeByte.LinkLib.UdpLink/README.md
@@ -0,0 +1,191 @@
+# π‘ ThreeByte.LinkLib.UdpLink
+
+**Asynchronous UDP client with message queuing, configurable endpoints, and thread-safe operation.**
+
+[](https://www.nuget.org/packages/ThreeByte.LinkLib.UdpLink)
+
+
+---
+
+## β¨ Features
+
+| Feature | Description |
+|---------|-------------|
+| π‘ **Connectionless** | Low-latency UDP datagrams β no handshake overhead |
+| π¦ **Message Queuing** | Incoming datagrams queued FIFO (up to 100 messages) |
+| π **Thread-Safe** | All operations protected with locking |
+| β‘ **Fully Async** | Non-blocking `BeginSend` / `BeginReceive` patterns |
+| ποΈ **Dual Port Config** | Separate remote and local port configuration |
+| π **Event-Driven** | Events for data arrival, errors, and enable/disable state |
+
+---
+
+## π¦ Installation
+
+```
+dotnet add package ThreeByte.LinkLib.UdpLink
+```
+
+or via the NuGet Package Manager:
+
+```
+Install-Package ThreeByte.LinkLib.UdpLink
+```
+
+---
+
+## π Quick Start
+
+```csharp
+using ThreeByte.LinkLib.UdpLink;
+
+// Send to a remote device on port 9000, listen on local port 9001
+var udp = new AsyncUdpLink("192.168.1.50", remotePort: 9000, localPort: 9001);
+
+// Subscribe to incoming data
+udp.DataReceived += (s, e) =>
+{
+ byte[]? data = udp.GetMessage();
+ if (data != null)
+ Console.WriteLine($"Received {data.Length} bytes");
+};
+
+udp.ErrorOccurred += (s, ex) =>
+ Console.WriteLine($"Error: {ex.Message}");
+
+// Send a datagram
+byte[] payload = System.Text.Encoding.ASCII.GetBytes("PING");
+udp.SendMessage(payload);
+
+// Check for queued data
+while (udp.HasData)
+{
+ byte[]? response = udp.GetMessage();
+}
+
+// Clean up
+udp.Dispose();
+```
+
+### Dynamic Local Port
+
+```csharp
+// Let the OS assign a local port (default behavior)
+var udp = new AsyncUdpLink("10.0.0.1", remotePort: 8080);
+```
+
+---
+
+## π API Reference
+
+### `AsyncUdpLink`
+
+#### Constructors
+
+```csharp
+AsyncUdpLink(string address, int remotePort, int localPort = 0, bool enabled = true)
+AsyncUdpLink(UdpLinkSettings settings, bool enabled = true)
+```
+
+#### Properties
+
+| Property | Type | Description |
+|----------|------|-------------|
+| `IsEnabled` | `bool` | Whether the link is actively receiving |
+| `Address` | `string` | Remote host address |
+| `Port` | `int` | Remote port number |
+| `HasData` | `bool` | Whether there are queued incoming datagrams |
+
+#### Methods
+
+| Method | Returns | Description |
+|--------|---------|-------------|
+| `SendMessage(byte[])` | `void` | Sends a byte array datagram to the remote endpoint |
+| `GetMessage()` | `byte[]?` | Dequeues the next incoming datagram (FIFO) |
+| `SetEnabled(bool)` | `void` | Starts or stops the receive loop |
+| `Dispose()` | `void` | Releases the UDP socket and all resources |
+
+#### Events
+
+| Event | Args | Description |
+|-------|------|-------------|
+| `IsEnabledChanged` | `bool` | Fires when enabled state changes |
+| `ErrorOccurred` | `Exception` | Fires on communication errors |
+| `DataReceived` | `EventArgs` | Fires when a datagram arrives |
+
+---
+
+## π§ Configuration
+
+Use `UdpLinkSettings` for structured configuration:
+
+```csharp
+// With explicit local port
+var settings = new UdpLinkSettings("10.0.0.1", remotePort: 8080, localPort: 8081);
+
+// With dynamic local port (default 0)
+var settings = new UdpLinkSettings("10.0.0.1", remotePort: 8080);
+```
+
+| Property | Type | Description |
+|----------|------|-------------|
+| `Address` | `string` | Remote host address |
+| `RemotePort` | `int` | Remote port to send to |
+| `LocalPort` | `int` | Local port to bind (0 = OS-assigned) |
+
+---
+
+## ποΈ Architecture
+
+```
+ββββββββββββββββββββββββββββββββββββββββββββββ
+β AsyncUdpLink β
+β β
+β ββββββββββββββββ ββββββββββββββββββββ β
+β β Send (Async) β β Receive (Async) β β
+β β β Remote:Port β β β Local:Port β β
+β ββββββββ¬ββββββββ ββββββββββ¬ββββββββββ β
+β β β β
+β βΌ βΌ β
+β ββββββββββββββββββββββββββββββββββββββββ β
+β β Thread-Safe Message Queue β β
+β β (FIFO, max 100) β β
+β ββββββββββββββββββββββββββββββββββββββββ β
+β β β
+β βΌ β
+β ββββββββββββββββββββββββββββββββββββββββ β
+β β Event Dispatch (Data / Error) β β
+β ββββββββββββββββββββββββββββββββββββββββ β
+ββββββββββββββββββββββββββββββββββββββββββββββ
+```
+
+---
+
+## π‘ TCP vs UDP β When to Use This Package
+
+| Scenario | Use |
+|----------|-----|
+| Reliable, ordered data transfer | `ThreeByte.LinkLib.TcpLink` |
+| Low-latency, fire-and-forget messaging | **`ThreeByte.LinkLib.UdpLink`** β
|
+| Broadcast / multicast discovery | **`ThreeByte.LinkLib.UdpLink`** β
|
+| Streaming sensor data | **`ThreeByte.LinkLib.UdpLink`** β
|
+| Command-response protocols | `ThreeByte.LinkLib.TcpLink` |
+
+---
+
+## π― Platform Support
+
+| Platform | Supported |
+|----------|-----------|
+| .NET 10.0 | β
|
+| .NET Standard 2.1 | β
|
+| .NET Standard 2.0 | β
|
+| Windows | β
|
+| Linux | β
|
+| macOS | β
|
+
+---
+
+## π License
+
+Part of the [ThreeByte.LinkLib](https://github.com/Three-Byte/three-byte.link-lib) family of communication libraries.
diff --git a/ThreeByte.LinkLib/ThreeByte.LinkLib.UdpLink/ThreeByte.LinkLib.UdpLink.csproj b/ThreeByte.LinkLib/ThreeByte.LinkLib.UdpLink/ThreeByte.LinkLib.UdpLink.csproj
index 9354acf..7a5b99b 100644
--- a/ThreeByte.LinkLib/ThreeByte.LinkLib.UdpLink/ThreeByte.LinkLib.UdpLink.csproj
+++ b/ThreeByte.LinkLib/ThreeByte.LinkLib.UdpLink/ThreeByte.LinkLib.UdpLink.csproj
@@ -4,8 +4,13 @@
net10.0;netstandard2.0;netstandard2.1
enable
latest
+ README.md
+
+
+
+