Tellurian.Trains.Communications.Channels
1.8.0
Prefix Reserved
dotnet add package Tellurian.Trains.Communications.Channels --version 1.8.0
NuGet\Install-Package Tellurian.Trains.Communications.Channels -Version 1.8.0
<PackageReference Include="Tellurian.Trains.Communications.Channels" Version="1.8.0" />
<PackageVersion Include="Tellurian.Trains.Communications.Channels" Version="1.8.0" />
<PackageReference Include="Tellurian.Trains.Communications.Channels" />
paket add Tellurian.Trains.Communications.Channels --version 1.8.0
#r "nuget: Tellurian.Trains.Communications.Channels, 1.8.0"
#:package Tellurian.Trains.Communications.Channels@1.8.0
#addin nuget:?package=Tellurian.Trains.Communications.Channels&version=1.8.0
#tool nuget:?package=Tellurian.Trains.Communications.Channels&version=1.8.0
Tellurian.Trains.Communications.Channels
A protocol-agnostic transport layer library for model train control systems. Provides UDP, serial port, TCP, and UDP multicast communication with async/await patterns and observer-based notifications.
Features
- Protocol-agnostic: Works with any byte-based protocol (Z21, LocoNet, XpressNet)
- Async-first: All I/O operations use async/await with cancellation support
- Observer pattern: Standard
IObservable<T>for receiving data notifications - Result types: Explicit success/failure handling without exceptions
- Testable: Interface-based design with mock implementations
Quick Start
UDP Channel (Z21 Command Station)
using Microsoft.Extensions.Logging;
using Tellurian.Trains.Communications.Channels;
using System.Net;
// Create channel
var logger = loggerFactory.CreateLogger<UdpDataChannel>();
var remoteEndPoint = new IPEndPoint(IPAddress.Parse("192.168.1.100"), 21105);
await using var channel = new UdpDataChannel(localPort: 21105, remoteEndPoint, logger);
// Subscribe to received data
var subscription = channel.Subscribe(new MyObserver());
// Start background receive loop
var cts = new CancellationTokenSource();
await channel.StartReceiveAsync(cts.Token);
// Send data
var result = await channel.SendAsync(new byte[] { 0x04, 0x00, 0x10, 0x00 }, cts.Token);
if (result.IsSuccess)
{
Console.WriteLine("Sent successfully");
}
// Cleanup
cts.Cancel();
subscription.Dispose();
Serial Channel (LocoNet)
using Microsoft.Extensions.Logging;
using Tellurian.Trains.Communications.Channels;
// Create serial port adapter
var serialPort = new SerialPortAdapter("COM3", baudRate: 57600);
// Create channel with protocol framer
var framer = new LocoNetFramer(); // From Tellurian.Protocols.LocoNet
var logger = loggerFactory.CreateLogger<SerialDataChannel>();
await using var channel = new SerialDataChannel(serialPort, framer, logger);
// Subscribe and start receiving
var subscription = channel.Subscribe(new MyObserver());
var cts = new CancellationTokenSource();
await channel.StartReceiveAsync(cts.Token);
// Send LocoNet message
await channel.SendAsync(new byte[] { 0xB5, 0x01, 0x02, 0xF2 }, cts.Token);
TCP Channel (LoconetOverTcp)
using Tellurian.Trains.Communications.Channels;
// Connect to a LoconetOverTcp server (LbServer, JMRI, Rocrail)
var stream = new TcpStreamAdapter("192.168.1.100", 1234);
var logger = loggerFactory.CreateLogger<TcpLocoNetChannel>();
await using var channel = new TcpLocoNetChannel(stream, logger);
var subscription = channel.Subscribe(new MyObserver());
var cts = new CancellationTokenSource();
await channel.StartReceiveAsync(cts.Token);
await channel.SendAsync(new byte[] { 0xB5, 0x01, 0x02, 0xF2 }, cts.Token);
UDP Multicast Channel (LocoNet over UDP)
using System.Net;
using Tellurian.Trains.Communications.Channels;
// loconetd (Glenn Butcher): multicast 225.0.0.2, listen 4501, send to gateway on 4500
var adapter = new UdpLocoNetAdapter(
multicastGroup: IPAddress.Parse("225.0.0.2"),
listenPort: 4501,
sendEndpoint: new IPEndPoint(IPAddress.Parse("192.168.1.50"), 4500));
var logger = loggerFactory.CreateLogger<UdpLocoNetChannel>();
await using var channel = new UdpLocoNetChannel(adapter, logger);
var subscription = channel.Subscribe(new MyObserver());
var cts = new CancellationTokenSource();
await channel.StartReceiveAsync(cts.Token);
await channel.SendAsync(new byte[] { 0xB5, 0x01, 0x02, 0xF2 }, cts.Token);
Handling Received Data
public class MyObserver : IObserver<CommunicationResult>
{
public void OnNext(CommunicationResult result)
{
if (result is SuccessResult success)
{
byte[] data = success.Data();
Console.WriteLine($"Received {data.Length} bytes from {success.RemoteEndpointName}");
}
else if (result is FailureResult failure)
{
Console.WriteLine($"Error: {failure.Exception.Message}");
}
}
public void OnError(Exception error) => Console.WriteLine($"Channel error: {error.Message}");
public void OnCompleted() => Console.WriteLine("Channel closed");
}
Installation
Add a reference to the project or NuGet package:
<PackageReference Include="Tellurian.Trains.Communications.Channels" />
Documentation
See DOCUMENTATION.md for complete API documentation including:
- Dependency injection configuration
- Channel architecture and lifecycle
- Observer pattern implementation
- Result type handling
- Testing patterns
Requirements
- .NET 10.0 or later
- For serial ports: Windows, Linux, or macOS with serial port support, for example with a USB-to-serial adapter.
| Product | Versions 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. |
-
net10.0
- Microsoft.Extensions.Logging.Abstractions (>= 10.0.0)
- System.IO.Ports (>= 9.0.1)
NuGet packages (3)
Showing the top 3 NuGet packages that depend on Tellurian.Trains.Communications.Channels:
| Package | Downloads |
|---|---|
|
Tellurian.Trains.Protocols.LocoNet
Package Description |
|
|
Tellurian.Trains.Adapters.Z21
A .NET adapter for the Roco/Fleischmann Z21 digital command station. |
|
|
Tellurian.Trains.Adapters.LocoNet
A .NET adapter for LocoNet-based command stations via serial port |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.8.0 | 184 | 4/17/2026 |
| 1.7.15 | 158 | 4/16/2026 |
| 1.7.14 | 149 | 4/16/2026 |
| 1.7.13 | 154 | 4/16/2026 |
| 1.7.12 | 149 | 4/16/2026 |
| 1.7.11 | 162 | 4/15/2026 |
| 1.7.10 | 151 | 4/15/2026 |
| 1.7.9 | 148 | 4/15/2026 |
| 1.7.8 | 147 | 4/15/2026 |
| 1.7.7 | 150 | 4/15/2026 |
| 1.7.6 | 140 | 4/15/2026 |
| 1.7.5 | 144 | 4/15/2026 |
| 1.7.4 | 152 | 4/15/2026 |
| 1.7.3 | 268 | 3/28/2026 |
| 1.7.2 | 153 | 3/28/2026 |
| 1.7.1 | 155 | 3/27/2026 |
| 1.7.0 | 167 | 3/16/2026 |
| 1.6.1 | 170 | 2/22/2026 |
| 1.6.0 | 161 | 2/19/2026 |
| 1.5.0 | 155 | 2/11/2026 |