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
                    
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="Tellurian.Trains.Communications.Channels" Version="1.8.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Tellurian.Trains.Communications.Channels" Version="1.8.0" />
                    
Directory.Packages.props
<PackageReference Include="Tellurian.Trains.Communications.Channels" />
                    
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 Tellurian.Trains.Communications.Channels --version 1.8.0
                    
#r "nuget: Tellurian.Trains.Communications.Channels, 1.8.0"
                    
#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 Tellurian.Trains.Communications.Channels@1.8.0
                    
#: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=Tellurian.Trains.Communications.Channels&version=1.8.0
                    
Install as a Cake Addin
#tool nuget:?package=Tellurian.Trains.Communications.Channels&version=1.8.0
                    
Install as a Cake Tool

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 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 (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
Loading failed